Skip to content

How to Send Transactional Email from a Quake AI Workload

How-to · Updated Jun 2026

Coming from another cloud?

▸AWS·SES

This Quake AI feature maps to AWS’s SES.

Before this

How to send transactional email from a Quake AI workload

Send password resets, receipts, and other per-user transactional email from an application running on a Quake AI instance by relaying through a third-party email provider over an authenticated submission port.

Before you start#

This procedure assumes you have:

  • An application running on a Quake AI instance that needs to send email.
  • A domain you control, with access to edit its DNS records at your registrar or DNS host.
  • An account with one of the email providers compared below.

The application sends outbound connections only; it does not receive inbound mail. For inbound delivery, point your domain's MX records at your provider and follow the provider's inbound routing documentation.

Pick an email provider#

Each provider exposes an authenticated SMTP submission endpoint and an HTTP API. The SMTP path works the same from any language, so this page uses it as the common shape. Pick based on the workload:

ProviderWhen to choose it
PostmarkTransactional mail only, with separate message streams that stop transactional and broadcast traffic from sharing a sending reputation.
SendGridTransactional and marketing mail through one account, with event webhooks and per-message analytics.
MailgunDeveloper-focused service with inbound routing, address validation, and message tagging for analytics.
AWS SESLow-level sending service that fits workloads already integrated with AWS; new accounts start in a sandbox that limits sending to verified addresses until you request production access.

The steps below apply to any of the four. Where the provider-side setup diverges, the per-provider tabs call out the difference.

Step 1. Create a sending credential at your provider#

Create an SMTP credential (a username and password pair) in the provider console, then record the submission host and port. Treat the credential as a secret from the moment you create it.

  1. In the Postmark console, open your server and select API Tokens.
  2. Copy the Server API Token. Postmark uses this token as both the SMTP username and the SMTP password.
  3. Note the submission endpoint: host smtp.postmarkapp.com, port 587.

The submission endpoints share a common shape:

ProviderSubmission hostPortSMTP username
Postmarksmtp.postmarkapp.com587the Server API Token
SendGridsmtp.sendgrid.net587apikey
Mailgunsmtp.mailgun.org587postmaster@YOUR_SENDING_DOMAIN
AWS SESemail-smtp.YOUR_REGION.amazonaws.com587the SES SMTP username

Port 587 uses STARTTLS to upgrade the connection to TLS. Port 465 carries TLS from the first byte. Both are authenticated submission ports. Use 587 unless your client library only supports implicit TLS, in which case use 465.

Step 2. Store the credential as an application secret#

Keep the SMTP username and password out of your source tree and out of your instance image. Inject them at runtime as environment variables, or read them from a secrets manager your application already uses.

bash
# Set on the instance or in your deployment pipeline, not in source control.
export SMTP_HOST="smtp.postmarkapp.com"
export SMTP_PORT="587"
export SMTP_USERNAME="YOUR_SMTP_USERNAME"
export SMTP_PASSWORD="YOUR_SMTP_PASSWORD"

Step 3. Allow outbound submission traffic#

By default, a Quake AI security group permits the outbound traffic your instance needs to reach the provider. If you have tightened egress rules, add an egress rule that allows TCP to the submission port your provider uses (587 or 465).

bash
openstack security group rule create \
  --egress --protocol tcp --dst-port 587 \
  --remote-ip 0.0.0.0/0 \
  YOUR_SECURITY_GROUP

For the Console procedure and the full set of options, see Create security group rules. Confirm that no rule on your instance blocks outbound port 587 or 465 before you move on.

Step 4. Configure your application or mail server to relay#

Point your application at the submission endpoint using the credential from Step 2. Configure it at the application layer if your code sends mail directly, or at the system layer if your services hand mail to a local mail server such as Postfix.

Most SMTP client libraries accept the host, port, username, and password directly. This example uses Python's standard library:

Python
import os
import smtplib
from email.message import EmailMessage

message = EmailMessage()
message["From"] = "[email protected]"
message["To"] = "[email protected]"
message["Subject"] = "Your receipt"
message.set_content("Thanks for your order.")

with smtplib.SMTP(os.environ["SMTP_HOST"], int(os.environ["SMTP_PORT"])) as smtp:
    smtp.starttls()
    smtp.login(os.environ["SMTP_USERNAME"], os.environ["SMTP_PASSWORD"])
    smtp.send_message(message)

Step 5. Authenticate your sending domain in DNS#

Mailbox providers check three DNS records to decide whether to accept your mail. Add them at the DNS host for your sending domain. Your email provider generates the exact values; the records below show the shape.

  • SPF authorizes the provider to send for your domain. Publish one TXT record at the domain root that includes the provider's SPF host:
example.com.  IN  TXT  "v=spf1 include:PROVIDER_SPF_HOST -all"
  • DKIM signs each message so the receiver can verify it was not altered. Your provider gives you one or more CNAME or TXT records to publish under a selector subdomain:
SELECTOR._domainkey.example.com.  IN  CNAME  SELECTOR.dkim.PROVIDER_DOMAIN.
  • DMARC tells receivers what to do when SPF or DKIM fails and where to send reports. Start with a monitoring policy, then tighten to quarantine or reject once your reports are clean:
_dmarc.example.com.  IN  TXT  "v=DMARC1; p=none; rua=mailto:[email protected]"

After you publish the records, verify them in your provider's domain settings. Each provider shows a verified status once the records resolve. DNS changes take effect after the record's TTL elapses.

Authentication records get your mail accepted; sender behavior keeps it out of the spam folder. Work through this list before you send to real recipients at volume:

  • Use a subdomain for application mail, for example mail.example.com, so transactional sending does not affect the reputation of your primary domain.
  • Set a reply-to address that a person reads, even when the From address is [email protected].
  • Warm up new sending volume gradually. A new domain that sends thousands of messages on day one looks like a spam source. Ramp volume over the first weeks.
  • Honor unsubscribe and bounce signals. Stop sending to addresses that hard-bounce or mark you as spam. Most providers expose these as suppression lists and webhooks.
  • Separate transactional and marketing streams. Keep receipts and password resets on a different stream or subdomain from bulk campaigns so one does not damage the other's reputation.
  • Set a PTR record where you send from your own IP. This applies to the support-ticket path on the SMTP from your VM page, not to provider relay, where the provider owns the sending IP.
  • Monitor provider reports. Track bounce, complaint, and delivery rates in the provider dashboard and act on spikes.

Step 6. Send a test message and verify delivery#

Send one message to an address you control, then confirm it arrived and authenticated correctly.

bash
# Quick check with swaks, an SMTP test client.
swaks --to [email protected] \
  --from [email protected] \
  --server "$SMTP_HOST:$SMTP_PORT" \
  --auth-user "$SMTP_USERNAME" \
  --auth-password "$SMTP_PASSWORD" \
  --tls

A successful run ends with a 250 response code from the provider. In the received message, view the original headers and confirm that SPF, DKIM, and DMARC each show a pass result. Your provider's dashboard also records the message as delivered.

Networking and floating IPs#

This pattern allocates zero floating IPs. The workload makes outbound connections only, to the provider's submission endpoint. An instance on a private network reaches the internet through its router's external gateway using source NAT, which covers outbound submission traffic without a floating IP. Allocate a floating IP only if a separate part of your application needs inbound reachability; sending transactional email does not.

See also#

Usage Guidelines

The sample code, software libraries, command line tools, proofs of concept, templates, and other related technology on this page (including any of the foregoing that is provided by Quake AI personnel) is provided to you as Quake AI Content under the Quake AI Customer Agreement, or the relevant written agreement between you and Quake AI (whichever applies). Do not use this Quake AI Content in your production accounts, or on production or other critical data. You are responsible for testing, securing, and optimizing the Quake AI Content (such as sample code) as appropriate for production grade use based on your specific quality control practices and standards. Deploying Quake AI Content may incur Quake AI charges for creating or using Quake AI chargeable resources, such as running Compute instances or storing data in Object Storage. Your use is also subject to the Acceptable Use Policy.

For the full policy, see Usage Guidelines.

Last validated: 27.06.2026

Was this page helpful?