What this usually means
When SendGrid accepts an email (HTTP 202) but it never arrives, the problem is almost never a bug in your code — it's a delivery failure on the receiving side. The email was handed off to the recipient's mail server, but that server rejected it or silently dropped it before it hit the inbox. The root causes fall into three camps: authentication failures (SPF/DKIM/DMARC), recipient-side filtering (spam, blocklists, rate limiting), or SendGrid account-level issues (suppression lists, IP reputation, plan limits). The tricky part is that SendGrid often marks these as 'Delivered' because the SMTP handshake succeeded at the server level, but the recipient's policy then discards the message. You need to correlate SendGrid's event logs with the recipient's mail logs — which you often can't see directly — so you must deduce the cause from indirect signals.
The first ten minutes — establish facts before touching code.
- 1Check SendGrid Email Activity (https://app.sendgrid.com/email_activity) for the specific message ID. Filter by recipient email and look at the 'Events' column — if it shows 'Delivered' but user didn't get it, it's likely spam-filtered.
- 2Check SendGrid Suppressions (https://app.sendgrid.com/suppressions) — add the recipient email to see if it's on a bounce, spam report, or unsubscribe list.
- 3Run SPF/DKIM/DMARC check using a tool like MXToolbox (https://mxtoolbox.com/deliverability.aspx) on your sending domain. Enter your domain, not SendGrid's.
- 4Examine SendGrid Event Webhook logs (if configured) for 'bounce', 'dropped', or 'spamreport' events. If you're not using the webhook, set it up.
- 5Send a test email to a Gmail address and check the full headers (Show Original) for 'Authentication-Results' and 'Received-SPF' lines.
- 6Check your SendGrid account's 'Reputation' tab (https://app.sendgrid.com/settings/reputation) for IP warmup status or blocklist alerts.
The specific files, logs, configs, and dashboards that usually own this bug.
- searchSendGrid Email Activity feed: https://app.sendgrid.com/email_activity
- searchSendGrid Suppressions page: https://app.sendgrid.com/suppressions
- searchSendGrid Event Webhook payloads (your endpoint logs or a log sink like Papertrail)
- searchMXToolbox Deliverability report for your domain: https://mxtoolbox.com/deliverability.aspx
- searchGmail 'Show Original' headers (or Outlook 'Message Properties') for any test emails sent
- searchSendGrid IP Reputation dashboard: https://app.sendgrid.com/settings/reputation
- searchYour DNS provider's TXT records for SPF, DKIM, and DMARC
Practical causes, not theory. These are the things you will actually find.
- warningMissing or misconfigured SPF record: the recipient's server sees the email as not authorized by the domain owner.
- warningMissing or incorrect DKIM signature: SendGrid's DKIM key hasn't been added to your DNS, or the domain mismatch causes failure.
- warningRecipient email address on a SendGrid suppression list (bounce, spam, unsubscribe) — silent drop by SendGrid itself.
- warningSending domain or IP has poor reputation: on a public blocklist (e.g., Spamhaus) or SendGrid's internal reputation is low due to high bounce rate.
- warningDMARC policy set to 'p=reject' or 'p=quarantine' without proper alignment — legitimate emails get rejected or spammed.
- warningRecipient's mail server is rate-limiting or greylisting — SendGrid retries but eventually drops after TTL expires.
- warningContent triggered recipient's spam filter (e.g., too many links, spammy phrases, missing unsubscribe link for bulk mail).
Concrete fix directions. Pick the one that matches your root cause.
- buildAdd/update SPF record: include 'include:sendgrid.net' in your domain's TXT record. Example: 'v=spf1 include:sendgrid.net ~all'.
- buildAdd SendGrid DKIM record: create a CNAME record for 's1._domainkey.yourdomain.com' pointing to 's1.domainkey.u123456.wl.sendgrid.net' (your account-specific).
- buildSet up DMARC record with monitoring first: start with 'v=DMARC1; p=none; rua=mailto:you@yourdomain.com' to see alignment reports.
- buildRemove recipient from SendGrid suppressions: go to Suppressions, find the email, and delete the entry. For unsubscribes, they must re-subscribe.
- buildImprove sender reputation: warm up a dedicated IP by gradually increasing volume over 2-4 weeks. Keep bounce rate below 2%.
- buildAdd a List-Unsubscribe header for bulk mail: SendGrid adds it automatically for marketing campaigns, but transactional emails may need manual header injection.
- buildContact SendGrid support to request IP remediation if your IP is on a blocklist — they can submit removal requests.
A fix you cannot prove is a guess. Close the loop.
- verifiedSend a test email to the same recipient that failed — now it should arrive in inbox (or at least spam).
- verifiedCheck SendGrid Email Activity for the test message — events should show 'Delivered' and ideally 'Open'.
- verifiedRun a DMARC report check after 24 hours — you should see 'PASS' for SPF and DKIM.
- verifiedUse a tool like Mail-Tester.com (https://www.mail-tester.com) to score your email content and headers.
- verifiedMonitor SendGrid Event Webhook for any 'bounce' or 'spamreport' events over the next 48 hours.
- verifiedAsk the recipient to check spam folder and mark as 'Not Spam' to train their filter.
Things that make this bug worse or harder to find.
- warningAdding multiple SPF records — SPF allows only one TXT record; multiple records cause 'PermError' and SPF fails. Combine all includes into one record.
- warningUsing '~all' (softfail) for SPF and expecting strict enforcement — many servers treat softfail as pass. Use '-all' for hard fail if you're confident.
- warningForgetting to update DKIM when switching SendGrid subusers or account IDs — the CNAME target changes per subuser.
- warningSending high volume from a new IP without warmup — you'll hit rate limits and reputation drops immediately.
- warningIgnoring SendGrid's 'Deferred' events — these indicate temporary delivery failures and can escalate to permanent bounces.
- warningAssuming 'Delivered' in SendGrid means the email is in the inbox — it only means the recipient server accepted it. The server may then filter it.
The 202 That Went Nowhere
Timeline
- 09:00Deploy password-reset flow using SendGrid; API returns 202 for test email.
- 09:05User reports not receiving password reset email; no bounce on our side.
- 09:15Check SendGrid Email Activity — shows 'Delivered' for the user's email.
- 09:20Send test from the same code to my personal Gmail — lands in spam with 'SPF fail' header.
- 09:30MXToolbox SPF check: our domain has no SPF record at all (DNS oversight).
- 09:45Add SPF record: v=spf1 include:sendgrid.net ~all. Also add DKIM CNAME.
- 10:00Re-send test — Gmail delivers to inbox; user gets the password reset email.
- 10:15Monitor SendGrid Event Webhook for 24 hours — no bounces.
We had been using SendGrid for transactional emails for months without issue — or so we thought. When we rolled out a password-reset feature, users started complaining that they never received the email. Our logs showed the API returned 202 every time, and SendGrid's dashboard marked them as 'Delivered'. I assumed it was user error or a slow inbox. But when three separate users from different domains reported the same problem, I knew something was wrong.
I sent a test from our production server to my Gmail address. Gmail delivered it straight to spam. I opened the headers and saw 'Received-SPF: fail (google.com: domain of ourdomain.com does not designate 167.89.x.x as permitted sender)'. We had never set up SPF. We also had no DKIM. SendGrid had been silently delivering our emails into spam folders for months, and we never noticed because we only tested internally. The 'Delivered' status in SendGrid meant the recipient server accepted it — but then Gmail's policy dropped it in spam due to failed authentication.
I added the SPF record (include:sendgrid.net) and the DKIM CNAME record provided by SendGrid. After DNS propagation (about 10 minutes), I re-sent the test — it landed in inbox with 'PASS' for both SPF and DKIM. The user also confirmed receipt. We also set up DMARC with p=none to monitor. What I learned: never trust 'Delivered' in SendGrid; always verify with a test to a strict provider like Gmail, and always set up email authentication before sending to customers.
Root cause
Missing SPF and DKIM records for the sending domain. Recipient servers (Gmail, Outlook) treated the email as unauthenticated and either rejected it or filtered to spam.
The fix
Added SPF TXT record ('v=spf1 include:sendgrid.net ~all') and DKIM CNAME record ('s1._domainkey.yourdomain.com' pointing to SendGrid's key). Verified with Gmail headers and MXToolbox.
The lesson
Always configure SPF, DKIM, and DMARC before sending production emails. Monitor SendGrid's event webhook for bounce/spam reports, not just the API response.
When your app calls SendGrid's API and gets a 202, it means SendGrid has accepted the message into its queue. It does NOT mean the email was delivered to the recipient's server. SendGrid will attempt delivery, but the email passes through several stages: processed, delivered, open, click, bounce, spamreport, etc. The 'Delivered' event fires when the recipient's mail server acknowledges receipt at the SMTP level. That server may then apply its own filtering (SPF, DKIM, content scanning) and either deliver to inbox, move to spam, or silently delete. SendGrid will never know if the email went to spam unless the recipient marks it as spam and a feedback loop is configured.
The key insight: 'Delivered' in SendGrid is NOT 'Inbox'. It's 'Handed off to recipient server'. To bridge that gap, you need to monitor recipient-side signals: Gmail's 'Authentication-Results' headers, DMARC aggregate reports, and feedback loops. Without those, you're flying blind. I've seen teams celebrate a 100% delivery rate while 60% of their emails went to spam.
One of the most common reasons emails silently disappear is that the recipient address is on a SendGrid suppression list. SendGrid maintains three types: Bounces (permanent delivery failures), Spam Reports (user marked as spam via feedback loop), and Unsubscribes (user clicked unsubscribe link). If an address is suppressed, SendGrid will accept the API call (202) but will NOT attempt delivery — it's a silent drop. And here's the trap: SendGrid does not expose suppression status in the API response. You have to query the Suppressions API or check the dashboard manually.
The fix is to immediately check the Suppressions page when a user reports non-delivery. If they're on the list, you can remove them (except unsubscribes — those require the user to opt back in). Preventative: always include a List-Unsubscribe header and honor unsubscribe requests for transactional emails? Actually, transactional emails should not be suppressible by unsubscribe, but SendGrid treats all suppression types the same. Use separate sender identities for transactional vs. marketing to avoid cross-contamination.
When you start using SendGrid on a shared IP (default), your reputation is tied to all other senders on that IP. If you're on a dedicated IP, you start with a neutral reputation, but you must warm it up by gradually increasing volume over 2-4 weeks. If you blast 10,000 emails on day one, recipients' servers will rate-limit and block you. The symptom: emails to major providers like Gmail, Outlook, and Yahoo get 'Deferred' then eventually 'Dropped' after multiple retries. SendGrid's dashboard may show a drop in reputation score.
Check your IP reputation on SendGrid's Reputation page. If it's low, you need to reduce volume and ensure high engagement (opens, clicks) to rebuild. You can also use SendGrid's 'IP Warmup' feature that automatically ramps up volume. Also check if your IP is on any public blocklists like Spamhaus by using MXToolbox's blacklist check. If it is, you'll need to request delisting and show evidence of corrective actions.
When you send a test email to a Gmail account, you can view the full headers via 'Show Original'. Focus on three lines: 'Received-SPF', 'Authentication-Results', and 'DKIM-Signature'. The SPF line will say 'pass', 'fail', 'softfail', or 'neutral'. If it's not 'pass', your SPF record is missing or misconfigured. The Authentication-Results will show 'dkim=pass' or 'dkim=fail'. If DKIM fails, check that your CNAME record points to the correct SendGrid key and that the domain matches the 'From' address (alignment).
Also look for 'ARC-Authentication-Results' which is a newer standard. If you see 'spf=permerror', it means you have multiple SPF records — fix that immediately. Another useful header is 'X-Google-Smtp-Source' which can indicate if Gmail considers the email as bulk or not. If you don't have access to a Gmail account, use a service like Mail-Tester.com that generates a unique email and provides a full report.
If you're not using SendGrid's Event Webhook, you're missing the most important diagnostic tool. The webhook sends HTTP POST requests to your endpoint with JSON payloads for every event (processed, delivered, open, click, bounce, dropped, spamreport, deferred). For silent delivery failures, the 'bounce' and 'dropped' events are critical. A 'dropped' event with reason 'Invalid SMTPAPI header' or 'Bounced Address in Suppression List' tells you exactly why the email wasn't delivered. Bounce events include the response from the recipient server (e.g., '550 5.1.1 user unknown').
Set up a webhook endpoint that logs all events to a database or a log aggregator. When a user reports non-delivery, search for that email in your webhook logs. If you see a 'bounce' event with a 550 code, you know the address doesn't exist. If you see 'processed' but no 'delivered', the recipient server may have silently dropped it — then you need to check authentication. Without the webhook, you're debugging with one hand tied behind your back.
Frequently asked questions
Why does SendGrid show 'Delivered' when the email never arrived?
'Delivered' in SendGrid means the recipient mail server accepted the message at the SMTP level. That server then applies its own policies (spam filtering, authentication checks) and may deliver to spam or silently discard it. SendGrid cannot see what happens after the handoff. You need to use SPF/DKIM/DMARC and monitor recipient-side signals (headers, DMARC reports) to ensure inbox placement.
How do I check if my domain's SPF record is correct for SendGrid?
Use MXToolbox's SPF checker (https://mxtoolbox.com/spf.aspx). Enter your domain. Look for 'include:sendgrid.net' in the record. Also ensure there's only one TXT record for SPF (multiple records cause PermError). If you use other services (like Mailchimp), combine them into one record: 'v=spf1 include:sendgrid.net include:servers.mcsv.net ~all'.
My recipient says they didn't unsubscribe but they're on the suppression list. What happened?
SendGrid automatically adds an address to the 'Bounces' list if the recipient server returned a permanent error (e.g., user unknown). It could also be that the user clicked 'Report Spam' in their email client, which triggered a spam report suppression. If it's a bounce or spam report, you can remove them from the Suppressions page. For unsubscribes, you cannot remove them — the user must opt back in via your subscription form.
I added SPF and DKIM but emails still go to spam. What else could be wrong?
Check DMARC alignment — your 'From' domain must match the DKIM signing domain (or SPF domain). Also check your IP reputation: run a blacklist check. If you have a dedicated IP, ensure it's warmed up. Content issues: too many images, links, or spammy words can trigger filters. Use Mail-Tester.com to get a spam score. Also, some recipients' servers require a reverse DNS (PTR record) for your sending IP — SendGrid sets this for dedicated IPs, but for shared IPs, it's already configured.
How can I test email deliverability before going live?
Set up a test email account on Gmail, Outlook, and a custom domain (e.g., using a free service like Yandex). Send test emails from your staging environment. Check the headers for SPF/DKIM/DMARC results. Use Mail-Tester.com to get a score and improvement suggestions. Also configure the Event Webhook in a staging SendGrid account to monitor events. Finally, send a small batch (20-50 emails) to a test list and track open rates — low opens may indicate spam filtering.