How email actually works
Your email does not go straight to the recipient: it is handed to your own mail server first, that server asks DNS where the recipient domain keeps its mail server, and then delivers it there. The receiving server makes one of three decisions on the spot, accept or spam or refuse, and the three records SPF, DKIM and DMARC weigh most heavily on that decision.
- Lesson 9 of 12
- Intermediate
- Free, no signup
Five stations between the send button and the inbox
Nowhere on this path does your device connect directly to the recipient device.
-
1
You write it and press send
Webmail or a phone app, it makes no difference
-
2
Handover to your own mail server
Over SMTP. From here on it is out of your hands.
-
3
Asking DNS where the recipient mail server is
The MX record. A domain that accepts no mail declares it right here.
-
4
Connecting to that server and handing the message over
If it does not answer, the message queues and is retried later
-
5
The receiving server decides
Inbox, spam folder, or refusal on the spot
This path is for a message between two independent domains. If sender and recipient are on the same service, the second, third and fourth stations happen inside that service and the message never touches the internet.
Last checked: Facts and tool names in this lesson are re-checked against their sources on this date.
When you press send, where does the message actually go?
Five stations, and not one of them is a direct connection between you and the recipient. First the program you write in, webmail or an app on your phone, hands the message to your own mail server. That handover uses a protocol called SMTP, and the same protocol is later used between servers too; reading mail is a different job and uses IMAP or POP, which many people confuse with sending.
The second station is the interesting one. The sending server does not know where mail for example.ir should be delivered, so it asks DNS and reads a record called MX. That record names the mail server of the domain. Ours holds this: 10 mail.rgb.ir, meaning mail for rgb.ir is delivered to a machine by that name.
And a domain that accepts no mail at all says so explicitly. example.com publishes an empty MX record, the thing RFC 7505 named a null MX, and it means do not try. Our own server log shows exactly that: a message to an address on that domain bounced on the spot, with no connection attempted, for the reason Domain example.com does not accept mail (nullMX).
The third and fourth stations are connecting to that server and handing over the message. The fifth is the receiving server making its decision, and the rest of this lesson is about that one decision.

What is the difference between landing in spam and never arriving?
These two are not one event and they do not have one cure. A message that landed in spam was accepted; the receiving server took it and then decided where to file it. A message that was refused was never accepted at all, and you get a bounce back telling you why. There is a third state most people do not know: the message sits in a queue and the sending server tries again every few minutes.
Our own server log shows all four states within a few hours. Acceptance looks like this: status=sent (250 2.0.0 OK). The queue looks like this: status=deferred with the message 452-4.2.2 The recipient's inbox is out of storage space, which for one of our messages repeated for a little over two days. Refusal looks like this: status=bounced. And never leaving at all is the null MX case from the previous section.
Now the line that matters most. Gmail refused one of this server's messages with this answer: 550-5.7.26 Your email has been blocked because the sender is unauthenticated. Gmail requires all senders to authenticate with either SPF or DKIM. Then it printed the result: DKIM = did not pass and SPF [] with ip: [65.109.218.65] = did not pass.
In the same few minutes, from the same server and the same IP, ordinary messages were accepted with 250 2.0.0 OK. So neither the server nor the IP was the problem. That one message was a bounce notification and its envelope sender was empty, the from=<> you can see in the log; when the envelope carries no name, SPF has nothing to check, and with no DKIM signature either the message has no identity as far as Gmail is concerned. This is exactly where authentication starts to matter.
What do SPF, DKIM and DMARC each actually do?
All three are text records in your domain DNS, and all three answer one question from three angles: is this message really from this domain?
SPF is the list of servers allowed to send for your domain. Ours reads: v=spf1 +mx +a ~all, meaning the domain mail server and the site server itself are allowed and everything else is suspect. That ~all at the end is the middle setting, not a hard refusal; the stricter one is -all and we deliberately did not choose it, because forgetting one sending service is all it takes to have real mail refused.
DKIM is a signature the sending server puts on the message itself. The private key stays on the server and the public key is published in DNS, under a name called the selector. Ours sits at default._domainkey.rgb.ir and its private key is on this machine; we checked just now that the published key is byte for byte the key on disk. One limit stated plainly: our key is 1024 bit, which RFC 8301 sets as the floor while recommending 2048. So there is room to do better.
DMARC checks nothing by itself. It tells the receiving server what to do when the other two fail, and where to send reports. Ours reads v=DMARC1;p=quarantine;rua=mailto:admin@rgb.ir, meaning quarantine the suspect message and send the report.
The subtlety that usually goes unsaid: SPF looks at the address on the envelope and DKIM at the signature on the letter, and those two can differ. What DMARC adds is a demand that one of them belong to the same family as the sender name the user actually sees. That is why newsletter services which send from their own domain while showing your name are rejected under DMARC unless they are set up properly.
The three records that shape the receiving server decision
The third pillar checks nothing; it only says what to do when the first two fail.
-
SPF
Which servers may send for this domain. It checks the address on the envelope.
-
DKIM
A signature on the message itself, verified against the public key published in DNS.
-
DMARC
What to do when the two above fail, and where to send the report. Ours is set to quarantine.
All three together are still no guarantee of the inbox. The reputation of the sending IP and the text of the message matter too, and no DNS record fixes those.
Which of the three do you have? How to check
Three DNS queries answer the first two, and the third needs something else. For SPF read the text records of the domain itself, for DMARC the text record of the _dmarc subdomain:
dig +short example.ir TXT
dig +short _dmarc.example.ir TXTDKIM cannot be asked blind, though, because you need to know the selector name and every mail service has its own. Take it from your mail service panel and then run dig +short SELECTOR._domainkey.example.ir TXT. If you would rather not work with commands, our free DNS record and email health tool shows these three in one place, and says honestly that it does not check DKIM without knowing the selector.
None of that proves your mail is accepted in practice, however. The only real evidence is the recipient verdict. Send a message to an address you control and look in that service for the option that shows the raw headers; in Gmail it is called Show original. Find the line named Authentication-Results and read what it says beside all three.
Let us catch a common mistake here too: do not test the result by sending to an address on the same domain. A server does not treat a message from itself as a stranger, and the result misleads you.
Why a "sent" status proves nothing
When a contact form or a plugin says the email was sent, it means it handed the message to the local mail server. That is the start of the road, not the end of it. In WordPress, the wp_mail() function returning true says exactly that and no more; we have seen this on our own sites often enough that it has become a fixed rule here to say nothing about delivery until we have read the mail server log.
The place where the real answer is written is the mail server log, and there every message has a line ending in status= that quotes the receiving server answer word for word. The gap between those two views shows in this server own numbers: over the window the current log covers, 44 messages got status=sent and 24 got status=bounced. For some of those 24, the program that sent them had said the mail was sent.
If email matters to you, one habit is enough: after any change to your mail settings, send a real message and look at the log. If you have no access to the server log, ask your host to send you the line for that message. One log line is worth more than ten hours of guessing.
What sits under one "sent" message
Above the line is what the program shows you. Below it, the four fates that are actually possible.
Sent
It means the message was handed to the local mail server. It says nothing about the recipient.
-
Accepted
The receiving server answered 250. In the log: status=sent
-
Queued
A temporary answer. It is retried; one of our messages queued for two days.
-
Refused on the spot
A permanent answer and a bounce back. In the log: status=bounced
-
Never sent at all
The recipient domain has declared that it accepts no mail. No connection is made at all.
Even the first state does not say which folder the message landed in. Accepted means the receiving server took it, not that the recipient saw it.
The fast path, with AI
The ordinary way to handle mail that lands in spam is to search for a ready made SPF record and copy one. The fast way is to collect the evidence first and then force the language model to compare only that evidence against your own current records. The difference is that the second way tells you which of the three checks failed, and you do not add a second record to your domain that becomes tomorrow problem.
- Take the evidence. Either the full text of the bounce message, or the <code>Authentication-Results</code> line from a message you sent to an address outside your own domain. Without one of those two, the rest is guesswork.
- Take your own current records: the raw output of <code>dig +short DOMAIN TXT</code> and <code>dig +short _dmarc.DOMAIN TXT</code>. If you know your DKIM selector, take that one too.
- Hand both together to a frontier class model, the class you use for judgment rather than bulk work, and ask it to diagnose only, not to write a record.
- Change one record at a time and send another real message. DNS caches, and if you change two things at once you will never know which one worked.
Copy-ready recipe
You are an email deliverability specialist. Judge only from the data below and add no record from memory.
My domain: {domain}
The service I send mail through: {for example the hosting server, or a service name}
Raw output of dig +short {domain} TXT:
{raw output}
Raw output of dig +short _dmarc.{domain} TXT:
{raw output}
Evidence from the recipient side (the bounce text or the Authentication-Results line):
{raw text}
Write four things:
1. Which of the three checks failed: SPF, DKIM, or DMARC alignment. Based only on the evidence above, and say which part of the text shows it.
2. The likely cause, in one sentence.
3. Exactly which record must change and what about it must change. Do not write the final record text; only say what is missing or extra.
4. If the data is not enough to diagnose, write what else is needed.
Rules: if you do not see a DKIM selector in the data, do not say I have no DKIM; write that it cannot be checked. Count the DNS lookups inside the SPF record and if it passes ten, say so. Do not propose any ready made record.
Before you trust the output: Two things must not be pasted: the full raw message, and any record the model wrote itself. A raw message carries recipient addresses and sometimes one time password reset links; take only the <code>Authentication-Results</code> line and the bounce text. And the invented record: an SPF can look flawless and still not work, because RFC 7208 sets a ceiling of ten DNS lookups for evaluating one record and past that the result is a permanent failure. That error leaves no mark on the record text; it shows up only with an SPF validator or by counting the lookups by hand.
AI in this kind of work
Email is one of the few topics where a language model genuinely saves you time, because the actual work is reading raw text and numeric codes and the model is good at that. But the boundary is clear: hand it the diagnosis and not the writing of the record. A wrong record in DNS, unlike a wrong answer in a chat, sits on your domain for hours and costs you real mail.
Tools that actually help
- Claude The best pick on this list for reading a raw bounce and header lines, because it follows long unstructured text carefully. Iran is not on Anthropic list of supported countries, so there is no official route to sign up or pay.
- Gemini Good for translating deliverability jargon into Persian and explaining a numeric code. Google own page says the Gemini app works in more than 230 countries and territories, and Iran is not on that list.
- Gemini Notebook Its precise use here: upload the email documentation of your own host and ask for the DKIM selector and the exact setting name from inside that document, not from the model memory. It runs on a Google account, and Iran is not among the available regions.
Where it backfires
The main risk in this topic has one specific shape and is rarely stated: the model writes a record that looks entirely correct and does not work. An SPF text can be flawless and still fail, because RFC 7208 sets a ceiling of ten DNS lookups for evaluating a record and passing that ceiling makes the result a permanent failure; the eye cannot see it. The second risk is DMARC: a model that suggests setting p=reject from the start, without first watching the reports to see what fails, can cut off your real mail tomorrow. Anthropic itself calls this confident invention hallucination in its documentation and writes about reducing it, which means the vendor treats it as a real weakness. On data: Google own help page for Gemini says plainly not to enter confidential information, and a raw message is exactly that. For what paying for these tools looks like from Iran, see the buying guide.
Sources: RFC 7208: Sender Policy Framework, the DNS lookup limit Anthropic: reduce hallucinations Anthropic: supported countries Google: Gemini Apps privacy and data Google: where Gemini Apps are available
Where this advice stops
This lesson is about mail leaving your own domain from your own server or your host. If your mail sits on an organisational service such as Google Workspace or Microsoft 365, the same three records are needed but that service panel builds most of them and the DKIM selector is theirs, so the practical route differs. More importantly, authentication is the entry ticket and not a guarantee of the inbox: after these three, the reputation of the sending IP and the text of the message decide, and no DNS record fixes those. Two things are left out on purpose because they are not needed to start and deserve their own lesson: BIMI and ARC.
From our own work
Every number and log line in this lesson was taken from our own mail server on 7 September 2026. Three things we learned the expensive way. First: within the same few minutes, from one server and one IP, ordinary messages were accepted with 250 2.0.0 OK while a bounce notification was refused with 550-5.7.26 ... the sender is unauthenticated; the only difference was that a bounce notification has an empty envelope and SPF has nothing to check. Second: our mail service is deliberately set to IPv4 only (inet_protocols = ipv4), because this machine has a public IPv6 address with no reverse record and many receivers will not take mail arriving from such an address. We checked again now: this server IPv6 address still has no reverse record at all. Third: we compared the DKIM key published at default._domainkey.rgb.ir with the private key on disk and they matched byte for byte, and the same comparison showed the key is 1024 bit, which is on the RFC 8301 floor and not on its recommended value.
Real follow-up questions
My site emails land in spam. What should I do first?
Send a message to an address you own on a different service and read its Authentication-Results line. If SPF or DKIM failed there, that is where the work is and nowhere else. If both passed and it is still marked spam, the issue is sender reputation or the text of the message, and the fix has nothing to do with DNS.
Why does my message reach one person and not another?
Because the decision belongs to the receiving server and each service sets its own strictness. Gmail, Outlook and a small company server have three different policies, and a message one accepts another quarantines. This is why testing against one address is never enough; try at least two different services.
Can a domain have two SPF records?
No, and this is the most frequent mistake we see. A domain has exactly one SPF record, and publishing two makes the result an error, which is the same as having none. When you add a new sending service, put it inside the one existing record, not in a new one.