In this note we discuss how to configure a Django application running on App Engine Standard – or in any other deployment environment which doesn’t offer a default email server. (If you’re just getting started with Django on App Engine see also the general introduction here .)
Email and App Engine Standard
The original (“first generation”) Python App Engine runtime launched back in 2008 had a built-in, App Engine-specific API for sending emails. However, the current generation of App Engine Standard runtimes (including the Python 3.7 runtime), goes away from any App Engine-specific APIs, instead offering a genric, unopinionated hosting service (You write a standard Python app, not an App Engine Python app. ).
This means that there is no built-in email API, but as we will see in this note, we can easily set up the email functionality using a third-party email service provider.
Picking a third-party provider
The official docs note a few third-party mailing providers that can be used to send emails from App Engine:
Personally I’ve had good experience with Mailjet, which I picked because of their free tier of 200 emails per day unlimited in time (which is less than my personal project needs, so it’s essentially a free service) and because like me they’re based in Paris – so it almost feels like giving a shout-out to a local bakery 🥖.
Sign up and configure Mailjet
After signing up for Mailjet, we can configure the domain for the outgoing email that our app willl be sending – we can we add the domain under Sender domains & addresses .
Then, we need to configure domain authentication, so that Mailjet can prove to the computer systems on the receiving end that our application is legitimately authorized to send emails on behalf of the domain owner. This is achieved via two mechanisms: SPF and DKIM.
Both SPF and DKIM need to be configured in DNS records which we can set using our domain provider, according to guidance displayed in the Sending Domain Authentication interface of Mailjet.
- Sender Policy Framework (SPF) allows the domain owner to configure which servers are allowed to send emails on behalf of the domain
- DomainKeys Identified Mail (DKIM) allows Mailjet to sign each outgoing message with a private key. The corresponding public key is set in the DNS record, so that each receiver can validate the signature
django-anymail
If the application is using the regular Django APIs for mailing , actually integrating the email provider in the app is the easiest part, esp. with django-anymail – a library which can neatly bridge the Django mailing API to transparently use any of the most common email service providers, including Mailjet.
pip install django-anymail
After adding the dependency, we only need to add a few settings:
if os.getenv('GAE_APPLICATION', None):
EMAIL_BACKEND = "anymail.backends.mailjet.EmailBackend"
ANYMAIL = {
"MAILJET_API_KEY": os.getenv('MYAPP_MAILJET_API_KEY'),
"MAILJET_SECRET_KEY": os.getenv('MYAPP_MAILJET_API_SECRET'),
}
else:
EMAIL_BACKEND = 'django.core.mail.backends.filebased.EmailBackend'
EMAIL_FILE_PATH = '/tmp/django-emails'
DEFAULT_FROM_EMAIL = '<email in the domain of the app>'
In the snippet above, we configure the emails to be written to /tmp/django-email
for local development (when not running on App Engine).
Conclusion
And that’s it, outgoing email should “just work”!