Connect your domain: DNS records by provider
The five records MailFlat needs, plus the one habit that decides whether they work — written out for eleven DNS panels.
The one thing that breaks most setups
Half of these panels append your domain to whatever you type in the name field, and half store it literally. Type the full name into the first kind and your record lands at _mailflat-verify.acme.com.acme.com; type a short name into the second and it lands somewhere nothing queries. Both look saved. Neither ever verifies. Find your provider below and copy the column it shows you.
Your own verification token and DKIM key are on Domains in the dashboard — they are unique to your domain. Everything else is exactly what you see here.
The five records
| Type | Host (relative) | Value | What it does |
|---|---|---|---|
| TXT | _mailflat-verify | mf-verify-… (yours is in the dashboard) | Proves you own the domain. Verification fails without it. |
| MX | @ | mail.mailflat.net. | Routes incoming mail to MailFlat. |
| TXT | @ | v=spf1 include:mailflat.net ~all | Authorises MailFlat to send for your domain. |
| TXT | mail._domainkey | v=DKIM1; k=rsa; p=… (yours is in the dashboard) | Signs your outgoing mail. |
| TXT | _dmarc | v=DMARC1; p=none; | Tells receivers what to do when a check fails. |
Your provider
Eleven panels, each with the field names it actually uses and the mistake it makes easiest.
Cloudflarewants the full record name
Cloudflare wants the full record name
Paste the record name as shown, including .acme.com. In the dashboard, switch the Provider dropdown to full name so the Host column matches this panel.
Where the DNS editor is
- Log in to Cloudflare
- Pick your domain
- DNS → Records
- Add record
Field names here: Name for the record name, Content (Mail server for MX) for the value, Priority for MX priority.
The Host column, as Cloudflare wants it
| Type | Name | Content (Mail server for MX) |
|---|---|---|
| TXT | _mailflat-verify.acme.com | mf-verify-… (yours is in the dashboard) |
| MX | acme.com | mail.mailflat.net.Priority 10 — Priority |
| TXT | acme.com | v=spf1 include:mailflat.net ~all |
| TXT | mail._domainkey.acme.com | v=DKIM1; k=rsa; p=… (yours is in the dashboard) |
| TXT | _dmarc.acme.com | v=DMARC1; p=none; |
Cloudflare specifics
Cloudflare is forgiving about the Name field: it accepts @, a short name, or the full host.acme.com and stores the same record either way. That tolerance is exactly why a broken habit can survive here for years and then fail the day you move to another provider.
Leave TTL on Auto.
Proxy status must be DNS only (grey cloud). Mail is SMTP, not HTTP — an orange cloud cannot proxy it.
If another MX record already uses priority 10, give ours a different number rather than duplicating it.
Check it landed
dig +short TXT _mailflat-verify.acme.com
Expected: "mf-verify-…" (the token from your dashboard)
The usual wrong answer here: Nothing. Cloudflare keeps the "Name" field literally, so a bare "_mailflat-verify" is stored under a name this query never reaches. Nothing warns you; the record simply is not where the world looks for it.
All three records are added from the same place: Add record.
dig +short MX acme.com
Expected: 10 mail.mailflat.net.
The usual wrong answer here: An MX that is not ours, or none at all. Cloudflare will happily keep someone else's MX alongside ours; when two sets exist, priority alone decides which service receives the mail.
dig +short TXT mail._domainkey.acme.com
Expected: "v=DKIM1; k=rsa; p=…" (one long line)
The usual wrong answer here: Two quoted chunks instead of one, or nothing at all. The DKIM key has to survive as a single line through the "Content (Mail server for MX)" field — a key split in two parses fine and then fails every signature check, which looks like a mail problem rather than a DNS one.
When it goes wrong on Cloudflare
| What you see | Why | Fix |
|---|---|---|
| Verification fails and the record seems to be missing entirely | A short name went into "Name". Cloudflare stores it literally, so the record sits at a name nothing ever queries. | Re-enter each "Name" in full, including your domain. |
| Everything looks right in the panel, mail still never arrives | The record is proxied (orange cloud). Cloudflare's proxy handles HTTP; mail is SMTP and cannot pass through it. | Set Proxy status to DNS only (grey cloud) on every record you added. |
| Two MX records, both at priority 10 | Cloudflare accepts the duplicate without complaining, and delivery then depends on which one a sender picks. | Give ours a distinct priority instead of repeating an existing number. |
Hetzneradds your domain for you · trailing dot matters
Hetzner adds your domain to whatever you type
Enter names without your domain — _mailflat-verify, not _mailflat-verify.acme.com. Typing the full name stores it as _mailflat-verify.acme.com.acme.com, and no amount of waiting will make that verify. In the dashboard, keep the Provider dropdown on name only.
Where the DNS editor is
- Log in to the Hetzner DNS Console (dns.hetzner.com), or Console → Networking → DNS
- Pick your zone from the list
- Open the Records tab
- Add record
Field names here: Name for the record name, Value for the value, Priority for MX priority.
The Host column, as Hetzner wants it
| Type | Name | Value |
|---|---|---|
| TXT | _mailflat-verify | mf-verify-… (yours is in the dashboard) |
| MX | @ | mail.mailflat.net.Priority 10 — Priority |
| TXT | @ | v=spf1 include:mailflat.net ~all |
| TXT | mail._domainkey | v=DKIM1; k=rsa; p=… (yours is in the dashboard) |
| TXT | _dmarc | v=DMARC1; p=none; |
Keep the trailing dot on the MX value
mail.mailflat.net. ends with a dot on purpose. Hetzner treats a dotless target as relative and appends your domain to it, so mail is routed to a host that does not exist — with no error anywhere.
Hetzner specifics
Hetzner adds your domain for you. Type _mailflat-verify, not _mailflat-verify.acme.com — the full name becomes _mailflat-verify.acme.com.acme.com and nothing will ever verify, no matter how long you wait.
Keep the trailing dot on the MX value. mail.mailflat.net. is the target; drop the dot and Hetzner stores mail.mailflat.net.acme.com — your domain will look configured and still receive nothing.
Priority goes in its own field, never inside the value.
This is the provider that surfaced the bug behind this whole page. If your records are already one level too deep, edit each Name rather than starting over.
Check it landed
dig +short TXT _mailflat-verify.acme.com
Expected: "mf-verify-…" (the token from your dashboard)
The usual wrong answer here: Nothing. Hetzner appends your zone to whatever sits in "Name", so "_mailflat-verify.acme.com" is stored as _mailflat-verify.acme.com.acme.com. Query that longer name and the token turns up there — proof the value was right and only the Name field was wrong.
All three records are added from the same place: Add record.
dig +short MX acme.com
Expected: 10 mail.mailflat.net.
The usual wrong answer here: 10 mail.mailflat.net.acme.com. — the trailing dot fell off the "Value" field, so Hetzner read the target as relative and glued your domain onto it. Mail is routed to a host that does not exist, and no screen anywhere reports a problem.
dig +short TXT mail._domainkey.acme.com
Expected: "v=DKIM1; k=rsa; p=…" (one long line)
The usual wrong answer here: Two quoted chunks instead of one, or nothing at all. The DKIM key has to survive as a single line through the "Value" field — a key split in two parses fine and then fails every signature check, which looks like a mail problem rather than a DNS one.
When it goes wrong on Hetzner
| What you see | Why | Fix |
|---|---|---|
| Verification fails and the error names a record one level too deep | The full name went into "Name". Hetzner added your zone on top of it, so the record lives at _mailflat-verify.acme.com.acme.com. | Shorten each "Name" value rather than deleting the records — the same paste would only repeat the mistake. |
| The domain verifies, but no mail ever arrives | The MX target in "Value" lost its trailing dot, so Hetzner appended your domain to it. | Restore mail.mailflat.net. — dot included. Verify will never catch this on its own, because it reads TXT records and this is an MX fault. |
| The zone cannot be found in the Hetzner Cloud console | Hetzner DNS lives at dns.hetzner.com and is a separate product from Cloud; a zone added there is not visible under a Cloud project's networking screens. | Open the DNS Console directly and pick the zone from its own list. |
| An imported zone file lost the trailing dots | The Records tab accepts a zone file import, and a file written without terminal dots is stored exactly as written. | After importing, open the MX record and confirm the target still ends in a dot. |
| Records were fine yesterday and the zone now looks duplicated | This is the exact failure that made these guides exist (B-054): a full name pasted into a panel that appends the zone. | Edit the Name of each affected record. The values are still correct — only the names are one level too deep. |
Namecheapadds your domain for you
Namecheap adds your domain to whatever you type
Enter names without your domain — _mailflat-verify, not _mailflat-verify.acme.com. Typing the full name stores it as _mailflat-verify.acme.com.acme.com, and no amount of waiting will make that verify. In the dashboard, keep the Provider dropdown on name only.
Where the DNS editor is
- Log in to Namecheap
- Domain List → Manage
- Advanced DNS
- Add New Record
Field names here: Host for the record name, Value for the value, (unlabelled column after Value) for MX priority.
The Host column, as Namecheap wants it
| Type | Host | Value |
|---|---|---|
| TXT | _mailflat-verify | mf-verify-… (yours is in the dashboard) |
| MX | @ | mail.mailflat.net.Priority 10 — (unlabelled column after Value) |
| TXT | @ | v=spf1 include:mailflat.net ~all |
| TXT | mail._domainkey | v=DKIM1; k=rsa; p=… (yours is in the dashboard) |
| TXT | _dmarc | v=DMARC1; p=none; |
Namecheap specifics
Namecheap adds your domain for you. The Host field takes @, _mailflat-verify, mail._domainkey, _dmarc — never the full name.
MX is not in Host Records. Scroll to Mail Settings, switch the dropdown to Custom MX, and add it there. Until you do that, the MX box simply isn't shown and mail cannot arrive.
The Priority field has no header — it is the narrow column right after Value.
TTL: Automatic is fine.
Check it landed
dig +short TXT _mailflat-verify.acme.com
Expected: "mf-verify-…" (the token from your dashboard)
The usual wrong answer here: Nothing. Namecheap appends your zone to whatever sits in "Host", so "_mailflat-verify.acme.com" is stored as _mailflat-verify.acme.com.acme.com. Query that longer name and the token turns up there — proof the value was right and only the Host field was wrong.
All three records are added from the same place: Add New Record.
dig +short MX acme.com
Expected: 10 mail.mailflat.net.
The usual wrong answer here: An MX that is not ours, or none at all. Namecheap will happily keep someone else's MX alongside ours; when two sets exist, priority alone decides which service receives the mail.
The priority column on Namecheap carries no header — it is the narrow one immediately after "Value", which is why a 10 typed into the value itself is such a common mistake here.
dig +short TXT mail._domainkey.acme.com
Expected: "v=DKIM1; k=rsa; p=…" (one long line)
The usual wrong answer here: Two quoted chunks instead of one, or nothing at all. The DKIM key has to survive as a single line through the "Value" field — a key split in two parses fine and then fails every signature check, which looks like a mail problem rather than a DNS one.
When it goes wrong on Namecheap
| What you see | Why | Fix |
|---|---|---|
| Verification fails and the error names a record one level too deep | The full name went into "Host". Namecheap added your zone on top of it, so the record lives at _mailflat-verify.acme.com.acme.com. | Shorten each "Host" value rather than deleting the records — the same paste would only repeat the mistake. |
| Four records saved fine, the MX one has nowhere to go | MX does not live in Host Records on Namecheap. Until you switch Mail Settings to Custom MX, the box is not shown at all. | Scroll to Mail Settings, choose Custom MX, then add the MX record there. |
| The priority went into the wrong column | The Priority column has no header — it is the narrow one right after Value. | Re-open the record and check that 10 sits in that column, not inside the value. |
GoDaddyadds your domain for you
GoDaddy adds your domain to whatever you type
Enter names without your domain — _mailflat-verify, not _mailflat-verify.acme.com. Typing the full name stores it as _mailflat-verify.acme.com.acme.com, and no amount of waiting will make that verify. In the dashboard, keep the Provider dropdown on name only.
Where the DNS editor is
- Log in to GoDaddy
- DNS in the left navigation
- Pick your domain
- Add New Record
- Save
Field names here: Name for the record name, Value for the value, Priority for MX priority.
The Host column, as GoDaddy wants it
| Type | Name | Value |
|---|---|---|
| TXT | _mailflat-verify | mf-verify-… (yours is in the dashboard) |
| MX | @ | mail.mailflat.net.Priority 10 — Priority |
| TXT | @ | v=spf1 include:mailflat.net ~all |
| TXT | mail._domainkey | v=DKIM1; k=rsa; p=… (yours is in the dashboard) |
| TXT | _dmarc | v=DMARC1; p=none; |
GoDaddy specifics
GoDaddy adds your domain for you. Use @ for the root and the short name for everything else.
Each record needs its own Save — a half-saved set verifies as half-configured.
If priority 10 is already taken by another MX record, use 20 or 30 instead of repeating it.
Check it landed
dig +short TXT _mailflat-verify.acme.com
Expected: "mf-verify-…" (the token from your dashboard)
The usual wrong answer here: Nothing. GoDaddy appends your zone to whatever sits in "Name", so "_mailflat-verify.acme.com" is stored as _mailflat-verify.acme.com.acme.com. Query that longer name and the token turns up there — proof the value was right and only the Name field was wrong.
All three records are added from the same place: Save.
dig +short MX acme.com
Expected: 10 mail.mailflat.net.
The usual wrong answer here: An MX that is not ours, or none at all. GoDaddy will happily keep someone else's MX alongside ours; when two sets exist, priority alone decides which service receives the mail.
dig +short TXT mail._domainkey.acme.com
Expected: "v=DKIM1; k=rsa; p=…" (one long line)
The usual wrong answer here: Two quoted chunks instead of one, or nothing at all. The DKIM key has to survive as a single line through the "Value" field — a key split in two parses fine and then fails every signature check, which looks like a mail problem rather than a DNS one.
When it goes wrong on GoDaddy
| What you see | Why | Fix |
|---|---|---|
| Verification fails and the error names a record one level too deep | The full name went into "Name". GoDaddy added your zone on top of it, so the record lives at _mailflat-verify.acme.com.acme.com. | Shorten each "Name" value rather than deleting the records — the same paste would only repeat the mistake. |
| Verification says one record is missing although the list looks complete | GoDaddy sometimes keeps a newly added row on screen before it is committed, so the list can show a record the zone does not have yet. | Reload the DNS page and count the records again; add whichever one disappeared. |
| Some records are live and others are simply absent | GoDaddy saves one record at a time. A set added in one sitting can end up half-saved. | Re-open the DNS list and confirm all five are present before pressing Verify. |
AWS Route 53wants the full record name · trailing dot matters
AWS Route 53 wants the full record name
Paste the record name as shown, including .acme.com. In the dashboard, switch the Provider dropdown to full name so the Host column matches this panel.
Where the DNS editor is
- AWS console → Route 53
- Hosted zones → your zone
- Create record
- Simple routing
Field names here: Record name for the record name, Value for the value, (inside the MX value) for MX priority.
The Host column, as AWS Route 53 wants it
| Type | Record name | Value |
|---|---|---|
| TXT | _mailflat-verify.acme.com | mf-verify-… (yours is in the dashboard) |
| MX | acme.com | mail.mailflat.net.Priority 10 — (inside the MX value) |
| TXT | acme.com | v=spf1 include:mailflat.net ~all |
| TXT | mail._domainkey.acme.com | v=DKIM1; k=rsa; p=… (yours is in the dashboard) |
| TXT | _dmarc.acme.com | v=DMARC1; p=none; |
Keep the trailing dot on the MX value
mail.mailflat.net. ends with a dot on purpose. AWS Route 53 treats a dotless target as relative and appends your domain to it, so mail is routed to a host that does not exist — with no error anywhere.
AWS Route 53 specifics
Route 53 shows your zone next to the Record name box: leave it empty for the root, or type just _mailflat-verify. What it stores is the full name.
MX priority is part of the value here, not a separate field: enter 10 mail.mailflat.net. — trailing dot included.
Wrap TXT values in double quotes. Long DKIM keys must stay on one line.
Check it landed
dig +short TXT _mailflat-verify.acme.com
Expected: "mf-verify-…" (the token from your dashboard)
The usual wrong answer here: Nothing. AWS Route 53 keeps the "Record name" field literally, so a bare "_mailflat-verify" is stored under a name this query never reaches. Nothing warns you; the record simply is not where the world looks for it.
All three records are added from the same place: Simple routing.
dig +short MX acme.com
Expected: 10 mail.mailflat.net.
The usual wrong answer here: 10 mail.mailflat.net.acme.com. — the trailing dot fell off the "Value" field, so AWS Route 53 read the target as relative and glued your domain onto it. Mail is routed to a host that does not exist, and no screen anywhere reports a problem.
AWS Route 53 has no separate priority box at all: the whole string "10 mail.mailflat.net." goes into "Value". Looking for a Priority field here is looking for something that does not exist.
dig +short TXT mail._domainkey.acme.com
Expected: "v=DKIM1; k=rsa; p=…" (one long line)
The usual wrong answer here: Two quoted chunks instead of one, or nothing at all. The DKIM key has to survive as a single line through the "Value" field — a key split in two parses fine and then fails every signature check, which looks like a mail problem rather than a DNS one.
When it goes wrong on AWS Route 53
| What you see | Why | Fix |
|---|---|---|
| Verification fails and the record seems to be missing entirely | A short name went into "Record name". AWS Route 53 stores it literally, so the record sits at a name nothing ever queries. | Re-enter each "Record name" in full, including your domain. |
| The domain verifies, but no mail ever arrives | The MX target in "Value" lost its trailing dot, so AWS Route 53 appended your domain to it. | Restore mail.mailflat.net. — dot included. Verify will never catch this on its own, because it reads TXT records and this is an MX fault. |
| The TXT record exists but resolvers return nothing usable | Route 53 requires TXT values in double quotes; an unquoted value is stored differently. | Wrap the value in quotes and keep the DKIM key on a single line. |
| There is no Priority box for the MX record | Route 53 does not have one — priority is part of the value. | Enter the whole string, priority first: 10 mail.mailflat.net. |
Porkbunadds your domain for you
Porkbun adds your domain to whatever you type
Enter names without your domain — _mailflat-verify, not _mailflat-verify.acme.com. Typing the full name stores it as _mailflat-verify.acme.com.acme.com, and no amount of waiting will make that verify. In the dashboard, keep the Provider dropdown on name only.
Where the DNS editor is
- Log in to Porkbun
- Domain Management → your domain
- DNS
- Add record
Field names here: Host for the record name, Answer for the value, Priority for MX priority.
The Host column, as Porkbun wants it
| Type | Host | Answer |
|---|---|---|
| TXT | _mailflat-verify | mf-verify-… (yours is in the dashboard) |
| MX | @ | mail.mailflat.net.Priority 10 — Priority |
| TXT | @ | v=spf1 include:mailflat.net ~all |
| TXT | mail._domainkey | v=DKIM1; k=rsa; p=… (yours is in the dashboard) |
| TXT | _dmarc | v=DMARC1; p=none; |
Porkbun specifics
Porkbun adds your domain for you. Leave Host empty (or @) for the root; use the short name otherwise.
The value column is called Answer.
Priority appears only after you pick type MX.
Check it landed
dig +short TXT _mailflat-verify.acme.com
Expected: "mf-verify-…" (the token from your dashboard)
The usual wrong answer here: Nothing. Porkbun appends your zone to whatever sits in "Host", so "_mailflat-verify.acme.com" is stored as _mailflat-verify.acme.com.acme.com. Query that longer name and the token turns up there — proof the value was right and only the Host field was wrong.
All three records are added from the same place: Add record.
dig +short MX acme.com
Expected: 10 mail.mailflat.net.
The usual wrong answer here: An MX that is not ours, or none at all. Porkbun will happily keep someone else's MX alongside ours; when two sets exist, priority alone decides which service receives the mail.
dig +short TXT mail._domainkey.acme.com
Expected: "v=DKIM1; k=rsa; p=…" (one long line)
The usual wrong answer here: Two quoted chunks instead of one, or nothing at all. The DKIM key has to survive as a single line through the "Answer" field — a key split in two parses fine and then fails every signature check, which looks like a mail problem rather than a DNS one.
When it goes wrong on Porkbun
| What you see | Why | Fix |
|---|---|---|
| Verification fails and the error names a record one level too deep | The full name went into "Host". Porkbun added your zone on top of it, so the record lives at _mailflat-verify.acme.com.acme.com. | Shorten each "Host" value rather than deleting the records — the same paste would only repeat the mistake. |
| The record saved, but the Answer column looks empty for the root | Porkbun calls the value column Answer and accepts an empty Host as the root, so a root record can look blank in two places at once while being perfectly correct. | Read it back with dig rather than trusting the table — an empty Host plus a filled Answer is the normal appearance of a correct root record here. |
| A record was added at the wrong level after switching domains | Domain Management lists every domain you own and the DNS screen keeps the last one you opened. | Confirm the domain name at the top of the DNS screen before adding records. |
| The Priority field is nowhere to be found | Porkbun only reveals it once the record type is set to MX. | Pick type MX first, then fill in priority and answer. |
Verceladds your domain for you
Vercel adds your domain to whatever you type
Enter names without your domain — _mailflat-verify, not _mailflat-verify.acme.com. Typing the full name stores it as _mailflat-verify.acme.com.acme.com, and no amount of waiting will make that verify. In the dashboard, keep the Provider dropdown on name only.
Where the DNS editor is
- Vercel dashboard → Domains
- Pick your domain
- Add record
Field names here: Name for the record name, Value for the value, Priority for MX priority.
The Host column, as Vercel wants it
| Type | Name | Value |
|---|---|---|
| TXT | _mailflat-verify | mf-verify-… (yours is in the dashboard) |
| MX | @ | mail.mailflat.net.Priority 10 — Priority |
| TXT | @ | v=spf1 include:mailflat.net ~all |
| TXT | mail._domainkey | v=DKIM1; k=rsa; p=… (yours is in the dashboard) |
| TXT | _dmarc | v=DMARC1; p=none; |
Vercel specifics
Vercel adds your domain for you. Leave Name empty for the root record.
The default TTL (60) is fine.
If the domain is only *pointed* at Vercel and its DNS is hosted elsewhere, add the records at the provider holding the nameservers instead — check the NS records if you are unsure.
Check it landed
dig +short TXT _mailflat-verify.acme.com
Expected: "mf-verify-…" (the token from your dashboard)
The usual wrong answer here: Nothing. Vercel appends your zone to whatever sits in "Name", so "_mailflat-verify.acme.com" is stored as _mailflat-verify.acme.com.acme.com. Query that longer name and the token turns up there — proof the value was right and only the Name field was wrong.
All three records are added from the same place: Add record.
dig +short MX acme.com
Expected: 10 mail.mailflat.net.
The usual wrong answer here: An MX that is not ours, or none at all. Vercel will happily keep someone else's MX alongside ours; when two sets exist, priority alone decides which service receives the mail.
dig +short TXT mail._domainkey.acme.com
Expected: "v=DKIM1; k=rsa; p=…" (one long line)
The usual wrong answer here: Two quoted chunks instead of one, or nothing at all. The DKIM key has to survive as a single line through the "Value" field — a key split in two parses fine and then fails every signature check, which looks like a mail problem rather than a DNS one.
When it goes wrong on Vercel
| What you see | Why | Fix |
|---|---|---|
| Verification fails and the error names a record one level too deep | The full name went into "Name". Vercel added your zone on top of it, so the record lives at _mailflat-verify.acme.com.acme.com. | Shorten each "Name" value rather than deleting the records — the same paste would only repeat the mistake. |
| Records added, TTL 60, and still nothing resolves after an hour | Vercel only serves DNS for domains whose nameservers point at Vercel. A domain merely pointed at a Vercel project keeps its DNS elsewhere. | Run dig NS on your domain. Whatever it names is where these five records belong. |
| The root record refuses a value in the Name field | Vercel expects the Name field left empty for the root rather than an @ character. | Clear the field entirely for the MX and SPF records. |
| Records saved in Vercel, but queries return the old values | The domain is only pointed at Vercel while its DNS is hosted elsewhere, so Vercel's records are not authoritative. | Check the NS records for your domain and add MailFlat's records wherever the nameservers actually point. |
IONOSadds your domain for you
IONOS adds your domain to whatever you type
Enter names without your domain — _mailflat-verify, not _mailflat-verify.acme.com. Typing the full name stores it as _mailflat-verify.acme.com.acme.com, and no amount of waiting will make that verify. In the dashboard, keep the Provider dropdown on name only.
Where the DNS editor is
- Log in to IONOS
- Domains & SSL → your domain
- DNS tab
- Add record
Field names here: Host name (Name for MX) for the record name, Value (Points to for MX) for the value, Priority for MX priority.
The Host column, as IONOS wants it
| Type | Host name (Name for MX) | Value (Points to for MX) |
|---|---|---|
| TXT | _mailflat-verify | mf-verify-… (yours is in the dashboard) |
| MX | @ | mail.mailflat.net.Priority 10 — Priority |
| TXT | @ | v=spf1 include:mailflat.net ~all |
| TXT | mail._domainkey | v=DKIM1; k=rsa; p=… (yours is in the dashboard) |
| TXT | _dmarc | v=DMARC1; p=none; |
IONOS specifics
IONOS adds your domain for you. Use @ for the root, short names elsewhere.
The field is called *Host name* for TXT records and *Name* for MX — same thing.
The default TTL of one hour is fine.
Check it landed
dig +short TXT _mailflat-verify.acme.com
Expected: "mf-verify-…" (the token from your dashboard)
The usual wrong answer here: Nothing. IONOS appends your zone to whatever sits in "Host name (Name for MX)", so "_mailflat-verify.acme.com" is stored as _mailflat-verify.acme.com.acme.com. Query that longer name and the token turns up there — proof the value was right and only the Host name (Name for MX) field was wrong.
All three records are added from the same place: Add record.
dig +short MX acme.com
Expected: 10 mail.mailflat.net.
The usual wrong answer here: An MX that is not ours, or none at all. IONOS will happily keep someone else's MX alongside ours; when two sets exist, priority alone decides which service receives the mail.
dig +short TXT mail._domainkey.acme.com
Expected: "v=DKIM1; k=rsa; p=…" (one long line)
The usual wrong answer here: Two quoted chunks instead of one, or nothing at all. The DKIM key has to survive as a single line through the "Value (Points to for MX)" field — a key split in two parses fine and then fails every signature check, which looks like a mail problem rather than a DNS one.
When it goes wrong on IONOS
| What you see | Why | Fix |
|---|---|---|
| Verification fails and the error names a record one level too deep | The full name went into "Host name (Name for MX)". IONOS added your zone on top of it, so the record lives at _mailflat-verify.acme.com.acme.com. | Shorten each "Host name (Name for MX)" value rather than deleting the records — the same paste would only repeat the mistake. |
| The TTL of one hour makes a fix look like it did not work | IONOS defaults to 3600 seconds, so an edited record can keep serving the old value for up to an hour to resolvers that already cached it. | Wait out the hour, or lower the TTL before editing. A dig against 1.1.1.1 or 8.8.8.8 shows what a fresh resolver sees. |
| A record was entered under Domains & SSL but nothing changed | IONOS separates the domain contract screens from the DNS tab; edits made outside that tab do not touch the zone. | Open the domain, then the DNS tab specifically, and add the record there. |
| The field for the record name seems to change between records | IONOS labels it Host name for TXT and Name for MX. They are the same field. | Fill in whichever label is shown; the rule about short names does not change. |
Squarespaceadds your domain for you
Squarespace adds your domain to whatever you type
Enter names without your domain — _mailflat-verify, not _mailflat-verify.acme.com. Typing the full name stores it as _mailflat-verify.acme.com.acme.com, and no amount of waiting will make that verify. In the dashboard, keep the Provider dropdown on name only.
Where the DNS editor is
- Squarespace → Settings → Domains
- Pick your domain
- DNS Settings
- Add record (custom records)
Field names here: Host for the record name, Data for the value, Priority for MX priority.
The Host column, as Squarespace wants it
| Type | Host | Data |
|---|---|---|
| TXT | _mailflat-verify | mf-verify-… (yours is in the dashboard) |
| MX | @ | mail.mailflat.net.Priority 10 — Priority |
| TXT | @ | v=spf1 include:mailflat.net ~all |
| TXT | mail._domainkey | v=DKIM1; k=rsa; p=… (yours is in the dashboard) |
| TXT | _dmarc | v=DMARC1; p=none; |
Squarespace specifics
Squarespace adds your domain for you. @ is the root.
Add ours under custom records; leave Squarespace's own records alone.
If Squarespace email is active on the domain, it already owns the MX records — decide which service receives mail before adding ours, because two MX sets means mail lands wherever priority decides.
Check it landed
dig +short TXT _mailflat-verify.acme.com
Expected: "mf-verify-…" (the token from your dashboard)
The usual wrong answer here: Nothing. Squarespace appends your zone to whatever sits in "Host", so "_mailflat-verify.acme.com" is stored as _mailflat-verify.acme.com.acme.com. Query that longer name and the token turns up there — proof the value was right and only the Host field was wrong.
All three records are added from the same place: Add record (custom records).
dig +short MX acme.com
Expected: 10 mail.mailflat.net.
The usual wrong answer here: An MX that is not ours, or none at all. Squarespace will happily keep someone else's MX alongside ours; when two sets exist, priority alone decides which service receives the mail.
dig +short TXT mail._domainkey.acme.com
Expected: "v=DKIM1; k=rsa; p=…" (one long line)
The usual wrong answer here: Two quoted chunks instead of one, or nothing at all. The DKIM key has to survive as a single line through the "Data" field — a key split in two parses fine and then fails every signature check, which looks like a mail problem rather than a DNS one.
When it goes wrong on Squarespace
| What you see | Why | Fix |
|---|---|---|
| Verification fails and the error names a record one level too deep | The full name went into "Host". Squarespace added your zone on top of it, so the record lives at _mailflat-verify.acme.com.acme.com. | Shorten each "Host" value rather than deleting the records — the same paste would only repeat the mistake. |
| Squarespace's own records were edited by mistake | MailFlat's entries belong in the custom records area; the managed ones above it keep the site itself online. | Restore anything you changed outside custom records — a removed managed record can take the website down, not just the mail. |
| Mail goes to Squarespace instead of MailFlat | Squarespace email was already active on the domain and owns its own MX records; two MX sets compete and priority decides. | Decide which service receives mail for this domain, then remove the set you do not want. |
| The new records vanished after saving | They were added outside the custom records area, alongside Squarespace's managed ones. | Add MailFlat's five under custom records and leave Squarespace's own entries untouched. |
Gandiadds your domain for you · trailing dot matters
Gandi adds your domain to whatever you type
Enter names without your domain — _mailflat-verify, not _mailflat-verify.acme.com. Typing the full name stores it as _mailflat-verify.acme.com.acme.com, and no amount of waiting will make that verify. In the dashboard, keep the Provider dropdown on name only.
Where the DNS editor is
- Log in to Gandi
- Domain list → your domain
- DNS Records tab
- Add record
Field names here: Name for the record name, Value for the value, Priority for MX priority.
The Host column, as Gandi wants it
| Type | Name | Value |
|---|---|---|
| TXT | _mailflat-verify | mf-verify-… (yours is in the dashboard) |
| MX | @ | mail.mailflat.net.Priority 10 — Priority |
| TXT | @ | v=spf1 include:mailflat.net ~all |
| TXT | mail._domainkey | v=DKIM1; k=rsa; p=… (yours is in the dashboard) |
| TXT | _dmarc | v=DMARC1; p=none; |
Keep the trailing dot on the MX value
mail.mailflat.net. ends with a dot on purpose. Gandi treats a dotless target as relative and appends your domain to it, so mail is routed to a host that does not exist — with no error anywhere.
Gandi specifics
Gandi adds your domain for you. @ is the root.
Keep the trailing dot on the MX value (mail.mailflat.net.) — without it Gandi appends your domain to the target.
Gandi also offers a text editor for the whole zone; if you use it, the same two rules apply.
Check it landed
dig +short TXT _mailflat-verify.acme.com
Expected: "mf-verify-…" (the token from your dashboard)
The usual wrong answer here: Nothing. Gandi appends your zone to whatever sits in "Name", so "_mailflat-verify.acme.com" is stored as _mailflat-verify.acme.com.acme.com. Query that longer name and the token turns up there — proof the value was right and only the Name field was wrong.
All three records are added from the same place: Add record.
dig +short MX acme.com
Expected: 10 mail.mailflat.net.
The usual wrong answer here: 10 mail.mailflat.net.acme.com. — the trailing dot fell off the "Value" field, so Gandi read the target as relative and glued your domain onto it. Mail is routed to a host that does not exist, and no screen anywhere reports a problem.
dig +short TXT mail._domainkey.acme.com
Expected: "v=DKIM1; k=rsa; p=…" (one long line)
The usual wrong answer here: Two quoted chunks instead of one, or nothing at all. The DKIM key has to survive as a single line through the "Value" field — a key split in two parses fine and then fails every signature check, which looks like a mail problem rather than a DNS one.
When it goes wrong on Gandi
| What you see | Why | Fix |
|---|---|---|
| Verification fails and the error names a record one level too deep | The full name went into "Name". Gandi added your zone on top of it, so the record lives at _mailflat-verify.acme.com.acme.com. | Shorten each "Name" value rather than deleting the records — the same paste would only repeat the mistake. |
| The domain verifies, but no mail ever arrives | The MX target in "Value" lost its trailing dot, so Gandi appended your domain to it. | Restore mail.mailflat.net. — dot included. Verify will never catch this on its own, because it reads TXT records and this is an MX fault. |
| Changes made in the zone text editor did not appear in the records list | Gandi versions zones: editing the text creates a new version that has to be applied before it serves. | Apply the new version, then re-read the records list to confirm what is live. |
| The DNS Records tab shows values that differ from what was typed | Gandi normalises a zone as it stores it, so a name without a trailing dot comes back expanded with your domain attached. | Read the stored form, not the form you typed — the expanded name is what the internet will see. |
| The zone text editor was used and half the records broke | The text editor writes the zone literally, so the same two rules apply with no panel to soften them: short names, and a trailing dot on the MX target. | Re-read the zone file and check each name has no domain suffix and the MX target ends in a dot. |
Hostingeradds your domain for you
Hostinger adds your domain to whatever you type
Enter names without your domain — _mailflat-verify, not _mailflat-verify.acme.com. Typing the full name stores it as _mailflat-verify.acme.com.acme.com, and no amount of waiting will make that verify. In the dashboard, keep the Provider dropdown on name only.
Where the DNS editor is
- Log in to Hostinger
- Domains → Domain portfolio
- Pick your domain
- DNS / Nameservers
- Add record
Field names here: Name for the record name, Points to / TXT value for the value, Priority for MX priority.
The Host column, as Hostinger wants it
| Type | Name | Points to / TXT value |
|---|---|---|
| TXT | _mailflat-verify | mf-verify-… (yours is in the dashboard) |
| MX | @ | mail.mailflat.net.Priority 10 — Priority |
| TXT | @ | v=spf1 include:mailflat.net ~all |
| TXT | mail._domainkey | v=DKIM1; k=rsa; p=… (yours is in the dashboard) |
| TXT | _dmarc | v=DMARC1; p=none; |
Hostinger specifics
Hostinger adds your domain for you. @ is the root; mail._domainkey stays short.
Make sure the domain actually uses Hostinger's nameservers — if you changed them, edit DNS wherever they now point.
Check it landed
dig +short TXT _mailflat-verify.acme.com
Expected: "mf-verify-…" (the token from your dashboard)
The usual wrong answer here: Nothing. Hostinger appends your zone to whatever sits in "Name", so "_mailflat-verify.acme.com" is stored as _mailflat-verify.acme.com.acme.com. Query that longer name and the token turns up there — proof the value was right and only the Name field was wrong.
All three records are added from the same place: Add record.
dig +short MX acme.com
Expected: 10 mail.mailflat.net.
The usual wrong answer here: An MX that is not ours, or none at all. Hostinger will happily keep someone else's MX alongside ours; when two sets exist, priority alone decides which service receives the mail.
dig +short TXT mail._domainkey.acme.com
Expected: "v=DKIM1; k=rsa; p=…" (one long line)
The usual wrong answer here: Two quoted chunks instead of one, or nothing at all. The DKIM key has to survive as a single line through the "Points to / TXT value" field — a key split in two parses fine and then fails every signature check, which looks like a mail problem rather than a DNS one.
When it goes wrong on Hostinger
| What you see | Why | Fix |
|---|---|---|
| Verification fails and the error names a record one level too deep | The full name went into "Name". Hostinger added your zone on top of it, so the record lives at _mailflat-verify.acme.com.acme.com. | Shorten each "Name" value rather than deleting the records — the same paste would only repeat the mistake. |
| The DNS editor cannot be found in the panel | Hostinger keeps it under Domains → Domain portfolio → your domain → DNS / Nameservers, not under hosting. | Go through the domain portfolio rather than the hosting plan. |
| Records exist in Hostinger but the world sees different ones | The domain's nameservers were changed at some point, so Hostinger's zone is no longer authoritative. | Check dig NS and edit DNS wherever the nameservers point today. |
| Changes in Hostinger have no effect at all | The domain is not using Hostinger's nameservers any more, so this editor is not the authoritative one. | Check the current NS records and edit DNS wherever they point today. |
Then verify
Back on Domains, press Verify. A failure names the record it could not find, including the case where your entries landed one level too deep — that message is the fastest diagnosis you will get.
One thing Verify cannot tell you: it reads TXT records, so a broken MX passes it. If verification succeeds and mail still never arrives, run the dig +short MX check from your provider's section — that is the gap.
More on custom domains: Custom domains (BYOD).