Jens Segers on Feb 28 2016

Laravel SMTP driver vs. API drivers

After Mandrill changed their pricing model, I (as well as many others) started exploring different transactional email services. Laravel only supports a couple providers out of the box, but what about the others?

All Laravel mail drivers are managed by a core TransportManager, but it was a pain in the ass to register custom drivers in your application service provider. I even had to make a pull request to the Laravel framework to make it somewhat possible. Now that the pull request is merged you will be able to register a new mail driver like this:

 public function register()
    $this->app['swift.transport']->extend('postmark', function () {
        return new PostmarkTransport($this->app['config']->get('services.postmark.token'));

But is it worth it? I mean, almost every email service has support for SMTP, and Laravel has an SMTP driver by default. So why even bother registering a custom email driver?

First I thought it would make a difference in performance. So I did some quick tests on an Ubuntu Vagrant box:

Postmark API driver:
average duration: 0.66 seconds

Postmark SMTP driver:
average duration: 0.36 seconds

Mandrill API driver:
average duration: 0.67 seconds

Mandrill SMTP driver:
average duration: 0.54 seconds

At first sight, the API drivers are not quicker at all. Actually, in my simple test the SMTP driver was faster for both Postmark and Mandrill.

The main takeaway here is that it is fine to just use the SMTP driver rather than spending time on hooking a new API driver into Laravel. Unless you are using specific API features to get message ID's or bulk emails you should be perfectly fine with the default SMTP driver. Let me know in the comments what you think!


jules 3 years ago

The API approach might be a little slower, but in case of Postmark it gives you a couple of nice extra features like the 'trackopens' option & response with a MessageID which is useful in some cases. Also, the error responses coming back from the API are a lot easier to parse than whatever the STMP service returns.

jenssegers 3 years ago

@jules That's true! It looks like the SMTP driver just returns true or false. Most API drivers will probably return the json response with additional information (like Postmark).

Matt 3 years ago

How was the performance test conducted? From what I understand, the performance benefit with the APIs comes in when you're sending bulk email. If I'm sending out a newsletter to 500 people, SMTP should be a bottleneck. This also matters for larger sites that make extensive use of mail queues, instead of immediate mailing.

jenssegers 3 years ago

Hi @Matt, the test was done for just sending 1 single email. I don't know if Laravel even supports bulk email sending.

mikemandkmd 3 years ago

Now if only there was an easier way of making a SendWithUs transport. :)

Thank you for your pull request. When I was trying to add new transports, I had to disable the default Email service provider and extend it with my own. This will be so much better.

Isaac 3 years ago

I must be doing something wrong, I am on laravel version 5.2.22 and I am trying to extend swift.transport just like in your blog post, but I still get the error that "swift.transport" doesn't exist. I have tried in the AppServiceProvider as well as a new ServiceProvider I added to the the end of the Providers array. Either way I get the same error. Am I doing it wrong? Any help is greatly appreciated. Thanks

public function register()
        $this->app['swift.transport']->extend('gmail', function () {
            $gmail = new Google_Service_Gmail(app('google.client'));

            return new GmailTransport($gmail);

jenssegers 3 years ago

@Isaac The pull request is not tagged yet. It will be available in the next release of Laravel.

marcorivm 3 years ago

I think what @Matt mentions about performance for bulk email is an important point, some testing for this setup is needed.

I have seen this difference in performance for bulk email on my own apps, using the API method instead of SMTP proved a huge difference.

nicolas 3 years ago

I've tried to configure this in a register method, but it doesn't work. I finally created a new PostmarkServiceProvider, added the ->extend() in the Boot method, and it worked. Did anyone managed another way ?

Ash 2 years ago

The SMTP driver does only return true or false and I don't necessarily think that means the message was sent, just that it was passed to the SMTP server. API providers usually run queues in the background where they might try multiple times to send and give detailed information and have support for webhooks etc.. on fail.

fddf 1 year ago