Anatomy of an email notification setup
How to setup and email notification system for your application with basic considerations for templates with dynamic data and running the application in development, staging and production environments.
Email notifications are an integral part of any application. Whether it is about informing users of some required actions, or be it an acknowledgement to some of the actions that they performed in the application, emails are used to keep user engaged and informed about what they could expect next. And when I say emails, I do not mean those mass marketing emails, but the specific user targeted transactional emails that every application needs, to keep users posted about their user journey in the application. For an e-commerce platform, this could mean sending emails like order confirmation, product delivery status, etc.
On the surface level this might look like a trivial task, however there are many factors to consider to be able to build something generic that could be used for all your transactional email needs from the different parts of your application. Some of the very basic things that we would need to consider are:
- Email templates – We would want to create generic dynamic templates with placeholders, that could be used to send out similar emails to different users, just by passing the right data.
- Reply-to address – We would want to have different categories of
reply-to
addresses for our emails. It's useful for logical grouping so that we can generate automated responses and take appropriate actions when the user replies to those emails. Eg:
We may have some emails that users should never reply to and hence ano-reply@my-e-commerce.com
. While on the other hand say for all payment related emails we may have apayments@my-e-commerce.com
as the reply-to email address, so that we can have an automated ticketing system when someone replies to those email addresses. And it doesn't end there, we can even have a totally dynamic address generated for specific user actions so that a reply can be redirected to specific actions in the application, e.g. replying to email for a message notification, could actually send a message response to the sender. - Testing email delivery – Now to test out the application features and user flow on a staging or development environment, we would like the application to behave normally and send out email notifications like it usually does in the normal production environment. However the big catch is, we wouldn't want the emails to get to the inbox of our actual users. We would like all the emails from a non-production environment to get redirected to an internal shared test email group where we could see those emails. And while working locally with the application or during an automated test run, triggering those emails should just validate the signature and get redirected to some kind of a sandbox in order to not spam the shared email group.
The list is not exhaustive and depending upon your application needs, there might be some additional considerations that you would need to make. Nonetheless, the above points are crucial and in my opinion the bare minimum to any email notification service. Though there are a numerous ways to implement these points in your application, I'd show a setup with the use of a third party email service provider, SendGrid and a bit of code, to give you an idea which you can use to build upon. The same concept could be applied if we are using any other similar third party email service provider. However, in case we are using our own mail servers to deliver emails, it's a whole different implementation story that demands an article on its own.
Email templates and Reply-to address
For the dynamic email templates, SendGrid provides the option for creating transactional email templates using their web tools (or even APIs if you prefer that) and have placeholders within those templates, exactly what we needed. Once you have created a template, you get a unique template-id
which you can later use to send the email using their APIs/SDKs. However those ids are like how ids should be, non-human-readable, and so it's a pain to manually use them in our code, each time we need to invoke those email templates. Furthermore, as we mentioned earlier, we would like to have specific reply-to addresses attached to specific category of emails, as, manually setting those with each API call, doesn't make much of sense. And so we would create named templates with defaults, that we can use from all parts of our code.
We can create multiple such templates as per our needs and add them to the templates folder. Then create the index.js
file exporting all our templates.
Testing email delivery
Now this is the most important bit, where the magic happens. We would implement our wrapper sendEmail
function that we mentioned earlier. The function would internally use the third party email service APIs/SDKs to deliver the email. It would check the deployment environment during runtime to determine whether to redirect the email or to let the information flow through as is. Let me show the code and highlight the points with the help of code comments.
So finally, we have the setup that we need, with all the basic ingredients to get us going.
I hope by now you got a concrete idea about what it takes to build an email service that could be used throughout the different parts of your application, in a scalable and error-free manner. Building and maintaining our own mail servers to send out emails, is a whole different topic which I would leave out for a future article.
If you happen to run into issues or spot any mistakes with this article, please feel free to comment and I'd try my best to help you out / correct the mistakes.