Guide

Debug Email Delivery from the Terminal

'I sent it but they didn't get it' is the hardest email bug because the failure is invisible from where you sit. Work it methodically: confirm the message actually sent, check whether it bounced, then rule out spam filtering and the SPF, DKIM, and DMARC checks that route mail to junk. The Nylas CLI gives you the first two answers directly from the Sent folder and bounce events. This guide is a step-by-step delivery debugging runbook.

Written by Nick Barraclough Product Manager

VerifiedCLI 3.1.16 · Gmail, Outlook · last tested June 8, 2026

Command references used in this guide: nylas email list, nylas email search, and nylas email read.

Step 1: Did the message actually send?

Start by confirming the message left your mailbox, because a surprising share of “didn't arrive” reports are messages that never sent. nylas email list --folder Sent --json shows your Sent items; if the message isn't there, the send failed — an auth error, a bad recipient, or an unhandled exception in your code — and the problem is upstream of delivery entirely.

If it is in Sent, the message reached the provider and was accepted for delivery. That narrows the problem to what happens after sending: a bounce or filtering. Note the message ID and recipient now, since the next steps key off them. Confirming the send first saves you from debugging delivery for a message that was never on the wire.

# Confirm the message is in Sent (it actually left)
nylas email list --folder Sent --json --limit 20 \
  | jq -r '.[] | [.id, (.to[0].email // ""), (.subject // "")] | @tsv'

Step 2: Did it bounce?

If the message sent but vanished, check for a bounce. A hard bounce — a non-existent address or a rejecting server — comes back as a delivery-status notification, usually from mailer-daemon or postmaster, landing in your inbox within minutes. Search for it; the bounce body carries an SMTP status code like 550 (mailbox unavailable) that names the exact reason.

Read the bounce to classify it: a 5xx code is permanent (the address is bad or blocked), while a 4xx is temporary (the receiving server deferred and may accept a retry). A permanent bounce means stop sending to that address; a transient one means wait and retry. No bounce at all, with the message confirmed sent, points to the third cause: filtering.

# Look for a bounce / delivery-status notification
nylas email search "from:mailer-daemon OR subject:undelivered" --json --limit 10 \
  | jq -r '.[] | [.id, (.subject // "")] | @tsv'

# Read the bounce body for the SMTP status code (e.g. 550)
nylas email read MSG_ID --json | jq -r '.body' | grep -iE 'status|550|554|452'

Step 3: Did it land in spam?

If the message sent and didn't bounce, it almost certainly delivered — into the spam folder. The cause is usually authentication: receiving servers check SPF, DKIM, and DMARC, and a failure on any of them is a strong spam signal. Verify the sending domain publishes a valid SPF record, signs with DKIM, and has a DMARC policy, because a domain missing these gets filtered hard.

These three records are the backbone of modern deliverability; DMARC (RFC 7489) ties SPF and DKIM together and tells receivers what to do when a check fails. Since February 2024, Google and Yahoo require SPF, DKIM, and DMARC for bulk senders, so a domain without them sees real filtering. If all three pass and mail still lands in spam, the issue is reputation or content, not authentication.

Next steps