Skip to content

Mail

Handle bounces and protect your sending

Read and edit the suppression list, understand what a bounce or a complaint does to it, and keep your sender reputation below the thresholds that throttle sending.

Receiving mail servers judge a sender by how much of their mail is unwanted. Lessly Mail keeps two records that protect you from that judgement: a suppression list of addresses it will not send to, and a reputation report showing how your recent sending looks from the outside. Both are maintained for you — what you do is read them, and occasionally correct them.

Check whether an address is suppressed

This is the question you actually have when a customer says their reset link never arrived. An agent calls mail_suppression_list; over REST it is GET /mail/suppressions on the Mail API.

The list is read a page at a time — between 1 and 100 entries, 50 by default — with a cursor for the next page. You can narrow it to a single reason, or to addresses containing a given substring, which is the fastest way to answer “is this customer suppressed, and why”. Each entry carries its address, its reason, its note, the moment it was added, and, when the entry came from a bounce or a complaint, a reference to the event that caused it.

Why addresses land on the list

The suppression list is a set of recipient addresses, held per product. Every send is checked against it, whichever way the message was created.

ReasonHow the address got there
hard_bounceA message to it was permanently rejected
complaintThe recipient marked a message as spam
unsubscribeThe recipient used an unsubscribe link
manualYou added it yourself

The first three are added for you, as the outcome arrives; you never have to prune your own lists after a bounce.

Addresses are stored trimmed and lower-cased, and matched that way. No other canonicalisation is applied: user+tag@example.com and user@example.com are two different addresses as far as the list is concerned.

Add or remove an address yourself

  1. Add one. You can suppress an address yourself — someone asked you by email to stop, or you know a mailbox is dead. An agent calls mail_suppression_add; over REST, POST /mail/suppressions. It takes the address and, optionally, a free text note of up to 1000 characters for whoever reads the list later. The reason is always recorded as manual.

    Adding is idempotent, and the first entry wins: adding an address that is already suppressed leaves the existing entry, and its original reason, untouched.

  2. Remove one. An agent calls mail_suppression_remove; over REST, DELETE /mail/suppressions/:address. It tells you whether an entry was actually there, so removing an address that was never suppressed is not an error.

Removal is the only way an address leaves the list — nothing expires on its own. Remove an entry only when you know the address is deliverable again; re-sending to an address that hard-bounced will bounce again and suppress it a second time.

What happens when you send to a suppressed address

Nothing is rejected outright. Suppression is applied per recipient, across to, cc and bcc:

  • Suppressed recipients are dropped from the message before it goes anywhere.
  • Every dropped recipient produces an email.suppressed event, so the skip is visible in the message’s history and on your webhooks.
  • If some recipients survive, the message is queued and sent to those only.
  • If every recipient was dropped, the message is never handed over at all. It is created with the status suppressed and ends there.

The check runs twice: when the message is accepted, and again immediately before it goes out. That second check is what makes a scheduled message safe — an address suppressed during the wait is still dropped.

Bounces and complaints

When the receiving side reports back, the outcome is recorded as an event on the message and, where it is decisive, on the message’s status.

OutcomeWhat it isEffect
Hard bounceA permanent rejection — the mailbox does not exist, the domain does not accept mailStatus becomes bounced; the recipient is added to the suppression list
Soft bounceTemporary — a full mailbox, a server that was busyRecorded as an event with bounce kind soft, or undetermined when the receiving server was not specific. The status does not change and no address is suppressed
ComplaintThe recipient pressing “this is spam”Status becomes complained; the address is suppressed

Every one of these is delivered to your webhooks as it happens, and appears in the message’s own history. See receive delivery events for the payload and send a message for reading a message back.

Read your reputation

An agent calls mail_reputation_get; over REST, GET /mail/reputation. Your sender reputation is a rolling measurement of how badly your recent sending went, computed over the last 7 days.

FieldMeaning
volumeRecipients of messages handed over in the window
hard_bounces, complaintsCounts of each in the window
hard_bounce_rate, complaint_rateThose counts over volume, as ratios between 0 and 1
thresholdsThe limits the two rates are measured against, and the minimum volume
gatedWhether sending is currently throttled
tripped_metrichard_bounce, complaint, or null when nothing tripped
window_daysThe length of the window the numbers cover

Two limits apply: a hard-bounce rate above 4% and a complaint rate above 0.08%. Neither is considered until the window holds at least 1000 recipients, so a handful of bounces on your first day of sending cannot throttle you. Above that volume, either rate crossing its limit sets gated and names itself in tripped_metric.

What happens while you are gated

Sending is paused for the whole product. New messages are rejected with a reputation_throttled error and a message naming the rate, the limit and the window. Messages already queued or scheduled are not sent either — they are checked again when they come due and end with the status blocked.

Nothing has to be reset by hand. The window keeps rolling, and as the offending rate falls back under its limit sending resumes on its own. The way out is to stop sending to addresses that bounce and to people who did not ask to hear from you; the suppression list does the first of those for you.

Because the report is recomputed at most once a minute, it can lag your very latest sends by up to that long.

Read your statistics

An agent calls mail_stats_get; over REST, GET /mail/stats. The statistics view aggregates a whole product over a period of 7, 30 or 90 days — 30 by default. It answers “how much did we send, and how much of it landed”.

GroupWhat it holds
Totalssent, delivered, bounced and complained for the period. sent counts recipients of messages that were handed over, not messages, so a single message to four people counts as four.
DeltasThe change in each total against the immediately preceding period of the same length, as a percentage. A delta is null when the previous period was zero, because there is no meaningful change from nothing.
VolumeOne bucket per UTC day across the period, each with its sent, delivered and bounced counts. Days with no activity are present with zeroes, so the series is always the full length of the period.
Deliverabilitydelivered, bounced and complained as percentages of sent, rounded to one decimal place, and zero when nothing was sent.

Delivered, bounced and complained counts are the events that arrived in the window. Because a message sent late in a window can be delivered after it closes, the delivered percentage of a very recent window reads low and settles as the outcomes come in.

Next steps

Was this page helpful?
Esc

Start typing to search the docs.

navigateselect