Short answer
You can't send email from your customer's own address, such as jane@gmail.com, through your app's mail servers. DMARC checks that the domain in the From address matches a domain that passed SPF or DKIM, and your servers can't pass either for gmail.com. Yahoo and AOL publish a DMARC policy of reject, so receivers that honour DMARC refuse that mail outright, and Google tells senders not to impersonate Gmail addresses at all.
Three setups work. Send from your own domain with the customer's name in the From name and their address in Reply-To; give each customer a subdomain of yours, such as acme.mail.yourapp.com; or have each customer verify their own domain with a few DNS records so you can send as billing@acme.com. A common pattern is to start everyone on the first and offer the third to customers who want their own brand.
Why From: customer@gmail.com fails
DMARC passes only when SPF or DKIM passes for a domain that aligns with the visible From address. When your server sends a message with From: jane@gmail.com, SPF passes for your own bounce domain and DKIM for your own signing domain. Neither is gmail.com, so DMARC fails, and the receiver then applies whatever policy gmail.com publishes. SPF, DKIM and DMARC explains alignment in more detail.
Authentication-Results: mx.example.net;
dkim=pass header.d=yourapp.com;
spf=pass smtp.mailfrom=bounces@rp.yourapp.com;
dmarc=fail (p=REJECT) header.from=yahoo.com| From domain | Published DMARC policy | Spoofed From is likely to be |
|---|---|---|
yahoo.com | p=reject | Rejected |
aol.com | p=reject | Rejected |
icloud.com | p=quarantine | Sent to spam |
gmail.com | p=none, sp=quarantine | Filtered on reputation; Google warns against it |
outlook.com | p=none, sp=quarantine | Filtered on reputation |
hotmail.com | p=none | Filtered on reputation |
| Your customer's company domain | Whatever the company publishes | Spam or rejected if it enforces DMARC |
Policies read from each domain's _dmarc TXT record on Oct 28, 2026. They change over time: check any domain with the DMARC checker.
A p=none policy isn't permission. Google's sender guidelines say not to impersonate Gmail From headers, that Gmail will begin using a DMARC quarantine policy, and that spoofing other domains without permission can send your mail to spam. And a policy can tighten at any time, so mail that arrives today can bounce next month.
Most email providers refuse the send before it gets that far. On Groundmail, from has to be on a domain you've verified, so From: jane@gmail.com is refused with a 403 and nothing goes out.
Three ways to send for your customers
| Topic | 1. Your domain + Reply-To | 2. A subdomain per customer | 3. The customer's own domain |
|---|---|---|---|
| From | Jane Smith via YourApp <notifications@mail.yourapp.com> | Acme <hello@acme.mail.yourapp.com> | Acme <billing@acme.com> |
| Replies reach | The customer, through Reply-To | The customer, through Reply-To | The customer's own mailbox |
| Customer setup | None | None | Adds DNS records to their domain |
| DMARC aligns with | Your domain | Your domain | Their domain, once verified |
| Reputation | Shared by every customer on that domain | Partly separate per subdomain | The customer's own domain |
| Good for | Notifications, free plans, getting started | Separation without asking customers for DNS | Customers who want their own brand |
The options combine well. Send from your shared domain by default, move customers to their own domain when they verify it, and fall back to the shared domain if their DNS ever breaks.
Option 2: a subdomain of yours for each customer
Each customer sends from their own subdomain of your sending domain, such as acme.mail.yourapp.com. Because you own the DNS, you can create the records through your DNS provider's API when the customer signs up, with nothing for them to do.
Each subdomain needs its own DKIM key, and its own SPF record if it's used as the bounce domain. DMARC is inherited from your organizational domain unless you publish a record on the subdomain. Mailbox providers judge reputation by domain, so a separate subdomain keeps each customer's reputation partly apart, but it still sits under your domain: one customer's spam can still affect the rest.
Don't register a new lookalike domain per customer instead. A brand-new domain has no history, and names like acme-mail-notify.com read as phishing.
Option 3: customers verify their own domain
The best result for the customer: mail comes from their own address, DMARC aligns with their domain, and Gmail drops the "via" label it shows when the sending domain doesn't match the From address. The cost is a DNS step during onboarding.
- 01Suggest a subdomainAsk for something like
mail.acme.comrather thanacme.com. Their root domain probably already has Google Workspace or Microsoft 365 in its SPF record, and a subdomain avoids merging records and the 10-lookup SPF limit. The From address must then be on that subdomain:billing@mail.acme.com. - 02Create the domain and show the recordsYour email provider gives you the DKIM key, a return-path CNAME and an SPF include for that domain. Show them in your app with copy buttons and plain instructions, or send them to whoever runs the customer's DNS.
- 03Verify, then switchCheck the records, and send from the customer's domain only once they pass. Until then, keep sending with option 1.
- 04Keep checkingRecords get deleted when customers change DNS providers or clean up. Recheck regularly and fall back to option 1 if verification breaks, rather than sending mail that fails DMARC.
What about the Sender header?
RFC 5322 defines two headers for this. From is the author. Sender is the mailbox "responsible for the actual transmission", and the RFC's example is a secretary sending a message for someone else:
From: Jane Smith <jane@acme.com>
Sender: YourApp Notifications <notifications@mail.yourapp.com>Sender doesn't fix deliverability. DMARC only looks at the From domain, so From: jane@gmail.com with your address in Sender fails exactly as it would without it. Some mail clients show both addresses, for example as "on behalf of", and Gmail shows "via" whenever the domain a message was sent from doesn't match the From domain.
So Sender is only useful when the From domain already passes DMARC: for example, an assistant in the same company sending for a colleague. For a platform, options 1 to 3 are the fix. Groundmail doesn't let you set Sender: the From address is always on a domain you verified, so it isn't needed.
How Groundmail handles it: tenants
On Groundmail, a platform creates one tenant per customer inside its account. Each tenant has its own sending domains, suppression list, stats, sending ramp, daily limit and pause switch, so one customer's bad list doesn't hurt delivery for the others. Domains you add to your account as a whole, such as mail.yourapp.com, can be used by every tenant; a domain added to a tenant can only be used by that tenant.
| Setup | With tenants |
|---|---|
| 1. Your domain + Reply-To | Send from an account-wide domain with tenant and reply_to on each send. Suppressions, stats and the ramp still stay per customer. |
| 2. A subdomain per customer | Add each subdomain with POST /domains and tenant, and publish its records through your DNS provider's API. |
| 3. The customer's own domain | Add it with POST /domains and tenant, and show the customer the records from the response. Once it's verified, a send from that domain counts as the tenant's even without tenant, so SMTP works too. |
From the tenants docs and the platforms guide.
import { Groundmail } from 'groundmail'
const groundmail = new Groundmail(process.env.GROUNDMAIL_API_KEY!)
// When the customer signs up
await groundmail.tenants.create({ external_id: 'cust_8412', name: 'Acme Inc' })
// When they add their own domain: show them these DNS records
const { records } = await groundmail.domains.create({ name: 'mail.acme.com', tenant: 'cust_8412' })
// Until it's verified, send from your shared domain with Reply-To
await groundmail.emails.send({
tenant: 'cust_8412',
from: 'Acme via YourApp <notifications@mail.yourapp.com>',
replyTo: 'billing@acme.com',
to: 'jane@example.com',
subject: 'Invoice 1042 from Acme',
html: '<p>...</p>',
})- Separate suppressions. Bounces, complaints and unsubscribes on a tenant's email go on that tenant's list, so a complaint about one customer never stops another from reaching the same person. See List-Unsubscribe and one-click unsubscribe.
- A ramp per customer. Each new tenant starts at 1,000 product and 3,000 transactional recipients a day and grows as it sends clean mail, so a new customer can't burn the reputation the others send on.
- Automatic pausing. If one tenant's bounce or complaint rate gets too high, Groundmail pauses that tenant, not your account. You can also pause a tenant yourself, cap it with
daily_limit, or limit it to transactional email withstream_policy. - Keys and webhooks per customer. An API key limited to a tenant can only send as that tenant, and a webhook endpoint can receive just one tenant's events.
- A dedicated IP per customer when one needs its own reputation, at $25/mo per IP.
Tenants are included on pay as you go (up to 1,000 tenants) and on a dedicated server (up to 10,000), with no per-tenant fee, but not on the Free plan. Pay as you go also takes up to 1,000 sending domains. More on the tenants page.
Common mistakes
| Mistake | What happens | Fix |
|---|---|---|
From: the customer's Gmail or Yahoo address | DMARC fails; a Yahoo or AOL address in From gets rejected | Your domain in From, their address in Reply-To |
| The customer's email address as the display name | Looks like spoofing to readers | Use their name: "Jane Smith via YourApp" |
| Adding Sender to fix DMARC | No change: DMARC checks From only | Use one of the three setups |
| Sending from a customer domain before it's verified | DMARC fails until the records are in place | Verify first; use option 1 meanwhile |
| Asking for records on the customer's root domain | Clashes with their existing SPF record and mailbox setup | Suggest a subdomain such as mail.acme.com |
| One suppression list for every customer | A complaint about one customer blocks the same person for all of them | Keep suppressions per customer |
| New customers sending at full volume on day one | One bad list hurts every customer on the same domain and IPs | Ramp each customer up and watch their bounce rate |
| Using the domain your team emails from | Customer complaints affect your own company's mail | Send customer mail from a separate subdomain |
Frequently asked questions
Can I send email from my customer's Gmail address?
Not through your own servers. Your servers can't pass SPF or DKIM for gmail.com, so the message fails DMARC, and Google tells senders not to impersonate Gmail addresses. Send from your own domain with the customer's name in the From name and their address in Reply-To.
What does "sent on behalf of" mean in an email?
It usually means the message has a Sender header that differs from the From address: From is the author and Sender is the mailbox that actually sent it. Some mail clients show both. It doesn't affect DMARC, which only checks the From domain.
What is the difference between From, Sender and Reply-To?
From is the author the reader sees. Sender is the mailbox responsible for sending, when it differs from the author. Reply-To is where replies go. For a platform, the usual pattern is your domain in From and the customer's address in Reply-To.
Does Reply-To affect deliverability?
Not for authentication: SPF, DKIM and DMARC don't check Reply-To, so you can set it to the customer's address on any domain. Content filters do notice a free mail Reply-To that differs from From, so test a real message, and check the customer owns the address so it can't redirect replies to someone else.
Should each customer get their own sending domain?
It helps when customers send a lot or want their own brand. A subdomain of yours per customer keeps reputation partly separate with no setup for them; the customer's own verified domain gives full brand and DMARC alignment with their domain. Small customers are usually fine on a shared domain with Reply-To.
How does Groundmail handle sending for customers?
With tenants: one per customer, each with its own domains, suppression list, stats, sending ramp, daily limit and pause switch. Customers can send from a shared domain of yours or verify their own. See tenants and the tenants docs.
Sources
Facts on this page about other companies' products, prices and policies come from these public pages. They change, so check them before you decide.