Django
A custom email backend, so send_mail and every EmailMessage in the project goes through emails.sh.
Django routes all mail through EMAIL_BACKEND, including password resets and admin errors. Write one backend and everything in the project, including code you have not read, sends through emails.sh.
The key
# .env, loaded with django-environ or python-dotenv.
# The key comes from https://emails.sh/dashboard/api-keys.
EMAILSSH_API_KEY=esh_your_key_hereThe backend
# acme/email_backend.py
import json
import urllib.error
import urllib.request
from django.conf import settings
from django.core.mail.backends.base import BaseEmailBackend
ENDPOINT = "https://emails.sh/v1/emails"
class EmailsshBackend(BaseEmailBackend):
"""Send Django's EmailMessage objects through the emails.sh API."""
def send_messages(self, email_messages):
sent = 0
for message in email_messages:
payload = {
"from": message.from_email or settings.DEFAULT_FROM_EMAIL,
"to": list(message.to),
"subject": message.subject,
"text": message.body,
}
if message.cc:
payload["cc"] = list(message.cc)
if message.bcc:
payload["bcc"] = list(message.bcc)
if message.reply_to:
payload["reply_to"] = message.reply_to[0]
# EmailMultiAlternatives puts the HTML part here.
for content, mimetype in getattr(message, "alternatives", []):
if mimetype == "text/html":
payload["html"] = content
request = urllib.request.Request(
ENDPOINT,
data=json.dumps(payload).encode(),
headers={
"Authorization": f"Bearer {settings.EMAILSSH_API_KEY}",
"Content-Type": "application/json",
},
method="POST",
)
try:
with urllib.request.urlopen(request, timeout=10):
sent += 1
except urllib.error.HTTPError as err:
refusal = json.loads(err.read())["error"]
if not self.fail_silently:
raise RuntimeError(
f"emails.sh refused the send: {refusal['code']}: "
f"{refusal['message']} {refusal.get('next', '')}"
) from err
return sent# settings.py
import os
EMAIL_BACKEND = "acme.email_backend.EmailsshBackend"
EMAILSSH_API_KEY = os.environ["EMAILSSH_API_KEY"]
DEFAULT_FROM_EMAIL = "Acme <hello@acme.com>"Use it
from django.core.mail import EmailMultiAlternatives
from django.template.loader import render_to_string
def send_welcome(user):
html = render_to_string("email/welcome.html", {"user": user})
message = EmailMultiAlternatives(
subject="Welcome to Acme",
body="Confirm your address to finish signing up.",
to=[user.email],
)
message.attach_alternative(html, "text/html")
message.send()