Link to home
Start Free TrialLog in
Avatar of springthorpeSoftware
springthorpeSoftwareFlag for United States of America

asked on

PHPMailer Failing when Attachments Added

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?

Thanks!!
Bruce
Avatar of Peter Hart
Peter Hart
Flag of United Kingdom of Great Britain and Northern Ireland image

a quciky - I assume The file has been uploaded first or is an existing file on your web server.
if that's so can you show the code ?
Have you installed the current version of PHPMailer from http://code.google.com/a/apache-extras.org/p/phpmailer/wiki/PHPMailer ?
Avatar of springthorpeSoftware

ASKER

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->IsHTML(false);
            $mail->AddReplyTo("support@thenewais.com", "AIS Support");
            $mail->SetFrom("support@thenewais.com", "AIS");
      } else {
            $mail->IsHTML(true);
            $mail->AddReplyTo($cam_primary_email, $cam_primary_name);
            $mail->SetFrom("emails@thenewais.com", $cam_alias);
      }
      
      // Prepare To: and Cc: addresses.
      $ary2 = explode(";", $to);
      
      foreach($ary2 as $value) {
            $ary = explode("|", $value);
            $mail->AddAddress($ary[0]);
            
      }
      
      if ($cc > '') {
            $ary2 = explode(";", $cc);
            foreach($ary2 as $value) {
                  $ary = explode("|", $value);
                  $mail->AddCC($ary[0]);
                  
            }
      }
      
      // 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 {

            $mail->MsgHTML($body);

            // 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 . ")";
                                          $y++;
                                    }
                              }
                        }
                  }
                  unset($files);

                  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/vnd.ms-word.document";
                        elseif ($ext == "xls" || $ext == "xlsx")      $mimetype = "application/vnd.ms-excel";
                        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
                          if(is_file($file))
                              unlink($file); // delete file
                        }      
                        rmdir($temppathF);
                  }
*/                  
            } // 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
The recent versions are listed on the Downloads page: http://code.google.com/a/apache-extras.org/p/phpmailer/downloads/list  The version number is listed at the top of class.phpmailer.php .
Dave,
I'm using 5.2.1.  5.2.2 just came out Dec 3.  Will try new version in AM.
Bruce
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

http://us2.php.net/manual/en/regexp.reference.escape.php
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('smtp.example.org', 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.com' => 'John Doe'))

  // Set the To addresses with an associative array
  ->setTo(array('receiver@domain.org', 'other@domain.org' => '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()
  ->setFilename('my-file.pdf')
  ->setContentType('application/pdf')

$message->attach($attachment);

// 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.
Dave,

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!
Bruce
McNute:

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!
Bruce
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.
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.

Bruce
StreamBuffer.php
Swift_SmtpTransport::newInstance('domain.com', 25)
                ->setUsername('info@domain.com')
                ->setPassword('wrong_password')
                ->setTimeout(45);

Open in new window


If you set a timeout like so? What does it tell you?
McNute:
Same error, and still showing 30 seconds.
Bruce
ASKER CERTIFIED SOLUTION
Avatar of mcnute
mcnute
Flag of Germany image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
McNute:

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.

Bruce
Thanks to McNute for the extended time and effort!
Bruce
You're welcome! Have a nice christmas time.