mailsai
Email API for AI agents — Python SDK.
Per-agent email addresses on your domain, per-agent reputation, and prompt-injection scanning on every inbound. Your agent reads the reply and decides what to say — intent + entity extraction is opt-in.
pip install mailsai
Quick start
Create the agent once (this mints its inbox address), then send from it. Skipping the
create step is the most common first-run error — agent("sarah") only references an
agent, it does not create one, so sending returns 404 agent_not_found.
from mailsai import Client, agent
# Reads MAILS_API_KEY from env (or pass api_key=... explicitly)
client = Client()
# One-time setup: create the agent. It gets sarah@<your-workspace>.mails.ai
client.create_agent("sarah")
sarah = agent("sarah")
# mails.ai is transactional-only: mail the recipient asked for. Cold outreach and bulk
# marketing are refused with 422 cold_email_prohibited — that is deliberate, and it is
# what keeps the sending reputation clean for everyone on the platform.
sarah.send(
to="you@example.com",
subject="Your verification code is 481902",
body="Your verification code is 481902. It expires in 15 minutes.",
)
@sarah.on_reply
def handle(reply):
# Always present — the delivery + security + identity layer:
# reply["injection_score"] -> 0.02 # six-category prompt-injection scan
# reply["sender_reputation"] -> 0.91 # per-agent reputation
#
# Present only when classification is enabled (opt-in, +$0.003/inbound):
# reply["intent"] -> "schedule_demo" | "ask_question" | …
# reply["entities"] -> {"date": "...", "time": "..."}
# reply["urgency"] -> 0.8
#
# Your agent reads the reply and decides what to send next.
print(reply["injection_score"], reply["sender_reputation"])
sarah.start_listening() # blocks; opens SSE stream and dispatches replies
For non-blocking, pass blocking=False to start_listening() — it returns a daemon thread.
Lower-level client
from mailsai import create_client
c = create_client() # reads MAILS_API_KEY
# Send via any agent
c.send("sarah", to="lead@example.com", subject="Demo", body_text="…")
# Resources
threads = c.list_threads(agent_id="agent_abc123")
usage = c.usage()
rep = c.get_reputation(agent_id="agent_abc123")
# Drafts
draft = c.create_draft(agent="sarah", to="lead@example.com", subject="Demo", body_text="…")
c.send_draft(draft["id"])
Webhook verification
from mailsai import verify_webhook
# In your webhook handler:
event = verify_webhook(
body=request.body.decode(),
signature=request.headers["X-Mails-Signature"],
secret=os.environ["MAILS_WEBHOOK_SECRET"],
)
if event is None:
return Response(status=400)
# event is the verified inbound event dict
Errors
from mailsai import MailsError
try:
sarah.send(to="blocked@example.com", subject="…", body="…")
except MailsError as e:
print(e.type, e.code, e.message, e.status, e.request_id)
Configuration
| Param / env var | Default |
|---|---|
api_key / MAILS_API_KEY |
(required) |
base_url / MAILS_BASE_URL |
https://api.mails.ai |
Documentation
- Full docs: mails.ai/docs
- Source: github.com/RolloutsAI/mailsai
License
MIT
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file mailsai-0.2.0.tar.gz.
File metadata
- Download URL: mailsai-0.2.0.tar.gz
- Upload date:
- Size: 9.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/7.0.0 CPython/3.14.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
313dd5628e2019aa948d41fe9682a096f9c8647d64c3e719152ad56341946833
|
|
| MD5 |
8f8a7525f62e09e3687cc818ae3b75f0
|
|
| BLAKE2b-256 |
5799c03dde8452576ba6720c43a8f441f6f408cae7ab3dbc8c4340e729d35b72
|
File details
Details for the file mailsai-0.2.0-py3-none-any.whl.
File metadata
- Download URL: mailsai-0.2.0-py3-none-any.whl
- Upload date:
- Size: 9.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/7.0.0 CPython/3.14.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fd65b4841ba43f5d1bd6a8db24c2d2ad6080781a033bbe4b53a2a048b29530fa
|
|
| MD5 |
041de9f106bd68b97c179079de2c7d57
|
|
| BLAKE2b-256 |
4924cf2a8502e04f2f9b583a01fe64eb1e43af9b72c840f906f830a57f21bcb8
|