mheiduk's avatar

Mailjet integration with service provider

My plan is to integrate an email service provider for Mailjet and using their API for sending mails via the Mail facade from Laravel

I've set up a service provider where I'm a little bit stuck now. I have the following including the Mailjet driver:

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use App\Mail\MailjetTransport;

class MailjetServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap the application services.
     *
     * @return void
     */
    public function boot()
    {
        $this->app['swift.transport']->extend('mailjet', function($app) {
            return $transport;
        });
    }

    /**
     * Register the application services.
     *
     * @return void
     */
    public function register()
    {
        //
    }

    /**
     * Creating Mailjet Driver
     * @return [type] [description]
     */
    protected function createMailjetDriver()
    {
        $config = $this->app['config']->get('services.mailjet', []);

        return new MailjetTransport(
            $this->getHttpClient($config),
            getenv('MJ_APIKEY_PUBLIC'),
            getenv('MJ_APIKEY_PRIVATE')
        );
    }

I know I need some sort of transportation (marked with return $transport; for the the provider, but many things I've tried failed.

Here is the MailjetTransport class which I've tested and should work:

<?php

namespace App\Mail\Transport;

use GuzzleHttp\ClientInterface;
use Illuminate\Mail\Transport\Transport;
use Swift_Mime_Message;

class MailjetTransport extends Transport
{
    /**
     * Guzzle HTTP client.
     *
     * @var ClientInterface
     */
    protected $client;

    /**
     * The Mailjet "API key" which can be found at https://app.mailjet.com/transactional
     *
     * @var string
     */
    protected $apiKey;

    /**
     * The Mailjet "Secret key" which can be found at https://app.mailjet.com/transactional
     *
     * @var string
     */
    protected $secretKey;

    /**
     * The Mailjet end point we're using to send the message.
     *
     * @var string
     */
    protected $endPoint = 'https://api.mailjet.com/v3/send';

    /**
     * Create a new Mailjet transport instance.
     *
     * @param  \GuzzleHttp\ClientInterface $client
     * @param $apiKey
     * @param $secretKey
     */
    public function __construct(ClientInterface $client, $apiKey, $secretKey)
    {
        $this->client = $client;
        $this->apiKey = $apiKey;
        $this->secretKey = $secretKey;
    }

    /**
     * Send the given Message.
     *
     * Recipient/sender data will be retrieved from the Message API.
     * The return value is the number of recipients who were accepted for delivery.
     *
     * @param Swift_Mime_Message $message
     * @param string[] $failedRecipients An array of failures by-reference
     *
     * @return int
     */
    public function send(Swift_Mime_Message $message, &$failedRecipients = null)
    {
        $this->beforeSendPerformed($message);

        $payload = [
            'header' => ['Content-Type', 'application/json'],
            'auth' => [$this->apiKey, $this->secretKey],
            'json' => []
        ];

        $this->addFrom($message, $payload);
        $this->addSubject($message, $payload);
        $this->addContent($message, $payload);
        $this->addRecipients($message, $payload);

        return $this->client->post($this->endPoint, $payload);
    }

    /**
     * Add the from email and from name (If provided) to the payload.
     *
     * @param Swift_Mime_Message $message
     * @param array $payload
     */
    protected function addFrom(Swift_Mime_Message $message, &$payload)
    {
        $from = $message->getFrom();

        $fromAddress = key($from);
        if ($fromAddress) {
            $payload['json']['FromEmail'] = $fromAddress;

            $fromName = $from[$fromAddress] ?: null;
            if ($fromName) {
                $payload['json']['FromName'] = $fromName;
            }
        }
    }

    /**
     * Add the subject of the email (If provided) to the payload.
     *
     * @param Swift_Mime_Message $message
     * @param array $payload
     */
    protected function addSubject(Swift_Mime_Message $message, &$payload)
    {
        $subject = $message->getSubject();
        if ($subject) {
            $payload['json']['Subject'] = $subject;
        }
    }

    /**
     * Add the content/body to the payload based upon the content type provided in the message object. In the unlikely
     * event that a content type isn't provided, we can guess it based on the existence of HTML tags in the body.
     *
     * @param Swift_Mime_Message $message
     * @param array $payload
     */
    protected function addContent(Swift_Mime_Message $message, &$payload)
    {
        $contentType = $message->getContentType();
        $body = $message->getBody();

        if (!in_array($contentType, ['text/html', 'text/plain'])) {
            $contentType = strip_tags($body) != $body ? 'text/html' : 'text/plain';
        }

        $payload['json'][$contentType == 'text/html' ? 'Html-part' : 'Text-part'] = $message->getBody();
    }

    /**
     * Add to, cc and bcc recipients to the payload.
     *
     * @param Swift_Mime_Message $message
     * @param array $payload
     */
    protected function addRecipients(Swift_Mime_Message $message, &$payload)
    {
        foreach (['To', 'Cc', 'Bcc'] as $field) {
            $formatted = [];
            $method = 'get' . $field;
            $contacts = (array) $message->$method();
            foreach ($contacts as $address => $display) {
                $formatted[] = $display ? $display . " <$address>" : $address;
            }

            if (count($formatted) > 0) {
                $payload['json'][$field] = implode(', ', $formatted);
            }
        }
    }
}

Would be great if someone can help me out. Thanks!

0 likes
2 replies
gmgarrison's avatar

Okay, so I'm replying 5 YEARS LATER...

Just checking in to see if anyone's made any significant progress using MailJet in a Laravel project? I saw your package, @robrogers3 , but the dependencies haven't been updated in a while and it won't easily install in a Laravel 9 project.

I tried installing the official MailJet Laravel package but there's no documentation for actually, you know, sending an email and I keep getting errors on the fields I'm submitting to the API.

Anyone ever get this to work??

Please or to participate in this conversation.