Send as your domain
Send mail as an address at your domain: SMTP logins for a mail client, or one call to the send API with thread headers and idempotency keys.
mxgate sends mail as addresses at your domain in two ways: through SMTP from a mail client, or through one API call. Each domain signs with its own DKIM key.
Before you send
Two things must be true for the domain:
- The domain is verified.
- The DKIM record
mxgate._domainkey.example.comis published, and a check confirmed it:dkimisokinchecks.
mxgate setup writes the DKIM record. If you added the records by hand, add the DKIM record from mxgate domain show example.com, then run mxgate domain verify example.com. See DNS setup.
$ npx mxgate smtp example.com
Send-as is ready: smtp.mxgate.io, port 587 (STARTTLS) or 465 (TLS).When send-as is not ready, the command gives the reasons. The API call is GET /v1/domains/example.com/smtp, with ready and reasons.
SMTP logins
$ npx mxgate smtp create example.com
host smtp.mxgate.io
port 587 (STARTTLS) or 465 (TLS)
username mxg-1a2b3c4d@example.com
password ...The password is shown once. mxgate stores only a hash, so store the password now. A login sends only as addresses of its own domain: the envelope sender and the From header must be at that domain. A domain has at most 5 logins. Remove one with mxgate smtp rm example.com mxg-1a2b3c4d@example.com.
The API calls are POST /v1/domains/example.com/smtp and DELETE /v1/domains/example.com/smtp/{username}.
Settings for Gmail or a mail client
In Gmail, the settings go in "Send mail as". Other mail clients have the same fields for an outgoing server.
| Setting | Value |
|---|---|
| SMTP server | smtp.mxgate.io |
| Port | 587 with STARTTLS, or 465 with TLS |
| Username | The login, for example mxg-1a2b3c4d@example.com |
| Password | The password from mxgate smtp create |
| From address | An address at the domain, for example ada@example.com |
The send API
mxgate send, the MCP tool send_email and POST /v1/send send one message with no SMTP login. The From address must be at a domain of your account that is ready for send-as.
npx mxgate send --from "Ada <ada@example.com>" --to client@example.org \
--subject "Hello" --text "Hi"
npx mxgate send --from ada@example.com --to client@example.org \
--subject "Re: Offer" --file reply.txt \
--in-reply-to '<id-of-their-mail@example.org>' --copy --key offer-reply-1--file - reads the body from stdin. The same call with curl:
curl -X POST https://api.mxgate.io/v1/send \
-H "Authorization: Bearer $MXGATE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"from": "Ada <ada@example.com>",
"to": ["client@example.org"],
"subject": "Re: Offer",
"text": "Hello. Here is the answer to your question.",
"in_reply_to": "<id-of-their-mail@example.org>",
"copy_to_owner": true,
"idempotency_key": "offer-reply-1"
}'The answer is 202:
{
"message_id": "5f0c2a9e41b7d3680a1f9c2e7b4d6a13@example.com",
"from": "ada@example.com",
"to": ["client@example.org"],
"cc": [],
"bcc": ["you@gmail.com"],
"status": "queued",
"replayed": false,
"message": "Queued for 2 recipients. What each mail server answered: GET /v1/logs?direction=out&domain=example.com."
}queued means that the mail server took the message. The message log shows what the server of each recipient answered: mxgate logs example.com --out.
Fields
| Field | Required | Meaning |
|---|---|---|
from | Yes | "Name <you@example.com>" or an address only. |
to | Yes | One address or a list. |
cc | No | Copy recipients. The message shows them. |
bcc | No | Hidden copy recipients. No header shows them. |
reply_to | No | Where replies go, when it is not the sender. |
subject | Yes | 1 to 255 characters. |
text | Yes | The body as plain text. |
in_reply_to | No | The Message-ID of the message that you answer. |
references | No | Older Message-IDs of the thread, oldest first. At most 50. The default is in_reply_to. |
copy_to_owner | No | true adds your account address as a hidden copy. |
idempotency_key | No | 1 to 200 characters. The header Idempotency-Key does the same. |
Plain text only
The send API takes plain text. There is no HTML and no tracking: a link arrives as you wrote it. One message goes to at most 50 addresses: To, Cc and Bcc together. An address that is in two lists gets one copy.
Idempotency
Give an idempotency_key when a retry must not send a second copy. The same key with the same message sends once: the second call answers 200 with the first answer and "replayed": true. The same key with a different message is 409 idempotency_key_reused. mxgate keeps a key for 7 days.
Thread headers
To answer a message and keep the thread, give its Message-ID in in_reply_to and start the subject with "Re: ". The Message-ID is message_id in mxgate logs --json. Angle brackets are not necessary.
Limits
| Plan | Limit |
|---|---|
| Free | 50 recipients a day. The count starts again at 00:00 UTC. |
| Paid | 3,000 recipients a calendar month. |
Each recipient counts. SMTP and the send API use the same count. A call above the limit is 402 plan_limit, and an SMTP login above the limit gets a refusal with the reason. GET /v1/account shows sent_today and sent_this_month. See Plans and limits.
When sending is paused
All customers send from one IP address. If 10% or more of the mail you send bounces, or receiving servers refuse it as spam, mxgate pauses sending for your account. You get an email with the reason, and a person looks at each pause. Forwarding continues.
While sending is paused, send_hold in GET /v1/account has the reason, the send API answers 409 send_as_not_ready, and mail from an SMTP login is refused with the reason. Write to abuse@mxgate.io.
Forwarding and aliases
How mxgate aliases and the catch-all work, why a destination must confirm, and what happens to a message between the sender and your mailbox.
The message log
The mxgate log has one row for each message: forwarded, sent, deferred, bounced, expired or rejected, with the reply of the other server.