نحو SPF: مکانیزم‌ها، کوالیفایرها و سقف ده جستجو

مرجع دقیق نحو SPF: تعریف مکانیزم‌ها و کوالیفایرها، سقف ده جستجوی DNS، خطاهای نحوی رایج و روش تست رکورد با dig.

۶ دقیقه به‌روزرسانی ۷ آبان ۱۴۰۵

رکورد SPF شما احتمالاً کار می‌کند و همین بدترین حالت است. تا وقتی گیرنده‌ای permerror برنگرداند، کسی سراغش نمی‌رود؛ و وقتی برگرداند، ایمیل‌های تراکنشی بی‌صدا در صف می‌مانند یا به اسپم می‌روند. اگر اینجا هستید، یعنی می‌خواهید مقدار دقیق هر ترم را بدانید، نه توضیح کلی. پس مستقیم می‌رویم سر نحو.

ساختار یک رکورد SPF و ترتیب اجباری ترم‌ها

رکورد SPF یک TXT record روی نام دامنه است که با v=spf1 شروع می‌شود. بعد از آن، فهرستی از ترم‌ها می‌آید که با فاصله جدا شده‌اند و ترتیبشان معنادار است: مکانیزم‌ها از چپ به راست ارزیابی می‌شوند و اولین تطابق برنده است. اگر تطابقی پیدا نشود، کوالیفایر پیش‌فرض یعنی -all اعمال می‌شود. این «پیش‌فرض بودن» را خیلی‌ها نمی‌دانند و فکر می‌کنند نبودِ all یعنی خنثی.

example.com. 3600 IN TXT "v=spf1 mx a:mail.example.com include:_spf.google.com ip4:185.10.20.30 -all"

سه دسته ترم داریم. مکانیزم‌ها که مشخص می‌کنند چه میزبان‌هایی مجازند، کوالیفایرها که نتیجه هر مکانیزم را تعیین می‌کنند، و modifierها که با = می‌آیند و برخلاف مکانیزم‌ها ترتیبشان مهم نیست.

مکانیزم‌ها: هر کدام دقیقاً چه چیزی را تطبیق می‌دهد

مکانیزمتطبیق باهزینه جستجو
allهمه فرستنده‌ها؛ همیشه آخر می‌آیدصفر
aA یا AAAA رکورد دامنه (یا دامنه مشخص‌شده)۱
mxآدرس‌های IP همه MXهای دامنه۱ + تعداد MX
ip4 / ip6آدرس یا CIDR مشخصصفر
includeرکورد SPF دامنه دیگر و نتیجه‌اش۱ + جستجوهای آن دامنه
existsوجود یک نام دامنه (هر نوع رکوردی)۱
ptrreverse DNS آدرس فرستنده۱ به‌ازای هر IP

دو نکته که در عمل زیاد می‌بینم. اول، ptr منسوخ است و RFC 7208 صریحاً توصیه می‌کند استفاده نشود؛ اگر جایی می‌بینیدش، معمولاً از یک پنل قدیمی مانده. دوم، include نتیجه‌اش را از دامنه مقصد قرض می‌گیرد: اگر دامنه‌ای که include کرده‌اید با -all تمام شود و آدرس شما در آن لیست نباشد، نتیجه fail است، نه neutral. همین یک تفاوت، منبع بیشتر تیکت‌های «چرا ایمیل تراکنشی از سرور ما رد می‌شود» است.

کوالیفایرها: چهار مقدار و یک پیش‌فرض

هر مکانیزم می‌تواند با یکی از چهار کوالیفایر بیاید: + یعنی pass، - یعنی fail، ~ یعنی softfail، و ? یعنی neutral. نبودِ کوالیفایر معادل + است. یعنی mx و +mx یکی هستند.

  • -all: سخت‌گیرانه. هر فرستنده‌ای که در لیست نباشد رد می‌شود. برای دامنه‌ای که فقط از یک مسیر مشخص ایمیل می‌فرستد، درست‌ترین انتخاب است.
  • ~all: نرم. گیرنده می‌تواند بپذیرد و در اسپم بگذارد. برای دوره گذار و وقتی مطمئن نیستید همه فرستنده‌ها را پوشش داده‌اید منطقی است.
  • ?all: بی‌خاصیت. عملاً SPF را خنثی می‌کند و فقط برای دامنه‌های بدون ایمیل معنا دارد.

انتخاب من: -all. اگر لیست فرستنده‌هایتان را می‌شناسید، softfail فقط به گیرنده اجازه می‌دهد تصمیم بدی بگیرد. ~all را فقط در دو هفته اول مهاجرت نگه دارید و بعد سختش کنید.

سقف ده جستجوی DNS و خطای permerror

این جایی است که رکوردهای سالم از کار می‌افتند. RFC 7208 سقف ۱۰ جستجوی DNS برای هر ارزیابی SPF تعیین کرده. مکانیزم‌های include، a، mx، ptr و exists هر کدام یک جستجو مصرف می‌کنند، و include جستجوهای دامنه درونش را هم به حساب شما می‌نویسد. ip4 و ip6 و all صفر هستند.

نتیجه عبور از سقف، خطای permerror است و گیرنده‌ها آن را مثل fail یا بدتر رفتار می‌کنند. علامتش هم دقیقاً این است: رکورد syntactically درست است، dig هم تمیز جواب می‌دهد، ولی Gmail ایمیل را رد می‌کند. ابزارهایی مثل spfquery یا سرویس‌های آنلاین عدد نهایی را نشان می‌دهند:

dig +short TXT example.com | grep spf1
spfquery -i 185.10.20.30 -s mail.example.com -h example.com

یک include:_spf.google.com تنها یک جستجو نیست؛ خودش چند تا مصرف می‌کند. سه سرویس SaaS که هر کدام include دارند، راحت شما را به ۱۲ می‌رسانند. راه‌حل درست، جایگزینی includeهای تکراری با ip4 مستقیم است، چون صفر جستجو می‌خورد. هزینه‌اش این است که اگر آن سرویس IPهایش را عوض کند، باید دستی رکورد را به‌روز کنید. این هزینه را می‌پذیرم؛ permerror بدتر است.

اینجا اشتباه می‌کنند

رایج‌ترین خطای واقعی، گذاشتن all در وسط رکورد است. کسی رکورد را ویرایش می‌کند و -all می‌رود قبل از include. از آن لحظه، هر ارزیابی روی all متوقف می‌شود و بقیه ترم‌ها هرگز خوانده نمی‌شوند. علامتش گیج‌کننده است: رکورد به‌نظر کامل است، include هم سر جایش هست، ولی ایمیل‌های سرویس جدید رد می‌شوند و ایمیل‌های قدیمی می‌روند. چون all قبل از include تطبیق خورده.

خطای دوم، دو رکورد TXT جداگانه با v=spf1 است. RFC می‌گوید در این حالت نتیجه permerror است، نه انتخاب یکی از آن‌ها. اگر پنل DNS اجازه ویرایش رکورد موجود را نمی‌دهد و رکورد دوم می‌سازید، دقیقاً همین اتفاق می‌افتد. باید هر دو را در یک TXT ادغام کنید.

modifierها و redirect

دو modifier استاندارد دارید. redirect= کل ارزیابی را به دامنه دیگری می‌سپارد و فقط وقتی اعمال می‌شود که هیچ مکانیزمی تطبیق نخورده باشد. exp= یک دامنه توضیح می‌دهد که متن خطا را برمی‌گرداند؛ تقریباً هیچ گیرنده‌ای آن را نمایش نمی‌دهد و ارزش عملی‌اش نزدیک صفر است.

"v=spf1 include:_spf.example.net redirect=_spf.example.org -all"

نکته‌ای که کمتر گفته می‌شود: redirect خودش یک جستجو مصرف می‌کند و اگر دامنه مقصد هم سقف را رد کند، permerror به شما نسبت داده می‌شود. برای دامنه‌های اصلی از include صریح استفاده کنید و redirect را برای دامنه‌های پارک‌شده نگه دارید.

اگر روی هاست اشتراکی هستید و کنترل کامل DNS ندارید، قبل از دست‌زدن به رکورد، مطمئن شوید مسیر ارسال از کجا تعیین می‌شود. راهنمای ایمیل تراکنشی؛ چرا از هاست نفرستیم و جایگزین درست چیست؟ این تفکیک را روشن می‌کند و جلوی خیلی از رکوردهای اشتباه را می‌گیرد.

روش تست کردن رکورد قبل از انتشار

  1. رکورد را در یک دامنه آزمایشی بسازید، نه دامنه اصلی.
  2. با dig +short TXT test.example.com مقدار واقعی منتشرشده را ببینید، نه چیزی که در پنل تایپ کرده‌اید.
  3. با spfquery یا ابزار آنلاین، تعداد جستجوها و نتیجه را برای چند IP نمونه چک کنید.
  4. یک ایمیل واقعی به Gmail و Outlook بفرستید و هدر Received-SPF را بخوانید.
  5. اگر نتیجه softfail یا neutral بود، قبل از تغییر به -all علت را پیدا کنید.

برای بررسی رکوردهای MX و اطمینان از اینکه میزبان‌های دریافت هم درست تنظیم شده‌اند، بررسی رکورد MX نقطه شروع سریعی است. اگر بعد از تنظیم SPF باز هم ایمیل‌ها به اسپم می‌روند، مشکل معمولاً SPF نیست؛ چرا ایمیل‌های ما به اسپم می‌رود؟ راهنمای کامل رفع مشکل مسیر DKIM و DMARC و reputation را پوشش می‌دهد.

یک هشدار عملی: SPF فقط مسیر ارسال را تأیید می‌کند، نه محتوا را. دامنه‌ای با SPF بی‌نقص و DKIM خاموش، همچنان در Gmail مشکل دارد. اگر روی هاست لینوکس کار می‌کنید و دسترسی به تنظیمات DNS و کلید DKIM دارید، هر دو را با هم تنظیم کنید؛ SPF تنها نصف کار است.

پرسش‌های پرتکرار

حداکثر تعداد include در رکورد SPF چند تا است؟

محدودیت عددی روی تعداد include وجود ندارد، اما سقف ۱۰ جستجوی DNS عملاً آن را به دو یا سه include وابسته به سرویس‌های ابری محدود می‌کند. هر include حداقل یک جستجو مصرف می‌کند و جستجوهای داخلی خودش را هم اضافه می‌کند. اگر از این سقف رد شوید، نتیجه permerror است و ایمیل رد می‌شود.

تفاوت -all و ~all در SPF چیست؟

-all به گیرنده می‌گوید فرستنده‌های خارج از لیست را قطعاً رد کن، در حالی که ~all می‌گوید می‌توانی بپذیری ولی با احتیاط رفتار کن. در عمل، ~all باعث می‌شود ایمیل در اسپم بنشیند به‌جای اینکه رد شود. برای دامنه‌ای که همه فرستنده‌هایش را می‌شناسید، -all انتخاب درست است.

چرا رکورد SPF من permerror می‌دهد در حالی که درست به‌نظر می‌رسد؟

سه علت شایع: عبور از سقف ده جستجوی DNS، وجود دو رکورد TXT جداگانه که هر دو با v=spf1 شروع می‌شوند، و قرار گرفتن all قبل از مکانیزم‌های دیگر. مورد دوم را با dig +short TXT example.com ببینید؛ اگر دو خط برگشت، باید در یک رکورد ادغام شوند.

آیا ptr در SPF هنوز کار می‌کند؟

کار می‌کند ولی RFC 7208 استفاده از آن را منع کرده و بعضی گیرنده‌ها نادیده‌اش می‌گیرند. علاوه بر این، هر IP یک جستجو مصرف می‌کند و سریع شما را به سقف ده می‌رساند. جایش از ip4 یا include استفاده کنید.

قبل از هر تغییر دیگری، همین الان یک بار dig +short TXT روی دامنه‌تان بزنید و تعداد ترم‌های جستجومصرف را بشمارید. اگر به ده نزدیک است، مشکل بعدی‌تان SPF نخواهد بود؛ مشکل همین حالا شروع شده.

آیا این مطلب برایتان مفید بود؟