How Email Delivery Actually Works (What Happens After You Click Send)

When you press Send Campaign in AcelleMail, your message travels through five stages before it lands in someone's inbox. Knowing each stage tells you exactly where to look when a campaign goes sideways — and why some recipients see the email and others don't.

What this is for

You press Send Campaign in AcelleMail. The status badge turns from Draft to Queuing, then Queued, then Sending, then Done. Between Sending and the recipient's inbox, your message travels through five distinct stages run by other people's servers. This guide walks each stage in plain English — so when something goes wrong, you know which stage to investigate instead of guessing.

You don't need to run anything. You just need to know the path.

The 5-stage journey

Stage 1 — AcelleMail queues every recipient

When you click Send Campaign, AcelleMail doesn't try to dispatch all 50,000 emails at once. It queues each recipient as a separate job. A pool of background workers (your sending workers) picks jobs off the queue one by one. This is why the campaign status moves through Queuing (building the list) → Queued (waiting) → Sending (workers are picking up jobs).

Where you watch it: the campaign Overview page. The progress badge ticks from Queuing to Sending to Done as workers drain the queue.

Stage 2 — Your sending server looks up the recipient's mail server

For every email, your sending server has to find where to deliver it. It asks DNS: "What's the mail server for gmail.com?" DNS returns the recipient's MX record — a hostname like gmail-smtp-in.l.google.com for Gmail, or mail-protection.outlook.com for Outlook 365.

If the recipient's domain has no MX record, your server gets back a delivery failure here — that becomes a hard bounce, and AcelleMail flags the subscriber so future campaigns skip them.

Stage 3 — The SMTP handshake

Your server opens a connection to the recipient's mail server and they talk over the SMTP protocol — a short, formalized exchange that goes: hello, who are you, who's the message for, here's the message, goodbye. It takes a few hundred milliseconds when both sides are healthy. It can take 30+ seconds if the recipient server is slow or rate-limiting you (see Email Throttling and Rate Limits Explained).

Failures at this stage usually look like a soft bounce — the recipient server said "not right now," and your server can try again. AcelleMail will retry soft bounces a configurable number of times before giving up.

Stage 4 — Encryption (TLS)

Modern receiving servers expect the SMTP conversation to be encrypted with TLS. This stops anyone in the middle of the internet from reading your message in transit. Gmail, Outlook, Yahoo all require it. If your sending server doesn't support TLS, big providers either reject the message outright or quietly drop it into spam.

This is the rare stage you can't see from inside AcelleMail — it's a property of your SMTP setup. If you use AWS SES, SendGrid, or any modern provider, TLS is on automatically. If you use a homemade Postfix install, your operator needs to confirm STARTTLS is configured.

Stage 5 — Authentication checks (SPF, DKIM, DMARC)

Even after the message is delivered to the recipient server, the recipient's spam filter runs three identity checks before placing it in the inbox:

Check What it asks
SPF Is the IP that sent this message on the list of IPs the From-domain says are allowed to send for it?
DKIM Did the From-domain cryptographically sign this message? Does the signature verify?
DMARC Do the SPF or DKIM domain names line up with the visible From address?

All three need to pass for best inbox placement. If they don't, the message often lands in spam — or, with strict DMARC enforcement, gets rejected outright. This is the #1 cause of "I sent the email but my recipient says they never got it." Set up all three on day one — see Complete DNS Setup for Email Sending: SPF, DKIM, DMARC.

Where each stage shows up in AcelleMail

Stage AcelleMail signal What "failure" looks like
Queue Status badge: QueuingQueuedSendingDone Status stuck on Queuing for >5 min → your queue worker is not running
MX lookup Recipient is marked Hard bounced Subscriber moves to bounced status on the list
SMTP handshake Recipient is marked Soft bounced Subscriber stays subscribed but counts toward bounce rate
TLS Bulk drop to spam from one provider All Gmail recipients show 0% open suddenly — check your SMTP provider's TLS config
Authentication Spam-folder placement See your domain in Google Postmaster Tools / Microsoft SNDS

Common issues

What you see What to do
Status badge stuck on Queuing Your queue worker process is not running. Have your operator restart it (see Setting Up Queue Workers and Cron Jobs).
Lots of hard bounces on a freshly-imported list The list is dirty — too many addresses with no valid mail server. Use a verification service before importing. See Email List Hygiene.
Lots of soft bounces concentrated at one ISP You're being rate-limited by that ISP. Slow the send by configuring throttling on the sending server.
Recipient says "I never got it" but AcelleMail says delivered It's in their spam folder. Almost always an SPF / DKIM / DMARC misconfiguration — verify your DNS setup.

What to do after

  1. Set up SPF, DKIM, and DMARC if you haven't — this single step eliminates most "didn't arrive" mysteries.
  2. Bookmark the campaign Overview page during your next send and watch the status badge tick through the stages.
  3. If you operate your own server, read Email Queue Architecture in AcelleMail for the queue side.

Related articles

10 comments

4 comments

  1. akira.tnk88
    If you go dedicated IP — request the warmup support from your provider too. SES and SendGrid both have specific warmup features that help.
  2. femi.adeyemi
    Confirming: at 500k+/day, MySQL becomes the bottleneck before workers. Moving to Redis queue freed up DB headroom for everything else.
  3. emma.whitaker
    Dedicated IP made a measurable difference for us. We moved from shared SES to a dedicated IP at ~80k subs and saw ~8% lift in inbox placement within 6 weeks
  4. ravi.kumar.del…
    Has anyone tried PostgreSQL instead of MySQL for the AcelleMail DB? Curious if the indexes behave better at scale
    1. admin
      for your specific case, i'd recommend testing with `--dry-run` first. the behavior under high load isn't 100% deterministic and we want you to see your own pattern before committing.
    2. admin (edited)
      There's no built-in way today. Two workarounds: (1) cron + custom script polling the API every N minutes, (2) webhook-driven if your event source supports it. Most operators go with #2.
    3. admin (edited)
      suppression list import via csv captures all opt-outs including preference-center ones if you exported with the right field set. the export filter defaults exclude some — check the 'include unsubscribed' checkbox on mailchimp's export wizard
    4. admin (edited)
      we're aware of the silent-bail-out on deleted customers — there's an open issue for it. Workaround for now: monitor the campaign:rerun log for absence of expected log lines, alert when silent for > 20 min.
    5. admin (edited)
      Good question — and one that comes up often enough we should add an FAQ section. Short answer: yes for the common case; the exception is when you're running custom plugins that override the default behavior
    6. admin (edited)
      Depends on your version. 5.x supports it natively; 4.x needs a config flag set in `.env`. We'll note this caveat in the article on the next pass.

More in Email Infrastructure