Integration · SMTP

SMTP

Send through smtp.postfly.app on port 587 with STARTTLS and your API key — for apps and frameworks that speak SMTP.

For apps and frameworks that speak SMTP rather than HTTP. A message submitted over SMTP goes through the same pipeline as POST /v1/emails: the sender domain must be verified, suppressed recipients are refused, and each recipient becomes one message you can follow in the dashboard, the API and webhooks.

Connection settings

Hostsmtp.postfly.app
Port587 (STARTTLS)
Usernameapikey (any value is accepted and ignored)
Passwordyour API key, pf_live_… or pf_test_…, with the emails:send scope
EncryptionSTARTTLS is required; AUTH is refused on an unencrypted session.

How a message is read

  • The From: header is the sender; its domain must be a verified sender domain of the project. The envelope MAIL FROM is used only as the bounce address.
  • Each RCPT TO address becomes one message, up to 50 per SMTP message; a message with more is refused.
  • Subject:, the HTML and text parts and Reply-To: are taken as they are. A message with neither an HTML nor a text part is refused.
  • X-Postfly-Tag: sets the message's tag. Other custom headers are dropped; postfly builds the outgoing headers itself.
  • A message may be up to 25 MB.

Replies & limits

A refusal comes back as an SMTP reply. Validation, domain and suppression problems are permanent 550s. A paused project gets 550 5.7.1 at MAIL FROM. Temporary server faults are 451, safe to retry.

The rate limit is the REST default bucket, 120 per minute per key, counted per recipient, with its own counter separate from the REST API. Past it, further recipients get 452 and a new message gets 451 at MAIL FROM, both saying when to retry; standard clients keep the accepted recipients and retry the rest. The project's daily quota applies too: a message whose recipients would pass it gets 452 after DATA and none of them is queued. The full table is in SMTP replies.

Examples

smtp.postfly.app:587
import nodemailer from 'nodemailer';

const transport = nodemailer.createTransport({
  host: 'smtp.postfly.app',
  port: 587, // STARTTLS
  requireTLS: true,
  auth: { user: 'apikey', pass: process.env.POSTFLY_API_KEY },
});

await transport.sendMail({
  from: 'Your App <[email protected]>',
  to: '[email protected]',
  subject: 'Your sign-in code',
  text: 'Your code is 381902.',
  html: '<p>Your code is <strong>381902</strong>.</p>',
  headers: { 'X-Postfly-Tag': 'sign-in' },
});