Error handling with PHPMailer
Asked Answered
C

10

64

I'm trying to use PHPMailer for a small project, but I'm a bit confused about error handling with this software. Hoping someone has experience with it. When I've set up an email and I use:

$result = $mail->Send();

if(!$result) {
    // There was an error
    // Do some error handling things here
} else {
    echo "Email successful";
}

Which works fine, more or less. The problem is when there's an error, PHPMailer also seems to echo the error out, so if there's a problem, it just sends that info directly to the browser, essentially breaking any error handling I"m trying to do.

Is there a way to silence these messages? Its not throwing an exception, its just printing out the error, which in my test case is:

invalid address: @invalid@email You must provide at least one recipient email address.

Its meant to be an error, but it should be residing in $mail->ErrorInfo; not being echo'd out by the software.

Compile answered 5/3, 2010 at 12:11 Comment(0)
P
148

PHPMailer uses Exceptions. Try to adopt the following code:

require_once '../class.phpmailer.php';

$mail = new PHPMailer(true); //defaults to using php "mail()"; the true param means it will throw exceptions on errors, which we need to catch

try {
  $mail->AddReplyTo('[email protected]', 'First Last');
  $mail->AddAddress('[email protected]', 'John Doe');
  $mail->SetFrom('[email protected]', 'First Last');
  $mail->AddReplyTo('[email protected]', 'First Last');
  $mail->Subject = 'PHPMailer Test Subject via mail(), advanced';
  $mail->AltBody = 'To view the message, please use an HTML compatible email viewer!'; // optional - MsgHTML will create an alternate automatically
  $mail->MsgHTML(file_get_contents('contents.html'));
  $mail->AddAttachment('images/phpmailer.gif');      // attachment
  $mail->AddAttachment('images/phpmailer_mini.gif'); // attachment
  $mail->Send();
  echo "Message Sent OK\n";
} catch (phpmailerException $e) {
  echo $e->errorMessage(); //Pretty error messages from PHPMailer
} catch (Exception $e) {
  echo $e->getMessage(); //Boring error messages from anything else!
}
Plasmosome answered 5/3, 2010 at 12:17 Comment(8)
I had already tried catching it with exceptions, the part I had missed was new PHPMailer(true) which actually enables the exceptions. Thank you for your help.Compile
for me.. these lines are have errors..$mail->MsgHTML(file_get_contents('contents.html')); $mail->AddAttachment('images/phpmailer.gif'); // attachment $mail->AddAttachment('images/phpmailer_mini.gif'); // attachment how can i fix it.. thanks..Nessim
This is not good. Even with exception handling, you should still put the "Message Sent OK\n"confirmation inside of a conditional, else it'll lead to misleading confirmations saying it's okay when actually something went wrong. So use e.g.: if ( $mail->Send() ) {echo "E-mail sent OK<br>"; }Pathe
Using this code when mail send successfully they will return 'Resource id #7' with our success message. any solution?Logogram
@Fabien In fact, the throwing of an error means that the Message Sent OK line will not be reachedGemination
@GeoffKendall If Send() fails without triggering an error exception, which it can, then "Message Sent OK\n" will be shown, which is misleading. Hence my comment.Pathe
In the constructor, we provided the true parameter, which forces PHPMailer to throw exceptions in case of errors. Only if it would be set to false (the default), send might return false without throwing an Exception. If you don't trust me, also have a look at the code :-) Sorry it took 2 years to respond...Plasmosome
According to the official examples we should use Exception $e and \Exception $e. The first is from PHPMailer and the latter is the global one. github.com/PHPMailer/PHPMailer/blob/master/examples/…Denna
N
41

You can get more info about the error with the method $mail->ErrorInfo. For example:

if(!$mail->send()) {
    echo 'Message could not be sent.';
    echo 'Mailer Error: ' . $mail->ErrorInfo;
} else {
    echo 'Message has been sent';
}

This is an alternative to the exception model that you need to active with new PHPMailer(true). But if can use exception model, use it as @Phil Rykoff answer.

This comes from the main page of PHPMailer on github https://github.com/PHPMailer/PHPMailer.

Nappy answered 7/7, 2015 at 15:33 Comment(1)
I like this, because you don't have to pass constructor arguments nor catch expceptions.Cribriform
S
21

Please note!!! You must use the following format when instantiating PHPMailer!

$mail = new PHPMailer(true);

If you don't exceptions are ignored and the only thing you'll get is an echo from the routine! I know this is well after this was created but hopefully it will help someone.

Spatiotemporal answered 21/11, 2013 at 16:16 Comment(1)
@WOUNDEDStevenJones I struggled with the accepted answer. Perhaps I don't read close enough, but either way this answer helped me.Glaikit
A
20

Just had to fix this myself. The above answers don't seem to take into account the $mail->SMTPDebug = 0; option. It may not have been available when the question was first asked.

If you got your code from the PHPMail site, the default will be $mail->SMTPDebug = 2; // enables SMTP debug information (for testing)

https://github.com/Synchro/PHPMailer/blob/master/examples/test_smtp_gmail_advanced.php

Set the value to 0 to suppress the errors and edit the 'catch' part of your code as explained above.

Adamsen answered 29/3, 2013 at 13:53 Comment(1)
If that still doesn't work, go for $mail->SMTPDebug = 4; - this'll show each and every step PHPMailer doesBentwood
L
5

We wrote a wrapper class that captures the buffer and converts the printed output to an exception. this lets us upgrade the phpmailer file without having to remember to comment out the echo statements each time we upgrade.

The wrapper class has methods something along the lines of:

public function AddAddress($email, $name = null) {
    ob_start();
    parent::AddAddress($email, $name);
    $error = ob_get_contents();
    ob_end_clean();
    if( !empty($error) ) {
        throw new Exception($error);
    }
}
Levana answered 25/1, 2011 at 16:28 Comment(0)
Y
3

Even if you use exceptions, it still output errors.
You have to set $MailerDebug to False wich should look like this

$mail = new PHPMailer();
$mail->MailerDebug = false;
Yokefellow answered 14/4, 2011 at 18:27 Comment(1)
Just a note this has been removed: Version 1.25 (Mon, Jul 02 2001) * Added improved error handling by adding a $ErrorInfo variable * Removed MailerDebug variable (obsolete with new error handler)Bigname
S
2

This one works fine

use try { as above

use Catch as above but comment out the echo lines
} catch (phpmailerException $e) { 
//echo $e->errorMessage(); //Pretty error messages from PHPMailer
} catch (Exception $e) {   
//echo $e->getMessage(); //Boring error messages from anything else!
}

Then add this

if ($e) {
//enter yor error message or redirect the user
} else {
//do something else 
}
Stellate answered 30/5, 2011 at 12:43 Comment(0)
M
1

In PHPMailer.php, there are lines as below:

echo $e->getMessage()

Just comment these lines and you will be good to go.

Muirhead answered 27/4, 2012 at 14:53 Comment(0)
B
0
$mail = new PHPMailer();

$mail->AddAddress($email); 
$mail->From     = $from;
$mail->Subject  = $subject; 
$mail->Body     = $body;

if($mail->Send()){
    echo 'Email Successfully Sent!';
}else{
    echo 'Email Sending Failed!';
}

the simplest way to handle email sending successful or failed...

Blowtube answered 30/10, 2012 at 7:8 Comment(2)
You should append $mail->ErrorInfo to the else case to display errors.Platonism
This is the starting point of the original question - the question is only asked since this is not enough.Stormie
P
0

To address OPs problem:

"PHPMailer also seems to echo the error out, so if there's a problem, it just sends that info directly to the browser, essentially breaking any error handling I"m trying to do."

It's not obvious (to me anyway, being new to exceptions) that all exceptions will be fed to the output buffer. Should somebody turn on debugging in production, front end users might get a surprise. I didn't want to leave that to chance. To add, the exception output was ending up in (and breaking) my JSON response, so it actually hindered my debugging.

My solution was to clean the buffer before returning the front end output. My use-case was a JSON response to a fetch API request, so before sending my output, I called ob_clean() to clean the buffer of any unwanted debugging data. For example:

ob_clean(); //clean the buffer
echo json_encode( $public_output ); //echo response to browser

I should clarify that this is a fallback for potentially unwanted output and should not be a substitute for disabling the debugging. On the contrary, I imagine this may even be problematic for a dev expecting to see debugging output in the browser.

$mail->SMTPDebug = SMTP::DEBUG_OFF;

Finally, useful error output can still be sent to the logs even with debugging disabled:

error_log( $mail->ErrorInfo );

PHPMailer Troubleshooting Wiki on GitHub

Piecework answered 28/10, 2021 at 16:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.