使用PHP在电子邮件中发送多个附件

我有问题发送带有多个附件的电子邮件。 代码如下:

<?php

    if(isset($_POST['sendEmail']))
    {

        foreach($_FILES['uploadEmail']['error'] as $key=>$value){
            if(!$_FILES['uploadEmail']['error'][$key]){
                $target_path = "";
                $target_path = $target_path . basename( $_FILES['uploadEmail']['name'][$key]); 
                if(move_uploaded_file($_FILES['uploadEmail']['tmp_name'][$key], $target_path)){
                    $files[] = $_FILES['uploadEmail']['name'][$key];
                }
            }
        }

        $toEmails = explode(",",$_POST['toEmail']);
        $count = count($toEmails);
        $i = 0;    $j = 1;    $k = 100;
        $bcc = '';
        while($i<$count){
            $bcc .= $toEmails[$i].",";
            if($j==$k || $i==$count-1){
                $j=1;
                //echo $bcc.'<br />'.$sub.'<br />'.$message.'<br /><br />';
                $from = 'test@gmail.com';
                $sub = $_POST['subject'];
                $message = $_POST['message'];

                /////////////////////////
                $headers = 'From:'. $from . "rn";
                $headers .= "Bcc:". $bcc . "rn";


                // boundary 
                $semi_rand = md5(time()); 
                $mime_boundary = "==Multipart_Boundary_x{$semi_rand}x"; 

                // headers for attachment 
                $headers .= "nMIME-Version: 1.0n" . "Content-Type: multipart/mixed;n" . " boundary="{$mime_boundary}""; 

                // multipart boundary 
                $message = "This is a multi-part message in MIME format.nn" . "--{$mime_boundary}n" . "Content-Type: text/html; charset="iso-8859-1"n" . "Content-Transfer-Encoding: 7bitnn" . $message . "nn"; 
                $message .= "--{$mime_boundary}n";

                // preparing attachments
                for($x=0;$x<count($files);$x++){
                    $file = fopen($files[$x],"rb");
                    //echo "<br>".filesize($files[$x]);
                    $data = fread($file,filesize($files[$x]));
                    fclose($file);
                    $data = chunk_split(base64_encode($data));
                    $message .= "Content-Type: {"application/octet-stream"};n" . " name="$files[$x]"n" . 
                    "Content-Disposition: attachment;n" . " filename="$files[$x]"n" . 
                    "Content-Transfer-Encoding: base64nn" . $data . "nn";
                    $message .= "--{$mime_boundary}n";
                }

                    // send
                    /////////////////////////

                mail('',$sub,$message,$headers);
                $bcc = '';
            }else{
                $j++;
            }
            $i++;
        }
    }
?>
<html>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.min.js"></script>

<script src="http://js.nicedit.com/nicEdit-latest.js" type="text/javascript"></script>
<script type="text/javascript">bkLib.onDomLoaded(function() {
        new nicEditor().panelInstance('message');
       // new nicEditor({fullPanel : true}).panelInstance('area2');
  });</script>
</head>
<body>
<form method="POST" enctype="multipart/form-data">
    <table>
        <tr><td><label for="toEmail">Send To : </label></td><td><textarea id="toEmail" name="toEmail" cols="100" rows="10"></textarea></td></tr>
        <tr><td><label for="subject">Subject : </label></td><td><input type="text" name="subject" id="subject" size="98"></td></tr>
        <tr><td><label for="toEmail">Message : </label></td><td><textarea id="message" name="message" cols="100" rows="10"></textarea></td></tr>
        <tr><td><label for="upload[]">Attachments:</label></td><td></td></tr>
        <tr><td><label>1</label></td><td><input type="file" name="uploadEmail[]"></td></tr>
        <tr><td><label>2</label></td><td><input type="file" name="uploadEmail[]"></td></tr>
        <tr><td><label>3</label></td><td><input type="file" name="uploadEmail[]"></td></tr>
        <tr><td><label>4</label></td><td><input type="file" name="uploadEmail[]"></td></tr>
        <tr><td><label>5</label></td><td><input type="file" name="uploadEmail[]"></td></tr>
        <tr><td><label>6</label></td><td><input type="file" name="uploadEmail[]"></td></tr>
        <tr><td><label>7</label></td><td><input type="file" name="uploadEmail[]"></td></tr>
        <tr><td><label>8</label></td><td><input type="file" name="uploadEmail[]"></td></tr>
        <tr><td><label>9</label></td><td><input type="file" name="uploadEmail[]"></td></tr>
        <tr><td><label>10</label></td><td><input type="file" name="uploadEmail[]"></td></tr>
        <tr><td colspan="2" align="center"><input type="submit" value="Send Email" name="sendEmail" id="sendEmail"></td></tr>
    </table>
</form>
<body>
</html>

我收到了邮件,但找不到任何附件。 有谁知道什么可能是错的?

这是我收到的一封电子邮件正文:

MIME-Version: 1.0 Content-Type: multipart/mixed; 
boundary="==Multipart_Boundary_x2d454346f03d2c19cfefc838ce4d8623x"

This is a multi-part message in MIME format.

--==Multipart_Boundary_x2d454346f03d2c19cfefc838ce4d8623x Content-Type: text/html; charset="iso-8859-1"
Content-Transfer-Encoding: 7bit

ds fsdfsdfsdfsdfsdfsdfsf sffdfsdfsdfs fsdfdf sdf s

--==Multipart_Boundary_x2d454346f03d2c19cfefc838ce4d8623x Content-Type: {"application/octet-stream"};  name="/tmp/phpHFTvAw"
Content-Disposition: attachment;  filename="Lighthouse.jpg"
Content-Transfer-Encoding: base64




--==Multipart_Boundary_x2d454346f03d2c19cfefc838ce4d8623x Content-Type: {"application/octet-stream"};  name="/tmp/phpyX67HR"
Content-Disposition: attachment;  filename="Penguins.jpg"
Content-Transfer-Encoding: base64




--==Multipart_Boundary_x2d454346f03d2c19cfefc838ce4d8623x

我建议使用PHPMailer发送带有附件的邮件:

<?php

require 'PHPMailerAutoload.php';                      // If this file is not located in the same directory, use __DIR__ . "/path/to/PHPMailerAutoload.php"

$mail = new PHPMailer;

$mail->From = 'from@example.com';
$mail->FromName = 'Mailer';
$mail->addAddress('joe@example.net', 'Joe User');     // Add a recipient
$mail->addAddress('ellen@example.com');               // Name is optional
$mail->addReplyTo('info@example.com', 'Information');
$mail->addCC('cc@example.com');
$mail->addBCC('bcc@example.com');

$mail->addAttachment('/var/tmp/file.tar.gz');         // Add attachments
$mail->addAttachment('/tmp/image.jpg', 'new.jpg');    // Optional name
$mail->isHTML(true);                                  // Set email format to HTML

$mail->Subject = 'Here is the subject';
$mail->Body    = 'This is the HTML message body <b>in bold!</b>';
$mail->AltBody = 'This is the body in plain text for non-HTML mail clients';

if(!$mail->send()) {
    echo 'Message could not be sent.';
    echo 'Mailer Error: ' . $mail->ErrorInfo;
} else {
    echo 'Message has been sent';
}

?>

下载和文档:在这里。


回答

你的代码有几个问题,我在下面详细说明。

  • 线尾

    $headers = 'From:'. $from . "rn";
    $headers .= "Bcc:". $bcc . "rn";
    
    ...
    
    // headers for attachment 
    $headers .= "nMIME-Version: 1.0n"
             .  "Content-Type: multipart/mixed;n"
             .  " boundary="{$mime_boundary}""; 
    // multipart boundary 
    $message = "This is a multi-part message in MIME format.nn"
             . "--{$mime_boundary}n"
             . "Content-Type: text/html; charset="iso-8859-1"n"
             . "Content-Transfer-Encoding: 7bitnn"
             . $message
             . "nn"; 
    $message .= "--{$mime_boundary}n";
    

    电子邮件中的行由CRLFrn )序列分隔。 目前还不清楚mail()函数是否将n转换为rn ,但考虑到您的From:Bcc:标头正在使用rn ,这些应该可能使用相同的。 您的输出还表示行尾可能缺失或格式错误。

    从PHP手册:

    如果没有收到消息,请尝试仅使用LF( n)。 某些Unix邮件传输代理(最着名的是qmail)会自动用CRLF代替LF(如果使用CRLF,会导致CR翻倍)。 这应该是最后的手段,因为它不符合»RFC 2822。
  • 标题语法

    $message .= "Content-Type: {"application/octet-stream"};n"
             .  " name="$files[$x]"n" . 
    

    删除大括号和引号:

    $message .= "Content-Type: application/octet-streamn"
             .  " name="$files[$x]"n" . 
    

    而且, name参数已被弃用,以支持Content-Disposition头中的filename参数。 如果你想保持它的一些向后兼容性,你应该删除它的路径。 (您的输出表明您正在使用tmp_name而不是name )。

  • 分隔符

    $message .= "--{$mime_boundary}n";
    
    // preparing attachments
    for($x=0;$x<count($files);$x++){
      ...
      $message .= /* body part */;
      $message .= "--{$mime_boundary}n";
    }
    

    请注意,最后的分隔符必须有两个尾部破折号。 在循环的开始处插入分隔符,并在循环后添加一个紧密的分隔符:

    // preparing attachments
    for($x=0;$x<count($files);$x++){
      $message .= "--{$mime_boundary}n";
      ...
      $message .= /* body part */;
    }
    
    $message .= "--{$mime_boundary}--n";
    

    请参阅下面的电子邮件语法部分。

  • 线路长度

    $k = 100;
    ...
    while($i<$count){
      $bcc .= $toEmails[$i].",";
      if($j==$k || $i==$count-1){
        ...
        $headers .= "Bcc:". $bcc . "rn";
    

    请注意,电子邮件中存在线路长度限制。 RFC 5322:

       ...                    Each line of characters MUST be no more than
       998 characters, and SHOULD be no more than 78 characters, excluding
       the CRLF.
    

    你可能想要缩短你的Bcc或者引入FWS(折叠空白):

    $bcc .= $toEmails[$i].",rn ";  /* FWS */
    
  • 其他事宜

    一些可能会或可能不会有用的其他问题或通知:


    foreach($_FILES['uploadEmail']['error'] as $key=>$value){
        if(!$_FILES['uploadEmail']['error'][$key]){
    

    最后一行与以下内容相同:

        if(!$value){
    

    $target_path = "";
    $target_path = $target_path . basename( $_FILES['uploadEmail']['name'][$key]); 
    

    我假设$target_path应该被初始化为一个上传目录。


    $toEmails = explode(",",$_POST['toEmail']);
    

    通常,您不应允许随机用户提供传出电子邮件地址,但我怀疑这是一个可信用户的内部应用程序。


  • 电子邮件语法

    根据RFC 2046,这是多部分消息体结构的摘录。(BNF语法,有些简化。)

    multipart-body := [preamble CRLF]
                      dash-boundary CRLF
                      body-part *encapsulation
                      close-delimiter
                      [CRLF epilogue]
    
    dash-boundary := "--" boundary
    
    body-part := MIME-part-headers [CRLF *OCTET]
    
    encapsulation := delimiter
                     CRLF body-part
    
    delimiter := CRLF dash-boundary
    
    close-delimiter := delimiter "--"
    

    参考

  • RFC 2822 Internet邮件格式(由RFC 5322废弃)
  • RFC 5322 Internet邮件格式
  • RFC 2045(MIME)第一部分:Internet消息体的格式
  • RFC 2046(MIME)第二部分:媒体类型
  • 链接地址: http://www.djcxy.com/p/59639.html

    上一篇: Sending multiple attachment in an email using PHP

    下一篇: file attachment issue to email?