Error handling with PHPMailer
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 ou开发者_高级运维t 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.
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!
}
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.
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.
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.
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);
}
}
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;
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
}
In PHPMailer.php, there are lines as below:
echo $e->getMessage()
Just comment these lines and you will be good to go.
$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...
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
精彩评论