email-sender
A service to send email messages.
Features
- Multiple email service integrations that can be easily switched;
- Send custom emails or transactionals with POST requests;
- Transactional messages from jinja2 templates
- Requests must be authenticated with the x-api-key header;
- Request body validation with pydantic;
- Auto-generated API docs with fastapi
- Task queue for asyncronous processing of email requests with celery;
Architecture
Resources (all on free tiers)
- Heroku for automated deployment;
- Mailjet as an email service alternative (default);
- Sendgrid as another email service alternative;
- Sentry for error tracking;
- Travis-CI for automated testing;
- RabbitMQ on CloudAMQP as broker for task queue;
Development
Requirements
Installing
Install dependencies
make install
Testing
make test
Running
make run
Access the API documentation on http://localhost:8000/docs and use the default API_KEY
to authenticate (check it on Settings
class).
You can run the app and test its API as is, but no emails will be sent. To do so, you'll have to set up an email service.
Transactional messages make it easier to trigger events from other services, try including a new Transactional based on your needs.
Setting up an email service
The email service can be chosen by setting the EMAIL_SERVICE
environment variable to one of the values available on EmailService
enum ("mailjet" by default).
After choosing which service to use you'll need to:
- Sign up on its platform;
- Verify your email address as an authorized sender;
- Generate and set the API key as environment variable (check
Settings
class for naming references);
The verified email address must be used either as the from
attribute on requests or as the DEFAULT_EMAIL_ADDRESS
environment variable.
If the available services do not suffice, you can add a new email service integration.
Adding an email service integration
There are many email services available out there that you can choose from. If this project does not yet integrate with it, you can do so by:
- Creating a
YourEmailServiceAdapter
class that extendsBaseAdapter
and implements itssend
method; - Adding a value to
EmailService
enum corresponding to your new service; - Mapping your new service on the
ADAPTERS
dictionary, so it can be chosen from by theEMAIL_SERVICE
environment variable;
Including a new Transactional
You should be able to include a new Transactional message type by:
- Adding a jinja2 flavored template file to the
/templates
folder; - Mapping it as a new value on the
Transactional
enum including itstype
, that should uniquely identify the transactional, and itstemplate
file name;
Now your new Transactional can be triggered from the API by specifying its identifier and passing the data it needs to render.
Deployment
Heroku
The app.json
, Procfile
, and runtime.txt
files on this repository are specific for deployment on Heroku. It can be done by clicking the following button: