Skip to content

Sending Emails via External APIs

In addition to the built-in mailer utility, SØAD can integrate with third-party email providers such as Mailgun, SendGrid, or Amazon SES. These services provide reliable delivery and advanced features beyond simple SMTP.

The following recipe demonstrates how to send email through the SendGrid API using a Jetty HttpClient (implemented as a singleton). The same approach can be applied to other REST-based providers by adjusting the endpoint, authentication, and parameters.


mail_sender.py
from utils import render, Log
from org.eclipse.jetty.client import HttpClient, WWWAuthenticationProtocolHandler
from org.eclipse.jetty.client import StringRequestContent
from java.util.concurrent.locks import ReentrantLock
from java.util.function import Consumer

import json

# this class is shared across transactions
class HttpClientProvider:
    _client = None
    _lock = ReentrantLock()

    def get_client(self):
        # Double-checked locking to be safe under concurrency
        if self._client is None:
            self._lock.lock()
            try:
                if self._client is None:
                    client = HttpClient()
                    client.start()
                    # Disable default auth handler - if you have auth issue with mail API
                    client.getProtocolHandlers().remove(WWWAuthenticationProtocolHandler.NAME)
                    self._client = client
            finally:
                self._lock.unlock()
        return self._client

class HeadersConsumer(Consumer):
    def accept(self, fields):
        # Prefer env var or secure config for API key
        api_key = System.getenv("MAIL_API_KEY")
        fields.add("Authorization", "Bearer " + api_key)
        fields.add("Content-Type", "application/json")

class Mail_sender(object):
    def send(self, ctx):
        api_url = "https://api.sendgrid.com/v3/mail/send"
        fr = "[email protected]"
        to = "[email protected]"
        subject = "Test Email"
        content = "Hello, this is a test email."

        try:
            client = HttpClientProvider.get_client()
            client_request = client.POST(api_url)

            client_request.headers(HeadersConsumer())
            mail_data = {
                "personalizations": [{"to": [{"email": to}]}],
                "from": {"email": fr},
                "subject": subject,
                "content": [
                    {
                        "type": "text/plain",
                        "value": content
                    }
                ]
            }
            body = json.dumps(mail_data)
            client_request.body(StringRequestContent("application/json", body))
            client_response = client_request.send()
            Log.info(ctx, "Mail API response: %s" % client_response.getContentAsString())
        except Exception as e:
            Log.error(ctx, "Mail API error: %s" % str(e))