> ## Documentation Index
> Fetch the complete documentation index at: https://docs.orbit.devotel.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Gmail & Yahoo Bulk-Sender Requirements as a Compliance Posture

> Google and Yahoo's sender requirements, published October 2023 and enforced for bulk senders above 5,000 messages/day since February 2024 — SPF + DKIM signing, a DMARC record with p=none minimum, RFC 8058 one-click unsubscribe, and a spam-rate ceiling — mapped to the Orbit surfaces you configure them on.

# Gmail & Yahoo Bulk-Sender Requirements as a Compliance Posture

Google and Yahoo published a joint set of sender requirements in
October 2023 and have enforced them for **bulk senders — anyone above
5,000 messages per day — since February 2024**. The regime is not a
statute and not an Orbit policy: it is the acceptance policy of the two
largest mailbox providers your email lands on, and a violation is
answered with **rejection**, not merely spam-folder placement. Messages
from a non-compliant bulk sender bounce at Gmail's and Yahoo's doors
with a policy rejection, so the surface behaves like a compliance
gate even though no law created it.

The obligations are **tenant-owned**. Orbit verifies your domain and
carries the headers, but the SPF/DKIM/DMARC records live in *your* DNS,
the complaint rate is produced by *your* list, and the spam-rate floor
is scored by Google Postmaster Tools against *your* sending domain.
This page maps each obligation to the Orbit surface you read or
configure it on, so a bulk sender can close the regime deliberately
instead of discovering it in a rejection spike.

<Note>
  This page is guidance, not legal advice. The exposure here is not a
  fine — it is **deliverability rejection at the recipient mailbox
  provider**. The statutory layers that sit beside this regime
  (CAN-SPAM in the US, CASL in Canada, the Spam Act in Australia)
  specify content and consent rules and are documented on their own
  pages; nothing in this page replaces them.
</Note>

***

## The four obligations, mapped to Orbit surfaces

The 2024 regime has four mechanical requirements. For each: what the
rule demands, and where the control lives in Orbit.

| # | Obligation | Where the control lives in Orbit |
| - | - | - |
| 1 | **SPF + DKIM signing** — every bulk message must authenticate with SPF and DKIM for its `From` domain | **Domain verification** — Orbit provisions and verifies both records before a custom domain can send; the daily health check re-validates and the **Verify DNS** button re-checks on demand (see [Email → Domain Setup](/channels/email#domain-setup)) |
| 2 | **A DMARC record on the `From` domain** — `p=none` is the technical floor; `p=quarantine` or `p=reject` is the recommended posture | **The DMARC row in your domain's DNS table and the per-record traffic-light read** — `GET /api/v1/email/domains/:domainId/dns-status` returns the `dmarc` record's status and its live `recordActual` value, so the policy you published is observable (see [Posture configuration](#posture-configuration)) |
| 3 | **RFC 8058 one-click unsubscribe on marketing traffic** — the `List-Unsubscribe` + `List-Unsubscribe-Post` header pair; a bare mailto link no longer suffices | **Transport headers Orbit attaches automatically on every outbound email** — the signed HTTPS unsubscribe URL + `List-Unsubscribe=One-Click` POST signal pair (see [One-click unsubscribe](#one-click-unsubscribe-rfc-8058)) |
| 4 | **Spam rate below the complaint ceiling** — keep the user-reported spam rate under **0.30%** in Google Postmaster Tools; **0.10%** is the healthy target | **The suppression + reputation layer** — `GET /api/v1/email/suppressions/reputation` reports your complaint rate over a trailing window; the [deliverability overview](/guides/insights-deliverability-reading) and per-contact [deliverability health](/guides/contact-deliverability-health) surfaces read the same signal (see [Spam-rate thresholds](#spam-rate-thresholds)) |

Obligations 1 and 2 are DNS properties you publish and Orbit verifies;
obligations 3 and 4 are traffic properties your send behaviour
produces. The configuration sections below take them one at a time.

***

## SPF + DKIM signing

The regime's first obligation — authenticate with SPF and DKIM — is
already a hard gate in Orbit: a custom sending domain does not accept
traffic until its DNS verifies, and the DKIM `p=` public key is
bit-length-validated (minimum 1,024 bits per RFC 8301), so a
placeholder record never flips a domain to green. The records, the
**Verify DNS** flow, and the drift-regression health check are covered
in [Email → Domain Setup](/channels/email#domain-setup); that page owns
the mechanics and this page does not repeat them.

The posture gap the bulk-sender regime closes is **DMARC**, which the
Domain Setup table lists as one row among four. The next section is
the policy guidance that row does not carry.

***

## DMARC policy: p=none is the floor, not the posture

A DMARC record at `_dmarc.your-domain.com` must exist for Gmail and
Yahoo to accept your bulk traffic, and `p=none` technically satisfies
the checkbox. It is the wrong end-state. `p=none` tells receiver
filters "monitor only — take no action on failures," which means:

* A domain that spoofs you fails *nothing*: the failed-DMARC mail in
  your recipients' inboxes is indistinguishable from your own, and the
  reputation damage lands on your domain.
* You are one DNS edit away from enforcement anyway when the next
  escalation of the regime raises the floor — Yahoo and Google have
  both signalled `p=quarantine`/`p=reject` as the intended direction.

The recommended posture is a staged ramp: publish `v=DMARC1; p=none`
long enough to confirm your legitimate senders pass (SPF and DKIM
aligned — with a receiver's `rua` reports if you collect them), then
step to `p=quarantine`, then `p=reject`. Each stage raises the
penalty for spoofing you while your own authenticated traffic — which
Orbit only sends once DKIM and SPF both verify — passes unchanged.

Keep the DMARC record's policy coherent with the rest of the row: a
domain that fails its own DKIM/SPF checks *and* publishes `p=reject`
rejects its own mail. Orbit's verification gate makes that near-self-
inflicted — verification is green before the domain accepts traffic,
but an out-of-band edit to your DNS can drift it; the daily health
check and the per-record traffic-light read below catch the drift
before it becomes a rejection wave.

***

## One-click unsubscribe (RFC 8058)

Every outbound email Orbit dispatches already carries the mechanism the
regime names:

```
List-Unsubscribe: <https://orbit.devotel.io/unsubscribe/<signed-token>>,
    <mailto:unsubscribe@your-domain.com>
List-Unsubscribe-Post: List-Unsubscribe=One-Click
```

`List-Unsubscribe` (RFC 2369) names where the client should send the
opt-out — an HTTPS URL plus a mailto fallback. `List-Unsubscribe-Post`
(RFC 8058) is the signal the 2024 regime actually checks: it tells the
mailbox provider it may POST to the header URL and the opt-out must
**complete without any further interaction** — no confirmation page,
no login wall, no second click. Orbit's signed unsubscribe URL meets
that contract: the POST lands at the unsubscribe endpoint, the token
is verified, a suppression row is written with scope `email`, and an
`email.unsubscribed` audit event is appended. The mailbox-provider
"Unsubscribe" button and your in-body footer link resolve to the same
endpoint, so the statutory layer (CAN-SPAM's one-click requirement,
CASL, the Spam Act) and the mailbox-provider regime are satisfied by
the same mechanism — the framing this page adds. The in-body side is
in [US CAN-SPAM Compliance](/compliance/can-spam#list-unsubscribe-header-behavior).

Two points the regime adds beyond the statute:

* **The header pair is checked at the gate, not sampled.** A bulk
  sender whose marketing mail lacks `List-Unsubscribe-Post` is
  rejected outright, not filtered; the header has to be present on
  every marketing message, which Orbit's transport-layer injection
  guarantees by construction.
* **A mailto-only footer link no longer suffices.** The in-body
  unsubscribe link remains required by CAN-SPAM and by the Gmail/Yahoo
  content rules, but the *one-click POST* property is header-side.
  Keep both: the footer link for the statute and your template, the
  header pair for the mailbox-provider gate.

What you control at send time is the in-body placement: keep an
unsubscribe link in a shared footer block so every template carries
it, and let the transport layer attach the headers.

***

## Spam-rate thresholds

The numerical floor sits in **Google Postmaster Tools**, not in the
statute and not in Orbit: Gmail publishes a per-domain **spam rate**
(the share of your delivered mail recipients mark as spam), and the
regime's hard ceiling is **0.30%** — cross it and bulk traffic is
rejected. The healthy target is **0.10%**; between the two you are
accepting queued gunk, not compliance.

The complaint-suppression layer is what keeps you under the ceiling:

* A recipient's "Report spam" click arrives on the delivery events
  path and writes a `complaint` suppression entry — the recipient is
  held out of later sends and cannot re-complain. See
  [Email → Bounce and Complaint Handling](/channels/email#bounce-and-complaint-handling)
  for the lifecycle table.
* `GET /api/v1/email/suppressions/reputation` reports the aggregate
  `complaintRate` over a trailing window next to the bounce rate,
  the health tier (`healthy | at_risk | poor`), and the current list
  size — poll it during ramp and while you test a new segment.
* The consolidated [deliverability overview](/guides/insights-deliverability-reading)
  surfaces the same complaint signal in the Email tab's KPI row, and
  [contact deliverability health](/guides/contact-deliverability-health)
  reads it per contact and segment, so the propagation from a
  recipient's spam-folder click to a segment-level verdict is
  observable without Postmaster Tools.

<Note>
  Orbit's suppression of a complaining recipient keeps the same
  recipient from driving your rate up — it does not remove a complaint
  that already counted. The rate is scored by Google against your
  domain from recipient reports; Postmaster Tools is the measurement
  the regime enforces against, and the Orbit surfaces are what you
  watch between Postmaster check-ins. Cross-verifying both is the
  posture.
</Note>

***

## Posture configuration

Three concrete knobs close the regime end-to-end.

### 1. Read your DMARC posture from the DNS-status endpoint

The per-record traffic-light view reports the DMARC record's health
and its live value, so the policy you published is observable without
a DNS lookup:

```bash theme={null}
curl -X GET https://api.orbit.devotel.io/api/v1/email/domains/default/dns-status \
  -H "X-API-Key: dv_live_sk_..."
```

The `dmarc` entry in the `records` array carries both the `status`
(`valid | warning | invalid | unknown`) and the `recordActual` string
you actually published, e.g.
`{ "kind": "dmarc", "status": "valid", "recordActual": "v=DMARC1; p=quarantine; ..." }`.
Read `recordActual` not only for presence but for the `p=` policy —
that is the value the regime's floor and the staged ramp above are
about. The response format is in
[Email → Domain Setup](/channels/email#verification-fails-or-regresses).

### 2. Export the suppression ledger the complaint loop feeds

The suppression list that complaint events write is exportable as CSV
or JSON, and the export run is itself audited — the trail an auditor
or a deliverability consultant asks for. Both the ledger and its
export are documented on
[consent-suppression-export](/compliance/consent-suppression-export);
the email-side parameters (`channel=email`) filter the export to the
rows the regime's threshold is computed from.

### 3. Let the transport layer carry the header pair

You do not attach `List-Unsubscribe` or `List-Unsubscribe-Post`
headers yourself; Orbit injects the signed URL and the one-click POST
signal on every outbound message. What you control at send time is
the in-body placement: keep an unsubscribe link in a shared footer
block so every campaign template carries it, keep the physical postal
address beside it for the CAN-SPAM layer, and send. The
[template and merge-tag layer](/channels/email#personalization-with-merge-tags)
resolves `{{contact.unsubscribeUrl}}` into the body at dispatch, so
the footer stays template-bindable rather than hand-pasted per send.

***

## Worked pre-flight checklist

Run this the day you cross the 5,000-messages/day threshold and
before any new bulk segment launches:

1. **Domain verifies green.** Poll
   `GET /api/v1/email/domains/:domainId/dns-status` and confirm
   `overallStatus` is `valid` and no record is `warning`/`invalid`
   — especially `spf`, `dkim`, and `dmarc`.
2. **DMARC policy is at least `p=quarantine` on the ramp.**
   `recordActual` on the `dmarc` row shows the published policy; a
   still-`p=none` domain is compliant-but-unprotected today and one
   regime-escalation away from a gate tomorrow.
3. **Templates carry the unsubscribe footer.** The base template
   includes a footer block with the unsubscribe link (and the postal
   address for CAN-SPAM) — a template without the footer is a
   send-gate at the mailbox provider, not an Orbit error you will
   see locally.
4. **Header pair confirmed on a canary send.** Send one message to a
   seed Gmail address and inspect the raw headers — both
   `List-Unsubscribe` and `List-Unsubscribe-Post: List-Unsubscribe=One-Click`
   present — before you open the campaign to the segment.
5. **Suppression list is seeded.** Bulk-import any legacy opt-out
   list from your previous ESP
   (`POST /api/v1/email/suppressions/bulk-import`) so recipients who
   already opted out elsewhere do not re-receive and re-complain on
   the new platform.
6. **Complaint rate baseline is under 0.10%.** Poll
   `GET /api/v1/email/suppressions/reputation` for a trailing-window
   baseline, and re-check after the first day of the ramp; pair it
   with Postmaster Tools as the regime's authoritative read.
7. **Warm-up before volume.** A new domain's reputation is zero, not
   good; ramp daily volume per
   [Email → Warm-up posture](/channels/email#warm-up-posture) before
   bulk traffic, and watch the health tier on the reputation endpoint
   rather than the send rate.

***

## Related references

* [US CAN-SPAM Compliance for Email](/compliance/can-spam) — the
  statutory layer this regime sits next to; names the same
  one-click-unsubscribe surface but from the content side, and predates
  the mailbox-provider regime's rejection gate.
* [CASL — Canada's Anti-Spam Legislation](/compliance/casl-canada-anti-spam) —
  the express-consent regime; its unsubscribe and identification rules
  compose with (and are stricter than) the bulk-sender requirements.
* [Australia Spam Act](/compliance/au-spam-act) — same statutory class
  for Australian recipients.
* [Opt-Out & Suppression Lists](/compliance/opt-out-suppression) — the
  ledger the complaint and unsubscribe events write into.
* [Email](/channels/email) — Domain Setup, suppression lifecycle,
  reputation endpoint, warm-up.
* [Read the consolidated deliverability dashboard](/guides/insights-deliverability-reading)
  — the Email tab's KPI row where the complaint signal surfaces
  day-to-day.

<Note>
  Localized variants (FR/AR/TR and further locales) are follow-ups:
  the CAN-SPAM page already has fr/ar/tr mirrors to use as the
  pattern; this page ships in English first and mirrors next.
</Note>
