ChangelogStatus
Docs/Sending email

Sending over SMTP

Anypost accepts mail over SMTP as well as over the HTTP API. If your application, or off-the-shelf software you run, already sends through an SMTP server, point it at Anypost and you get the same authentication, delivery, and event reporting without writing code.

When to use SMTP

The HTTP API is the richer interface and what most of these docs describe. Reach for SMTP when:

  • An existing app already speaks SMTP and you would rather configure it than rewrite its mail layer.
  • You run software whose mail transport you do not control.
  • A library or framework you already use makes SMTP the path of least resistance.

Both transports send from the same verified domains, authenticate with the same API keys, and produce the same events.

Connection settings

SettingValue
Hostsmtp.anypost.com
Ports587, 2587, or 25
EncryptionSTARTTLS (required)
Usernameanypost
Passwordyour API key secret (ap_...)

All three ports behave identically: pick whichever your network allows. 587 is the standard submission port and the one to use by default. 2587 is an alternative for networks that block 587. 25 is also accepted, but many hosting providers and ISPs block outbound traffic on it, so treat it as a last resort rather than a default.

STARTTLS is mandatory on every port. The connection opens in plaintext and must upgrade to TLS before authenticating. There is no implicit-TLS port and no unencrypted submission path: Anypost refuses to authenticate, and refuses mail, on a session that has not upgraded to TLS.

Authentication

The username is always the literal string anypost. The password is an API key secret, the same ap_... value used as the bearer token on the HTTP API. A single key authenticates both transports. See Authentication for creating, scoping, and rotating keys.

Use a send_only key for an application that only sends. SMTP submission needs no other permission.

Authentication failures are reported in the SMTP exchange: a bad key is rejected at the AUTH step, and a session that never authenticates is refused at MAIL FROM. Repeated failures from one address are temporarily blocked.

Sender addresses

An SMTP submission carries two sender addresses, and Anypost checks both:

  • The envelope sender, set by the SMTP MAIL FROM command. It is where delivery failures are returned and is not shown to the recipient. Most SMTP clients set it automatically to match the From header.
  • The From header, the address the recipient sees in their mail client.

The domain of each must be both verified for your team and permitted for the API key:

  • The domain must be verified, exactly as on the HTTP API. See Domains & DNS setup.
  • The key must be allowed to use it. A key with an allowed_domains restriction can only send from the domains it lists; an unrestricted key may use any of the team's verified domains. See Authentication.

The envelope sender and the From header do not have to share a domain, but each is checked on its own. A submission is rejected if either one is on a domain that is unverified or not permitted for the key. Checking the From header separately is what stops an authenticated sender from passing the envelope check with one domain and then showing the recipient a From address on another.

Message size

A submitted message may be up to 5 MB, the same ceiling the HTTP API enforces. This is the size of the full MIME message, including encoded attachments. Anypost advertises the limit over the SIZE extension, so a well-behaved client can refuse an oversized message before sending it.

5 MB is ample for transactional and marketing email. For a send that would strain it, host large files elsewhere and link to them rather than attaching them.

A test submission

Any SMTP client works. This example uses swaks, a command-line SMTP tester:

swaks \
  --server smtp.anypost.com --port 587 --tls \
  --auth-user anypost --auth-password "$ANYPOST_API_KEY" \
  --from [email protected] \
  --to [email protected] \
  --header "Subject: Hello from Anypost" \
  --body "It worked."

--tls performs the required STARTTLS upgrade. A 250 OK on the DATA command means the message was accepted.

Anypost headers

Standard MIME covers most of a message: From, To, Cc, Bcc, Subject, Reply-To, the text and HTML parts, attachments, and inline images are all ordinary parts of the message you submit.

Anypost's send-time correlation dimensions have no MIME equivalent, so over SMTP you set them with headers. Anypost reads and then strips these headers, so recipients never see them:

HeaderSetsValue
X-Anypost-TagsTagsA JSON array of strings, for example ["welcome","onboarding"].
X-Anypost-TagOne tagA single tag value. Repeat the header for several. Cannot be combined with X-Anypost-Tags.
X-Anypost-TopicTopicA single topic string.
X-CampaignCampaignA single campaign string.

Each header may appear at most once per message (apart from repeated X-Anypost-Tag). A malformed value is rejected in the SMTP exchange rather than sent. See Tags, topics & campaigns for what these dimensions do.

The message ID

The 250 OK reply to the DATA command carries an ids= field: one email_ ID per recipient, space-separated.

250 OK ids=email_018f4f3e-7b2c-7c80-8e21-1a3a4f5b6c7d

Each ID identifies one recipient's copy of the message, and every event for that copy references it. Capture the ids= field from the DATA response if you want to correlate events back to a submission.

What differs from the HTTP API

SMTP reaches the same delivery and reporting, with a few interface differences:

  • Idempotency keys are an HTTP-only feature. SMTP has no equivalent; a resubmitted message is a new send.
  • Batch sending is HTTP-only. Over SMTP, submit each message separately on the same connection.
  • Templates are an HTTP-API feature. An SMTP submission is an already-rendered message: it cannot reference a stored template or carry per-recipient variables.
  • The remaining correlation dimensions (tags, topic, campaign) are set through headers, as above, rather than as JSON fields.

For anything beyond a straightforward send, the HTTP API is the fuller interface. See Send a single email.

Where to go next