MailKite
Get your API key
All guides Sending email

Send email with Mailgun

Transactional email is the mail your app sends one recipient at a time — receipts, password resets, magic links, notifications. This guide sends one through Mailgun, over both the API and SMTP, then shows the same send on MailKite.

What you'll need

  • A domain you control, with access to its DNS records.
  • An API key from your Mailgun account (and, for SMTP, the domain's SMTP password).

Part 1 — Send with Mailgun

1. Authenticate your domain

So your mail passes authentication and lands in the inbox, add your sending domain in Sending → Domains and publish the records Mailgun lists — an SPF include, a DKIM key, and the tracking CNAME:

DNS — yourdomain.com
Type    Name                          Value
TXT yourdomain.com v=spf1 include:mailgun.org ~all
TXT smtp._domainkey.yourdomain.com k=rsa; p=… (DKIM key shown in your dashboard)
CNAME email.yourdomain.com mailgun.org

Mailgun shows the exact DKIM record name and value in the domain's Domain Verification & DNS panel — copy them from there.

2. Send over the API

POST to /v3/<yourdomain>/messages with HTTP Basic auth — the username is the literal api, the password is your API key. Fields are form-encoded, and the from address must be on the domain you just authenticated:

send
curl -X POST https://api.mailgun.net/v3/yourdomain.com/messages \
--user "api:$MAILGUN_API_KEY" \
-F from="MyApp <hello@yourdomain.com>" \
-F to="ada@example.com" \
-F subject="Your invoice #1042" \
-F html="<p>Thanks! Your receipt is attached.</p>"
response
200 OK
{
"id": "<20240115174239.25659.5817@yourdomain.com>",
"message": "Queued. Thank you."
}

If your account is in Mailgun's EU region, send to api.eu.mailgun.net instead of api.mailgun.net.

3. Or send over SMTP

Prefer SMTP? Point your app at Mailgun's relay. The password here is the domain's SMTP password, not the API key:

smtp
Host:      smtp.mailgun.org
Port: 587 # STARTTLS
Username: postmaster@yourdomain.com # or an SMTP user you create
Password: (the domain's SMTP password)
From: hello@yourdomain.com

That's a transactional send on Mailgun: authenticate the domain, then call the API or the SMTP relay.

Part 2 — The same, on MailKite

When we built sending into MailKite, we wanted three things to be true: one set of DNS records, one API key that works for both HTTP and SMTP, and a body you don't have to nest. Here's the same message.

1. Authenticate your domain

Publish three TXT records — SPF, a MailKite DKIM key, and DMARC. The same domain also receives mail once its MX points at MailKite:

DNS — yourdomain.com
Type   Name                              Value
TXT yourdomain.com v=spf1 include:mailkite.dev ~all
TXT mailkite._domainkey.yourdomain.com v=DKIM1; k=rsa; p=…
TXT _dmarc.yourdomain.com v=DMARC1; p=none;

The exact DKIM value is shown in the dashboard; MailKite verifies the records for you over DNS.

2. Send over the API

One POST /v1/send with a flat from/to/ subject/html body. A 202 means it's queued:

Pick your language in the card — the dashboard and the AI assistant do the same send, and every SDK takes the same fields:

send
import { MailKite } from "mailkite";

const mk = new MailKite(process.env.MAILKITE_API_KEY);

const { id, status } = await mk.send({
from: "hello@myapp.ai",
to: "ada@example.com",
subject: "Your invoice #1042",
html: "<p>Thanks! Receipt attached.</p>",
});
Install Docs →
response
202 Accepted
{ "id": "msg_2Hk9…", "status": "queued" }

3. Or send over SMTP

The same key is your SMTP password — no separate credential to generate:

smtp
import nodemailer from "nodemailer";

const tx = nodemailer.createTransport({
host: "smtp.mailkite.dev",
port: 587, // STARTTLS · use 465 for implicit TLS
auth: {
user: "mailkite", // any username works
pass: process.env.MAILKITE_API_KEY, // your mk_live_… key
},
});

await tx.sendMail({
from: "hello@myapp.ai", // an address on a verified domain
to: "ada@example.com",
subject: "Your invoice #1042",
html: "<p>Thanks! Receipt attached.</p>",
});

See Send API and SMTP relay for the full reference — attachments, headers, and delivery events.

A little about MailKite

MailKite is programmable email for developers and AI agents. One API key and one set of DNS records cover both directions: send with a single POST (or the SMTP relay), and the same verified domain receives replies as a signed webhook of clean JSON. Behind the send, MailKite routes across multiple providers to keep you in the inbox — and any address can be handed to an agent that reads and replies on its own. Sending and receiving are on the free tier.

Next: the Send API for attachments and delivery tracking, or the Quickstart to get a verified domain and API key.