当前位置: 首页 > 知识库问答 >
问题:

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

宋臻
2023-03-14

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

<?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 . "\r\n";
                $headers .= "Bcc:". $bcc . "\r\n";


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

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

                // multipart boundary 
                $message = "This is a multi-part message in MIME format.\n\n" . "--{$mime_boundary}\n" . "Content-Type: text/html; charset=\"iso-8859-1\"\n" . "Content-Transfer-Encoding: 7bit\n\n" . $message . "\n\n"; 
                $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: base64\n\n" . $data . "\n\n";
                    $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>

我收到邮件,但找不到任何附件。有人知道会出什么问题吗?

下面是我在Mail中得到的电子邮件正文:

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

共有1个答案

葛宏爽
2023-03-14

您的代码有一些问题,我将在下面详细介绍。

  • Line endings

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

    电子邮件中的行由CRLF(\r\n)序列分隔。不清楚mail()函数是否将\n转换为\r\n,但考虑到您的from:bcc:头使用的是\r\n,这些头可能应该使用相同的。您的输出还指示行尾可能丢失或格式不正确。

    从PHP手册:

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

    删除大括号和引号:

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

    此外,在content-disposition头中,不推荐使用name参数,而使用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 . "\r\n";
    

    请注意,电子邮件中有行长限制。RFC 5322:

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

    您可能希望缩短密件抄送或引入FWS(折叠空白):

    $bcc .= $toEmails[$i].",\r\n ";  /* 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']);
    

    一般情况下,您不应该允许随机用户提供传出电子邮件地址,但我怀疑这是一个可信任用户的内部应用程序

    这是根据RFC2046的多部分消息体结构的摘录。(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)第二部分:介质类型

 类似资料:
  • 问题内容: 我正在使用sendgrid发送电子邮件,并且使用以下代码可以正常工作,但没有附件。 但是我需要发送附件,因此我搜索了github源和Web文档API,由于某种原因,没有javadocs,但是有一个示例GitHub sendgrid, 所以我一直在尝试直到它起作用为止,我缩小了一些异常和响应代码,起初我是被禁止的未经授权,最好是响应202,表示有效且已排队(在此处检查),这是我的代码发送

  • 有人能告诉我使用phpMailer发送带有附件的电子邮件的步骤吗?我已经准备好了发送电子邮件本身的所有代码,它工作正常,但我不明白如何发送附件。我有表单,如果我从POST上的文件输入中获得值,它只会给我文件名而不是完整路径。我认为为了添加附件,我需要获取文件的完整路径,对吗?我不必将文件存储在服务器上,只需通过电子邮件发送即可。

  • 问题内容: 我似乎找不到我编写的应该发送带有附件的电子邮件的php函数的问题。我已经为此苦苦挣扎了一段时间了。 编辑 问题是邮件的消息与文件混合在一起并作为附件发送。 问题答案: Artefacto让我更加关注输出,并且找到了解决方法:

  • 我已经看到了一些关于堆栈溢出的类似问题,但我找不到解决这些问题的方法。 我正在尝试使用Python发送一封带有。pdf附件。当我在gmail上查看邮件时,它似乎工作正常。但是当我通过苹果的邮件程序查看邮件时,我没有看到附件。知道是什么原因吗? 我的代码如下。很多都是从stack overflow上的不同位置复制的,所以我不完全理解每个部分在做什么,但它似乎(大部分)起作用: 我不确定它是否相关,但

  • 尝试发送带有pdf附件的电子邮件,尝试使用swickmailer,但没有成功,此代码使用zip但不使用PDF:( 邮件被发送罚款,我得到的邮件:但附件是不存在的,在meial有所有的bas64编码在电子邮件像: onatatent-Type: Application/octet-stream; name="media.pdf"Content-transver-Encode: base 64 Con

  • 问题内容: 我目前正在写一个音乐博客。管理员每2-3天发布一次新文章。管理员发布文章后,将立即向大约5000个订阅者发送大量电子邮件。 实施群发邮件功能的最佳方法是什么? 下列功能有效吗? 另一个问题:如果所有5000个订阅者都在使用Yahoo Mail,Yahoo是否会将其视为DDOS攻击并阻止我的SMTP服务器的IP地址? 问题答案: 首先,使用PHP随附的mail()函数不是最佳解决方案。它