Email jobs

Backed by: @pithy-sh/email. Scopes: email:jobs:read · email:jobs:retry · email:suppressions:read · email:suppressions:write · email:suppressions:delete.

Silent email failure costs a signup, which is why this pane exists.

The statuses

Each is the job model’s own. Bounces and suppression is why a send stops, deliverability is how to keep it from happening, and feedback tracking is what the opens and clicks are.

pendingImmediate, awaiting dispatch
scheduledA future send time
sendingIn flight
sentSucceeded
failedExhausted its retries
suppressedSkipped — the address is on the list
bouncedReported undeliverable
undispatchedThis composition binds no send Workflow
canceledWithdrawn before sending

undispatched is a configuration fact, not a transient one. Nothing was started and nothing is coming while that holds — and the scheduler claims those rows as soon as a host Worker exists.

A status that says your wiring is incomplete is worth more than a pending row that quietly never moves.

Retrying one

email:jobs:retry, and the retry sets the batch id in the same statement that makes the row queryable again — because a row naming an instance that is not working it turns the scheduler’s veto into a lie in one of two directions.

The suppression list

Four reasons, and two of them block everything:

Blocks
hard_bounceEverything
complaintEverything
unsubscribeElective mail only
manualWhat you set it for

Somebody who unsubscribed from your newsletter has not stopped being able to sign in.

Removing a suppression is a POST with a body

Not a path parameter.

An address in a path is an address in every access log, proxy, trace and referrer between the client and the Worker.

The suppression database is shared across environments

Deliberately — an unsubscribe has to apply everywhere, and somebody who opted out in production has not agreed to receive staging’s mail.

One thing this pane cannot show you everywhere

Bounce attribution is platform-limited. There is one inbound Worker per domain, and it is production’s.

So feature and staging environments see their own opens, clicks and unsubscribes — but not asynchronously-routed bounces.

email/suppressed is not a failure to fix

The address is on the opt-out list, and that is the list working.

ESC