← Back to blog
·9 min read

Why Verification Emails Arrive Late (and What You Can Do)

Why OTP and verification emails get delayed: sender queues, SPF/DKIM/DMARC checks, greylisting, retry backoff and spam filters, plus fixes for users and devs.

Email Was Never Designed to Be Instant

You request a code, the website says "We've sent you an email", and nothing appears. Two minutes later you request another one. Then both arrive at once, and the first one is already invalid.

This happens with every email provider, not just temporary inboxes. Email is a store-and-forward system: each server along the way accepts responsibility for a message, stores it, and passes it on when it can. Most of the time that takes a second or two. But the protocol explicitly allows any server to say "not now, try later", and "later" can mean minutes. One-time codes that expire in five or ten minutes sit uncomfortably on top of a system that tolerates delays of that size.

This guide walks through the path a verification email takes, where delays come from at each step, and what users and developers can realistically do about them.

The Journey of a Verification Email

A typical verification message passes through these stages:

  1. The application generates a code, stores it, and asks its mail system to send a message.
  2. The sending service (the company's own mail server or an email delivery provider) queues the message.
  3. DNS lookup: the sending server looks up the MX records of the recipient domain to find which servers accept its mail.
  4. The SMTP conversation: the sending server connects to the receiving server, identifies itself, names the sender and recipient, and transmits the message.
  5. Receiving checks: the receiving server evaluates the connection and the message, including SPF, DKIM and DMARC, reputation and content filtering.
  6. Local delivery: the receiving system hands the message to whatever stores it and makes it visible: a mailbox, or in a temporary email service, a parser that writes it to a database.
  7. Display: the user's client learns about the new message, through polling, a push connection or a refresh.

Any of these steps can add delay. Some add milliseconds; a few can add many minutes.

Delay 1: The Sender's Own Queue

Delays often start before the message leaves the sending company. Applications rarely send mail inline with the web request. They put a job on a queue, and a background worker sends it. If that worker is busy, for example because the company is also sending a marketing campaign or a large batch of notifications through the same pipeline, the verification email waits its turn.

Email delivery providers also apply sending limits per account, and sometimes per recipient domain. A service that suddenly sends far more mail than usual may be throttled by its own provider. Well-run systems send transactional mail (codes, password resets) through a separate, higher-priority stream than bulk mail. Not all do.

From the outside, this kind of delay is invisible. The website says the email was sent when, in reality, it was only queued.

Delay 2: Authentication Checks (SPF, DKIM and DMARC)

When a message arrives, the receiving server usually checks whether the sender is who it claims to be:

  • SPF checks whether the connecting server's IP address is authorised, by a DNS record of the sending domain, to send mail for the domain used in the envelope sender.
  • DKIM verifies a cryptographic signature in the message headers, using a public key published in DNS.
  • DMARC ties these together: it requires that SPF or DKIM passes for a domain aligned with the visible From address, and tells receivers what the domain owner wants done with failures.

These checks are mostly fast, because they involve a handful of DNS lookups that are often cached. They add delay mainly when DNS is slow or timing out. Their bigger effect is indirect: a message that fails authentication is more likely to be rejected, deferred or treated as spam, and some of those outcomes look like "the email never came" to the user.

If you run a sending domain, you can check its published records with the Email DNS Checker.

Delay 3: Greylisting

Greylisting is an old but still-used anti-spam technique. When a receiving server sees a combination of sending IP, sender address and recipient address for the first time, it deliberately responds with a temporary failure, a 4xx SMTP code meaning "try again later". A legitimate mail server will queue the message and retry. Much spam software historically did not retry, so the spam simply disappeared.

The cost is that the first legitimate message from a new sender is delayed by however long the sender waits before retrying, which is often several minutes and sometimes much longer. Subsequent messages from the same combination are usually accepted immediately because the receiver remembers it.

Greylisting is a particularly bad fit for one-time codes because, by definition, a verification email is often the first message from that sender to that recipient.

Delay 4: Retry Backoff After a Deferral

Greylisting is just one source of temporary failure. A receiving server may also defer mail because it is overloaded, because a database or filter behind it is unavailable, because it has reached a connection limit, or because the sender is being rate limited. In all these cases the message is not lost; it stays in a queue and is retried.

How long it waits depends on the queue software. Postfix, one of the most widely used mail servers, is a useful reference point: its default minimal_backoff_time is 300 seconds. A message that is deferred is typically not retried for about five minutes, and later retries are spaced further apart up to maximal_backoff_time. Other mail servers and delivery providers use their own schedules, but the principle is the same: a deferral rarely costs a few seconds. It usually costs minutes.

That is why a delayed code so often arrives "about five minutes late". The first attempt was deferred, and the message arrived on the first retry.

This applies on both sides of the internet. The sender's server may retry after a deferral from the receiver, and inside a receiving system, the mail server may retry local delivery if the component that stores mail was temporarily unavailable. When that happens, the message is not lost: it waits in the queue and is delivered on the next attempt, which from the user's side looks like a delay of roughly the backoff interval. Retries are the safety net that prevents loss, which is why the right fix for repeated delays is a more robust pipeline rather than skipping the queue.

Delay 5: Spam and Content Filtering

Receiving systems scan messages for spam signals and, often, for malware in attachments. Most scanning finishes in well under a second. But filters can also take longer under load, and messages judged suspicious may be quarantined or routed to a spam folder rather than delayed. To the user the effect is the same: the code is not where they are looking.

Verification emails trip filters for predictable reasons: brand-new sending domains with no reputation, missing or broken authentication, link-shortener URLs, image-only layouts and wording that resembles phishing ("verify your account immediately"). Senders can test a message's spam signals with the Spam Checker.

Delay 6: Rate Limits on Your Own Requests

Many sites limit how often you can request a new code, and some silently ignore requests made too quickly. Clicking "resend" five times may produce one email, five emails, or a temporary block, depending on the service. When several emails do arrive, usually only the most recent code is valid, because issuing a new code invalidates the old one.

Delay 7: The Last Step, Seeing the Message

Even after a message is stored, your screen has to find out about it. Desktop clients poll on a schedule, mobile apps may rely on push notifications that the operating system batches, and a browser tab in the background may be throttled. In a temporary inbox, the page receives new messages while it is open; a tab you closed, or one the browser has suspended, may need a refresh.

What You Can Do as a User

  1. Open the inbox first. Have the destination inbox open and visible before you press "send code". With InboxBurn, generate the address, copy it, and keep that tab open.
  2. Wait before resending. Give a delayed message at least a few minutes. Remember the retry interval: a single deferral often costs about five minutes. If you resend, use only the newest code.
  3. Check spam and promotions folders in a regular mailbox. Temporary inboxes show everything that arrives, so this step does not apply there.
  4. Check the address for typos. A mistyped domain is a common cause of mail that never arrives at all, not merely late.
  5. Choose a sensible lifetime. If a code may be slow and the account may need a second email later, do not pick the shortest option. InboxBurn lifetimes range from 10 minutes to 7 days, default 24 hours; see how long temporary emails last.
  6. Accept that some sites refuse disposable domains. If a site blocks temporary addresses, no amount of waiting will produce a code. See why websites block disposable email and use an address you control for that service.

What You Can Do as a Developer

If you send verification email, most delay is in your power to reduce.

  • Separate transactional and bulk mail. Use a separate queue, worker pool and ideally a separate sending stream or subdomain for codes and password resets so a newsletter can never delay a login.
  • Authenticate properly. Publish SPF, sign with DKIM, and set up DMARC for the sending domain. Check them with the Email DNS Checker.
  • Make code lifetimes realistic. A code that expires after two minutes will fail every time a greylisting server or a retry interval intervenes. Ten to fifteen minutes with a limited number of attempts is a common compromise.
  • Show the user what is happening. Tell them where the email was sent, how long to wait, and when the resend button becomes available. Keep previous codes valid for a short overlap or state clearly that only the newest works.
  • Put the code in the subject or first line so it shows in notification previews.
  • Monitor delivery time, not just send success. "Accepted by our provider" is not delivery.

Testing your own flow

Delays are easy to miss in testing because test mail usually goes to the same well-known inbox every time. Use fresh addresses and measure the time from request to arrival. A disposable inbox API is convenient for this: create an address, trigger your sign-up flow, then wait for the message with a timeout that reflects real-world delays rather than ideal ones.

js
// Create an inbox, then poll for the verification message.
const gen = await fetch('https://api.inboxburn.com/api/generate').then(r => r.json());
// ...trigger your app to send mail to gen.address...

async function waitForMail(address, token, timeoutMs = 120000) {
  const start = Date.now();
  while (Date.now() - start < timeoutMs) {
    const res = await fetch(`https://api.inboxburn.com/api/inbox/${address}`, {
      headers: { 'X-Inbox-Token': token },
    });
    const { emails } = await res.json();
    if (emails && emails.length) return emails[0];
    await new Promise(r => setTimeout(r, 5000)); // stay well under read limits
  }
  throw new Error('No email within timeout');
}

Keep polling intervals reasonable: the documented limits allow 20 inbox reads per minute and 10 anonymous address creations per minute. For pipelines that should not poll at all, API-key inboxes can deliver signed email.received webhooks. The API documentation has details, and the Playwright and Cypress guides show complete test setups.

When you record timings, store the distribution, not just the average. The average hides the cases that matter: the occasional message that took five minutes because of a deferral is the one that makes a real user give up.

The Short Version

Most verification emails arrive in seconds. When they do not, the usual causes are a backed-up sender queue, a temporary failure followed by a retry, greylisting of a first-time sender, or a filter routing the message somewhere unexpected. Retries are why a late code so often appears around five minutes late, and they are also why the message eventually arrives at all.

As a user, open the inbox first, wait a few minutes before resending, and use only the newest code. As a developer, separate transactional mail, authenticate your domain, and give codes a lifetime that survives a retry. For more background on codes themselves, read What Is OTP Verification, or get a temporary inbox for your next code.