PHPMailer Failing when Attachments Added

Posted on 2012-12-21
Last Modified: 2012-12-23
Have a PHPMailer routine that has been working fine sending HTML emails to users.  Just added ability to include an attachment and it now fails on send with the following error:

PHPMailer Send function failed: Could not instantiate mail function.

Using echos, I have verified that paths to the file(s) are correct, are complete (all the way back to the server's drive letter) and use the "double backslash" when assigning the path variable.  Echos verify that the file exists where indicated.

Doesn't matter if the file is a .zip (the normal) or a .pdf or .txt (also used).  Same error on both.

When I comment out just the $mail->AddAttachment() command, the email sends fine.

Here is the command (I added the "die" to see if this function was the problem):
if ($mail->AddAttachment($filepath, $name, 'base64', $mimetype) === false)
die("Failed when adding " . $filepath . '<br>');

These are individual emails to a single individual, not a blast going out to hundreds of addresses.

Can anyone point me in the right direction?

Question by:springthorpeSoftware
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 8
  • 5
  • 3
  • +1
LVL 29

Expert Comment

ID: 38714715
a quciky - I assume The file has been uploaded first or is an existing file on your web server.
LVL 29

Expert Comment

ID: 38714718
if that's so can you show the code ?
LVL 83

Expert Comment

by:Dave Baldwin
ID: 38714737
Have you installed the current version of PHPMailer from ?
Transaction Monitoring Vs. Real User Monitoring

Synthetic Transaction Monitoring Vs. Real User Monitoring: When To Use Each Approach? In this article, we will discuss two major monitoring approaches: Synthetic Transaction and Real User Monitoring.


Author Comment

ID: 38714893
Dave: Installed about a year ago.  How do I find version info to see if I'm current?

Chiltern:  Files are already on server, not uploaded at the moment.  

Thanks, guys!!

The user has the option to either attach a .zip file (which a lot of folks can't get) or to attach the individual files from the .zip.  If the latter, routine unzips the one file into a temp folder, then adds the individual files as attachments.  I've tested with both, and with just a single .pdf.  Same error all three ways.

Done a print_r on the array holding the attachments.  Everything there seems fine.

Note that it works fine if I just comment out the $mail->AddAttachment() line.

Here's the relevant code for the email.  It is called as part of a function that is passed an order ID.  The function retrieves the data, builds the email based upon values in the data, then sends it.  Pretty basic, really.

            // Build the paths and file names.
            $zipspathF = $sitepath . "/clients/" . $cam_code . "/" . $ord_ca . "/zips";
            $temppathF = $sitepath . "/temp/" . str_pad('' . $_SESSION['sn_user_id'], 6, "0", STR_PAD_LEFT);

...  Build body, email address list, etc.  Code pretty extensive, so it's been cut.

// Instantiate the email class.
      $mail = new PHPMailer();

      // Prepare From: and ReplyTo addresses.
      if ($sqlType == "User") {
            $mail->AddReplyTo("", "AIS Support");
            $mail->SetFrom("", "AIS");
      } else {
            $mail->AddReplyTo($cam_primary_email, $cam_primary_name);
            $mail->SetFrom("", $cam_alias);
      // Prepare To: and Cc: addresses.
      $ary2 = explode(";", $to);
      foreach($ary2 as $value) {
            $ary = explode("|", $value);
      if ($cc > '') {
            $ary2 = explode(";", $cc);
            foreach($ary2 as $value) {
                  $ary = explode("|", $value);
      // Subject.
      $mail->Subject = $subj;
      // Importance/Priority.
      $mail->Priority = 3;
      if ($type == "Ack" || $type == "Del" || $type == "Rdy") {
            if ($ord_rush == "Y") $mail->Priority = 1;
      // Body.      
      if ($type == "Reg")      {
            $mail->Body = $body;
      } else {


            // Attachments.
            if ($type == "Del" && $del_attch != "N") {
                  // Create a copy of the attachments array and fix any duplicate file names.
                  // Only affects name.  Creates "Doc(1)", "Doc(2)", etc.
                  // This prevents one attachment from overwriting a subsequent one.
                  $files = $attachments;
                  foreach($files as $key => $value) {
                        $ary = array_keys($files, $value);
                        $x = count($ary);
                        if ($x > 1) {
                              $y = 1;
                              foreach($attachments as $key2 => $value2) {
                                    if ($value2 == $value) {
                                          $attachments[$key2] = $value2 . "(" . $y . ")";

                  foreach($attachments as $filepath => $name) {
                        $ext = strtolower(substr(strrchr($filepath,'.'),1));
                        if ($ext == "pdf")                                          $mimetype = "application/pdf";
                        elseif ($ext == "zip")                                    $mimetype = "application/zip";
                        elseif ($ext == "txt")                                    $mimetype = "text/plain";
                        elseif ($ext == "png")                                    $mimetype = "image/png";
                        elseif ($ext == "gif")                                    $mimetype = "image/gif";
                        elseif ($ext == "jpg" || $ext == "jpeg")      $mimetype = "image/jpeg";
                        elseif ($ext == "tif" || $ext == "tiff")      $mimetype = "image/tiff";
                        elseif ($ext == "doc" || $ext == "docx")      $mimetype = "application/";
                        elseif ($ext == "xls" || $ext == "xlsx")      $mimetype = "application/";
                        else                                                             $mimetype = "application/octet-stream";
//                        $name = substr(strrchr($filepath, '\\'), 1);
                        echo $filepath . "; " . $name . "; " . $mimetype . '<br>';
                        if (is_file($filepath)) echo "File found!<br>";
                        else echo "Not there!<br>";
//                        if ($mail->AddAttachment($filepath, $name, 'base64', $mimetype) === false) {
//                              die("Failed when adding " . $filepath . '<br>');
//                        }
                  // Cleanup
                  if (is_dir($temppathF)) {
                        $files = glob($temppathF . '/*'); // get all file names
                        foreach($files as $file){ // iterate files
                              unlink($file); // delete file
            } // end of delivery with attachments.
      } // end of Reg or not.
      // Send the email.
      if ($mail->Send()) {
            // This is where it fails.
            ... }  
// end of relevant code
LVL 83

Expert Comment

by:Dave Baldwin
ID: 38714914
The recent versions are listed on the Downloads page:  The version number is listed at the top of class.phpmailer.php .

Author Comment

ID: 38714946
I'm using 5.2.1.  5.2.2 just came out Dec 3.  Will try new version in AM.
LVL 83

Expert Comment

by:Dave Baldwin
ID: 38715107
I just downloaded 5.2.1 and 5.2.2 and compared the main class and they made a bunch of changes though a lot of them were just the comments.  I also found a problem in the Gmail example file.  Their version of 'preg_replace' on line 20 doesn't work.  Below is their version and the version I replaced it with.  I posted a notice on the Google code site about it.
// original version
$body             = preg_replace('/[\]/','',$body);
// my working version
$body             = preg_replace('#\\\\#','',$body);

Open in new window
LVL 11

Expert Comment

ID: 38715356
if you use another framework such as swiftmailer. I always succeeded with swift mailer.

Swfitmailer Attachments

This wouldn't affect all of your code, just the part where you send the email.

So you would include the swiftmail class on top of your mail php page:

require_once '/path/to/swift-mailer/lib/swift_required.php';

Open in new window

Create the message like so:

//create a traonsport mail, smtp or sendmail as far as I know
$transport = Swift_SmtpTransport::newInstance('', 25)
  ->setUsername('your username')
  ->setPassword('your password')

// Create the message
$message = Swift_Message::newInstance()

  // Give the message a subject
  ->setSubject('Your subject')

  // Set the From address with an associative array
  ->setFrom(array('' => 'John Doe'))

  // Set the To addresses with an associative array
  ->setTo(array('', '' => 'A name'))

  // Give it a body
  ->setBody('Here is the message itself')

  // And optionally an alternative body
  ->addPart('<q>Here is the message itself</q>', 'text/html')

// You can alternatively use method chaining to build the attachment
$attachment = Swift_Attachment::newInstance()


// Create the Mailer using your created Transport
$mailer = Swift_Mailer::newInstance($transport);

// send the message
$result = $mailer->send($message);

Open in new window

It always worked for me so far, I've sent dynamic pdf with it. No worries, only transport differs from server to server. Some support mail(), others do not, and I used smtp instead.

Author Comment

ID: 38715870

Installed PHPMailer 5.2.2.  No change.  Still fails with attachment, but works fine without.  

McNute: Going to try Swift.  We'll see what happens.

Thanks, guys!

Author Comment

ID: 38716501

Installed Swift.  Seems to take the server a little longer to process and it sends an attachment as long as it's not too large.  One or two .pdf files of less than 100K each are fine.  I haven't worked it upward gradually to see where it hits the limit.

If I attach my example .zip file (4 meg) I get the following error:

Fatal error: Maximum execution time of 30 seconds exceeded in D:\WWWRoot\TheNewAIS\software\Swift-4.2.2\lib\classes\Swift\Transport\StreamBuffer.php on line 232

Kicker on the .zip file is that it DOES get sent even though the error message shows.  The email that arrives is complete, as is the .zip attachment.

If I attach all of the docs as individual attachments (4.2 meg), I get a "FastCGI" error:

FastCGI Error
The FastCGI Handler was unable to process the request.

Error Details:

•The FastCGI process exceeded configured activity timeout
•Error Number: 258 (0x80070102).
•Error Description: The wait operation timed out.
HTTP Error 500 - Server Error.
Internet Information Services (IIS)
 from the server.

On the FastCGI, no email goes out.

Note:  Using my 1and1 account for the test smtp server.  Can get dedicated smtp from site host (not 1&1), but it will take until after the new year.

These deliveries go upwards of 20 meg total, with individual documents as large as 8 meg.  Yes, I know that most public email services won't allow emails that large and have told the client, but he wants attachment options because his clients are mostly large title companies and mortgage lenders that are used to getting big documents.  

The current delivery method is a download link in the email, but more and more companies are blocking .zip downloads. (Duh! How about .zip attachments?!)  He's right on one thing, though:  The individual doc attachments will probably be the only way to deliver the info to security-conscious clients in the near future.  

So close!!  Any ideas on how to extend these time limits?  Should I close this question and post the timeout problem as a new question?

Thank you for your time and expertise!
LVL 11

Expert Comment

ID: 38716885
Open the StreamBuffer.php file which resides in D:\WWWRoot\TheNewAIS\software\Swift-4.2.2\lib\classes\Swift\Transport\ with a text-editor (NOT MS WORD) such as Notepad++.

Goto line 232 and change the value from 30 to 60 seconds. See if that resolves your timeout issue.

Author Comment

ID: 38717069
Line numbers seem a little off.  Line 232 is a "fwrite($this->_in, $bytes)".

Attaching copy of my file installed yesterday, as edited.  In that code, they set timeout at 15, (line 250) but then overwrite that with whatever is in _params['timeout'].  Spent only a few minutes browsing around, but couldn't find where values in _params array come from initially.  I forced 60 into _params['timeout'].

In any case, same error (still showing 30 seconds, not 15 or 60), same line number.  Email with attachment still gets delivered.  Still get FastCGI when using individual attachments.

LVL 11

Expert Comment

ID: 38717076
Swift_SmtpTransport::newInstance('', 25)

Open in new window

If you set a timeout like so? What does it tell you?

Author Comment

ID: 38717182
Same error, and still showing 30 seconds.
LVL 11

Accepted Solution

mcnute earned 500 total points
ID: 38717198
Add this to your script:

ini_set('max_execution_time', 600); 

Open in new window

This line of code was postet on stackoverflow on this question.

Author Comment

ID: 38717357

Thanks!!  That cured the Swift error, but now both sends (zips and individual files) are giving me FastCGI error.  Thinking I'm going to have to contact the host.

You get the points!  I'll repost if host can't help.


Author Closing Comment

ID: 38717359
Thanks to McNute for the extended time and effort!
LVL 11

Expert Comment

ID: 38717381
You're welcome! Have a nice christmas time.

Featured Post

Announcing the Most Valuable Experts of 2016

MVEs are more concerned with the satisfaction of those they help than with the considerable points they can earn. They are the types of people you feel privileged to call colleagues. Join us in honoring this amazing group of Experts.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

JavaScript can be used in a browser to change parts of a webpage dynamically. It begins with the following pattern: If condition W is true, do thing X to target Y after event Z. Below are some tips and tricks to help you get started with JavaScript …
This article discusses how to create an extensible mechanism for linked drop downs.
The viewer will learn how to look for a specific file type in a local or remote server directory using PHP.
The viewer will learn how to create a basic form using some HTML5 and PHP for later processing. Set up your basic HTML file. Open your form tag and set the method and action attributes.: (CODE) Set up your first few inputs one for the name and …

688 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question