BookMySpot

Developer Guides

Logging email so you can answer "where did it go?"

The question that arrives in support is always the same shape: a specific person did not get a specific message, and someone needs to know why.

Answering it requires three things, and systems that cannot answer it are usually missing the third.

What to record

Accepted. When the message entered the system, who it was for, which stream, and the ID you gave it. Without an ID you cannot discuss a message at all.

Attempted. When delivery was tried, which IP it went out on, and which host it connected to.

The remote response, verbatim. The full line the receiving server returned, including the text after the code. This is the one that gets dropped, and it is the one that contains the answer.

A log that says status=deferred tells you nothing. A log that says deferred: 421 4.7.0 too many connections from your IP tells you exactly what to change.

What to key on

Give every message an ID at acceptance, return it from the API, and put it in every subsequent log line, event and webhook. Everything else follows from being able to join on one value.

Also record the SMTP queue ID from your MTA. When you need to correlate with the MTA's own logs — and eventually you will — that is the join key on the other side.

Bounces have to join back

A bounce arrives as a separate message, potentially hours later. Attributing it requires either VERP or reliable Message-ID quoting, and the second is unreliable.

Without attribution, your bounce log is a list of failures nobody can connect to anything, and suppression becomes guesswork.

Retention

Message content and recipient addresses are personal data under most regimes. Metadata — IDs, timestamps, status codes — is far less sensitive and far more useful for debugging.

A workable split: content for days, metadata for months. That answers "what happened to this message" long after you have stopped storing what the message said.

Make it visible to the customer

In a multi-tenant system, the customer should be able to look up a message themselves and see the status, the timeline and the remote response. This is not a nice-to-have: it is the difference between a support ticket and a customer who diagnosed their own typo in thirty seconds.

Show the remote response text. It frequently contains a URL explaining the policy that was applied, and the customer can read it as well as you can.

What not to log

Credentials, obviously. API keys in full — log a prefix so a key can be identified without being usable. And be careful with full message bodies at debug level, which is how production logs end up holding password reset links.

Ready to send authenticated mail?

DKIM signing, SPF alignment and DMARC are set up the moment you verify a domain.

Get started