Skip to content

SMTP setup

Ampout doesn’t ship with shared SMTP infrastructure. You bring your own provider — SMTP2GO, Postmark, Mailgun, AWS SES, even a Gmail App Password. This is deliberate: deliverability and sender reputation are yours, not ours, and that’s how you want it for cold outreach.

A shared SMTP pool would mean:

  • Your sending reputation is mixed with every other tenant’s.
  • One bad actor’s spam complaint hits everyone.
  • IP warmup is meaningless — IPs get rotated/cycled at the provider’s discretion.

By contrast, BYO-SMTP means:

  • Your domain → your reputation. Spam complaints on your sender don’t affect other ampout users.
  • You control the warmup curve. Ramp up volume on your timeline.
  • You can swap providers without changing ampout configuration (just update the credential).
ProviderPlanNotes
SMTP2GOPro $30/50kBest webhook integration (we have a built-in inbound bounce handler). Strong deliverability.
Postmark$15/10kExcellent reputation, slightly stricter content policies.
MailgunFlex pricingGood for high volume; webhook integration is custom.
AWS SES$0.10/1kCheapest at scale; you manage warmup yourself.
Gmail App PasswordFree up to 500/dayFine for very small lists; not recommended for cold outreach at scale.

Credentials live on a campaign. You can attach them at campaign creation or via POST /campaigns/:id/smtp_credentials later. See the API reference.

{
"smtp_credential": {
"label": "Primary",
"smtp_host": "mail.smtp2go.com",
"smtp_port": 587,
"smtp_username": "your_smtp2go_username",
"smtp_password": "your_smtp2go_password",
"from_name": "Ada",
"from_email": "ada@yourdomain.com",
"daily_limit": 200,
"imap_host": "imap.gmail.com",
"imap_port": 993,
"imap_username": "ada@yourdomain.com",
"imap_password": "<app password>"
}
}

Multiple credentials per campaign work — the dispatcher rotates among enabled credentials. Useful for warming multiple sender domains in parallel.

Each credential has a daily_limit capping sends per UTC day. Step 2/3 sends don’t count against today’s limit (only step-1 fires consume capacity), so a daily_limit: 200 setting realistically supports ~200 new contacts per day, while step 2/3 follow-ups continue independently.

When all enabled credentials hit their daily caps, the dispatcher logs a warning and stops queueing for the day.

Set verify_email_mx: true on the campaign and ampout will run a DNS MX lookup at dispatch time:

  • Contacts whose domain has no MX record → marked bounced with reason “MX check failed at dispatch”, no SMTP transaction attempted.
  • Contacts whose domain has a valid MX → proceed normally.

This is the cheapest way to clean an old/imported list — costs one DNS lookup per contact, eliminates ~40% of bounces from typo’d or defunct domains.

Trade-off: MX checks add a small dispatch delay and don’t catch invalid mailboxes (only invalid domains). For full email verification, run your list through a service like NeverBounce or ZeroBounce before importing.

If you set imap_host / imap_port / imap_username / imap_password on a credential, ampout polls the IMAP inbox every few minutes and matches inbound messages to enrollments by email address. Matched enrollments transition to replied and emit an enrollment.replied webhook.

Auto-reply detection (vacation responders, OOO messages) is built in — we filter by:

  • Auto-Submitted header
  • Precedence: bulk|auto_reply|junk header
  • X-Auto-Response-Suppress header
  • Subject lines matching out of office, automatic reply, etc.

If you don’t configure IMAP, you can still use the SMTP for sending — reply detection just won’t fire. You’d track replies via your own inbox.

When a credential’s bounce rate (per-send) exceeds the campaign’s bounce_rate_threshold (default 8%), the credential is automatically disabled (disabled_at set). The dispatcher skips disabled credentials.

If all credentials on a campaign are disabled, the campaign is auto-paused and a campaign.paused webhook fires.

To re-enable after cleaning your list:

Terminal window
curl -X POST "https://ampout.fly.dev/campaigns/$CAMPAIGN_ID/smtp_credentials/$CRED_ID/reenable" \
-H "Authorization: Bearer $KEY"

The threshold is configurable per campaign:

Terminal window
curl -X PATCH "https://ampout.fly.dev/campaigns/$CAMPAIGN_ID" \
-H "Authorization: Bearer $KEY" \
-H "Content-Type: application/json" \
-d '{"campaign": {"bounce_rate_threshold": 10.0}}'

Range: 0.5–25.0%. Default 8.0%.

The denominator for bounce_rate is total SMTP transactions (step 1 + step 2 + step 3 each count), not enrollment count. This matches what your SMTP provider reports — SMTP2GO’s dashboard percentage and ampout’s bounce_rate field will agree.

Earlier we used per-enrollment, but that diverged sharply from the provider’s number once step 2/3 started firing (denominator stopped growing on enrollments-based math). The per-send denominator is the universally-comparable one.