---
title: "Mail Relay"
description: "Keep Google Workspace as your mailbox provider and get every message in Primitive too, with webhooks, Functions and the API."
canonical: "https://docs.primitive.dev/docs/mail-relay"
last-updated: "2026-05-17T00:00:00.000Z"
---

# Mail Relay

A mail relay domain keeps your existing mailbox provider. Your team keeps using Gmail as
before, and Primitive gets a copy of the domain's mail: incoming mail is stored and
triggers webhooks and Functions like any other domain, and mail your team sends from
Gmail is recorded in your outbox.

Mail relay domains currently support Google Workspace. They are available to accounts
with mail relay enabled.

## How mail flows

- Inbound: the domain's MX points at a Primitive mail relay. The relay forwards each message to your Google Workspace mailboxes and, at the same time, stores a copy in Primitive.

- Outbound: Google Workspace routes outgoing mail through the relay. The relay checks the message really comes from your Workspace, sends it on, and records it in your Primitive outbox with its delivery result.

- Inside Workspace: by default, mail between users of the same Workspace stays inside Google and is not stored in Primitive. An optional routing rule (below) sends it through the relay as well.

## Setup

Add the domain on the Domains page and choose **Keep my existing mailbox provider (mail
relay)**. The domain gets its own setup checklist. Every item is required: the relay
needs all of them to keep mail flowing, and the domain only verifies once they all pass
in the same check.

Do the Google Workspace steps first. Switch MX last: if MX changes before Google is
ready, Gmail sees all incoming mail arriving from the relay's address and may treat it as
spam.

- Google DKIM. In the Google Admin console, open Apps, Google Workspace, Gmail, Authenticate email. Generate a record, publish it, then select Start authentication.

- Inbound gateway. In Gmail, Spam, phishing and malware, Inbound gateway, add the relay addresses shown in the checklist, select "Automatically detect external IP", and require TLS.

- Outbound route. In Gmail, Hosts, add the relay hostname from the checklist on port 25 with TLS required. Then add a Routing rule for outbound mail whose envelope sender matches your domain, routed to that host.

- Catch-all. Create a group to receive mail for addresses that have no mailbox, and a routing rule that sends unknown recipients to it, as described in the checklist. This stops Google bouncing mail that the relay already accepted.

- DNS. Publish the records the checklist shows: the MX to the relay, the ownership TXT, one SPF record, Primitive's DKIM records, DMARC, and TLS reporting.

The checklist checks every DNS record and the Google DKIM key for you. The Google Admin
steps cannot be seen from outside Google, so you confirm them yourself.

### SPF

A domain must have exactly one SPF record. The checklist shows the record to publish; it
authorises the relay, Google and Primitive. If you send from other services, add their
mechanisms to that same record rather than publishing a second one. Two SPF records (or
two DMARC records) make receivers treat both as broken, and the checklist reports them.

### Optional: store mail between your own users

In Gmail, Routing, add a rule for **Internal - Sending** messages whose envelope sender
matches your domain, with **Change route** set to the relay host from the outbound route.
Internal mail is then stored in Primitive like other mail: in your outbox for the sender
and as an incoming message for the recipient.

The trade-off: internal mail then depends on the relay. If the relay cannot be reached,
Google retries and that mail is delayed. The relay accepts internal mail only when it
carries your Google DKIM signature, and whether Google signs mail routed this way has not
been confirmed yet; if it does not, internal mail on the rule bounces.

Try the rule on one organizational unit first. Send between two of its users and check
that the recipient gets the message once with no bounce, and that Primitive shows it in
your outbox and as an incoming message. If the test bounces, delete the rule, which
returns internal mail to staying inside Google. Widen the rule only after it passes.

## What you get

- Inbound mail is stored and delivered to your webhooks and Functions as usual. The email object and the `email.received` event carry a `relay` object, for example `{ "hostname": "relay-mx.example.com", "via": "mail_relay" }`, and `relay: null` for mail that did not come through a relay.

- Delivery to Google Workspace is shown per recipient: `GET /v1/emails/{id}` returns `relay.delivery`, a list of `{ recipient, status, smtp_code, enhanced_status_code, smtp_response, at }` with `status` one of `delivered`, `deferred` or `bounced`, and the dashboard shows the same on the email page. The `email.received` webhook fires when the message reaches Primitive, before the Google result is known, so it does not include `delivery`.

- Mail sent from Gmail appears in your outbox, threaded with the conversation, with its delivery result for each recipient.

- Sending through the API from the domain works as for any verified domain. Mail sent to an address on a relay domain always goes through the relay, so it reaches the mailbox as well as Primitive.

## While setup is in progress

Until the domain verifies, the relay answers mail for it with a temporary failure, so
senders retry and nothing bounces. Mail sent before verification arrives once the domain
verifies, within the senders' normal retry window.

## Limits

- The relay accepts messages up to 45 MiB, in both directions, and stores them in Primitive at that size.

- Mail sent from Gmail is recorded in the outbox; it does not trigger webhooks or Functions.

- Addresses with quoted or non-ASCII local parts are delivered to Google Workspace but not stored in Primitive.

## Removing the relay

Point the MX back at Google (`smtp.google.com`, or the records Google gave you), remove
the outbound routing rule and host in the Google Admin console, then remove the relay
addresses from the inbound gateway. Mail already accepted by the relay is still delivered.

Maintained by the [primitive.dev team](/about) · [Trust & security](/trust)Last updated: May 17, 2026
