发送带附件的PHP HTML邮件

时间:2012-03-01 16:04:47

标签: php html email attachment

我遇到了一个问题:直到今天,我使用包含

的标头发送了带有PHP的HTML邮件
Content-type: text/html;

现在,我添加了添加附件的功能。为此,我不得不将此行更改为

Content-Type: multipart/mixed;

现在,使用multipart/mixed,其他邮件(正常文本)将显示为text / plain。我怎么才能意识到附件是有效的,而mailtext仍然是HTML?

4 个答案:

答案 0 :(得分:26)

我尝试了几个小时的答案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.">\r\n";
$header .= "Reply-To: ".$replyto."\r\n";
$header .= "MIME-Version: 1.0\r\n";
$header .= "Content-Type: multipart/mixed; boundary=\"".$uid."\"\r\n\r\n";
$header .= "This is a multi-part message in MIME format.\r\n";
$header .= "--".$uid."\r\n";
$header .= "Content-type:text/html; charset=iso-8859-1\r\n";
$header .= "Content-Transfer-Encoding: 7bit\r\n\r\n";
$header .= $message."\r\n\r\n";

    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."\r\n";
        $header .= "Content-Type: application/octet-stream; name=\"".$filename."\"\r\n"; // use different content types here
        $header .= "Content-Transfer-Encoding: base64\r\n";
        $header .= "Content-Disposition: attachment; filename=\"".$filename."\"\r\n\r\n";
        $header .= $content."\r\n\r\n";
    }

$header .= "--".$uid."--";
return mail($mailto, $subject, "", $header);
}

答案 1 :(得分:10)

要发送带附件的电子邮件,我们需要使用multipart / mixed MIME类型,指定混合类型将包含在电子邮件中。此外,我们希望使用multipart / alternative 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 \r\n 
$headers = "From: webmaster@example.com\r\nReply-To: webmaster@example.com"; 
//add boundary string and mime type specification 
$headers .= "\r\nContent-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规范匹配,然后将其作为附件包含。

答案 2 :(得分:3)

php中的SWIFTMAIL使用gr8来附加邮件。

从这里下载swiftmailer http://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');

OR

//FOR NORMAL MAIL
$transport = Swift_MailTransport::newInstance();

MAILER OBJECT

// 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);

答案 3 :(得分:1)

如果您真的想学习如何格式化Internet消息,那么您应该参考其Request For Comments(又名RFC)。定义&#34;多用途Internet邮件扩展 - 互联网邮件正文的格式&#34;是RFC2045于1996年11月发布的。

格式在某种程度上非常严格,必须按原样遵循。

消息基本上包含标题和正文。标题定义了消息的类型,它的格式,以及其他一些不同类型的字段。

身体由不同的实体组成。例如,实体可以是纯文本,例如&#34; Hello there!&#34;但也可以是一个图像,一个附件,等等。

  

注意在以下示例中,括号内的所有内容(例如{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}"

在上面的示例中,{mixed-boudary}可以是任何唯一的哈希值,如000008050800060107020705。其他哈希值不言自明。

现在,只要我们想要在邮件中添加新实体(如邮件正文,图片,附件),我们就必须告诉电子邮件代理新部分即将到来,即。使用{mixed-boundary}值为该实体添加前缀。我们称之为&#34;打开边界&#34;。请注意,通过打开边界,我们不会插入最初定义的边界,我们在前面使用另外2个减号,例如 - {mixed-boudary}。当我们关闭边界时,我们也会这样做,除了我们必须在末尾使用其他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 / mixed标题仍然存在!)。每个替代表示将被这个新边界包围。

以下完整示例:

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,一个混合,和   然后每个早期但附有一个文件附件。什么时候   您收到的消息只是研究它的来源(查看 - &gt;消息   源)。

@Edit:一个记录完备的案例研究+ PHP示例可以在here找到