Sending email from your customers' domains
If you’re building a multi-tenant app (a helpdesk, CRM, or any platform that sends email on behalf of your customers), you eventually hit one question: should mail go out from your domain or theirs? Get it wrong and messages bounce with 550 sender is unacceptable. Here is the model that works on MailerToGo.
The two approaches
1. Platform sender (recommended starting point)
Send from your own domain (for example support@yourapp.com) and put the customer’s address in Reply-To. It works immediately, needs no customer DNS setup, and keeps deliverability fully under your control. This is what Zendesk, Intercom, and most SaaS helpdesks do by default.
- From:
support@yourapp.com(or a per-tenantsupport@acme.yourapp.com) - Reply-To:
support@customerdomain.com - Trade-off: recipients see your brand in the From line, not the customer’s.
2. Customer domain (better brand and deliverability)
Provision a DKIM key for the customer’s domain so mail is signed as theirs. This requires the customer to add DNS records, but it gives brand consistency and, once DKIM and DMARC align on their own domain, better deliverability.
- From:
support@customerdomain.com, signed with their DKIM key - Trade-off: requires customer DNS action before you can send.
Most platforms offer both: start every tenant on the platform sender, and let customers upgrade to their own domain when they are ready.
What happens if you skip DKIM provisioning
This is the trap. If your app sends from a customer domain that has no DKIM key provisioned on MailerToGo, one of two things happens: the message is rejected (550 sender is unacceptable), or the envelope sender is rewritten to your default domain as a fallback.
Neither is something to build on. A rejection means dropped customer mail. A silent envelope rewrite means your DMARC alignment quietly breaks. We have seen this exact failure in the wild: an app sending as info@customerdomain.com with no DKIM provisioned, and every message bouncing 550 sender is unacceptable.
Don’t rely on the fallback. Decide the sender in your own code.
The recommended pattern: choose the sender yourself
Track, per customer, whether their sending domain is verified on MTG. Pick the MAIL FROM accordingly, and fall back to your platform domain when it is not:
# Ruby
PLATFORM_DOMAIN = "yourapp.com"
def sender_for(customer)
if customer.sending_domain_verified?
{ from: "support@#{customer.domain}" } # signed as theirs
else
{ from: "support@#{PLATFORM_DOMAIN}", # your domain
reply_to: customer.support_address } # replies still reach them
end
end
// Node
const PLATFORM_DOMAIN = "yourapp.com";
function senderFor(customer) {
return customer.sendingDomainVerified
? { from: `support@${customer.domain}` }
: { from: `support@${PLATFORM_DOMAIN}`, replyTo: customer.supportAddress };
}
A few things to get right:
sending_domain_verified?is a flag your app owns. Set it once the customer’s DKIM is confirmed on MTG; don’t re-check verification on every send.- Always set
Reply-Toon platform-sent mail so replies reach the customer. - Never construct a From on a domain you have not confirmed is provisioned.
Provisioning a customer’s domain
When a customer wants mail sent as their own domain:
- Add a sending subdomain on MailerToGo. Use a dedicated subdomain like
mtg.customerdomain.comrather than the root domain. It isolates sending reputation and is the pattern MTG is built around. See Why MailerToGo sends from mtg.yourdomain.com. - Have the customer publish the DNS records. The simplest path is a single delegated
NSrecord: MailerToGo then manages SPF, DKIM, and DMARC for that subdomain for them. The manual path, publishing the SPF, DKIM, and DMARC TXT records yourself, is also supported if the customer prefers to own the records. See Use a subdomain for sending email. - Verify, then flip the flag. Once MTG reports the domain verified, set
sending_domain_verified = truefor that customer and start sending as their domain.
Until step 3 completes, keep the customer on your platform sender. New tenants can send from day one, and upgrade to their own domain with zero downtime.
TL;DR
- Start every tenant on your platform domain (
support@yourapp.complusReply-To). It just works. - Let customers upgrade to their own domain by provisioning DKIM, ideally on an
mtg.sending subdomain via a delegated NS record. - Choose the sender in your code from a per-customer “domain verified” flag. Never send from an unprovisioned domain and hope the fallback saves you. It will not.