{"id":1247,"date":"2025-11-03T17:58:40","date_gmt":"2025-11-03T14:58:40","guid":{"rendered":"https:\/\/www.dchost.com\/blog\/inbox-or-spam-a-friendly-step-by-step-guide-to-spf-dkim-dmarc-and-rdns\/"},"modified":"2025-11-03T17:58:40","modified_gmt":"2025-11-03T14:58:40","slug":"inbox-or-spam-a-friendly-step-by-step-guide-to-spf-dkim-dmarc-and-rdns","status":"publish","type":"post","link":"https:\/\/www.dchost.com\/blog\/en\/inbox-or-spam-a-friendly-step-by-step-guide-to-spf-dkim-dmarc-and-rdns\/","title":{"rendered":"Inbox or Spam? A Friendly, Step-by-Step Guide to SPF, DKIM, DMARC and rDNS"},"content":{"rendered":"<div class=\"dchost-blog-content-wrapper\"><div id=\"toc_container\" class=\"toc_transparent no_bullets\"><p class=\"toc_title\">\u0130&ccedil;indekiler<\/p><ul class=\"toc_list\"><li><a href=\"#So_Why_Are_My_Emails_Going_to_Spam\"><span class=\"toc_number toc_depth_1\">1<\/span> So, Why Are My Emails Going to Spam?<\/a><\/li><li><a href=\"#The_Trust_Chain_How_Mail_Servers_Decide_to_Believe_You\"><span class=\"toc_number toc_depth_1\">2<\/span> The Trust Chain: How Mail Servers Decide to Believe You<\/a><\/li><li><a href=\"#Step_1_Set_a_Clean_Server_Identity_Hostname_HELOEHLO_and_rDNS\"><span class=\"toc_number toc_depth_1\">3<\/span> Step 1: Set a Clean Server Identity (Hostname, HELO\/EHLO, and rDNS)<\/a><ul><li><a href=\"#Pick_a_proper_hostname\"><span class=\"toc_number toc_depth_2\">3.1<\/span> Pick a proper hostname<\/a><\/li><li><a href=\"#Align_rDNS_PTR_with_your_hostname\"><span class=\"toc_number toc_depth_2\">3.2<\/span> Align rDNS (PTR) with your hostname<\/a><\/li><li><a href=\"#Make_sure_your_MTA_says_the_right_HELOEHLO\"><span class=\"toc_number toc_depth_2\">3.3<\/span> Make sure your MTA says the right HELO\/EHLO<\/a><\/li><\/ul><\/li><li><a href=\"#Step_2_Publish_a_Lean_Accurate_SPF_Record\"><span class=\"toc_number toc_depth_1\">4<\/span> Step 2: Publish a Lean, Accurate SPF Record<\/a><ul><li><a href=\"#Start_with_the_basics\"><span class=\"toc_number toc_depth_2\">4.1<\/span> Start with the basics<\/a><\/li><li><a href=\"#Use_a_subrecord_if_needed\"><span class=\"toc_number toc_depth_2\">4.2<\/span> Use a subrecord if needed<\/a><\/li><li><a href=\"#Make_SPF_align_with_your_From_domain\"><span class=\"toc_number toc_depth_2\">4.3<\/span> Make SPF align with your From domain<\/a><\/li><\/ul><\/li><li><a href=\"#Step_3_DKIM_Sign_What_You_Send\"><span class=\"toc_number toc_depth_1\">5<\/span> Step 3: DKIM \u2013 Sign What You Send<\/a><ul><li><a href=\"#Generate_a_2048-bit_key_and_selector\"><span class=\"toc_number toc_depth_2\">5.1<\/span> Generate a 2048-bit key and selector<\/a><\/li><li><a href=\"#Publish_the_DKIM_public_key_in_DNS\"><span class=\"toc_number toc_depth_2\">5.2<\/span> Publish the DKIM public key in DNS<\/a><\/li><li><a href=\"#Wire_OpenDKIM_to_your_MTA\"><span class=\"toc_number toc_depth_2\">5.3<\/span> Wire OpenDKIM to your MTA<\/a><\/li><li><a href=\"#Check_alignment\"><span class=\"toc_number toc_depth_2\">5.4<\/span> Check alignment<\/a><\/li><\/ul><\/li><li><a href=\"#Step_4_DMARC_Set_the_Rules_Start_Gentle\"><span class=\"toc_number toc_depth_1\">6<\/span> Step 4: DMARC \u2013 Set the Rules (Start Gentle)<\/a><ul><li><a href=\"#Begin_with_pnone_and_reports\"><span class=\"toc_number toc_depth_2\">6.1<\/span> Begin with p=none and reports<\/a><\/li><li><a href=\"#Nudge_toward_enforcement\"><span class=\"toc_number toc_depth_2\">6.2<\/span> Nudge toward enforcement<\/a><\/li><\/ul><\/li><li><a href=\"#Testing_and_Verifying_Dont_Skip_This_Part\"><span class=\"toc_number toc_depth_1\">7<\/span> Testing and Verifying: Don\u2019t Skip This Part<\/a><ul><li><a href=\"#Check_DNS_propagation_and_formatting\"><span class=\"toc_number toc_depth_2\">7.1<\/span> Check DNS propagation and formatting<\/a><\/li><li><a href=\"#Send_real_messages_and_read_the_headers\"><span class=\"toc_number toc_depth_2\">7.2<\/span> Send real messages and read the headers<\/a><\/li><li><a href=\"#Monitor_reputation_over_time\"><span class=\"toc_number toc_depth_2\">7.3<\/span> Monitor reputation over time<\/a><\/li><\/ul><\/li><li><a href=\"#Step-by-Step_Putting_It_All_Together_on_a_Fresh_Server\"><span class=\"toc_number toc_depth_1\">8<\/span> Step-by-Step: Putting It All Together on a Fresh Server<\/a><ul><li><a href=\"#1_Prep_the_server\"><span class=\"toc_number toc_depth_2\">8.1<\/span> 1) Prep the server<\/a><\/li><li><a href=\"#2_Install_and_configure_your_MTA\"><span class=\"toc_number toc_depth_2\">8.2<\/span> 2) Install and configure your MTA<\/a><\/li><li><a href=\"#3_rDNS_and_HELO_alignment\"><span class=\"toc_number toc_depth_2\">8.3<\/span> 3) rDNS and HELO alignment<\/a><\/li><li><a href=\"#4_SPF_record_in_DNS\"><span class=\"toc_number toc_depth_2\">8.4<\/span> 4) SPF record in DNS<\/a><\/li><li><a href=\"#5_DKIM_signing\"><span class=\"toc_number toc_depth_2\">8.5<\/span> 5) DKIM signing<\/a><\/li><li><a href=\"#6_DMARC_policy\"><span class=\"toc_number toc_depth_2\">8.6<\/span> 6) DMARC policy<\/a><\/li><li><a href=\"#7_TLS_certificate\"><span class=\"toc_number toc_depth_2\">8.7<\/span> 7) TLS certificate<\/a><\/li><li><a href=\"#8_Test_iterate_and_warm_up\"><span class=\"toc_number toc_depth_2\">8.8<\/span> 8) Test, iterate, and warm up<\/a><\/li><\/ul><\/li><li><a href=\"#Common_Pitfalls_And_How_I_Got_Out_of_Them\"><span class=\"toc_number toc_depth_1\">9<\/span> Common Pitfalls (And How I Got Out of Them)<\/a><\/li><li><a href=\"#Advanced_Tips_That_Quietly_Move_the_Needle\"><span class=\"toc_number toc_depth_1\">10<\/span> Advanced Tips That Quietly Move the Needle<\/a><\/li><li><a href=\"#Working_with_External_Providers_And_Keeping_Alignment\"><span class=\"toc_number toc_depth_1\">11<\/span> Working with External Providers (And Keeping Alignment)<\/a><\/li><li><a href=\"#Troubleshooting_Flow_When_Things_Go_Sideways\"><span class=\"toc_number toc_depth_1\">12<\/span> Troubleshooting Flow When Things Go Sideways<\/a><\/li><li><a href=\"#Final_Checks_Before_You_Hit_Send_at_Scale\"><span class=\"toc_number toc_depth_1\">13<\/span> Final Checks Before You Hit Send at Scale<\/a><\/li><li><a href=\"#A_Quick_Word_on_Content_and_Engagement\"><span class=\"toc_number toc_depth_1\">14<\/span> A Quick Word on Content and Engagement<\/a><\/li><li><a href=\"#Wrap-Up_Your_Email_Trusted_by_Default\"><span class=\"toc_number toc_depth_1\">15<\/span> Wrap-Up: Your Email, Trusted by Default<\/a><\/li><\/ul><\/div>\n<h2 id=\"section-1\"><span id=\"So_Why_Are_My_Emails_Going_to_Spam\">So, Why Are My Emails Going to Spam?<\/span><\/h2>\n<p>A few years back, I was sipping a not-so-great office espresso when a client called me in a panic: \u201cWe launched the new newsletter and\u2026 crickets. Not a single reply.\u201d I checked the logs, ran a few tests, and there it was\u2014the dreaded spam folder. It wasn\u2019t the content. It wasn\u2019t the timing. It was trust. The receiving mail servers simply didn\u2019t trust the mail was who it claimed to be.<\/p>\n<p>Ever had that moment when you send an important message and it vanishes into the void? No bounce, no error\u2014just silence. That\u2019s usually a deliverability problem, and more often than not, the fix isn\u2019t mystical\u2014it&#8217;s methodical. You establish identity, you prove authorship, and you ask the receiving servers to enforce those rules. That\u2019s SPF, DKIM, DMARC, and rDNS in a nutshell.<\/p>\n<p>In this guide, I\u2019ll walk you through a practical, server-first setup that I use for clients: set your server\u2019s identity, publish a correct SPF record, sign mail with DKIM, enforce policy with DMARC, and make reverse DNS (rDNS) match up. We\u2019ll talk about gotchas, share a few war stories, and make sure by the end you\u2019ve got a clean, trustworthy sending setup. No fluff\u2014just the stuff that actually keeps your emails out of spam.<\/p>\n<h2 id=\"section-2\"><span id=\"The_Trust_Chain_How_Mail_Servers_Decide_to_Believe_You\">The Trust Chain: How Mail Servers Decide to Believe You<\/span><\/h2>\n<p>Here\u2019s the thing about email: it\u2019s older than most of the web, and it was never designed with modern-day spam in mind. So the industry bolted on a \u201ctrust chain.\u201d Think of it like a bouncer at an event. SPF is the guest list. DKIM is your government-issued ID. DMARC is the policy that says, \u201cIf the ID doesn\u2019t match the name on the list, don\u2019t let them in.\u201d And rDNS is your return address on the invitation\u2014if it looks sketchy or doesn\u2019t match, you\u2019re on thin ice.<\/p>\n<p>In my experience, deliverability issues almost always trace back to one of three things. First, identity isn\u2019t aligned\u2014your envelope sender says one thing, your From address another, and the signature yet another. Second, DNS is messy\u2014SPF includes too many lookups or is missing the active sending IPs. Third, server basics are off\u2014your hostname and rDNS don\u2019t match, or your HELO is something generic like \u201cserver.local\u201d and providers mark you as suspicious. We\u2019ll clean all of that up step by step.<\/p>\n<p>Before we dive in, a quick reminder: if your DNS infrastructure is a bit complex, it\u2019s worth considering how you secure it end-to-end. I like to think of domain trust as a chain that\u2019s only as strong as its weakest link. If you want to go deeper later, you can read more about <a href=\"https:\/\/www.dchost.com\/blog\/en\/dnssec-nedir-web-sitenizi-nasil-daha-guvenli-hale-getirir\/\">what DNSSEC is and how it protects your domain\u2019s DNS records<\/a>, but for now let\u2019s stick to the core email records.<\/p>\n<h2 id=\"section-3\"><span id=\"Step_1_Set_a_Clean_Server_Identity_Hostname_HELOEHLO_and_rDNS\">Step 1: Set a Clean Server Identity (Hostname, HELO\/EHLO, and rDNS)<\/span><\/h2>\n<p>One of my clients once ran a perfectly fine transactional mail server on a dedicated IP, yet they were constantly flagged by some providers. The problem? Their PTR (reverse DNS) pointed to something like <em>ip-203-0-113-17.exampledc.net<\/em>, while their server introduced itself as <em>mail.brand.com<\/em>. That mismatch might seem small, but it\u2019s a red flag. Let\u2019s fix that.<\/p>\n<h3><span id=\"Pick_a_proper_hostname\">Pick a proper hostname<\/span><\/h3>\n<p>Choose a fully qualified domain name that you control, like <strong>mail.yourdomain.com<\/strong>. Create an A record pointing this name to your sending IP. If you have IPv6, also create an AAAA record. Now set your server\u2019s hostname to that exact value.<\/p>\n<p>On Linux, that usually means:<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">sudo hostnamectl set-hostname mail.yourdomain.com\n<\/code><\/pre>\n<p>Then make sure it\u2019s in <code>\/etc\/hosts<\/code> and your DNS has an A record:<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\"># DNS (at your DNS provider)\nmail 3600 IN A 203.0.113.17\n<\/code><\/pre>\n<h3><span id=\"Align_rDNS_PTR_with_your_hostname\">Align rDNS (PTR) with your hostname<\/span><\/h3>\n<p>rDNS is controlled by whoever owns the IP space\u2014often your hosting provider. You\u2019ll need to set the PTR record for your IP to your hostname (e.g., <strong>203.0.113.17 &rarr; mail.yourdomain.com<\/strong>), then make sure forward DNS resolves <strong>mail.yourdomain.com<\/strong> back to that IP. That two-way match\u2014sometimes called forward-confirmed reverse\u2014is one of those silent credibility boosters.<\/p>\n<h3><span id=\"Make_sure_your_MTA_says_the_right_HELOEHLO\">Make sure your MTA says the right HELO\/EHLO<\/span><\/h3>\n<p>If you use Postfix, set <code>myhostname<\/code> and <code>smtpd_banner<\/code> appropriately:<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\"># \/etc\/postfix\/main.cf\nmyhostname = mail.yourdomain.com\nsmtpd_banner = $myhostname ESMTP\n<\/code><\/pre>\n<p>For Exim:<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\"># \/etc\/exim\/exim.conf or exim4 config\nprimary_hostname = mail.yourdomain.com\n<\/code><\/pre>\n<p>This helps receiving servers see a consistent story: HELO says <em>mail.yourdomain.com<\/em>, reverse DNS says the IP is <em>mail.yourdomain.com<\/em>, and forward DNS confirms it. Simple, but powerful.<\/p>\n<h2 id=\"section-4\"><span id=\"Step_2_Publish_a_Lean_Accurate_SPF_Record\">Step 2: Publish a Lean, Accurate SPF Record<\/span><\/h2>\n<p>SPF is your \u201cwho\u2019s allowed to send\u201d list. When I audit SPF, I\u2019m looking for three things. First, are all legitimate sources included\u2014your server IPs, any SaaS senders, and a relay if you use one? Second, are we within the ten DNS-lookup limit? Third, do we end with a clear enforcement directive, not a nervous <code>~all<\/code> that never graduates to <code>-all<\/code>?<\/p>\n<h3><span id=\"Start_with_the_basics\">Start with the basics<\/span><\/h3>\n<p>In DNS, create a TXT record for your root domain. If your mail is sent only from your server\u2019s IP, a minimal SPF might look like:<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">yourdomain.com. 3600 IN TXT &quot;v=spf1 ip4:203.0.113.17 -all&quot;\n<\/code><\/pre>\n<p>If you send from multiple places\u2014maybe your app server plus a marketing platform\u2014add their mechanisms. For example:<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">&quot;v=spf1 ip4:203.0.113.17 include:_spf.mailservice.com -all&quot;\n<\/code><\/pre>\n<p>Be mindful of nested <code>include:<\/code> chains. Every include can trigger multiple lookups. I\u2019ve seen SPF records silently break because they hit the lookup cap and receivers treated them as \u201cpermerror,\u201d which acts a lot like a fail.<\/p>\n<h3><span id=\"Use_a_subrecord_if_needed\">Use a subrecord if needed<\/span><\/h3>\n<p>When SPF grows complicated, I like to centralize sender IPs in a subdomain such as <em>_spf.yourdomain.com<\/em> and include it from the main record:<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">_spf.yourdomain.com. 3600 IN TXT &quot;v=spf1 ip4:203.0.113.17 ip4:198.51.100.44 -all&quot;\nyourdomain.com.       3600 IN TXT &quot;v=spf1 include:_spf.yourdomain.com -all&quot;\n<\/code><\/pre>\n<p>Keep it concise. Don\u2019t list things that don\u2019t actually send. Don\u2019t use overly broad mechanisms unless you absolutely have to. And, yes, eventually you should be comfortable with <code>-all<\/code> once you\u2019re confident the list is complete.<\/p>\n<h3><span id=\"Make_SPF_align_with_your_From_domain\">Make SPF align with your From domain<\/span><\/h3>\n<p>DMARC cares about alignment between the From domain (what humans see) and the domain authenticated by SPF (the envelope sender or Return-Path). If your Return-Path uses <em>bounce.yourdomain.com<\/em> and your From uses <em>yourdomain.com<\/em>, you\u2019re good under relaxed alignment. If your processor sends bounces from a completely different domain, consider adjusting so they live under your domain. It helps your DMARC story later.<\/p>\n<h2 id=\"section-5\"><span id=\"Step_3_DKIM_Sign_What_You_Send\">Step 3: DKIM \u2013 Sign What You Send<\/span><\/h2>\n<p>DKIM is your signature. It says, \u201cThis message left my server intact, and here\u2019s a cryptographic way to verify it.\u201d If you\u2019ve ever struggled with changing HTML templates and watched SPF still pass, that\u2019s expected\u2014SPF doesn\u2019t validate content integrity. DKIM does.<\/p>\n<h3><span id=\"Generate_a_2048-bit_key_and_selector\">Generate a 2048-bit key and selector<\/span><\/h3>\n<p>Most setups today prefer 2048-bit keys. You\u2019ll also choose a selector\u2014something like <em>mail<\/em> or <em>mta1<\/em>\u2014that lets you rotate keys without downtime.<\/p>\n<p>Using OpenDKIM with Postfix is a common path. Install packages, generate keys, publish the public part, and configure signing:<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">sudo apt-get install opendkim opendkim-tools\nsudo mkdir -p \/etc\/opendkim\/keys\/yourdomain.com\ncd \/etc\/opendkim\/keys\/yourdomain.com\nsudo opendkim-genkey -b 2048 -s mail -d yourdomain.com\nsudo chown opendkim:opendkim mail.private\n<\/code><\/pre>\n<p>This gives you two files: <code>mail.private<\/code> (your private key) and <code>mail.txt<\/code> (a template for your DKIM DNS record).<\/p>\n<h3><span id=\"Publish_the_DKIM_public_key_in_DNS\">Publish the DKIM public key in DNS<\/span><\/h3>\n<p>Take the contents from <code>mail.txt<\/code> and create a TXT record at <em>mail._domainkey.yourdomain.com<\/em>. It looks like this:<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">mail._domainkey.yourdomain.com. 3600 IN TXT &quot;v=DKIM1; k=rsa; p=MIIBIjANBgkqh...IDAQAB&quot;\n<\/code><\/pre>\n<p>Make sure there are no stray spaces or missing quotes; copy-paste errors here are notorious for subtle delivery issues.<\/p>\n<h3><span id=\"Wire_OpenDKIM_to_your_MTA\">Wire OpenDKIM to your MTA<\/span><\/h3>\n<p>For Postfix, add the milter settings:<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\"># \/etc\/opendkim.conf\nSyslog                  yes\nUMask                   002\nMode                    sv\nCanonicalization        relaxed\/relaxed\nKeyTable                \/etc\/opendkim\/key.table\nSigningTable            \/etc\/opendkim\/signing.table\nExternalIgnoreList      \/etc\/opendkim\/trusted.hosts\nInternalHosts           \/etc\/opendkim\/trusted.hosts\nSocket                  inet:8891@localhost\n<\/code><\/pre>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\"># \/etc\/opendkim\/key.table\nmail._domainkey.yourdomain.com yourdomain.com:mail:\/etc\/opendkim\/keys\/yourdomain.com\/mail.private\n\n# \/etc\/opendkim\/signing.table\n*@yourdomain.com mail._domainkey.yourdomain.com\n\n# \/etc\/opendkim\/trusted.hosts\n127.0.0.1\nlocalhost\nmail.yourdomain.com\n<\/code><\/pre>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\"># \/etc\/postfix\/main.cf additions\nmilter_default_action = accept\nmilter_protocol = 6\nsmtpd_milters = inet:localhost:8891\nnon_smtpd_milters = inet:localhost:8891\n<\/code><\/pre>\n<p>Restart services:<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">sudo systemctl restart opendkim\nsudo systemctl restart postfix\n<\/code><\/pre>\n<p>If you run Exim, you\u2019ll configure DKIM parameters in Exim\u2019s configuration to point at the same private key and selector; most modern Exim builds support DKIM natively.<\/p>\n<h3><span id=\"Check_alignment\">Check alignment<\/span><\/h3>\n<p>DKIM alignment for DMARC uses the <code>d=<\/code> domain in the signature. If you sign with <em>d=yourdomain.com<\/em> and your From is <em>yourdomain.com<\/em>, you\u2019re aligned under relaxed mode. Signing with a vendor\u2019s domain (like <em>d=vendor-mail.com<\/em>) won\u2019t align unless it\u2019s your domain. Many SaaS senders let you bring your own DKIM; use that feature so the signature shows your domain.<\/p>\n<h2 id=\"section-6\"><span id=\"Step_4_DMARC_Set_the_Rules_Start_Gentle\">Step 4: DMARC \u2013 Set the Rules (Start Gentle)<\/span><\/h2>\n<p>DMARC is the policy layer. It tells receivers what to do if SPF and DKIM don\u2019t align with your From domain. I like to start soft, watch the reports, then dial up enforcement. Think of DMARC like a thermostat\u2014you don\u2019t set it to max on day one. You nudge it until it feels right.<\/p>\n<h3><span id=\"Begin_with_pnone_and_reports\">Begin with p=none and reports<\/span><\/h3>\n<p>Create a TXT record at <em>_dmarc.yourdomain.com<\/em>:<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">_dmarc.yourdomain.com. 3600 IN TXT \n&quot;v=DMARC1; p=none; rua=mailto:dmarc-aggregate@yourdomain.com; ruf=mailto:dmarc-forensic@yourdomain.com; fo=1; adkim=r; aspf=r&quot;\n<\/code><\/pre>\n<p>What does this do? <code>p=none<\/code> means \u201cdon\u2019t quarantine or reject yet.\u201d <code>rua<\/code> collects aggregate reports (XML summaries) and <code>ruf<\/code> can collect forensic samples. <code>fo=1<\/code> asks for failure reports. <code>adkim<\/code> and <code>aspf<\/code> set relaxed alignment. If you\u2019re new to DMARC, I recommend relaxed at first; you can tighten to strict (<code>s<\/code>) later.<\/p>\n<h3><span id=\"Nudge_toward_enforcement\">Nudge toward enforcement<\/span><\/h3>\n<p>After a couple of weeks of watching reports, you\u2019ll know who\u2019s sending on your behalf and whether they align. Clean up any stragglers, then move to quarantine for a portion of traffic:<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">&quot;v=DMARC1; p=quarantine; pct=25; rua=mailto:dmarc-aggregate@yourdomain.com; adkim=r; aspf=r&quot;\n<\/code><\/pre>\n<p>If that looks good\u2014no legitimate traffic getting caught\u2014raise <code>pct<\/code> and eventually go to <code>p=reject<\/code>. It\u2019s incredibly satisfying to see spoofed mail get stopped in its tracks while your real mail sails through.<\/p>\n<p>If you want an accessible, vendor-neutral overview to share with your team, the high-level summary at <a href=\"https:\/\/dmarc.org\/\" rel=\"nofollow noopener\" target=\"_blank\">dmarc.org<\/a> is a nice reference point.<\/p>\n<h2 id=\"section-7\"><span id=\"Testing_and_Verifying_Dont_Skip_This_Part\">Testing and Verifying: Don\u2019t Skip This Part<\/span><\/h2>\n<p>Every time I think \u201cthis setup is too simple to fail,\u201d I\u2019m reminded of the time a hidden character in a DKIM record broke signing for a week. Testing isn\u2019t optional; it\u2019s the part that saves you those quiet lost conversions.<\/p>\n<h3><span id=\"Check_DNS_propagation_and_formatting\">Check DNS propagation and formatting<\/span><\/h3>\n<p>Use a reputable tool to query your SPF, DKIM, and DMARC records and check for obvious issues. I\u2019ve had good experiences with the suite over at <a href=\"https:\/\/mxtoolbox.com\/\" rel=\"nofollow noopener\" target=\"_blank\">MXToolbox for SPF\/DKIM\/DMARC checks<\/a>. Test your domain and selectors, and make sure there are no syntax mistakes.<\/p>\n<h3><span id=\"Send_real_messages_and_read_the_headers\">Send real messages and read the headers<\/span><\/h3>\n<p>Send a message to Gmail, Outlook, and another provider if you can. Open the raw headers and look for <code>Authentication-Results<\/code>. You want to see something like:<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">Authentication-Results: mx.google.com;\n       spf=pass (google.com: domain of bounce@yourdomain.com designates 203.0.113.17 as permitted sender) smtp.mailfrom=bounce@yourdomain.com;\n       dkim=pass (signature verified) header.d=yourdomain.com;\n       dmarc=pass (p=REJECT sp=NONE dis=NONE) header.from=yourdomain.com\n<\/code><\/pre>\n<p>If any result shows \u201cneutral,\u201d \u201csoftfail,\u201d or \u201cfail,\u201d trace it back. Sometimes the Return-Path is a service domain not under your control. Sometimes DKIM is signing with the wrong selector. And sometimes DMARC alignment is off because the From domain doesn\u2019t match the domain authenticated by SPF or DKIM.<\/p>\n<h3><span id=\"Monitor_reputation_over_time\">Monitor reputation over time<\/span><\/h3>\n<p>Warm up new IPs slowly and watch how receivers react. Gmail\u2019s <a href=\"https:\/\/postmaster.google.com\/\" rel=\"nofollow noopener\" target=\"_blank\">Postmaster Tools<\/a> can give you a feel for IP and domain reputation, complaint rates, and delivery errors. Changes to volume, complaint spikes, or a sudden surge in bounces can all drag down deliverability. If you\u2019re doing transactional mail, consistency is your friend.<\/p>\n<h2 id=\"section-8\"><span id=\"Step-by-Step_Putting_It_All_Together_on_a_Fresh_Server\">Step-by-Step: Putting It All Together on a Fresh Server<\/span><\/h2>\n<p>Let\u2019s roll up our sleeves. Imagine you\u2019ve just deployed a fresh <a href=\"https:\/\/www.dchost.com\/vps\">VPS<\/a> to send transactional email for your app. Here\u2019s the pragmatic sequence I follow, because it saves time and avoids dead ends.<\/p>\n<h3><span id=\"1_Prep_the_server\">1) Prep the server<\/span><\/h3>\n<p>Set the hostname, update packages, and sync time (NTP helps with DKIM and TLS handshakes):<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">sudo hostnamectl set-hostname mail.yourdomain.com\nsudo apt-get update &amp;&amp; sudo apt-get upgrade -y\nsudo timedatectl set-ntp true\n<\/code><\/pre>\n<p>If you\u2019re running a VPS in the wild, it\u2019s worth a quick security sweep\u2014firewall essentials, SSH hardening, and safe defaults. If you need a practical checklist later, I wrote up a guide on <a href=\"https:\/\/www.dchost.com\/blog\/en\/vps-sunucu-guvenligi-pratik-olceklenebilir-ve-dogrulanabilir-yaklasimlar\/\">how to secure a VPS server with step-by-step hardening<\/a>.<\/p>\n<h3><span id=\"2_Install_and_configure_your_MTA\">2) Install and configure your MTA<\/span><\/h3>\n<p>For Postfix, install and set a clean banner:<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">sudo apt-get install postfix\n# choose Internet Site and set mail.yourdomain.com as system mail name\n\n# \/etc\/postfix\/main.cf (relevant bits)\nmyhostname = mail.yourdomain.com\nmyorigin = \/etc\/mailname\nmydestination = $myhostname, localhost.$mydomain, localhost\ninet_interfaces = all\ninet_protocols = ipv4\nsmtpd_banner = $myhostname ESMTP\n<\/code><\/pre>\n<p>Reload Postfix:<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">sudo systemctl restart postfix\n<\/code><\/pre>\n<p>If you use Exim, install via your distro, set <code>primary_hostname<\/code>, and confirm the daemon is listening only where it should. Keep open relays far away from your setup\u2014you don\u2019t want to wake up with a blacklisted IP because someone abused your server overnight.<\/p>\n<h3><span id=\"3_rDNS_and_HELO_alignment\">3) rDNS and HELO alignment<\/span><\/h3>\n<p>Configure the PTR with your provider so the IP points to <em>mail.yourdomain.com<\/em>, and make sure forward DNS points back. Test it with:<\/p>\n<pre class=\"language-bash line-numbers\"><code class=\"language-bash\">host 203.0.113.17\n# should show pointer to mail.yourdomain.com\n\nhost mail.yourdomain.com\n# should resolve to 203.0.113.17\n<\/code><\/pre>\n<h3><span id=\"4_SPF_record_in_DNS\">4) SPF record in DNS<\/span><\/h3>\n<p>Publish your SPF TXT record with the exact senders and end with an enforcement directive. If you\u2019re still running tests, <code>~all<\/code> is okay for a day or two, but plan to move to <code>-all<\/code> once you trust the configuration.<\/p>\n<h3><span id=\"5_DKIM_signing\">5) DKIM signing<\/span><\/h3>\n<p>Install OpenDKIM, generate a 2048-bit key with a selector (e.g., <em>mail<\/em>), publish the TXT record from the generated <code>mail.txt<\/code>, then wire the milter into Postfix or Exim. Restart services and send a test message to yourself at a Gmail account to inspect headers.<\/p>\n<h3><span id=\"6_DMARC_policy\">6) DMARC policy<\/span><\/h3>\n<p>Create the initial DMARC record with <code>p=none<\/code> and set <code>rua<\/code> for aggregate reports. After you verify SPF\/DKIM alignment for your legitimate mail sources, move to <code>p=quarantine<\/code> with <code>pct=25<\/code>, then ramp up. Eventually, <code>p=reject<\/code> is the goal for maximum spoofing protection.<\/p>\n<h3><span id=\"7_TLS_certificate\">7) TLS certificate<\/span><\/h3>\n<p>Modern MTAs increasingly care about encryption on the wire. Configure STARTTLS with a valid certificate so that providers aren\u2019t eyeballing your server suspiciously. If you need a refresher on why certificates matter and how to think about them, here\u2019s a friendly primer on <a href=\"https:\/\/www.dchost.com\/blog\/en\/ssl-sertifikasi-nedir-web-sitenizi-guvence-altina-almanin-yollari\/\">what an SSL certificate is and how it secures connections<\/a>.<\/p>\n<h3><span id=\"8_Test_iterate_and_warm_up\">8) Test, iterate, and warm up<\/span><\/h3>\n<p>Send small volumes first. Check your <code>Authentication-Results<\/code> headers, watch bounces, and monitor reputation with the tools we discussed. Adjust DNS if a provider reports alignment issues. Then slowly increase your volume. Think of it like training a new barista\u2014hand them a few orders, watch their technique, and then let them handle the rush.<\/p>\n<h2 id=\"section-9\"><span id=\"Common_Pitfalls_And_How_I_Got_Out_of_Them\">Common Pitfalls (And How I Got Out of Them)<\/span><\/h2>\n<p>I\u2019ve lost count of how many times these same issues popped up. The silver lining? They\u2019re fixable, and once you know them, you\u2019ll spot them from a mile away.<\/p>\n<p>First, SPF \u201cpermerror\u201d from too many lookups. If you include a vendor that includes five other vendors, you can hit the ten-lookup ceiling without realizing it. Solution: consolidate IP ranges when possible, remove dead includes, and avoid unnecessary mechanisms. You can also move some senders to DKIM-first alignment to ease SPF pressure.<\/p>\n<p>Second, DKIM record formatting. DNS control panels sometimes wrap long strings, or they add extra quotes. If your DKIM fails, check exactly what the TXT record returns with a direct dig. Compare it to what your <code>mail.txt<\/code> generated. A single missing character can tank your signature.<\/p>\n<p>Third, DMARC alignment mismatches. Maybe your Return-Path is <em>bounce@mailer.vendor.com<\/em> while your From is <em>you@yourdomain.com<\/em>. SPF might pass, but it won\u2019t align. Either switch to a Return-Path under your domain or ensure DKIM signs with your domain and passes, so DMARC can pass via DKIM alignment instead.<\/p>\n<p>Fourth, rDNS mismatches or generic PTRs. If your IP\u2019s PTR is something like <em>ec2-203-0-113-17.compute-1.amazonaws.com<\/em> and you HELO as <em>mail.yourdomain.com<\/em>, that mismatch can degrade your reputation. Ask your provider for a custom PTR, and ensure forward-confirmation.<\/p>\n<p>Fifth, content and sudden volume spikes. Even with perfect authentication, sending too many identical messages too quickly can look like bot behavior. I once watched a clean IP lose favor for a week because an app bug retried the same message for thousands of users. Fix the bug, drip the retries, and your reputation recovers.<\/p>\n<h2 id=\"section-10\"><span id=\"Advanced_Tips_That_Quietly_Move_the_Needle\">Advanced Tips That Quietly Move the Needle<\/span><\/h2>\n<p>Over time, I\u2019ve adopted a handful of habits that keep deliverability steady, even when campaigns get ambitious.<\/p>\n<p>Consider using a dedicated subdomain for outbound mail\u2014like <em>mail.yourdomain.com<\/em> as the visible From domain\u2014if your brand allows it. This gives you room to evolve policy and isolate reputation without risking your apex domain. If you do this, make sure SPF, DKIM, and DMARC live under that subdomain too.<\/p>\n<p>Rotate DKIM keys annually or after team changes. That\u2019s the magic of selectors\u2014you can publish a new selector, start signing with it, and remove the old one when you\u2019re done. No downtime, no drama.<\/p>\n<p>For mailing list traffic, watch ARC and List-Id behaviors. While ARC isn\u2019t strictly necessary for standard transactional mail, some forwarders play nicer when signed messages carry through. If your messages are often forwarded (think internal aliases or helpdesk systems), understanding ARC can help with edge-case troubleshooting.<\/p>\n<p>Use suppression lists and bounce handling. SPF, DKIM, DMARC, and rDNS get you in the door, but engagement keeps you inside. If people don\u2019t open your mail, providers notice. Respect unsubscribes, remove hard bounces, and don\u2019t hammer soft bounces indefinitely.<\/p>\n<p>Lastly, keep an eye on your infrastructure. If your server is under load or misconfigured, delays and timeouts can cascade into delivery issues. If this topic interests you from a performance angle\u2014tuning PHP-FPM, OPcache, Redis, and MySQL for web apps\u2014there\u2019s a post I love referring back to about <a href=\"https:\/\/www.dchost.com\/blog\/en\/wordpress-icin-sunucu-tarafi-optimizasyon-php-fpm-opcache-redis-ve-mysql-ile-neyi-ne-zaman-nasil-ayarlamalisin\/\">server-side optimization that makes WordPress fly<\/a>. While it\u2019s not email-specific, a healthy server helps everything behave, including your MTA.<\/p>\n<h2 id=\"section-11\"><span id=\"Working_with_External_Providers_And_Keeping_Alignment\">Working with External Providers (And Keeping Alignment)<\/span><\/h2>\n<p>Plenty of teams use a cocktail of services: transactional mail from the app server, marketing blasts through a SaaS, and maybe a support desk with its own outbound setup. There\u2019s nothing wrong with that. Just make sure each source can either align via SPF or DKIM with your From domain.<\/p>\n<p>For SaaS platforms, use custom domains for both Return-Path and DKIM whenever possible. Most reputable senders provide a DNS wizard that asks you to add CNAMEs or TXT records so they can sign on your behalf with <em>d=yourdomain.com<\/em>. Don\u2019t skip this. If the vendor says it\u2019s \u201coptional,\u201d treat it as mandatory for deliverability.<\/p>\n<p>When onboarding a new sender, add it to your SPF carefully. If they provide an <code>include:<\/code> mechanism, check whether that include fans out into multiple lookups. If you\u2019re tight on the limit, consider relying on DKIM alignment instead and keep SPF minimal. And, of course, test again after adding the new service.<\/p>\n<h2 id=\"section-12\"><span id=\"Troubleshooting_Flow_When_Things_Go_Sideways\">Troubleshooting Flow When Things Go Sideways<\/span><\/h2>\n<p>Here\u2019s the flow I use when someone messages me late on a Friday with, \u201cWhy did Outlook suddenly hate our emails?\u201d<\/p>\n<p>First, check your domain with a testing tool for DNS record health and blacklists. A quick pass with <a href=\"https:\/\/mxtoolbox.com\/\" rel=\"nofollow noopener\" target=\"_blank\">MXToolbox deliverability tests<\/a> can save you thirty minutes of guesswork.<\/p>\n<p>Second, send yourself a fresh message and inspect the raw headers at the destination. Look for <code>spf=pass|fail<\/code>, <code>dkim=pass|fail<\/code>, <code>dmarc=pass|fail<\/code>. If DKIM fails, check the selector\u2019s public key in DNS and confirm it matches the signing key. If SPF fails, verify the Return-Path domain and the IP that actually sent the message.<\/p>\n<p>Third, compare the results across providers. Gmail might pass you while Outlook quarantines you. It\u2019s not always a policy issue; sometimes volume or user feedback nudges a provider to be stricter. That\u2019s when I\u2019ll peek at <a href=\"https:\/\/postmaster.google.com\/\" rel=\"nofollow noopener\" target=\"_blank\">Postmaster Tools<\/a> to see trends and error codes and adjust sending cadence or segment the list.<\/p>\n<p>Fourth, review recent changes. Did a developer roll out a new marketing sender? Did you migrate DNS providers? Did an <a href=\"https:\/\/www.dchost.com\/ssl\">SSL certificate<\/a> expire and force a weird fallback? Most deliverability issues are change-related. Find the change, fix the alignment, and your results usually normalize within a few days.<\/p>\n<h2 id=\"section-13\"><span id=\"Final_Checks_Before_You_Hit_Send_at_Scale\">Final Checks Before You Hit Send at Scale<\/span><\/h2>\n<p>Before a big campaign or that all-important invoice batch, I run through a quick gut-check.<\/p>\n<p>Is the server identity clean? Hostname, rDNS, and HELO match? Are SPF and DKIM passing <em>and<\/em> aligning with the From domain? Is DMARC at the right enforcement level for this audience? Do we have a valid TLS certificate? Are unsubscribe links and suppression lists up to date? If a few of these make you hesitate, fix them now. It\u2019s much easier to adjust before you dump thousands of messages into the queue.<\/p>\n<p>If your underlying platform or DNS governance still feels shaky, circle back and strengthen the base. For many teams, the weak link isn\u2019t the mail config; it\u2019s the surrounding infrastructure. Solid DNS practices, sane server security, and healthy performance tuning create a rhythm that keeps mail flowing. If you\u2019re building your skills in that direction, the deeper dive into <a href=\"https:\/\/www.dchost.com\/blog\/en\/dnssec-nedir-web-sitenizi-nasil-daha-guvenli-hale-getirir\/\">DNSSEC for domain authenticity<\/a> and the earlier notes on <a href=\"https:\/\/www.dchost.com\/blog\/en\/vps-sunucu-guvenligi-pratik-olceklenebilir-ve-dogrulanabilir-yaklasimlar\/\">VPS hardening<\/a> are worth bookmarking.<\/p>\n<h2 id=\"section-14\"><span id=\"A_Quick_Word_on_Content_and_Engagement\">A Quick Word on Content and Engagement<\/span><\/h2>\n<p>Even a perfectly authenticated email can stumble if the content screams \u201cspam.\u201d I once watched a transactional password reset template start to dip simply because a well-meaning designer stuffed it with promotional banners. Keep transactional emails lean and focused. For marketing, test subject lines and avoid language that feels too urgent or misleading. The best signal to mailbox providers is real engagement\u2014opens, clicks, and low complaint rates. Respect your audience; your deliverability will thank you.<\/p>\n<h2 id=\"section-15\"><span id=\"Wrap-Up_Your_Email_Trusted_by_Default\">Wrap-Up: Your Email, Trusted by Default<\/span><\/h2>\n<p>Let\u2019s bring it home. If you set a clean server identity (hostname, HELO\/EHLO, and rDNS), publish a tight SPF record, sign messages with DKIM, and enforce with DMARC, you\u2019re no longer hoping your emails get delivered\u2014you\u2019re <em>engineering<\/em> their path to the inbox. Add steady testing, gentle ramp-ups, and a watchful eye on reputation, and you\u2019ll avoid the mysterious disappearances that drive people crazy.<\/p>\n<p>The best part? None of this is magic. It\u2019s a series of small, dependable steps that add up. So, take an hour, tighten your SPF, publish that DKIM selector, and turn on DMARC reporting. Send a few test emails, read the headers, and adjust. Next week, push the DMARC policy a little further. A month from now, rotate your DKIM key and feel oddly proud no one noticed.<\/p>\n<p>If you\u2019d like to strengthen the broader foundation\u2014encryption, trust, and server hygiene\u2014my note earlier about <a href=\"https:\/\/www.dchost.com\/blog\/en\/ssl-sertifikasi-nedir-web-sitenizi-guvence-altina-almanin-yollari\/\">using SSL certificates across services<\/a> and the piece on <a href=\"https:\/\/www.dchost.com\/blog\/en\/vps-sunucu-guvenligi-pratik-olceklenebilir-ve-dogrulanabilir-yaklasimlar\/\">hardening a VPS<\/a> are great companions to this guide. Keep going, keep testing, and you\u2019ll notice your emails start landing not just reliably\u2014but confidently. Hope this was helpful! See you in the next post.<\/p>\n<\/div>","protected":false},"excerpt":{"rendered":"<p>\u0130&ccedil;indekiler1 So, Why Are My Emails Going to Spam?2 The Trust Chain: How Mail Servers Decide to Believe You3 Step 1: Set a Clean Server Identity (Hostname, HELO\/EHLO, and rDNS)3.1 Pick a proper hostname3.2 Align rDNS (PTR) with your hostname3.3 Make sure your MTA says the right HELO\/EHLO4 Step 2: Publish a Lean, Accurate SPF [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":1248,"comment_status":"","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[26],"tags":[],"class_list":["post-1247","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-teknoloji"],"_links":{"self":[{"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/posts\/1247","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/comments?post=1247"}],"version-history":[{"count":0,"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/posts\/1247\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/media\/1248"}],"wp:attachment":[{"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/media?parent=1247"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/categories?post=1247"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.dchost.com\/blog\/en\/wp-json\/wp\/v2\/tags?post=1247"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}