No Idempotency Key? How I Make Gmail Sends Safe to Retry Anyway
Description and use
Gmail lacks an idempotency key, so a failed send leaves uncertainty about delivery. The solution is to generate a deterministic Message‑ID, store it, query Gmail for that ID, and if ambiguous, move the job to a review queue. This enables safe retries and avoids duplicates.
Problem
Gmail’s messages.send lacks an idempotency-key, so a failed send with no response leaves uncertainty whether the email was delivered.
Outcome
Implementing deterministic Message‑IDs and mailbox reconciliation turns Gmail sends into a safe, retry‑friendly process, reducing duplicate emails and ensuring critical actions are not retried automatically.
Workflow
- 1. Classify failure into Bucket 1 (definitely not accepted) or Bucket 2 (maybe accepted).
- 2. For Bucket 1, back off and retry automatically.
- 3. For Bucket 2, place job in a review queue for human decision.
- 4. When sending, set a deterministic Message‑ID derived from the job’s dedup key.
- 5. After sending, query Gmail with messages.list?q=rfc822msgid:
<Message‑ID>to check if the message exists. - 6. If not found, wait 1–2 minutes and retry the query.
- 7. If found, count occurrences; if >1, flag duplicate.
- 8. Store job state in Postgres table ai_jobs with fields id, message_id, state, payload, attempts, claimed_at, provider_ref.
- 9. Sweeper reconciles mailbox status before re‑sending any job.
Evidence
Gmail's messages.send has no idempotency-key parameter.
Bucket 2 never auto-retries. It lands in a review queue with everything a human needs to decide.
When I build the raw MIME for the send, I set the header myself: Message-ID: <job-9f3a2c1b@yourdomain>
Gmail stores the Message-ID you gave it, so the mailbox becomes your acceptance log.
Caveat 1 — the search index lies for a minute.
- Record date: 2026-10-11T14:41:22.046Z