Email for every product you ship.
Receive any message as a webhook, send with
one API — across
unlimited domains and mailboxes, free.
No mail server, no MX/SPF/DKIM/DMARC to rebuild for every launch.
A transactional email API for your stack
Send and receive from your app in a few lines — Next.js, Nuxt, Node, Python, PHP, Go, Ruby, and more. One shape everywhere, plus CLI, REST, SMTP, and IMAP.
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>",
}); import { MailKite } from "mailkite";
const mk = new MailKite(process.env.MAILKITE_API_KEY);
export async function POST() {
const { id, status } = await mk.send({
from: "hello@myapp.ai",
to: "ada@example.com",
subject: "Your invoice #1042",
html: "<p>Thanks! Receipt attached.</p>",
});
return Response.json({ id, status });
} import { MailKite } from "mailkite";
const mk = new MailKite(process.env.MAILKITE_API_KEY);
export async function action() {
const { id, status } = await mk.send({
from: "hello@myapp.ai",
to: "ada@example.com",
subject: "Your invoice #1042",
html: "<p>Thanks! Receipt attached.</p>",
});
return Response.json({ id, status });
} import { MailKite } from "mailkite";
const mk = new MailKite(process.env.MAILKITE_API_KEY);
export default defineEventHandler(async () => {
const { id, status } = await mk.send({
from: "hello@myapp.ai",
to: "ada@example.com",
subject: "Your invoice #1042",
html: "<p>Thanks! Receipt attached.</p>",
});
return { id, status };
}); import express from "express";
import { MailKite } from "mailkite";
const app = express();
const mk = new MailKite(process.env.MAILKITE_API_KEY);
app.post("/send", async (_req, res) => {
const { id, status } = await mk.send({
from: "hello@myapp.ai",
to: "ada@example.com",
subject: "Your invoice #1042",
html: "<p>Thanks! Receipt attached.</p>",
});
res.json({ id, status });
}); import { Hono } from "hono";
import { MailKite } from "mailkite";
const app = new Hono();
app.post("/send", async (c) => {
const mk = new MailKite(c.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>",
});
return c.json({ id, status });
});
export default app; import type { APIRoute } from "astro";
import { MailKite } from "mailkite";
const mk = new MailKite(import.meta.env.MAILKITE_API_KEY);
export const POST: APIRoute = async () => {
const { id, status } = await mk.send({
from: "hello@myapp.ai",
to: "ada@example.com",
subject: "Your invoice #1042",
html: "<p>Thanks! Receipt attached.</p>",
});
return Response.json({ id, status });
}; import { MailKite } from "mailkite";
const mk = new MailKite(Bun.env.MAILKITE_API_KEY);
Bun.serve({
async fetch() {
const { id, status } = await mk.send({
from: "hello@myapp.ai",
to: "ada@example.com",
subject: "Your invoice #1042",
html: "<p>Thanks! Receipt attached.</p>",
});
return Response.json({ id, status });
},
}); // wrangler.jsonc → "compatibility_flags": ["nodejs_compat"]
import { MailKite } from "mailkite";
export default {
async fetch(_req: Request, env: Env) {
const mk = new MailKite(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>",
});
return Response.json({ id, status });
},
}; import { MailKite } from "mailkite";
const mk = new MailKite(process.env.MAILKITE_API_KEY);
// Deploys as a Vercel Function — same code on Netlify or any Node runtime.
export async function POST() {
const { id, status } = await mk.send({
from: "hello@myapp.ai",
to: "ada@example.com",
subject: "Your invoice #1042",
html: "<p>Thanks! Receipt attached.</p>",
});
return Response.json({ id, status });
} import { MailKite } from "mailkite";
const mk = new MailKite(process.env.MAILKITE_API_KEY);
export const handler = async () => {
const { id, status } = await mk.send({
from: "hello@myapp.ai",
to: "ada@example.com",
subject: "Your invoice #1042",
html: "<p>Thanks! Receipt attached.</p>",
});
return { statusCode: 200, body: JSON.stringify({ id, status }) };
}; import { MailKite } from "npm:mailkite";
const mk = new MailKite(Deno.env.get("MAILKITE_API_KEY"));
Deno.serve(async () => {
const { id, status } = await mk.send({
from: "hello@myapp.ai",
to: "ada@example.com",
subject: "Your invoice #1042",
html: "<p>Thanks! Receipt attached.</p>",
});
return Response.json({ id, status });
}); import { MailKite } from "npm:mailkite";
const mk = new MailKite(Deno.env.get("MAILKITE_API_KEY"));
Deno.serve(async () => {
const { id, status } = await mk.send({
from: "hello@myapp.ai",
to: "ada@example.com",
subject: "Your invoice #1042",
html: "<p>Thanks! Receipt attached.</p>",
});
return Response.json({ id, status });
}); import os
from mailkite import MailKite
mk = MailKite(os.environ["MAILKITE_API_KEY"])
res = mk.send({
"from": "hello@myapp.ai",
"to": "ada@example.com",
"subject": "Your invoice #1042",
"html": "<p>Thanks! Receipt attached.</p>",
}) import os
from django.http import JsonResponse
from mailkite import MailKite
mk = MailKite(os.environ["MAILKITE_API_KEY"])
def send(request):
res = mk.send({
"from": "hello@myapp.ai",
"to": "ada@example.com",
"subject": "Your invoice #1042",
"html": "<p>Thanks! Receipt attached.</p>",
})
return JsonResponse(res) import os
from flask import Flask, jsonify
from mailkite import MailKite
app = Flask(__name__)
mk = MailKite(os.environ["MAILKITE_API_KEY"])
@app.post("/send")
def send():
res = mk.send({
"from": "hello@myapp.ai",
"to": "ada@example.com",
"subject": "Your invoice #1042",
"html": "<p>Thanks! Receipt attached.</p>",
})
return jsonify(res) import os
from fastapi import FastAPI
from mailkite import MailKite
app = FastAPI()
mk = MailKite(os.environ["MAILKITE_API_KEY"])
@app.post("/send")
def send():
return mk.send({
"from": "hello@myapp.ai",
"to": "ada@example.com",
"subject": "Your invoice #1042",
"html": "<p>Thanks! Receipt attached.</p>",
}) <?php
$mk = new \MailKite\Client(getenv('MAILKITE_API_KEY'));
$res = $mk->send([
'from' => 'hello@myapp.ai',
'to' => 'ada@example.com',
'subject' => 'Your invoice #1042',
'html' => '<p>Thanks! Receipt attached.</p>',
]); <?php
use MailKite\Client;
Route::post('/send', function () {
$mk = new Client(env('MAILKITE_API_KEY'));
$res = $mk->send([
'from' => 'hello@myapp.ai',
'to' => 'ada@example.com',
'subject' => 'Your invoice #1042',
'html' => '<p>Thanks! Receipt attached.</p>',
]);
return response()->json($res);
}); <?php
use MailKite\Client;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\Routing\Attribute\Route;
class SendController
{
#[Route('/send', methods: ['POST'])]
public function send(): JsonResponse
{
$mk = new Client($_ENV['MAILKITE_API_KEY']);
return new JsonResponse($mk->send([
'from' => 'hello@myapp.ai',
'to' => 'ada@example.com',
'subject' => 'Your invoice #1042',
'html' => '<p>Thanks! Receipt attached.</p>',
]));
}
} require "mailkite"
mk = Mailkite::Client.new(ENV["MAILKITE_API_KEY"])
res = mk.send(
"from" => "hello@myapp.ai",
"to" => "ada@example.com",
"subject" => "Your invoice #1042",
"html" => "<p>Thanks! Receipt attached.</p>"
) class SendsController < ApplicationController
def create
mk = Mailkite::Client.new(ENV["MAILKITE_API_KEY"])
res = mk.send(
"from" => "hello@myapp.ai",
"to" => "ada@example.com",
"subject" => "Your invoice #1042",
"html" => "<p>Thanks! Receipt attached.</p>"
)
render json: res
end
end require "sinatra"
require "mailkite"
mk = Mailkite::Client.new(ENV["MAILKITE_API_KEY"])
post "/send" do
res = mk.send(
"from" => "hello@myapp.ai",
"to" => "ada@example.com",
"subject" => "Your invoice #1042",
"html" => "<p>Thanks! Receipt attached.</p>"
)
content_type :json
res.to_json
end mk := mailkite.New(os.Getenv("MAILKITE_API_KEY"))
res, err := mk.Send(mailkite.Message{
From: "hello@myapp.ai",
To: "ada@example.com",
Subject: "Your invoice #1042",
HTML: "<p>Thanks! Receipt attached.</p>",
}) MailKite mk = new MailKite(System.getenv("MAILKITE_API_KEY"));
Object res = mk.send(Map.of(
"from", "hello@myapp.ai",
"to", "ada@example.com",
"subject", "Your invoice #1042",
"html", "<p>Thanks! Receipt attached.</p>"
)); @RestController
public class SendController {
private final MailKite mk = new MailKite(System.getenv("MAILKITE_API_KEY"));
@PostMapping("/send")
public Object send() {
return mk.send(Map.of(
"from", "hello@myapp.ai",
"to", "ada@example.com",
"subject", "Your invoice #1042",
"html", "<p>Thanks! Receipt attached.</p>"
));
}
} npm i -g @mailkite/cli && mailkite login
mailkite send --from hello@myapp.ai --to ada@example.com \
--subject "Your invoice #1042" --html "<p>Thanks! Receipt attached.</p>"
mailkite messages tail # watch inbound arrive curl https://api.mailkite.dev/v1/send \
-H "Authorization: Bearer $MAILKITE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"from": "hello@myapp.ai",
"to": "ada@example.com",
"subject": "Your invoice #1042",
"html": "<p>Thanks! Receipt attached.</p>"
}' wget -qO- https://api.mailkite.dev/v1/send \
--header "Authorization: Bearer $MAILKITE_API_KEY" \
--header "Content-Type: application/json" \
--post-data '{
"from": "hello@myapp.ai",
"to": "ada@example.com",
"subject": "Your invoice #1042",
"html": "<p>Thanks! Receipt attached.</p>"
}' // No SDK — one POST with the built-in fetch.
const res = await fetch("https://api.mailkite.dev/v1/send", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.MAILKITE_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
from: "hello@myapp.ai",
to: "ada@example.com",
subject: "Your invoice #1042",
html: "<p>Thanks! Receipt attached.</p>",
}),
});
const { id, status } = await res.json(); # No SDK — one POST with requests.
import os, requests
res = requests.post(
"https://api.mailkite.dev/v1/send",
headers={"Authorization": f"Bearer {os.environ['MAILKITE_API_KEY']}"},
json={
"from": "hello@myapp.ai",
"to": "ada@example.com",
"subject": "Your invoice #1042",
"html": "<p>Thanks! Receipt attached.</p>",
},
)
print(res.json()) # { "id": "msg_…", "status": "queued" } # Point WordPress, a CRM, or any app that speaks SMTP at the relay.
SMTP_HOST=smtp.mailkite.dev
SMTP_PORT=587 # STARTTLS · 465 for implicit TLS
SMTP_USER=mailkite # any username works
SMTP_PASS=mk_live_… # your MailKite API key — not a separate SMTP password
SMTP_FROM=you@your-verified-domain.dev 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>",
}); import os
EMAIL_HOST = "smtp.mailkite.dev"
EMAIL_PORT = 587 # STARTTLS · 465 for implicit TLS
EMAIL_USE_TLS = True
EMAIL_HOST_USER = "mailkite" # any username works
EMAIL_HOST_PASSWORD = os.environ["MAILKITE_API_KEY"] # your mk_live_… key
DEFAULT_FROM_EMAIL = "hello@myapp.ai" # an address on a verified domain
# Anywhere in your app:
# from django.core.mail import send_mail
# send_mail("Your invoice #1042", "Thanks! Receipt attached.",
# "hello@myapp.ai", ["ada@example.com"]) MAIL_MAILER=smtp
MAIL_HOST=smtp.mailkite.dev
MAIL_PORT=587 # STARTTLS · 465 for implicit TLS
MAIL_USERNAME=mailkite # any username works
MAIL_PASSWORD=mk_live_… # your MailKite API key
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS=hello@myapp.ai # an address on a verified domain
# Then Mail::to('ada@example.com')->send(new InvoiceMail) just works. config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
address: "smtp.mailkite.dev",
port: 587, # STARTTLS · 465 for implicit TLS
user_name: "mailkite", # any username works
password: ENV["MAILKITE_API_KEY"], # your mk_live_… key
enable_starttls_auto: true,
}
# Action Mailer now sends from any address on a verified domain. # Read your MailKite inbox from any IMAP client or library — over IMAPS,
# with a scoped app-password (Settings → IMAP), never your API key.
import imaplib
M = imaplib.IMAP4_SSL("imap.mailkite.dev", 993)
M.login("agent@yourdomain.com", "mk_imap_…") # your IMAP app-password
M.select("INBOX")
typ, data = M.search(None, "UNSEEN") /plugin marketplace add mailkite/claude-code
/plugin install mailkite@mailkite claude mcp add --transport http mailkite https://mcp.mailkite.dev/mcp claude mcp add mailkite \
-e MAILKITE_API_KEY=mk_live_3a9f… \
-- npx -y @mailkite/mcp claude mcp add --transport http mailkite https://mcp.mailkite.dev/mcp \
--header "Authorization: Bearer mk_live_3a9f…" npx skills add mailkite/agent-skills Install the MailKite agent skill. Download
https://github.com/mailkite/claude-code/releases/latest/download/mailkite.zip
and unzip it into ~/.claude/skills/ (user-wide) or .claude/skills/ (this project), then load it. {
"mcpServers": {
"mailkite": {
"type": "http",
"url": "https://mcp.mailkite.dev/mcp"
}
}
} {
"mcpServers": {
"mailkite": {
"command": "npx",
"args": ["-y", "@mailkite/mcp"],
"env": { "MAILKITE_API_KEY": "mk_live_3a9f…" }
}
}
} {
"mcpServers": {
"mailkite": {
"type": "http",
"url": "https://mcp.mailkite.dev/mcp"
}
}
} {
"mcpServers": {
"mailkite": {
"command": "npx",
"args": ["-y", "@mailkite/mcp"],
"env": { "MAILKITE_API_KEY": "mk_live_3a9f…" }
}
}
} {
"servers": {
"mailkite": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@mailkite/mcp"],
"env": { "MAILKITE_API_KEY": "mk_live_3a9f…" }
}
}
} {
"mcpServers": {
"mailkite": {
"serverUrl": "https://mcp.mailkite.dev/mcp"
}
}
} {
"mcpServers": {
"mailkite": {
"command": "npx",
"args": ["-y", "@mailkite/mcp"],
"env": { "MAILKITE_API_KEY": "mk_live_3a9f…" }
}
}
} {
"mcpServers": {
"mailkite": {
"httpUrl": "https://mcp.mailkite.dev/mcp"
}
}
} {
"mcpServers": {
"mailkite": {
"command": "npx",
"args": ["-y", "@mailkite/mcp"],
"env": { "MAILKITE_API_KEY": "mk_live_3a9f…" }
}
}
} [mcp_servers.mailkite]
command = "npx"
args = ["-y", "@mailkite/mcp"]
env = { MAILKITE_API_KEY = "mk_live_3a9f…" } Connect to the MailKite MCP server (Streamable HTTP) at
https://mcp.mailkite.dev/mcp and authenticate in the browser when prompted.
Then use the mailkite_* tools to send, read inbound, and reply to email. {
"mcpServers": {
"mailkite": {
"type": "http",
"url": "https://mcp.mailkite.dev/mcp"
}
}
} {
"mcpServers": {
"mailkite": {
"command": "npx",
"args": ["-y", "@mailkite/mcp"],
"env": { "MAILKITE_API_KEY": "mk_live_3a9f…" }
}
}
} - Send transactional mail, replies, and broadcasts with one POST
- Receive every inbound message as clean JSON at your webhook
- Official SDKs for six languages — one API shape across all languages to send/receive email
- Scoped, idempotent API keys; DKIM-signed sending on your domain
Your next email starts here.
Start with a transactional email template. Match your product’s colors, edit the content, and send it to yourself from the playground.
Welcome
Give new users a useful first step.
Email verification
Confirm an address and keep them moving.
Payment receipt
Put payment details in their inbox.
Preview excerpts · 10 templates in the playground · No account needed to edit
A shared inbox your team actually reads
Marketers, support, and developers work the same inbox @yourdomain — every address in one place, tagged and triaged, reply as any of them. No per-seat tax on support@ or billing@.
- Every address on every domain, in one inbox
- Tag, assign, and reply as any address on the domain
- Marketers, support, and devs — one place, no context-switching
- Pay per human who logs in, never per address
Re: refund for order #1042
Loading…
Agent inboxes, with instant auto-reply
Give any agent a real catch-all inbox — it receives, reads, and replies over MCP, an AI skill, or plain REST. Turn on auto-reply and it triages, answers, filters spam, tags, and escalates on its own.
- A dedicated inbox per agent, per task, or per tenant
- MCP-native — send, list, read, and reply as tools
- Auto-reply: triage, answer, tag, and escalate without a server
- Sign-ups, verification, and 2FA codes handled autonomously
Newsletters and campaigns that land
Draft in a template editor, send to a list or segment, and let compliance handle itself. Every address is validated before it leaves — as you type, and again on the server — so you reach people, not bounces.
- A template editor — reusable templates with merge tags like {{first_name}}, no HTML needed
- Send to a list, tag, or segment — one click, with a live recipient count
- ~99% inbox placement, on the same warmed sending path
- Compliance handled — unsubscribe, List-Unsubscribe, and suppression are automatic
- Validation on every send — dead domains, disposables, and typos flagged before they bounce
Newsletter — August update
From hello@yourdomain.com
Hi {{first_name}},
Read more →Step 01 · Protect your list
Validate first
Email validation runs before you hit send. Instant client-side checks catch typos ("did you mean gmail.com?") and disposable addresses as you type; server-side validation flags dead domains and bad formats on every message. Use it to clean a list before it touches your reputation.
Step 02 · Reach the inbox
Then send
Marketing email is the send itself — the newsletter or campaign to that now-clean list, with templates, merge tags, automatic unsubscribe, and ~99% placement on the way out. A clean list is what keeps your sender reputation intact, and that reputation is what keeps you out of the spam folder.
Emails fly to the inbox, not spam.
Every message goes out authenticated — SPF, DKIM, and DMARC configured for you — and routed across tier-1 networks to the highest-deliverability tier your sending earns. You ship features; we keep you out of the spam folder.
Auto-routed across Cloudflare · Amazon SES + more — AI-tuned per domain, promoted to the highest tier your sending earns.
Authorizes MailKite's servers to send for your domain. Receivers check the sending host against your published record — we keep it aligned.
Every message is cryptographically signed with a key on your domain, so receivers can prove it wasn't altered in transit. We publish and rotate the keys.
Ties SPF and DKIM to the From: address recipients actually see, and tells inboxes to trust aligned mail. Configured and monitored for you.
Warm pools from day one
New domains start on shared IP pools we've already warmed, with an established reputation — so your very first send lands. No weeks-long warm-up, no reputation to babysit.
Best-path routing
Your mail rides Cloudflare, Amazon SES, Postmark, and other tier-1 networks. MailKite routes every message down the path most likely to land it — and reroutes if one degrades, so delivery never rides on a single provider.
Climbs on its own
MailKite learns how each domain sends and promotes it to the highest-deliverability tier its sending earns — AI-tuned as you go. Inbox placement gets better with nothing to configure.
Switched from SendGrid, inbox placement went from ~92% to ~99% in two weeks.
Mark — AdRender.app
Live in three steps
One domain setup covers every email job — for code, for people, and for agents.
Point your domain
Add the MX, SPF, and DKIM records we generate. We verify them and your whole domain goes live — send and receive, both directions.
Wire up each address
Send a webhook, open the shared inbox, or hand an address to an agent — pick per address. Grab an API key for your code.
Run it all in one place
Transactional mail, your team's inbox, and your agents' inboxes — one platform, one bill, one domain setup.
One email platform for your whole team
Developers, humans, and agents — send, receive, and auto-reply on one domain. Unlimited domains, free to start.
Compliant by design
Ask about MailKite
I can see the page you're on, and I can change it for you.
