As a digital business, email is key to communicating with customers. It is very important to make sure that delivery of transactional emails, like purchase confirmations and license information, is reliable. Thus the need for a transactional email service. It may not be particularly exciting, but it is definitely an important consideration. There are plenty of providers out there, but I’ve narrowed down the list a bit to these: Mailgun, SendInBlue, Postmark, SendGrid, Mandrill, Mailjet, and SparkPost. Others have ruled out Mandrill as it requires a paid MailChimp account, but I just happen to have one of those. So I figured I might as well give Mandrill a try too.
What is Transactional Email?
As I’ve alluded to, transactional email includes things like purchase confirmations, license information, invoices, subscription and billing reminders, etc. It all seems so ho-hum… until it isn’t getting where it needs to go. I’ve been pretty fortunate so far. I send all my transactional email through a Digital Ocean droplet, and the reputation for the IP address is pretty good. The two problems I’ve had are an odd blacklist in Chile, and bad neighbors. When some jerk signs up for Digital Ocean and starts using their droplet to send out spam in the same network subnet as my droplet, email delivery from that subnet can suffer. In particular, when lists like UCE Protect detect a spammer, they like to blacklist entire subnets (groups of servers). While Digital Ocean doesn’t tolerate spamming, it takes a few days for the listing to clear.
I started looking for a transactional email provider to avoid such issues, but there’s something else in the mix here. While my primary mail server has a good IP address, I have 17 servers, and I can’t say the same for all of them. Configuring SPF and DKIM to improve reliability across such a server fleet gets messy fast. As a result I’ve configured all my servers to relay mail through the primary email server. The problem is that I’m trading one mess for another. Setting up firewall rules for 16 other servers, making sure to include both IPv4 and IPv6 addresses, updating the allowed relay IPs list on the primary (again with IPv4 and IPv6 addresses), and trying to automate all that, is a real pain in the neck.
I’m not looking for awesome, but if we find it in the process, all the better. What I am looking for are these:
- Ability to send email via PHP.
- Ability to send email via SMTP.
- 100% delivery rate. If they can’t deliver my emails, I might as well go back to my old setup. This doesn’t include bad addresses and the like. I’m simply looking for a service that keeps their IP addresses clean and off any blacklists. If they are smart, they shouldn’t use an IP address when it is on a blacklist.
I was originally only going to test Mailgun and SendGrid. However, SendGrid blocked my initial signup, so I tried a couple others in the meantime. That also meant that Mailgun was the first transactional email platform up for testing.
Mailgun had a nice looking interface, and made it nice and simple to setup SPF and DKIM records for best deliverability. They also mentioned something interesting during setup. They recommended using a sub-domain like mg.example.com for sending transactional email. If the reputation of your sub-domain gets ruined for some reason, you can ditch it and move on. That would be a lot harder to do if you used your primary top-level domain (like example.com).
Extras with Mailgun
The setup also included setting up a CNAME for tracking opens and links, which is a nice bonus. “Open tracking” uses invisible images, which some email clients block, but human curiosity tends to take care of that. They also included instructions for setting up MX records for the custom sub-domain. You can use this in conjunction with their API to perform certain actions when your custom sub-domain receives an email. That isn’t something I’ll be using, but I will continue to note services which had similar features.
Mailgun allows 10,000 free emails each month, which is a nice feature, but I wonder how abuse they see from that. They did require a credit card before allowing much activity, so I suppose that helps weed out most spammers. At any rate, 10,000 emails/month should be enough for my needs currently, and free is a nice price.
The Beginning of the End
Call me weird, but I don’t use Composer with any of my PHP projects. Most of the scripts I would be sending email from are completely standalone. While I use some extra libraries, using Composer just seems nuts to me. Mailgun’s PHP library only works with Composer. I was about to give up on them, but then I found a couple posts that detailed how to build your own Mailgun integration using PHP and Curl.
I also wasn’t quite sure how to setup Mailgun with Exim4, but an article on the SendGrid Docs showed me the way. With that done, I let things run overnight and checked back on the dashboard the next morning. And that was the end. In less than 12 hours, one email had already been blocked because one of their servers was on the Proofpoint blacklist: “5.7.0 Blocked – see https://support.proofpoint.com/dnsbl-lookup.cgi?ip=220.127.116.11”.
This transactional email service also has a free tier where you can send up to 9,000 emails per month. This should be sufficient for my business currently, so the price here is free. Signup is simple, but the lack of custom domain setup surprised me. I suspect one of the paid plans might include custom domains, but nothing on their pricing page indicates such a thing.
Marketing vs. Transactional
Once I logged in, SendInBlue requires email and mobile phone validation, similar to Mailgun. Once I verified those, I landed on the dashboard page. Here’s where things got interesting. The dashboard gave me three steps to “validate” my account. Two of the three steps were things totally irrelevant for transactional email. They were clearly pushing the marketing side of their email service:
- Import all of your contacts
- Complete your profile
- Create and schedule your campaign
I didn’t really want to do 1 & 3, but my account was limited to 300 emails per day. Not knowing if that would be enough, I figure I should validate my account. So, I complete my profile, and then try importing a few emails and sending out a test campaign. The profile worked properly, but the others still show as incomplete. Further review shows that the free plan only allows 300 emails per day. That makes makes sense since 300 x 30 = 9,000.
SendInBlue seems to focus more on marketing emails, which made me nervous, but I want to give SendInBlue a fair shot. Next, I started with their PHP integration, but the link in their setup steps sent me to a deprecated library. Fortunately, the deprecated library had a link to the new one, but that was a bit odd. Also, one other place had the link to the deprecated library twice:
The API library docs were also a bit sparse, with just a simple three line example, and no mention of how to send an email. With the lingering aftertaste from the outdated link, this didn’t help matters much. Fortunately, a little browsing around the docs found an example of how to actually send an email. In short order, I had a test email sent. Or at least that’s what it said in the dashboard. I had to wait for 20 minutes for delivery of my test email. I discovered that “Sent” merely meant the email was in the queue. Once they sent the message, the log showed the status as “Delivered”.
Slow Mail is No Mail
While it isn’t as bad as a bounced email, slow email can frustrate customers. SendInBlue had another downside though. They include SendInBlue branding on your emails, unless you pay $39/month for the Bronze package. After the inconsistent PHP documentation, the slow email delivery, and the unwanted branding, I was done with SendInBlue.
Reviews indicated Postmark was more expensive and geared toward higher-end clients. However, I was nearing the end of the day, Mailgun had turned out to be unreliable, and SendInBlue was slow. I still hadn’t heard back from SendGrid, so I gave in and signed up for a Postmark account. They have a very generous free trial of 25,000 credits, once they’ve manually reviewed your signup information. At once, this inspired a bit more confidence than those with completely automated signups. Beyond the 25,000 credits there is no free plan. So going with a rough average of 10,000 emails per month, I would pay $15/month.
Integration with Postmark
Postmark had a very simple setup for DKIM and SPF, which included MX and CNAME records similar to Mailgun. I really appreciated their API documentation, which included PHP instructions for Composer, and without Composer (for folks like me). While manual verification might slow you down a little, their setup process is quick and straightforward. I also kept a close eye on the spam score assigned to my test emails. While it will vary some depending on the content of the test email, the scores on Postmark emails were several points lower than SendInBlue, which is great for delivery.
Postmark was the only service that doesn’t allow marketing email. Their sole focus is on providing a transactional email service. Blacklists are less likely to flag their servers for spam with marketing emails out of the mix. Have you ever seen someone flag a legitimate email as spam because they didn’t bother to unsubscribe? Me too… Additionally, the custom domain allows them to send emails without them saying “sent as” or “on behalf of”. Unlike SendInBlue, they can use legitimate addresses from your custom domain without triggering spam filters.
Postmark includes automatic open and click tracking, and they even have chat support available from the dashboard. Lack of support is one reason I didn’t try Amazon SES. Most of their computing services do not include support, you have to pay extra for that.
They also have a bonus for bootstrapped startups: 50,000 free credits if you are charging for your products and have not taken any outside funding. There was one more thing that I haven’t seen anywhere else. Their logs include the message contents of all emails sent. That may not matter for some, but I would have used such a feature many times if I had it.
Delivery was almost instant with Postmark, and they update their logs very quickly too. After leaving Postmark active all weekend, only two emails bounced, and these were invalid addresses, not blacklist rejections. All of the services will automatically disable sending to bounced addresses, to improve delivery rates. However, I had wondered what would happen if you needed to re-enable an address. For such an occasion, Postmark has a built-in reactivation button, accessible right from the logs.
So far, Postmark has a lot going for it. We’ll see if SendGrid can dethrone them.
Pricing for SendGrid’s transactional email service is $9.95/month for 10,000 emails. In fact you can send up to 40,000/month with that plan. So that would give us very reasonable pricing, with room to grow.
As I mentioned before, SendGrid’s automated filters blocked my signup. As a result, I had to email support to manually activate my service and it took 6 hours for a response. Then, once I replied with the required information, it took less than 30 minutes for review and activation. Most of these services send out welcome emails and such, but I received nothing from SendGrid. This was probably a glitch due to manual activation of my account. As a result, I had to have the email verification resent, which ended up in my spam folder. Not what I was expecting from a reputable provider, but I pushed on regardless.
Sending via the Grid
Here is where SendGrid really shines. Integrating SendGrid into your PHP application (or one of several other languages) is dead simple. They walk you through the entire process, with complete code examples. As I noted earlier, the SendGrid docs were also where I found documentation for setting up Exim4. So SendGrid definitely leads the pack on ease of setup and integration. When it came to domain validation, it was a little bit awkward though. The buttons and terminology were not as clear as they could have been. As a result, several times I thought I had missed something, only to find out that I wasn’t at that step yet. My only real complaint with their setup process was the domain verification.
Verifying a custom domain was similar to the others, except there was a Default checkbox when I was setting up the DKIM and SPF records. It claimed that checking the default box would make it the default domain for click and open tracking as well. I didn’t see how that could be, as custom domains for click/open tracking usually require a CNAME, and there was no mention of any CNAME records to add. When I sent a test email, it confirmed my suspicions, as there were no links to my custom domain for verification. So I proceeded to setup a custom link-tracking domain. Strangely, the open/click-tracking domain needed to be unique from the previous domain I setup with them. Once I set that up, a second test confirmed it was working for open-tracking.
Emails sent through SendGrid seem to be very quick, at least on par with Postmark, which is saying something. However, their activity logs are a bit lacking. In my testing, the logs were a bit slow to update, but that’s not a huge issue. On the positive side, there is nothing to click on, even though the cursor makes it appear you should. Instead, there is a little information icon for each log entry that displays the delivery status when you hover over it. On the other side, the logs don’t contain message subjects. So if you send multiple emails to a customer, it will be difficult to tell which specific email is being referenced. The graphs on the dashboard also lag behind a day. Perhaps they are trying to conserve resources, but every other platform I tested has real-time graphs available.
I ended up having a small issue where I emailed support for assistance in resolving. This time, it took about 4 business hours to receive a response. Fortunately, it turned out I had a typo in my code, so that was an easy fix. One thing I’m not particularly pleased with is that their servers convert plain text emails to HTML. That by itself wouldn’t be a problem, but the line breaks do not appear to convert properly.
I kept a close eye on the delivery rate for SendGrid, because I had already seen SORBS listings in the spam headers. Most providers shouldn’t block (solely) on a SORBS listing. However, I noticed later that spamcop.net had blacklisted one of the two IP addresses sending my messages as well. Sure enough, within the first 24 hours, I saw my first block. That’s one block too many in such a short period of time. With the line break conversion issues, the blocked email, multiple blacklists, and the fact that the activity log was very limited in detail, I was done with SendGrid.
Mandrill is easily the most expensive transactional email service in my tests. You can only use Mandrill if you are a MailChimp user, so I was a bit surprised that they did not have a bundling discount. The email credits come in blocks, the cheapest being 25,000 emails for $20. Additionally, the credits expire at the end of the month. Fortunately, they give you 2,000 credits to test things out, so that’s what I’ll be using. They do impose an hourly limit of 25 emails, lower than any other I’ve seen. Hopefully that doesn’t become a problem. With paid accounts, the hourly limit adjusts automatically depending on your reputation and usage patterns.
This is getting to be old hat by this time. The interface for adding domains was pretty clear, although they didn’t pre-populate the domain name like some others did. I ran into a small snag, which is that you must have an email address under whatever domain you choose. So unlike others that recommend you use a separate sub-domain, that wasn’t really an option. That is, unless you want to go through the bother of setting up a brand new email address and MX records just for domain verification… The open/click-tracking domains have their own menu item, and setup was as quick as adding a CNAME record. It took less than 5 minutes to have my domains setup and verified.
While Mandrill doesn’t have the sleek walk through like SendGrid, their documentation was easy to follow, and I had my PHP function setup in no time. The instructions included steps for folks on either side of the fence with Composer, which is always nice to see. The only oddity I’ve noticed is that the “from name” is missing from some of my system notices. Not that I care whether the email says “Cron Daemon” or not, but it leaves me wondering “why?” It took 4 business days to receive a first response from support, but they finally discovered the reason. Normally, a “From” header looks like “Sender <firstname.lastname@example.org>”, but the cron daemon is sending it like “email@example.com (Sender)”. Not a huge issue, and I don’t imagine it affects “normal” usage of Mandrill.
You do need to be sure that you have added all domains that you use to send email. Most of the other services have a fall-back feature if the sending domain doesn’t match a verified domain. Instead, Mandrill will simply reject any attempts to send using an unverified domain. This is further confirmation that using sub-domains with Mandrill is a bad idea. For example, say you setup a sub-domain for sending like mandrill.example.com, but you are sending your emails from firstname.lastname@example.org. Mandrill will reject those emails, since the domain portion doesn’t match exactly. The reverse is also true: if you validate example.com and try to send email from email@example.com, they will also reject the message.
Mandrill’s activity log is definitely more streamlined than Postmark, and includes the ability to see the message contents too. Mandrill doesn’t include the ability to view the original raw message (headers and all). However, it does have a Resend button, which is something I haven’t seen anywhere else. It also includes a graph above the logs to visualize your sending data better. While pretty much all of these transactional email providers have graphs, most are on a separate page.
Mailjet has a free plan with 6,000 transactional emails month. I’m not sure if that will be enough, but their next plan is still very reasonable at $7.49 for 30k emails. Signup was quick and simple, but this was another case where the signup email ended up in spam. Similar to SendGrid, the message structure caused the issue and not the server setup.
Setup with Mailjet
Mailjet’s domain verification uses a little different process. Instead of the usual DNS verification, they use a text file on your website to verify ownership. This may present a small problem for some folks who use a domain for email that does not have a website setup. The process doesn’t require DKIM/SPF setup, but it was easy enough to setup through the domain management page afterwards.
The management interface contained code examples with a link to the PHP library on GitHub. The GitHub page included a link to a separate repository for non-Composer integration. The main page for the alternate repository gave plenty of example code, and I sent a test email in short order. Once I sent the test email, I discovered a perk unique to Mailjet’s transactional service. Anytime they auto-validate a new address on one of your custom domains, Mailjet sends you an email notification. This could be handy to prevent misuse of API credentials.
Does Mailjet Deliver?
While the “real-time email stats” aren’t exactly real-time, email delivery seems to be pretty quick. Within the first hour, one message said “Sent” but not “Delivered”. I clicked on the message for more detail to see what was going on. The message detail page claims that they delivered the message, but the activity log does not update. Contacting support reveals that the message is still in the queue as it had encountered a problem on the receiving end. They said that there is a bug with the message details screen, but the activity log is accurate.
Mail headers indicate that the SORBS blacklist contains several of Mailjet’s servers, so I kept a close eye on the logs. Unfortunately, the activity log only lets you see the last 50 messages. The log has toggles for “Last 24H”, Today, Yesterday, and Last Month, but they don’t work. No matter what I do, I cannot go back to check the status of that delayed message. Their message detail page is also lacking something any useful detail whatsoever. If the destination server bounces a message, there is no indication of why.
Within 24 hours, the logs showed one message stuck in the queue and another with a status of “bounced”. I sent a message to the bounce recipient to see if it was an invalid address, but the customer responded just fine. Since the log just says “bounced”, I had to contact Mailjet support for more detail. Apparently, Mailjet has the information I need, and I can access it via their API. So, why don’t they make that information easy to see? I still don’t know why they can’t process the “stuck” message either, so with that, we say adieu to Mailjet…
When MailChimp converted Mandrill into a (much more expensive) paid add-on, SparkPost stepped in to try and fill the gap. No one else I looked at has a more generous starter plan. Their free plan comes with 100,000 emails each month. If you need the next plan with 150k/month, I’m sure you can afford $29.
Off to the Races
SparkPost wastes no time in getting things rolling. As soon as you signup, they walk you through domain verification. SparkPost also continues the trend of abnormal verification. Instead of DNS verification, they use your postmaster or abuse email addresses. This can be tricky, because it requires that you actually have a postmaster or abuse address configured. Once you choose which email to use for domain verification, they jump right into sending email. SparkPost provides you with SMTP credentials as well as an API example using Curl. You can copy the Curl example as-is since it includes your API key and email address for testing.
After you click the domain verification link from your email, you can setup DKIM/SPF just like any other transactional email provider.
Sending Email, Maybe
I began to setup my PHP integration, but that is where I hit a snag. SMTP is easy enough following the instructions from SendGrid, but I could not find non-Composer instructions for PHP anywhere. They use Slack instead of a forum for asking development and integration questions, so that is handy. One of their developers is looking into what it will take to use SparkPost without Composer, so I’ll update this when I find out more.
Making the Call
In my search for a reliable transactional email platform, three candidates have made it through to the end without any emails blocked: SendInBlue, Postmark, and Mandrill. However, as I mentioned earlier, SendInBlue has too many red flags for me to trust them with my business. I could look beyond their apparent focus on marketing emails. However, the outdated documentation links, the sluggish email delivery, and the unwanted branding are just too much. I could get rid of the branding issue for $39/month, but that’s a high premium to pay for my usage.
Postmark and Mandrill both provide a reliable transactional email product. They both have nice activity logs with the ability to view message content. Postmark allows re-activation of banned emails right from the logs, whereas Mandrill lets you resend from the logs. It would almost be a toss up between the two, if it weren’t for the pricing. The big factor is that Mandrill requires a paid MailChimp account, which starts at $10/month. If you compare their pricing for 25,000 emails, Mandrill comes out on top. But I’m not sending that much yet, so I can save money with Postmark. Additionally, I received 75,000 credits to use for my transactional emails. So I can use Postmark with no cost for several months. I might come back around to Mandrill at some point, but for now my business is with Postmark.
If you’re sending less than 20,000 emails a month, Postmark is your best option for transactional email. The other bonus to Postmark’s pricing is that credits don’t expire. This allows you to buy a year’s worth of credits to get lower rates. Generally though, if you go over 20,000 emails per month, Mandrill is going to be the cheaper option. Since they both offer reliable service, I can’t find anything besides price to make the call between the two. Choose whichever fits your budget, and you’ll be in good hands. You’ll also be glad you read this instead of an article on dirt…
Shameless plug here, if you want to see transactional email in action, sign-up for our image optimization service. We’ll send you a bunch, but hopefully not too many! Disclaimer: clicking any MailChimp link gets you (and me) $30 in account credit, but that credit is no good for Mandrill. Weird, but that’s the way it is. Just to be clear, getting MailChimp credit has nothing to do with my opinion of Mandrill. I totally forgot about an affiliate link until I had nearly finished writing this post. You can go straight to mailchimp.com or mandrill.com and ignore my links if you like.