emailverifier.dev
Posts

Email Feedback Loops: ARF Reports vs Aggregate Complaints

| 5 min read | Usama Ejaz
One email complaint splits into an individual recipient-suppression path and an aggregate campaign-investigation path.

An email feedback loop is a channel through which a mailbox provider reports user complaints to a verified sender. A traditional loop can send one Abuse Reporting Format (ARF) message for one complaint and may identify the recipient. An aggregate loop reports a campaign-level signal without naming the person who complained. Suppress an identified recipient from the first; investigate the campaign from the second.

The same complaint can produce two different records

RFC 6449 describes the traditional complaint feedback loop: a mailbox user marks a message as spam, the provider creates a feedback message, and an authorized feedback consumer receives it. M3AAWG’s feedback-loop overview separates that model from aggregate feedback loops that roll complaints up by IP, domain, or a sender-defined identifier.

Question Traditional ARF report Aggregate feedback
What arrives? One report about one original message Counts or rates grouped by an identifier
Can it identify a recipient? Sometimes; providers may redact it No recipient-level identity
Safe immediate action Suppress the identified recipient in the relevant messaging scope Investigate or pause the affected campaign
What it proves A provider relayed a complaint about that message A campaign or stream has a complaint signal

A complaint is not a legal verdict that the sender is a spammer. RFC 6449 says the provider forwards complaints without judging their validity. Operationally, I still treat an individual complaint as a strong send-preference signal. The goal is to stop unwanted repeat mail, not debate the recipient.

What is actually inside an ARF complaint?

RFC 5965 defines an ARF report as multipart/report with report-type=feedback-report. It has three parts:

  1. A human-readable explanation.
  2. A machine-readable message/feedback-report part.
  3. The original message or its complete header block.

This is a hypothetical, shortened machine-readable part:

Content-Type: message/feedback-report

Feedback-Type: abuse
User-Agent: ExampleMailbox/1.0
Version: 1
Original-Mail-From: <bounce@news.example>
Original-Rcpt-To: <alex@example.net>
Arrival-Date: Sat, 03 Oct 2026 03:30:00 +0000

Do not build the decision from the prose section. Read the MIME structure, inspect the machine-readable fields, and use the attached original headers to correlate the message with your own send log.

There are two limits worth keeping visible. First, Original-Rcpt-To is optional, and a provider may redact recipient data. Second, RFC 5965 warns that assertions in the machine-readable fields are not necessarily verifiable. I would accept reports only through a provider channel that was enrolled and authenticated, then match the report to a message or campaign I actually sent.

Gmail’s feedback loop is aggregate, not a recipient feed

As of October 3, 2026, Gmail’s Feedback Loop documentation tells large-volume senders to add one Feedback-ID header with up to three optional identifiers and one mandatory sender identifier:

Feedback-ID: onboarding-42:customer-7:transactional:sender1

Gmail aggregates complaint data for those identifiers in Postmaster Tools. The message must be DKIM-signed by a controlled domain after the header is added, and that domain must be verified in Postmaster Tools. Gmail explicitly says not to use a value unique to each message, such as Message-ID.

This means Gmail’s dashboard can point to a campaign, customer, or mail type with an unusual complaint signal. It cannot tell your application which mailbox to suppress. Google also notes that dashboard data is not real time, can take more than 24 hours to update, and may be withheld on low-volume days for privacy.

So the absence of a Gmail feedback-loop row is not proof of zero complaints. It can mean insufficient volume, insufficient distinct complaints, delayed data, or no qualifying signal.

Route complaints through two scopes

I use one intake boundary and two possible scopes: recipient and campaign. Here is the policy core, intentionally separate from MIME parsing and provider authentication:

export function planComplaint(event, seen = new Set()) {
  if (!event.trustedSource) {
    return { action: 'quarantine', scope: 'none' };
  }

  const key = `${event.provider}:${event.reportId}`;
  if (seen.has(key)) return { action: 'ignore', scope: 'none' };
  seen.add(key);

  if (event.kind === 'aggregate') {
    return { action: 'investigate', scope: 'campaign' };
  }

  if (event.kind === 'arf' && event.recipient) {
    return {
      action: 'suppress',
      scope: 'marketing',
      recipient: event.recipient,
    };
  }

  return { action: 'investigate', scope: 'campaign' };
}

The surrounding pipeline should record the enrolled provider or trusted transport, a stable report ID for idempotency, whether the evidence identifies a recipient or only a campaign, the message class covered by a suppression, and the original send record used for correlation.

I ran this policy against five fixtures: an identified ARF complaint, a redacted ARF complaint, an aggregate report, an untrusted payload, and a duplicate delivery. All five checks passed.

But what if the recipient clicked “spam” by mistake?

That happens. It still does not justify sending the same marketing campaign again. I would record the complaint as an event, suppress marketing for that recipient, and require an explicit later action before reversing it. I would not automatically disable password resets, receipts, or another legally or operationally required message class.

This is why the suppression-list model stores reason, source, scope, and time instead of one global Boolean. It is also why a working one-click unsubscribe path matters: a recipient who can leave cleanly has less reason to use the spam button.

Email verification does not replace complaint handling

Email verification answers questions about address format, routing, provider risk, and available mailbox evidence before a send or signup decision. It does not prove continuing consent, and it cannot promise that a recipient will welcome a future campaign.

Keep those systems separate. Verification can protect signup quality. Confirmation can show that someone controlled an inbox at a point in time. A feedback loop tells you how recipients reacted after delivery. The validation, verification, and confirmation guide owns the first boundary; the complaint pipeline owns the last one.

Recipient-level evidence can create a scoped suppression. Aggregate or redacted evidence should change the campaign state and trigger investigation. Keeping those actions separate prevents repeat unwanted mail without guessing which person complained.

Continue reading