简体   繁体   中英

How to send email attachments in PHP

  <?php
  // array with filenames to be sent as attachment
  $files = array("sendFiles.php");

  // email fields: to, from, subject, and so on
  $to = "dfjdsoj@googlemail.com";
  $from = "mail@mail.com";
  $subject ="My subject";
  $message = "A logo has been sen't by". $_SESSION['loggedin_business_name'];
  $headers = "From: $from";

  // 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/plain; 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");
      $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       
  echo sizeof($files);
  $ok = @mail($to, $subject, $message, $headers);
  if ($ok) {
      echo "<p>mail sent to $to!</p>";
  } else {
      echo "<p>mail could not be sent!</p>";
  }
  ?>

I get an email with my sendfiles.php then a text file ATT00424.txt. The number changes everytime. Send it to my gmail and it's fine! Very Strange!


$files = array("sendFiles.php");

  // email fields: to, from, subject, and so on

  $to = "hdfiuhufsadhfu@yaho.com";

  $from = "mail@mail.com";

  $subject ="My subject";

  $message = "A logo has been sen't by". $_POST['loggedin_business_name'];

  $headers = "From: $from";

  // boundary

  $semi_rand = md5(time());

  $mime_boundary = "==Multipart_Boundary_x{$semi_rand}x";

// headers for attachment

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

  $message = "This is a multi-part message in MIME format.\r\n" . "--{$mime_boundary}\r\n" . "Content-Type: text/plain; charset=\"iso-8859-1\"\r\n" . "Content-Transfer-Encoding: 7bit\r\n" . $message . "\r\n";

  $message .= "--{$mime_boundary}\r\n";
  // preparing attachments

  for($x=0;$x<count($files);$x++){

      $file = fopen($files[$x],"rb");

      $data = fread($file,filesize($files[$x]));

      fclose($file);

      $data = chunk_split(base64_encode($data));

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

      "Content-Disposition: attachment;\r\n" . " filename=\"$files[$x]\"\r\n" .

      "Content-Transfer-Encoding: base64\r\n" . $data . "\r\n";

      $message .= "--{$mime_boundary}\r\n";

  }

Adding CRLF in the code fixed the attachment issue however now the message "A logo has been sen't by" has disappeared. Why is this?

Use phpMailer()

<?php 
require_once('phpmailer.php');

$mail = new PHPMailer(true); // the true param means it will throw exceptions on errors, which we need to catch
$mail->IsSendmail(); // telling the class to use SendMail transport

try {
    $mail->AddReplyTo('email@example.com', 'First Last');
    $mail->AddAddress('John@example.com', 'John Doe');

    $mail->SetFrom('email@example.com', 'First Last');
    $mail->Subject  =  "Subject Line";
    $mail->AltBody    = "Alternate Text"; // optional, comment out and test

    $mail->WordWrap     =   50; // set word wrap    
    $mail->Body = "This is the body of the email";
    $mail->IsHTML(true); // send as HTML

    // Single or Multiple File Attachments
    $mail->AddAttachment('../path-to-file.pdf', 'File-Name.pdf');
    $mail->Send(); // Try to send email
    //echo "Message Sent OK<p></p>\n";
    } catch (phpmailerException $e) {
        echo $e->errorMessage(); //Pretty error messages from PHPMailer
    } catch (Exception $e) {
        echo $e->getMessage(); //Boring error messages from anything else!
}
// end try


?>

Try having CRLF (\\r\\n) line breaks. Outlook can be a bit funny about these things.

You can use this class

<?php   

/*   
Usage   
=====   
    set $this->to
    set $this->subject
    set $this->message (with html tags)
    set $this->from (Optional)
    set $this->cc (this can be an array or a variable) (Optional)
    set $this->bcc (this can be an array or a variable) (Optional)
    set $this->reply_to (Optional)
    set $this->return_path (Optional)
    set $this->x_mailer (Optional)
    set $this->attach_file_name (this can be an array or a variable) (Optional)

    $this->SendMail();

This function returns an array of 2 elements which e[0] = true (on success) or false and e[1] = message
*/

class EMail
{
    var $to;
    var $from;
    var $cc;
    var $bcc;
    var $reply_to;
    var $return_path;
    var $x_mailer;
    var $subject;
    var $message;
    var $attach_file_name;

    function EMail()
    {
        $this->to = "";
        $this->subject = "";
        $this->message = "";
        $this->from = "Administrator <admin@" . $_SERVER['SERVER_NAME'] . ">";
        $this->cc = "";
        $this->bcc = "";
        $this->reply_to = $this->from;
        $this->return_path = $this->from;
        $this->x_mailer = "PHP v" . phpversion();
        $this->attach_file_name = "";
    }

    function makeFileName ($url)
    {
        $pos=true;
        $PrePos=0;
        while (!$pos==false)
        {
            $pos = strpos($url,'\\',$PrePos);
            if ($pos===false)
            {
                $temp = substr($url,$PrePos);
            }
            else
            {
                $PrePos = $pos + 1;
            }
        }
        return $temp;
    }

    function processAttachment()
    {
        if(is_array($this->attach_file_name))
        {
            $s = sizeof($this->attach_file_name);
            for($i=0; $i<$s; $i++)
            {
                if($this->attach_file_name[$i] != "")
                {
                    $handle = fopen($this->attach_file_name[$i], 'rb');
                    $file_contents = fread($handle, filesize($this->attach_file_name[$i]));
                    $Attach['contents'][$i] = chunk_split(base64_encode($file_contents));
                    fclose($handle);
                    $Attach['file_name'][$i] = $this->makeFileName ($this->attach_file_name[$i]);
                    $pos=true;
                    $PrePos=0;
                    while (!$pos==false)
                    {
                        $pos = strpos($this->attach_file_name[$i], '.', $PrePos);
                        if ($pos===false)
                        {
                            $Attach['file_type'][$i] = substr($this->attach_file_name[$i], $PrePos);
                        }
                        else
                        {
                            $PrePos = $pos+1;
                        }
                    }
                }
            }
            return $Attach;
        }
        else
        {
            $handle = fopen($this->attach_file_name, 'rb');
            $file_contents = fread($handle, filesize($this->attach_file_name));
            $Attach['contents'][0] = chunk_split(base64_encode($file_contents));
            fclose($handle);
            $Attach['file_name'][0] = $this->makeFileName ($this->attach_file_name);
            $pos=true;
            $PrePos=0;
            while (!$pos==false)
            {
                $pos = strpos($this->attach_file_name, '.', $PrePos);
                if ($pos===false)
                {
                    $Attach['file_type'][0] = substr($this->attach_file_name, $PrePos);
                }
                else
                {
                    $PrePos = $pos+1;
                }
            }
        }
        return $Attach;
    }

    function validateMailAddress($MAddress)
    {
        if (eregi("@", $MAddress) && eregi(".", $MAddress))
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    function Validate()
    {
        if(is_array($this->to))
        {
            $msg[0] = false;
            $msg[1] = "You should provide only one receiver email address";
            return $msg;
        }
        if(is_array($this->from))
        {
            $msg[0] = false;
            $msg[1] = "You should provide only one sender email address";
            return $msg;
        }
        if($this->to == "")
        {
            $msg[0] = false;
            $msg[1] = "You should provide a receiver email address";
            return $msg;
        }
        if($this->subject == "")
        {
            $msg[0] = false;
            $msg[1] = "You should provide a subject for your email";
            return $msg;
        }
        if($this->message == "")
        {
            $msg[0] = false;
            $msg[1] = "You should provide message for your email";
            return $msg;
        }
        if(!$this->validateMailAddress($this->to))
        {
            $msg[0] = false;
            $msg[1] = "Receiver E-Mail Address is not valid";
            return $msg;
        }
        if(!$this->validateMailAddress($this->from))
        {
            $msg[0] = false;
            $msg[1] = "Sender E-Mail Address is not valid";
            return $msg;
        }
        if(is_array($this->cc))
        {
            $s = sizeof($this->cc);
            for($i=0; $i<$s; $i++)
            {
                if(!$this->validateMailAddress($this->cc[$i]) && $this->cc[$i] != "")
                {
                    $msg[0] = false;
                    $msg[1] = $this->cc[$i] . " is not a valid E-Mail Address";
                    return $msg;
                }
            }
        }
        else
        {
            if(!$this->validateMailAddress($this->cc) && $this->cc[$i] != "")
            {
                $msg[0] = false;
                $msg[1] = "CC E-Mail Address is not valid";
                return $msg;
            }
        }
        if(is_array($this->bcc))
        {
            $s = sizeof($this->bcc);
            for($i=0; $i<$s; $i++)
            {
                if(!$this->validateMailAddress($this->bcc[$i]) && $this->bcc[$i] != "")
                {
                    $msg[0] = false;
                    $msg[1] = $this->bcc[$i] . " is not a valid E-Mail Address";
                    return $msg;
                }
            }
        }
        else
        {
            if(!$this->validateMailAddress($this->bcc) && $this->bcc[$i] != "")
            {
                $msg[0] = false;
                $msg[1] = "BCC E-Mail Address is not valid";
                return $msg;
            }
        }
        if(is_array($this->reply_to))
        {
            $msg[0] = false;
            $msg[1] = "You should provide only one Reply-to address";
            return $msg;
        }
        else
        {
            if(!$this->validateMailAddress($this->reply_to))
            {
                $msg[0] = false;
                $msg[1] = "Reply-to E-Mail Address is not valid";
                return $msg;
            }
        }
        if(is_array($this->return_path))
        {
            $msg[0] = false;
            $msg[1] = "You should provide only one Return-Path address";
            return $msg;
        }
        else
        {
            if(!$this->validateMailAddress($this->return_path))
            {
                $msg[0] = false;
                $msg[1] = "Return-Path E-Mail Address is not valid";
                return $msg;
            }
        }
        $msg[0] = true;
        return $msg;
    }

    function SendMail()
    {
        $mess = $this->Validate();
        if(!$mess[0])
        {
            return $mess;
        }

        # Common Headers
        $headers  = "From: " . $this->from . "\r\n";
        $headers .= "To: <" . $this->to . ">\r\n";

        if(is_array($this->cc))
        {
            $headers .= "Cc: " . implode(", ", $this->cc) . "\r\n";
        }
        else
        {
            if($this->cc != "")
                $headers .= "Cc: " . $this->cc . "\r\n";
        }

        if(is_array($this->bcc))
        {
            $headers .= "BCc: " . implode(", ", $this->bcc) . "\r\n";
        }
        else
        {
            if($this->bcc != "")
                $headers .= "BCc: " . $this->bcc . "\r\n";
        }

        // these two to set reply address
        $headers .= "Reply-To: " . $this->reply_to . "\r\n";
        $headers .= "Return-Path: " . $this->return_path . "\r\n";

        // these two to help avoid spam-filters
        $headers .= "Message-ID: <message-on " . date("d-m-Y h:i:s A") . "@".$_SERVER['SERVER_NAME'].">\r\n";
        $headers .= "X-Mailer: " . $this->x_mailer . "\r\n";
        $headers .= "MIME-Version: 1.0\r\n";

        # Tell the E-Mail client to look for multiple parts or chunks
        $headers .= "Content-type: multipart/mixed; boundary=AttachMail0123456\r\n";

        # Message Starts here
        $msg  = "--AttachMail0123456\r\n";

        $msg .= "Content-type: multipart/alternative; boundary=AttachMail7890123\r\n\r\n";
        $msg .= "--AttachMail7890123\r\n";

        $msg .= "Content-Type: text/plain; charset=iso-8859-1\r\n";
        $msg .= "Content-Transfer-Encoding: quoted-printable\r\n\r\n";

        $msg .= strip_tags($this->message) . "\r\n";

        $msg .= "--AttachMail7890123\r\n";

        $msg .= "Content-Type: text/html; charset=iso-8859-1\r\n";
        $msg .= "Content-Transfer-Encoding: quoted-printable\r\n\r\n";

        $msg .= "<html><head></head><body>" . $this->message . "</body></html>\r\n";

        $msg .= "--AttachMail7890123--\r\n";


        if($this->attach_file_name != "" || is_array($this->attach_file_name))
        {
            $Attach = $this->processAttachment();

            $s = sizeof($Attach['file_name']);
            for($i=0; $i<$s; $i++)
            {
                # Start of Attachment chunk
                $msg .= "--AttachMail0123456\r\n";

                if ($Attach['file_type'][$i]=="gif")
                {
                    $msg .= "Content-Type: image/gif; name=" . $Attach['file_name'][$i] . "\r\n";
                }
                elseif ($Attach['file_type'][$i]=="jpg" || $Attach['file_type'][$i]=="jpeg")
                {
                    $msg .= "Content-Type: image/jpeg; name=" . $Attach['file_name'][$i] . "\r\n";
                }
                else
                {
                    $msg .= "Content-Type: application/file; name=" . $Attach['file_name'][$i] . "\r\n";
                }

                $msg .= "Content-Transfer-Encoding: base64\r\n";
                $msg .= "Content-Disposition: attachment; filename=" . $Attach['file_name'][$i] . "\r\n\r\n";

                $msg .= $Attach['contents'][$i] . "\r\n";
            }
        }

        $msg .= "--AttachMail0123456--";

        $result = mail($this->to, $this->subject, $msg, $headers);
        if ($result)
        {
            $mess[0] = true;
            $mess[1] = "Mail Successfully delivered";
        }
        else
        {
            $mess[0] = false;       
            $mess[1] = "Mail can not be send this time. Please try latter.";
        }
        return $mess;
    }
}
?>
$from = stripslashes("from@demo.com");
$to = stripslashes("to@to.com");
$subject =$_POST['subject'];  
$message = $_POST['mailbody'];  

// Temporary paths of selected files  
$file1 = $_FILES['file1']['tmp_name'];  
$file2 = $_FILES['file2']['tmp_name'];  
$file3 = $_FILES['file3']['tmp_name'];  

// File names of selected files  
$filename1 = $_FILES['file1']['name'];  
$filename2 = $_FILES['file2']['name'];  
$filename3 = $_FILES['file3']['name'];  

// array of filenames to be as attachments  
$files = array($file1, $file2, $file3);  
$filenames = array($filename1, $filename2, $filename3);  

// include the from email in the headers  
$headers = "From: $from";  

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

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

// multipart boundary  
$message = "--{$boundary}\n" . "Content-Type: text/plain; charset=\"iso-8859-1\"\n" . "Content-Transfer-Encoding: 7bit\n\n" . $message . "\n\n";  
$message .= "--{$boundary}\n";  

// attach the attachments to the message  
for($x = 0; $x < count($files); $x++){

    if($files[$x] != ""){

        $file = fopen($files[$x],"r");  
        $content = fread($file,filesize($files[$x]));  
        fclose($file);  
        $content = chunk_split(base64_encode($content));  
        $message .= "Content-Type: {\"application/octet-stream\"};\n" . " name=\"$files[$x]\"\n" . "Content-Disposition: attachment;\n" . " filename=\"$filenames[$x]\"\n" . "Content-Transfer-Encoding: base64\n\n" . $content . "\n\n";  
        $message .= "--{$boundary}\n";
    }
}  

// sending mail  
$sendmail = mail($to, $subject, $message, $headers);

As I understand it, Outlook creates ATT12345.txt attachments when it receives messages in sections with mixed encoding. If it is unable to convert the remainder of the message after a change in encoding (or new MIME part), it dumps the rest in an attachment with the generic names you have been seeing. It seems as if Gmail is handling the format better than Outlook (unsurprising).

I am no Outlook expert (never touch the thing), but it looks as if this answer on SO might help (check your $mime_boundary variable for a trailling '--' after the last part).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM