16

I've been trying to get the list of recipients who did not get email using laravel Mail::send() function. I am trying following code. for loop is used as because each user to be received customized message.

// First recipient is actual, the second is dummy.
$mail_to_users = ["original_account@domain.com","dummy_account@domain.com"];
$failures = [];

foreach($mail_to_users as $mail_to_user) {
   Mail::send('email', [], function($msg) use ($mail_to_user){
     $msg->to($mail_to_user);
     $msg->subject("Document Shared");
   });

   if( count( Mail::failures() ) > 0 ) {
      $failures[] = Mail::failures()[0];
   }
}

print_r($failures);

I've been trying all the possible option. I changed the correct mail config in config/mail.php to the wrong one. But if I do this then laravel shows error page, but $failure variable always return empty.

Rajan Rawal
  • 6,171
  • 6
  • 40
  • 62
  • 4
    It's worth nothing that only very specific types of failures are retuned from Swiftmailer: pretty much only failures in the sense that the method used for mail rejected the address/email. With `SMTP` this is generally okay, as SMTP servers will immediately return a failure, but something like using sendmail will rarely (if ever) return a failure, as the emails are just accepted regardless, and then sent later. As such, if you use `sendmail` (or maybe even `mail`) in your mail config, you'll probably need to use a different way to monitor delivery failures. – alexrussell Aug 17 '15 at 08:03
  • 1
    See http://swiftmailer.org/docs/sending.html for the documentation on when you do and do not get failures returned. – alexrussell Aug 17 '15 at 08:04

3 Answers3

5

I think there is no way to check email is actually gone to the receipient or not. As long as the email is valid (even though dummy) it will return true. However, Instead of Mail::failures() you can use try catch block as follows:

foreach ($mail_to_users as $mail_to_user) {
            try {
                Mail::send('email', [], function($msg) use ($mail_to_user) {
                    $msg->to($mail_to_user);
                    $msg->subject("Document Shared");
                });
            } catch (Exception $e) {

                if (count(Mail::failures()) > 0) {
                    $failures[] = $mail_to_user;
                }
            }
        }
Hasan Tareque
  • 1,761
  • 11
  • 21
2

I am working with a similar issue. When an email fails to be sent, I want to do a few things with it. I read the source code and the Illuminate\Mail\SendQueuedMailable::failed() method indicates that we can add a failed method to the Mailable object to handle the $exception when the email fails.

So we can do this:

class SampleMail extends Mailable
{
    public function failed($e)
    {
        // Do something with the exception when the email fails.
    }
}

As I understand, this only works with queued mailables.

Kevin Bui
  • 2,754
  • 1
  • 14
  • 15
0

I had the same issue. You can use try..catch statement with multiple catch().So for any type of failure, you will get an email Id in the failure list. I also put a log to get an error message.

Try the below code.

$failures = [];

foreach ($mail_to_users as $mail_to_user) {

    try {
        Mail::send('email', [], function($msg) use ($mail_to_user) {
            $msg->to($mail_to_user);
            $msg->subject("Document Shared");
        });
    }
    catch(\Swift_TransportException $e){

      Log::info('------> err swift:--  '.$e->getMessage()); // for log, remove if you not want it
      Log::info(''. PHP_EOL .'');

      $failures[] = $mail_to_user;
    }
    catch(\Swift_RfcComplianceException $e){
      Log::info('------> err Swift_Rfc:'.$e->getMessage());
      Log::info(''. PHP_EOL .'');

      $failures[] = $mail_to_user;
    }
    catch (Exception $e) {
      Log::info('------> err'.$e->getMessage());
      Log::info(''. PHP_EOL .'');

      $failures[] = $mail_to_user;
    }
}
print_r($failures);
Yasin Patel
  • 5,624
  • 8
  • 31
  • 53