我遇到了一个问题:直到今天,我用PHP发送HTML邮件,邮件头包含
Content-type: text/html;
现在,我添加了添加附件的功能。为此,我不得不将这条线路改为
Content-Type: multipart/mixed;
现在,使用multipart/mixed
,邮件的其余部分,即普通文本,将显示为text/plain。我如何才能意识到附件可以工作,而邮件文本仍然是HTML?
我试了几个小时的答案1,但没有成功。我在这里找到了一个解决方案:http://www.finalwebsites.com/forums/topic/php-e-mail-attachment-script
效果就像一个魅力-不到5分钟!您可能想要更改(就像我所做的那样),第一个内容类型从text/plain更改为text/html。
这是我的略有修改的版本,可以处理多个附件:
function mail_attachment($files, $path, $mailto, $from_mail, $from_name, $replyto, $subject, $message) {
$uid = md5(uniqid(time()));
$header = "From: ".$from_name." <".$from_mail.">rn";
$header .= "Reply-To: ".$replyto."rn";
$header .= "MIME-Version: 1.0rn";
$header .= "Content-Type: multipart/mixed; boundary="".$uid.""rnrn";
$header .= "This is a multi-part message in MIME format.rn";
$header .= "--".$uid."rn";
$header .= "Content-type:text/html; charset=iso-8859-1rn";
$header .= "Content-Transfer-Encoding: 7bitrnrn";
$header .= $message."rnrn";
foreach ($files as $filename) {
$file = $path.$filename;
$file_size = filesize($file);
$handle = fopen($file, "r");
$content = fread($handle, $file_size);
fclose($handle);
$content = chunk_split(base64_encode($content));
$header .= "--".$uid."rn";
$header .= "Content-Type: application/octet-stream; name="".$filename.""rn"; // use different content types here
$header .= "Content-Transfer-Encoding: base64rn";
$header .= "Content-Disposition: attachment; filename="".$filename.""rnrn";
$header .= $content."rnrn";
}
$header .= "--".$uid."--";
return mail($mailto, $subject, "", $header);
}
要发送带有附件的电子邮件,我们需要使用多部分/混合MIME类型,该类型指定混合类型将包含在电子邮件中。此外,我们希望使用多部分/替代MIME类型来发送纯文本和HTML版本的电子邮件。看看这个例子:
<?php
//define the receiver of the email
$to = 'youraddress@example.com';
//define the subject of the email
$subject = 'Test email with attachment';
//create a boundary string. It must be unique
//so we use the MD5 algorithm to generate a random hash
$random_hash = md5(date('r', time()));
//define the headers we want passed. Note that they are separated with rn
$headers = "From: webmaster@example.comrnReply-To: webmaster@example.com";
//add boundary string and mime type specification
$headers .= "rnContent-Type: multipart/mixed; boundary="PHP-mixed-".$random_hash.""";
//read the atachment file contents into a string,
//encode it with MIME base64,
//and split it into smaller chunks
$attachment = chunk_split(base64_encode(file_get_contents('attachment.zip')));
//define the body of the message.
ob_start(); //Turn on output buffering
?>
--PHP-mixed-<?php echo $random_hash; ?>
Content-Type: multipart/alternative; boundary="PHP-alt-<?php echo $random_hash; ?>"
--PHP-alt-<?php echo $random_hash; ?>
Content-Type: text/plain; charset="iso-8859-1"
Content-Transfer-Encoding: 7bit
Hello World!!!
This is simple text email message.
--PHP-alt-<?php echo $random_hash; ?>
Content-Type: text/html; charset="iso-8859-1"
Content-Transfer-Encoding: 7bit
<h2>Hello World!</h2>
<p>This is something with <b>HTML</b> formatting.</p>
--PHP-alt-<?php echo $random_hash; ?>--
--PHP-mixed-<?php echo $random_hash; ?>
Content-Type: application/zip; name="attachment.zip"
Content-Transfer-Encoding: base64
Content-Disposition: attachment
<?php echo $attachment; ?>
--PHP-mixed-<?php echo $random_hash; ?>--
<?php
//copy current buffer contents into $message variable and delete current output buffer
$message = ob_get_clean();
//send the email
$mail_sent = @mail( $to, $subject, $message, $headers );
//if the message is sent successfully print "Mail sent". Otherwise print "Mail failed"
echo $mail_sent ? "Mail sent" : "Mail failed";
?>
正如您所看到的,发送带有附件的电子邮件很容易完成。在前面的示例中,我们有多部分/混合MIME类型,其中有指定两个版本的电子邮件的多部分/替代MIME类型。为了在消息中包含附件,我们将指定文件中的数据读取为字符串,用base64对其进行编码,将其拆分为更小的块,以确保其符合MIME规范,然后将其作为附件包含。php中的
SWIFTMAIL适用于邮件附件的gr8。
从这里下载swiftmailerhttp://swiftmailer.org/
看看下面的简单代码
包括文件
require_once('path/to/swiftMailer/lib/swift_required.php');
创建传输
//FOR SMTP
// Create the Transport
$transport = Swift_SmtpTransport::newInstance('smtp.googlemail.com', 465, 'ssl')
->setUsername('user@gmail.com')
->setPassword('gmailpassword');
或
//FOR NORMAL MAIL
$transport = Swift_MailTransport::newInstance();
MAILER对象
// Create the Mailer using your created Transport
$mailer = Swift_Mailer::newInstance($transport);
创建消息对象
$message = Swift_Message::newInstance($subject)
->setFrom(array($from => $from))
->setTo($to)
->setBody($body);
$message->attach(Swift_Attachment::fromPath($filepath));
发送消息
$result = $mailer->send($message);
如果你真的想学习如何格式化互联网消息,那么你应该参考它的征求意见(又名RFC)。定义"多用途互联网邮件扩展-互联网消息体格式"的是1996年11月发布的RFC2045。
格式在某种程度上非常严格,必须按原样执行。
基本上,消息包含一个标头和正文。标头定义消息的类型、格式化方式以及不同类型的其他字段。
身体是由不同的实体组成的。例如,一个实体可以只是一个纯文本,比如"你好!",也可以是一个图像、一个附件等等。
注意在以下示例中,括号中的所有内容(例如{hello})都应替换为实际值。任何换行符实际上都是CRLF(即ASCII 13+ASCII 10)。在你看到两个CRLF的地方坚持下去。这将是最糟糕的时刻来展示你的创造力。
基本上,对于有附件的电子邮件,标题应该是这样的:
MIME-Version: 1.0
To: {email@domain}
Subject: {email-subject}
X-Priority: {2 (High)}
Content-Type: multipart/mixed; boundary="{mixed-boudary}"
在上面的例子中,{混合边界}可以是任何唯一的散列值,比如000008050800060107020705。其他的都是不言自明的。
现在,每当我们想在消息中添加一个新的实体(如消息正文、图像、附件)时,我们都必须告诉电子邮件代理一个新部分即将到来,即用{mixed-boundary}值作为该实体的前缀。我们称之为"开放边界"。请注意,通过打开边界,我们不会像最初定义的那样插入该边界,而是在前面再使用两个减号,比如-{混合边界}。当我们关闭一个边界时,我们同样进行,只是我们必须在末尾使用其他2个减号,比如--{mixed-boudary}--
--{mixed-boudary}
the entity content
--{mixed-boudary}--
因为电子邮件代理应该了解我们新插入实体的内容属于哪种类型,所以我们必须在打开边界后立即声明。声明只是一个头,它只包含那些与实体兼容的参数/值。
对于HTML正文内容,我的实体标题看起来像:
Content-Type: text/html; charset=utf-8
Content-Transfer-Encoding: 7bit
所以整个身体(被包围在边界内)最终会看起来像:
--{mixed-boudary}
Content-Type: text/html; charset=utf-8
Content-Transfer-Encoding: 7bit
<html>
<head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head>
<body bgcolor="#FFFFFF" text="#000000">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque vel
dapibus arcu. Duis quam dui, ornare non mi nec, luctus faucibus massa. Vivamus
quis purus in erat euismod ullamcorper vitae eget dolor. Aliquam tempor erat
accumsan, consectetur ex et, rhoncus risus.
</body>
</html>
如果必须插入另一个实体,我们将按照上述步骤进行操作。当没有更多数据添加到消息中时,我们关闭混合边界,即CRLF+--{mixed-boudary}--.
如果出于任何原因,实体必须使用替代表示形式插入(例如,正文消息以纯文本格式和HTML格式插入),则实体内容必须使用内容类型multipart/alternative声明(尽管全局multipart/mexed标头仍然保留!)。每个替代表示都将被这个新边界包围。
下面是一个完整的例子:
MIME-Version: 1.0
To: {email@domain}
Subject: {email-subject}
X-Priority: {2 (High)}
Content-Type: multipart/mixed; boundary="{mixed-boudary}"
--{mixed-boudary}
Content-Type: multipart/alternative; boundary="{alternative-boudary}"
--{alternative-boudary}
Content-Type: text/plain; charset=utf-8;
Content-Transfer-Encoding: 7bit
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque vel
dapibus arcu. Duis quam dui, ornare non mi nec, luctus faucibus massa. Vivamus
quis purus in erat euismod ullamcorper vitae eget dolor. Aliquam tempor erat
accumsan, consectetur ex et, rhoncus risus.
--{alternative-boudary}
Content-Type: text/html; charset=utf-8;
Content-Transfer-Encoding: 7bit
<html>
<head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head>
<body bgcolor="#FFFFFF" text="#000000">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque vel
dapibus arcu. Duis quam dui, ornare non mi nec, luctus faucibus massa. Vivamus
quis purus in erat euismod ullamcorper vitae eget dolor. Aliquam tempor erat
accumsan, consectetur ex et, rhoncus risus.
</body>
</html>
--{alternative-boudary}--
--{mixed-boudary}
Content-Type: application/pdf; name="myfile.pdf"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="myfile.pdf"
JVBERi0xLjINOCAwIG9iag08PCAvTGVuZ3RoIDkgMCBSIC9GaWx0ZXIgL0ZsYXRlRGVjb2Rl
ID4+DXN0cmVhbQ1oQ51bbY/cNg7+BfsfhAUO11w3riW/B7gPaZEAAdpcm06RL8EBzoyn68uM
vZ3xZLv//khKsuUxNaMNiiabpUg+pKiHsmxJEcN/UsgiilP4ab2/+XF1I81vszSqclHIOEpj
sdrf/PC2EFVUpmK1vXkZxVKs1uJlJJVYPYrvPra7XVvvxYdIrE7rL83hhVj97+bNyjUoFam7
FnOB+tubGI3FZEkwmhpKXpVRnqJi0PCyjBJ1DjyOYqWBxxXp/1h3X+ov9abZt434pV0feoG/
ars/xU/9/qEZmm7diJ+abmgOr0TGeFNFEuXx5M4B95Idns/QAaJMI1IpKeXi9+ZhaPafm4NQ
cRwzNpK0iirlRvisRBZpVJa+PP51091kkjBWBXrJxUuZRjIXh0Z8FN3MnB5X5st5Kay9355n
--{mixed-boudary}--
TIPS
使用您喜欢的电子邮件客户端(我的是Thunderbird)并发送到您自己一条纯文本、一条纯HTML、一条混合消息,以及然后是前面的每一个,但附带一个文件附件。什么时候您收到的消息只需研究其来源(查看->消息来源)。
@编辑:一个非常好的案例研究+PHP示例可以在这里找到