Sending multiple attachment in an email using PHP

前端 未结 2 1025
心在旅途
心在旅途 2020-11-27 21:59

I have problem sending an email with multiple attachments. Here is the code:



        
相关标签:
2条回答
  • 2020-11-27 22:33

    Answer

    There are a few problems with your code that I have detailed below.

    • 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";
      

      Lines in email messages are separated by CRLF (\r\n) sequences. It is unclear whether the mail() function converts \n into \r\n or not, but considering that your From: and Bcc: headers are using \r\n, these should probably use the same. Your output also indicates that the line endings are possibly missing or malformed.

      From the PHP Manual:

      If messages are not received, try using a LF (\n) only. Some Unix mail transfer agents (most notably » qmail) replace LF by CRLF automatically (which leads to doubling CR if CRLF is used). This should be a last resort, as it does not comply with » RFC 2822.
    • Header syntax

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

      Remove the braces and the quotes:

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

      Also, the name parameter has been deprecated in favour of the filename parameter in the Content-Disposition header. If you want to keep it for some backward compatibility, you should remove the path from it. (Your output indicates that you're using tmp_name rather than name).

    • Delimiters

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

      Note that the final delimiter must have two trailing dashes. Insert the dividing delimiters at the beginning of the loop, and add a close delimiter after the loop:

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

      See the section on Email syntax below.

    • Line lengths

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

      Note that there are line length limits in email messages. RFC 5322:

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

      You may want to cut your Bcc's shorter or introduce FWS (Folding White Space):

      $bcc .= $toEmails[$i].",\r\n ";  /* FWS */
      
    • Other issues

      Some further issues or notices that might or might not be useful:


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

      The last line is the same as:

          if(!$value){
      

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

      I'm assuming that $target_path should be initialized to an upload directory.


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

      Generally, you should not allow random users to provide outgoing email addresses, but I suspect that this is an internal application for trusted users.


    Email syntax

    This is an excerpt of what the structure of a multi-part message body looks like according to RFC 2046. (BNF syntax, somewhat simplified.)

    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 "--"
    

    References

    • RFC 2822 Internet Message Format (Obsoleted by RFC 5322)
    • RFC 5322 Internet Message Format
    • RFC 2045 (MIME) Part One: Format of Internet Message Bodies
    • RFC 2046 (MIME) Part Two: Media Types
    0 讨论(0)
  • 2020-11-27 22:44

    I propose to use PHPMailer for sending mails with attachements:

    <?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';
    }
    
    ?>
    

    Download and documentation: here.

    0 讨论(0)
提交回复
热议问题