62

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.

Stomped
  • 2,010
  • 6
  • 21
  • 25

10 Answers10

145

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('name@yourdomain.com', 'First Last');
  $mail->AddAddress('whoto@otherdomain.com', 'John Doe');
  $mail->SetFrom('name@yourdomain.com', 'First Last');
  $mail->AddReplyTo('name@yourdomain.com', '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!
}
Martin
  • 22,212
  • 11
  • 70
  • 132
Phil Rykoff
  • 11,999
  • 3
  • 39
  • 63
  • 30
    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. – Stomped Mar 05 '10 at 12:32
  • 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.. – pcs May 28 '15 at 12:06
  • 3
    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
    "; }`
    – Fabien Snauwaert Aug 19 '17 at 11:44
  • Using this code when mail send successfully they will return 'Resource id #7' with our success message. any solution? – Mitul Koradiya Jun 11 '19 at 14:13
  • @Fabien In fact, the throwing of an error means that the Message Sent OK line will not be reached – Geoff Kendall Jun 16 '19 at 11:59
  • @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. – Fabien Snauwaert Jun 16 '19 at 17:46
  • 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... – Phil Rykoff Jun 21 '19 at 11:46
  • 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. https://github.com/PHPMailer/PHPMailer/blob/master/examples/exceptions.phps – Jette Apr 15 '21 at 11:11
38

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.

PhoneixS
  • 10,574
  • 6
  • 57
  • 73
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.

kleopatra
  • 51,061
  • 28
  • 99
  • 211
PhilMDev
  • 351
  • 3
  • 6
  • @WOUNDEDStevenJones I struggled with the accepted answer. Perhaps I don't read close enough, but either way this answer helped me. – Goose Jun 28 '16 at 18:26
19

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.

Dwza
  • 6,494
  • 6
  • 41
  • 73
Simon Roberts
  • 617
  • 1
  • 7
  • 14
  • If that still doesn't work, go for `$mail->SMTPDebug = 4;` - this'll show each and every step PHPMailer does – Mave Feb 02 '15 at 09:01
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);
    }
}
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;
Fred
  • 141
  • 6
  • 4
    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) – John Magnolia Oct 09 '12 at 14:12
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 
}
forsvarir
  • 10,749
  • 6
  • 46
  • 77
Patdundee
  • 21
  • 1
1

In PHPMailer.php, there are lines as below:

echo $e->getMessage()

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

Haris ur Rehman
  • 2,593
  • 30
  • 41
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...

Prince-W
  • 33
  • 2
  • 5
    You should append $mail->ErrorInfo to the else case to display errors. – Westy92 Jun 12 '13 at 01:44
  • This is the starting point of the original question - the question is only asked since this is not enough. – pgr Sep 04 '17 at 14:37
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

Jefferson
  • 89
  • 1
  • 8