2

I am using Mailgun as a mail driver in my laravel application, as well as nexmo for SMS purposes.

What I am trying to achieve is to maintain the delivery status of the notifications that are sent either via Mailgun or Nexmo. Incase of Nexmo I am able achieve this, since I get the nexmo MessageId in the NotificationSent event that is fired after processing a notification.

However in the event instance for email, the response is empty.

Any idea what I am missing or, how I can retrieve the mailgun message-id?

Ammadu
  • 1,675
  • 15
  • 17

2 Answers2

2

I have found a workaround that does the job for now. Not as neat as I want it to be, but posting for future references incase anyone needs this.

I have created a custom notification channel extending Illuminate\Notifications\Channels\MailChannel

class EmailChannel extends MailChannel
{
    /**
     * Send the given notification.
     *
     * @param  mixed  $notifiable
     * @param  \Illuminate\Notifications\Notification  $notification
     * @return void
     */
    public function send($notifiable, Notification $notification)
    {

        if (! $notifiable->routeNotificationFor('mail')) {
            return;
        }

        $message = $notification->toMail($notifiable);

        if ($message instanceof Mailable) {
            return $message->send($this->mailer);
        }

        $this->mailer->send($message->view, $message->data(), function ($m) use ($notifiable, $notification, $message) {
            $recipients = empty($message->to) ? $notifiable->routeNotificationFor('mail') : $message->to;

            if (! empty($message->from)) {
                $m->from($message->from[0], isset($message->from[1]) ? $message->from[1] : null);
            }

            if (is_array($recipients)) {
                $m->bcc($recipients);
            } else {
                $m->to($recipients);
            }

            if ($message->cc) {
                $m->cc($message->cc);
            }

            if (! empty($message->replyTo)) {
                $m->replyTo($message->replyTo[0], isset($message->replyTo[1]) ? $message->replyTo[1] : null);
            }

            $m->subject($message->subject ?: Str::title(
                Str::snake(class_basename($notification), ' ')
            ));

            foreach ($message->attachments as $attachment) {
                $m->attach($attachment['file'], $attachment['options']);
            }

            foreach ($message->rawAttachments as $attachment) {
                $m->attachData($attachment['data'], $attachment['name'], $attachment['options']);
            }

            if (! is_null($message->priority)) {
                $m->setPriority($message->priority);
            }

            $message = $notification->getMessage(); // I have this method in my notification class which returns an eloquent model
            $message->email_id = $m->getSwiftMessage()->getId();
            $message->save();
        });
    }
}

I am still looking for a solution to achieve this with NotificationSent event.

Ammadu
  • 1,675
  • 15
  • 17
1

When looking at the code (MailgunTransport) it will do the following

    $this->client->post($this->url, $this->payload($message, $to));
    $this->sendPerformed($message);
    return $this->numberOfRecipients($message);

Since the Laravel contract requires the implementation to send back the number of e-mails send.

Even if you would be able to get into the mail transport it doesn't store the response from for this reason it not possible to catch the message id.

What you could do is to implement your own (or look in packagist) to adapt mail client but this is not a perfect solution and will require some ugly instanceof checks.

Ken
  • 2,654
  • 3
  • 26
  • 29
  • Thanks @ken, I actually worked it around by extending the MailChannel. Will be posting it as an answer in a bit. – Ammadu Jan 27 '17 at 15:57