I recently had to add password-reset emails to my project npoint.io. In case you haven’t heard, creating HTML emails is a huge mess.
Think back to 1999, when we called ourselves “webmasters” and used Frontpage, WYSIWYG editors and tables to mark up our websites.
Not much has changed in email design. In fact, it has gotten worse. With the introduction of mobile devices and more and more email clients, we have even more caveats to deal with when building HTML email.
Here’s my research on the best/quickest way to set up emails for a side project or as a solo developer.
(TL;DR: I went with SendGrid)
Sending emails in two steps
There are two challenges in setting up an automated email:
- Creating an email template
- Sending the email
Since I was using Rails, my default option was using Rails mailers. I could create a template using a high-level language (MJML or ZURB Foundation) or a service like Bee Free that spits out HTML. There’s also Litmus for cross-platform testing, though that was out of my budget as an indie developer.
I was ready to go with ZURB Foundation (templates) + Sparkpost (delivery), until I realized there was an easier way.
Sending emails in one step
There are services that combine (1) and (2). You create a template using their template builder, then send them an API request to actually send an email.
This is faster to set up, and doesn’t require a deploy to change what an email looks like. Ideally, the template editor should also take care of cross-platform issues without you even thinking about it.
I think SendGrid is the best option for a small project. They have a WYSIWYG template editor which is (barely) good enough for simple emails, and their free tier goes up to 10,000 emails a day.
Setting up my template in SendGrid was a solid 4⁄5 star experience:
And my app code looks roughly like this: (real code here)
def self.reset_password(user) mail = SendGrid::Mail.new mail.from = SendGrid::Email.new( email: 'n:point <firstname.lastname@example.org>' ) personalization = SendGrid::Personalization.new personalization.add_to( SendGrid::Email.new(email: user.email) ) personalization.add_substitution( SendGrid::Substitution.new( key: '%name%', value: user.name ) ) mail.add_personalization(personalization) mail.template_id = 'bdf0a64b-087d-4c5f-a955' sg = SendGrid::API.new(api_key: ENV['SENDGRID_API_KEY']) response = sg.client.mail._('send') .post(request_body: mail.to_json) end
I don’t like getting emails from
email@example.com. I like getting
firstname.lastname@example.org, which I can reply to directly.
Setting that up was pretty easy:
Inbound emails (Using Namecheap)
- Namecheap guide
- Add a simple alias (forward
support@to my personal gmail)
- Add a catch-all (forward everything else to my personal gmail, too)
A caveat that bit me for a while: Namecheap might not forward inbound emails if they’re from the same email account as they’re being forwarded to. At least I was able to use my old hotmail account for something other than receiving spam.
Outbound manual emails (Using Gmail)
- Add a send-from address in Gmail settings
- Uncheck “treat as alias”
- Your username is your sendgrid username; your password is your SendGrid API key.
Emails look passable:
Bonus: SendGrid is totally happy to send emails in dev mode too. I found this to be a feature because it was really easy to test my reset-password flow locally.
Posted on April 5, 2018