AMS
Send outbound email from verified domains with per-address credentials.
Anything Mail Service (AMS) sends transactional mail from domains you have verified. A message is accepted by the sending API or a Worker email binding, queued in AQS, signed with DKIM by a sender worker, and delivered over SMTP. The console shows sending domains, access, delivery metrics, and recent activity.
Apply for access
AMS is available to approved members and administrators. Approval keeps the sending pool clean, which protects deliverability for everyone.
- Open AMS and choose Apply.
- List the domains you will send from, describe the use case, and give a rough monthly volume. Submit the application.
- An administrator reviews it. The application page shows whether it is pending, approved, or rejected, along with any notes from the review.
An approved account has a daily sending limit, 100 messages by default.
An administrator can raise or lower it when approving an application.
Messages beyond the limit are refused with 429 until the
24-hour window passes. Each funded account gets 500 accepted messages free
in every calendar month, starting after the first card or crypto deposit;
after that, messages are billed per thousand.
How it fits
AMS builds on a root domain that is already verified for AnythingCloud. The root proves ownership; a sending domain under it carries the mail configuration.
| Piece | What it is |
|---|---|
| Root domain | A domain verified with a TXT record at _anythingcloud.<root>. See Custom domains. |
| Sending domain | The verified root itself (label @) or a subdomain such as mail.example.com. It has its own DKIM key and Return-Path bounce host. |
| Address | A local part at the sending domain, such as [email protected], with an optional display name. |
| Credential | A bearer token scoped to one address. The secret is shown once, when it is created. |
AMS is available to approved members and administrators. Applications
send with a per-address credential rather than a console session. A Worker
can send through a bound address with env.EMAIL.send; see
Workers → Email.
Onboard a domain
Verifying a root domain is enough to start sending. AMS creates an apex sending domain for each verified root that does not have one yet.
- Verify the root domain under Networking. Its status must be Active.
- Open AMS. The root appears as a
sending domain with the
@label, or you can choose Add domain and enter a label such asmailto createmail.example.com. - Choose Onboard to see every sending domain in one list, then open the DNS tab for the records that are still missing.
- Publish the records, then choose Verify all on the Onboard page. Each domain becomes Active as soon as its DKIM, Return-Path SPF, and Return-Path MX records resolve.
| Purpose | Type | Name | Value |
|---|---|---|---|
| DKIM | TXT | ams._domainkey.<host> | v=DKIM1; k=rsa; p=<public key> |
| Return-Path SPF | TXT | bounce.<host> | v=spf1 include:spf.anything-cloud.com ~all |
| Return-Path MX | MX | bounce.<host> | 10 mx.anything-cloud.com |
| DMARC | TXT | _dmarc.<host> | v=DMARC1; p=none; |
<host> is the sending domain, for example
mail.example.com. ams is the default DKIM
selector, and the public key is generated for that sending domain. Copy
each value from the console rather than typing it. Verification checks
DKIM, Return-Path SPF, and Return-Path MX; DMARC is listed for the domain's
policy but is not required to activate it.
Senders and credentials
Open an active sending domain and choose Senders → Add
sender. Enter the local part, for example receipts,
and optionally a display name. The sender is created as
[email protected].
Open the address and choose Create under
Credentials. Name the credential for the application that
will use it. The token starts with ams_live_ and is shown once;
store it in the application's secret store, because the console keeps only
its prefix afterwards.
- A credential belongs to exactly one address and can only send from that address.
- Revoking a credential stops requests that use it immediately.
- Retiring an address revokes its credentials. A retired address cannot be reused.
An address can have more than one active credential, up to the limit in Limits. Create separate credentials for separate applications so one can be revoked without affecting the others.
Sending API
Send one message with a credential from the address:
POST https://anything.solutions/api/mail/v1/send
Authorization: Bearer <credential>
Content-Type: application/json
| Field | Required | Description |
|---|---|---|
from | No | The sending address. It must match the credential's address. Omit it to use that address. |
to | Yes | One recipient address. |
subject | Yes | Subject line, up to 500 characters. |
text | Yes | Plain-text body. |
html | No | HTML body. When present, the message is sent as multipart alternative. |
reply_to | No | Reply-To address for the message. |
attachments | No | Up to 5 files. Each entry has a filename, standard base64 content, and an optional content_type (default application/octet-stream). |
An attachment filename is reduced to its base name. Attachments are sent as multipart/mixed, with the text and HTML body first. Sizes in Limits apply to the decoded file.
curl -X POST https://anything.solutions/api/mail/v1/send \
-H "Authorization: Bearer $AMS_CREDENTIAL" \
-H "Content-Type: application/json" \
-d '{
"from": "[email protected]",
"to": "[email protected]",
"subject": "Your receipt",
"text": "Thanks for your order.",
"html": "<p>Thanks for your order.</p>",
"reply_to": "[email protected]"
}'
A successful request returns the queued message:
{"ok": true, "id": "ams_...", "status": "queued"}
The id identifies the queued message. A queued response means the message was accepted for delivery, not that it has reached the recipient.
| Status | When |
|---|---|
401 | The credential is missing, unknown, or revoked. |
403 | The address is retired, the sending domain is not active, AMS access is not approved, or from does not match the credential. |
422 | A field is missing or invalid, the message is too large, or the queue rejected it. |
429 | The daily sending limit has been reached. |
503 | The delivery queue is unavailable. Try again shortly. |
Delivery
Accepted messages enter the shared ams-delivery AQS queue.
A sender worker leases one job, fetches the sending domain's DKIM key, builds
the message, signs it with DKIM, and delivers it over SMTP. Delivery uses the
per-message Return-Path at bounce.<host> as the envelope
sender and STARTTLS when the receiving server offers it.
A 2xx SMTP response marks the message sent. A 4xx response, or a connection, TLS, or timeout error, defers it for a retry. Retries wait 5 minutes, 15 minutes, 1 hour, 4 hours, then 12 hours between attempts, up to 10 attempts in total. A 5xx response, a permanent DNS failure, or an invalid job fails the message without another attempt.
| Status | Meaning |
|---|---|
queued | Accepted and waiting for a sender worker. |
deferred | A delivery attempt was deferred and is waiting to retry. |
sent | The receiving server accepted the message. |
failed | Delivery failed permanently or the retry attempts were exhausted. |
The Activity page lists recent messages with their from address, recipient, subject, status, and last error. An address page shows recent mail for that address, and a sending domain page shows recent mail for the domain.
Metrics
The Metrics page counts accepted, sent, failed, and retried messages for each day, with a chart per metric and a per-domain breakdown. Choose the last 7 or 30 days.
Daily metrics are kept for 30 days on every account.
Limits and current behavior
| Limit | Value |
|---|---|
| Recipients per request | One. to takes a single address. |
| Daily sending limit | 100 messages per 24 hours by default; set per member when an application is approved. |
| Burst rate | 20 messages per minute per account. |
| Free allowance | 500 accepted messages per calendar month, after the first deposit. |
| JSON job size | 900,000 bytes (about 900 KB) for the whole queued job. |
| Body size | 500 KB each for the text and HTML bodies. |
| Attachments | 5 files per message, 400 KB each and 600 KB in total, measured after base64 decoding. |
| Credentials | Scoped to one address; up to 5 active credentials per address. |
| Sending domains | 10 per account, with 5 per verified root domain. |
| Senders | 100 per sending domain, and 1,000 per account. |
| Sender workers | 4 concurrent workers per sender process by default. |
| Console access | Approved members and administrators. |
Pricing
Funded accounts include 500 accepted messages per calendar month at no charge; the allowance unlocks after the first card or crypto deposit. After the allowance, messages cost $0.09 per 1,000, which is 90% of the AWS SES list price. A message is accepted when it is queued, whether or not delivery succeeds. Delivery retries are free.
Sender worker operations
These steps are for administrators running the delivery worker on a server.
- Open Admin →
Cloud → Mail Worker and choose Create token. Name
it for the host that will run the worker. The token starts with
ams_worker_, is shown once, and can be revoked from the same page. Up to 10 worker tokens can be active at a time. - Install the worker binary at
/opt/ams/ams-sender. Theams-senderservice reads its configuration from/etc/ams/sender.env, which is readable only by root. SetAMS_WORKER_TOKENin that file and do not commit it or paste it into shell history. - Restart the service and check its loopback health endpoint:
sudo systemctl restart ams-sender curl -fsS http://127.0.0.1:8099/health - Health is available only on
127.0.0.1. A failed check usually means the token, control URL, or DNS is wrong; followsudo journalctl -u ams-sender -fwhile it starts.
Build, PTR and port 25 checks, installation, updates, and token rotation
are covered in deploy/mail/README.md in the repository.
Roadmap
Inbound email and email-triggered Workers are not available yet. AMS is outbound only.