Why Gmail SMTP fails in production

Pointing your app at `smtp.gmail.com` is the fastest way to get email working, and the fastest way to acquire a production incident. It fails in at least four independent ways, and each one produces a different symptom, which is why people fix one and think they are done.

4 min read

Your password stopped working

Google withdrew basic authentication for SMTP. A regular account password no longer authenticates, so the failure looks like this:

535-5.7.8 Username and Password not accepted.

The workaround is an app password, which requires two-step verification on the account. It is a sixteen character credential scoped to one application, which is better than your account password but still a long-lived secret sitting in an environment variable, tied to a human's personal account, and revoked the day that person leaves or Google prompts a security review.

Workspace administrators can also disable app passwords for the whole domain, at which point your production sending stops with no code change on your side.

The daily limit is a person's limit

Gmail's SMTP relay is metered for a human sending mail, not an application sending notifications. Free Gmail accounts have a substantially lower ceiling than Workspace accounts, and the exact figures move, so check Google's current sending limits documentation rather than trusting a number in a tutorial.

What matters is the shape: the limit is per day, it counts recipients rather than messages, and hitting it does not fail loudly at first. You get a temporary block, sends start deferring, and the account may be restricted for a period. A single launch email to a few hundred users will find it.

You also cannot send to a large bcc list to get around it, because recipients are what is counted.

Your From address is being rewritten

This is the failure nobody predicts. Gmail will not let you send as an arbitrary address. Set from: 'noreply@acme.com' while authenticating as you@gmail.com and one of two things happens: the header is rewritten to the authenticated account, or the message is sent with a mismatch that receivers treat as spoofing.

Even after you add the address as a verified alias, the DMARC problem remains. Gmail signs with gmail.com, your From says acme.com, and the DKIM signature does not align with the visible From domain. DMARC fails, and if you publish p=quarantine or p=reject you are asking receivers to bin your own mail. This is the alignment concept explained in SPF, DKIM, and DMARC explained for developers.

The result is a message that is technically delivered and practically invisible, sitting in a spam folder your users never open.

Serverless makes it worse

If the code sending through Gmail runs in a serverless function, add the transport problems on top: outbound SMTP ports are commonly blocked, the handshake plus a cold start can exhaust the execution budget, and there is no persistent connection to reuse. Those are covered in why nodemailer does not work on Vercel.

What each symptom actually means

SymptomCauseFix
535-5.7.8 on authBasic auth withdrawnApp password, or move off Gmail
Sends work then stop for hoursDaily recipient limit reachedMove off Gmail
From address appears as your GmailGmail rewrote an unverified senderMove off Gmail
Delivered but always in spamDKIM signed by gmail.com, not alignedMove off Gmail
Connection times out in production onlyServerless, port blocked or budget exceededSend over HTTPS
550-5.7.1 on a bulk sendTreated as unsolicited bulk mailMove off Gmail

Four of six rows say the same thing, which is the point. Gmail SMTP is a personal mail transport being used as an application transport.

What to do instead

Send over an HTTPS API from a domain you control and can sign with your own DKIM. One request, no ports, no personal account in the loop, and a DKIM signature that aligns with your From address.

Shell
curl -X POST https://emails.sh/v1/emails \
  -H "Authorization: Bearer $EMAILSSH_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "from": "Acme <noreply@acme.com>",
    "to": ["someone@example.com"],
    "subject": "Reset your password",
    "html": "<p>Choose a new password using the link below.</p>",
    "text": "Choose a new password using the link below.",
    "reply_to": "support@acme.com"
  }'
Python
import os, requests

requests.post(
    "https://emails.sh/v1/emails",
    headers={"Authorization": f"Bearer {os.environ['EMAILSSH_API_KEY']}"},
    json={
        "from": "Acme <noreply@acme.com>",
        "to": ["someone@example.com"],
        "subject": "Reset your password",
        "html": "<p>Choose a new password using the link below.</p>",
        "text": "Choose a new password using the link below.",
    },
    timeout=10,
).raise_for_status()

Set reply_to to an address a human reads. noreply@ as a From address is fine; as the only route back to you it is hostile.

When Gmail SMTP is genuinely fine

It is not always wrong. A cron job on a server you own that mails you and two colleagues once a day is exactly what the relay is for. The line is whether the recipients are people you know or people who signed up. As soon as strangers receive it, you need your own authenticated domain.

Check what receivers see

The fastest confirmation that you have fixed it is the header block on a delivered message.

Authentication-Results: mx.example.com;
  dkim=pass header.d=acme.com;
  dmarc=pass header.from=acme.com

header.d matching your own domain is the line that matters. Paste a full header block into the email header analyzer if you want it read out, or run a message through the mail tester.

Questions

Can I use Gmail SMTP for a production app?
Only if the recipients are you and a handful of colleagues. For user-facing mail the daily recipient limit, the From rewriting, and the DKIM alignment failure make it unsuitable regardless of how you authenticate.
Does a Google Workspace account fix the limits?
It raises them, but the ceiling is still a per-user daily figure meant for a person. The alignment problem also remains unless you send from a domain you sign yourself.
Why do my Gmail-sent emails go to spam?
Most often because the DKIM signature belongs to gmail.com while the From header shows your domain, so DMARC does not pass alignment. Receivers treat unaligned mail claiming to be from your brand as suspicious.
What is the minimum change to fix this?
Verify your domain with a sending provider, publish the DKIM entries they give you, and swap the SMTP call for an HTTPS POST. The code change is one function; the DNS change is a single visit to your registrar.

Give your agent an address it can answer from.

Create an inbox