اصطلاح · پروتکل ایمیل SMTP

پروتکل ایمیل SMTP چیست و چه تأثیری بر ایمیل اپلیکیشن دارد؟

SMTP یا Simple Mail Transfer Protocol، پروتکل استانداردی است که سیستم‌های ایمیل برای ارسال (submission)، relay و تحویل ایمیل خروجی به یکدیگر از آن استفاده می‌کنند. اپلیکیشن معمولاً یک پیام کامل را به یک سرویس ارسال احرازهویت‌شده می‌دهد؛ سپس سرورهای ایمیل با فرمان‌های SMTP و مسیریابی DNS آن را به سمت هر گیرنده جابه‌جا می‌کنند. پاسخ‌های SMTP نشان می‌دهند که یک hop مشخص گیرنده‌ای را پذیرفته یا رد کرده است، اما پذیرش با رسیدن به صندوق ورودی یکی نیست. اپلیکیشن‌ها همچنان به صف‌های ماندگار، تلاش‌های مجدد ایمن، شناسه‌های پیام، احراز هویت و پردازش برگشت ایمیل نیاز دارند.

SMTP ایمیل را بین سیستم‌های مسئول منتقل می‌کند

SMTP یک پروتکل انتقال از نوع store-and-forward است. کلاینت با سرور یک نشست باز می‌کند، خود را معرفی می‌کند، فرستنده envelope را ارائه می‌دهد، یک یا چند گیرنده envelope پیشنهاد می‌کند و پس از موافقت سرور با دریافت، محتوای پیام را منتقل می‌کند. سرور ممکن است برخی گیرندگان را بپذیرد و برخی را رد کند؛ بنابراین وضعیت به یک گیرنده و یک تراکنش تعلق دارد، نه فقط به کل پیام. وقتی سروری مسئولیت را پذیرفت، ممکن است پیام را به‌صورت محلی تحویل دهد یا آن را به سمت سیستم دیگری که از طریق رکوردهای Mail Exchanger در DNS انتخاب شده relay کند. این طراحی hop-by-hop باعث می‌شود که اپلیکیشن وضعیت ایمیل را صرفاً به یک مقدار بولی sent تقلیل ندهد. اپلیکیشن، سرویس ارسال، relay، سرور گیرنده و سیستم فیلترینگ صندوق ایمیل هر کدام بخش متفاوتی از نتیجه را می‌دانند. SMTP پیام را بین سیستم‌ها جابه‌جا می‌کند، در حالی که سوابق سطح محصول و رویدادهای ارائه‌دهنده این جابه‌جایی را برای کاربران و اپراتورها قابل‌فهم می‌کنند.

ارسال (submission) و relay دو نقش متفاوت در پروتکل هستند

RFC 6409 ارسال پیام (message submission) را از relay پیام جدا می‌کند. submission نخستین تحویل از یک کاربر یا اپلیکیشن مجاز به یک Message Submission Agent است که معمولاً از پورت 587 استفاده می‌کند. relay انتقال بین Message Transfer Agentها است و طبق عرف از پورت 25 استفاده می‌کند. سرویس‌های submission می‌توانند احراز هویت را الزامی کنند، فیلدهای پیام را اعتبارسنجی یا تکمیل کنند و سیاست فرستنده را اعمال کنند، چون می‌دانند چه کسی ایمیل جدید را وارد سیستم می‌کند. سرورهای relay عمومی باید با دامنه‌های دیگر سازگار باشند و از قوانین اعتماد متفاوتی پیروی کنند. بنابراین کد اپلیکیشن باید به endpoint مستند submission ارائه‌دهنده وصل شود یا از HTTP API آن استفاده کند، نه اینکه اتصال‌های دلبخواهی روی پورت 25 به سرورهای مقصد باز کند. این تقسیم‌بندی موضوع اعتبارنامه‌ها را هم روشن می‌کند: نام کاربری یا توکن SMTP اجازه ارسال به یک سرویس مشخص را می‌دهد؛ اختیاری بر دامنه مقصد نمی‌دهد. اعتبارنامه‌های submission را سمت سرور نگه دارید، در صورت پشتیبانی ارائه‌دهنده آن‌ها را به بار کاری ارسال محدود کنید و بدون جاسازی در محتوای پیام یا نرم‌افزار کلاینت، آن‌ها را بچرخانید.

envelope در SMTP با هدرهای قابل‌مشاهده پیام متفاوت است

یک تراکنش SMTP یک envelope با `MAIL FROM` و یک یا چند فرمان `RCPT TO` حمل می‌کند. محتوای منتقل‌شده جداگانه از Internet Message Format تعریف‌شده در RFC 5322 پیروی می‌کند که فیلدهایی مانند From، To، Date، Subject و Message-ID به‌علاوه یک بدنه دارد. استانداردهای MIME این محتوا را برای HTML، بخش‌های جایگزین، پیوست‌ها و داده‌های غیر ASCII گسترش می‌دهند. فرستنده envelope نشانی‌ای است که برای خطاهای انتقال استفاده می‌شود و ممکن است با نویسنده From قابل‌مشاهده متفاوت باشد. گیرندگان envelope نیز ممکن است با فیلدهای To و Cc قابل‌مشاهده متفاوت باشند، مانند Bcc. این ساختارها را با چسباندن رشته‌های غیرقابل‌اعتماد نسازید. از یک کتابخانه پیام نگهداری‌شده استفاده کنید، نشانی‌ها را اعتبارسنجی کنید، جلوی تزریق newline به فیلدهای هدر را بگیرید و یک Message-ID پایدار نگه دارید. هنگام عیب‌یابی، هر دو لایه را بررسی کنید: فیلد From قابل‌مشاهده درست نمی‌تواند یک هویت envelope غیرمجاز را اصلاح کند و یک envelope معتبر هم باعث نمایش درست MIME نادرست نمی‌شود.

تراکنش را به‌صورت یک ماشین حالت بخوانید

یک نشست پایه Extended SMTP با خوشامدگویی سرور شروع می‌شود و سپس `EHLO` می‌آید تا سرور افزونه‌هایش را اعلام کند. کلاینت ممکن است برای submission، TLS و احراز هویت را مذاکره کند. سپس یک تراکنش ایمیل از `MAIL FROM`، یک `RCPT TO` برای هر مقصد، `DATA`، پیام کامل که طبق قاب‌بندی SMTP پایان می‌یابد و `QUIT` استفاده می‌کند. این مثال را دلیلی برای پیاده‌سازی دستی پروتکل در سطح wire ندانید؛ کتابخانه‌های بالغ SMTP پایان خطوط، dot transparency، مذاکره قابلیت‌ها، احراز هویت و وضعیت TLS را ایمن‌تر مدیریت می‌کنند. کتابخانه را در سطح دسته فرمان و کد پاسخ ابزارگذاری کنید، بدون اینکه اعتبارنامه‌ها یا بدنه کامل پیام‌ها را لاگ کنید. ثبت کنید کدام گیرنده در کدام مرحله fail شده و آیا سرور پس از داده پیام مسئولیت را پذیرفته بود یا نه. این مرز تعیین می‌کند که آیا تلاش مجدد مناسب است، آیا احتمال تکرار وجود دارد و آیا خطا به‌جای پاسخ فوری، در یک اعلان وضعیت تحویل بعدی گزارش خواهد شد.

پیش از تصمیم به تلاش مجدد، کدهای پاسخ را دسته‌بندی کنید

کلاس‌های پاسخ SMTP اقدام لازم را نشان می‌دهند. پاسخ 2xx نشان‌دهنده تکمیل موفق آن فرمان است. پاسخ 4xx یک تکمیل منفی گذراست، پس فرستنده‌ای که صف دارد می‌تواند پس از تأخیر دوباره تلاش کند. پاسخ 5xx یک تکمیل منفی دائمی برای فرمان مورد تلاش است و معمولاً به‌جای تلاش‌های مکرر، به اصلاح، قرار دادن در فهرست توقف ارسال یا بررسی انسانی نیاز دارد. کدهای وضعیت پیشرفته یک تشخیص ساختاریافته `X.Y.Z` برای شرایط نشانی، صندوق ایمیل، سیستم، مسیریابی، پروتکل، محتوا یا امنیت و سیاست اضافه می‌کنند. هم کد عددی و هم متن سرور را نگه دارید، چون هر دو می‌توانند ارزش عیب‌یابی داشته باشند، اما پاسخ‌های خام حاوی داده گیرنده را به‌طور گسترده در دسترس قرار ندهید. برای خطاهای گذرا از exponential backoff همراه با jitter و حداکثر عمر صف استفاده کنید. هرگز آن‌قدر تهاجمی دوباره تلاش نکنید که یک مشکل موقت مقصد به ترافیک مزاحم تبدیل شود. برای خطای دائمی نشانی، ارسال خودکار به آن مقصد را متوقف کنید و وضعیت فهرست توقف ارسال را به‌روز کنید. برای خطای سیاست یا احراز هویت، پیش از تلاش دیگر، هویت، DNS، اعتبارنامه‌ها یا محتوا را اصلاح کنید.

از ارسال رمزنگاری‌شده و احرازهویت‌شده استفاده کنید

SMTP به‌عنوان یک پروتکل انتقال بین شبکه‌هایی با فرض‌های اعتماد متفاوت شکل گرفت؛ بنابراین ارسال امن به افزونه‌ها و سیاست استقرار وابسته است. STARTTLS یک اتصال SMTP را به TLS ارتقا می‌دهد و پس از آن کلاینت باید قابلیت‌هایی را که پیش از handshake آموخته کنار بگذارد و دوباره `EHLO` بفرستد. RFC 8314 راهنمای submission را به‌روز می‌کند؛ دسترسی و ارسال به‌صورت متن ساده (cleartext) را منسوخ می‌داند و TLS ضمنی را برای submission توصیف می‌کند. SMTP AUTH که در RFC 4954 استاندارد شده، به سرور submission اجازه می‌دهد کلاینت را از طریق سازوکارهای اعلام‌شده احراز هویت کند. به‌جای حدس زدن یک ترکیب، از hostname، پورت، حالت TLS و دستورالعمل‌های احراز هویت فعلی ارائه‌دهنده استفاده کنید. گواهی سرور را اعتبارسنجی کنید و وقتی بار کاری به ارسال محافظت‌شده نیاز دارد، بی‌صدا به متن ساده برنگردید. رمزهای عبور یا توکن‌ها را در یک secret manager نگه دارید، برای هر محیط اعتبارنامه جداگانه داشته باشید و سازوکارهای احراز هویت منسوخ را غیرفعال کنید. TLS از یک hop اتصال محافظت می‌کند؛ نویسنده پیام را برای همه گیرندگان پایین‌دستی احراز هویت نمی‌کند و جایگزین هم‌راستایی هویت در SPF، DKIM و DMARC نمی‌شود.

خطای ایمیل اپلیکیشن را hop به hop عیب‌یابی کنید

با سابقه ماندگار ایمیل خروجی در اپلیکیشن شروع کنید: آیا رویداد محصول مجاز بود و آیا فقط یک job در صف آن را برداشت؟ سپس مرحله submission را بررسی کنید: resolve شدن DNS، اتصال TCP، مذاکره TLS، اعتبارسنجی گواهی، احراز هویت، مجوز فرستنده envelope، پاسخ‌های مربوط به هر گیرنده و پاسخ نهایی DATA. اگر سرویس submission پیام را پذیرفته است، اجرای مجدد کورکورانه درخواست را متوقف کنید و شناسه پیام و جریان رویدادهای آن را دنبال کنید. وضعیت پردازش‌شده توسط ارائه‌دهنده را از پذیرش توسط سرور گیرنده جدا کنید. یک برگشت بعدی ممکن است پس از پذیرش اولیه همچنان خطای دائمی گزارش کند. اگر سرور گیرنده پیام را پذیرفته است، به‌جای اینکه آن را خطای انتقال SMTP بنامید، نتایج احراز هویت، اعتبار، سیاست گیرنده، محتوا و دسته‌بندی صندوق ایمیل را بررسی کنید. هر دو هویت envelope و هدر را بررسی کنید و زمان‌ها، کدهای پاسخ، تعداد تلاش‌های صف و شناسه‌های ارائه‌دهنده را نگه دارید. برای آزمون‌ها از گیرندگان کنترل‌شده استفاده کنید. هرگز اعتبارنامه‌های SMTP محیط عملیاتی یا پیام‌های کامل مشتریان را در تیکت‌ها، promptها، تاریخچه ترمینال یا ابزارهای عیب‌یابی عمومی paste نکنید.

پذیرش، تحویل و رسیدن به صندوق ورودی را از هم جدا کنید

دقت در پروتکل در رابط‌های محصول اهمیت دارد. پذیرش در اپلیکیشن یعنی سیستم محلی یک درخواست را ثبت کرده است. پذیرش در submission یعنی نخستین سرویس ایمیل مسئولیت پردازش آن را پذیرفته است. تحویل به سرور گیرنده یعنی سرور SMTP مقصد برای این تحویل پاسخ موفق برگردانده است. رسیدن به صندوق ورودی تصمیمی بعدی در زمینه سیاست و دسته‌بندی درون محیط گیرنده است. پیام ممکن است از یک وضعیت عبور کند و در وضعیت بعدی fail شود یا به شکل دیگری دسته‌بندی شود. SMTP شاهد مستقیمی درباره تراکنش فعلی می‌دهد و ممکن است بعداً اعلان‌های وضعیت تحویل تولید کند، اما پوشه نهایی گیرنده را نشان نمی‌دهد. این وضعیت‌ها را مستقل از هم ذخیره کنید، نه اینکه هر پاسخ 250 را تحویل به صندوق ورودی بنامید. رویداد ارائه‌دهنده‌ای که پاسخ موفق SMTP مقصد را در بر دارد، می‌تواند پشتوانه وضعیت «تحویل‌شده به سرور» باشد. برگشت پشتوانه رسیدگی به خطا یا توقف ارسال است. هیچ‌کدام پشتوانه وعده‌ای درباره دیده شدن، خوانده شدن یا تعامل نیستند. این مدل وضعیت را صادقانه نگه می‌دارد و پس از انتقال مسئولیت، از تلاش‌های مجدد ناایمن جلوگیری می‌کند.

از API مستندشده SendHQ استفاده کنید

یک اپلیکیشن می‌تواند از طریق library یک ارائه‌دهنده با SMTP صحبت کند یا یک API ایمیل HTTP را فراخوانی کند که ارائه‌دهنده‌اش انتقال ایمیل اینترنتی را زیر آن رابط مدیریت می‌کند. SendHQ یک API ایمیل در سطح فضای کاری با بررسی‌های دامنه تأییدشده، منابع پیام خروجی و ورودی، رویدادها، موارد توقف ارسال، صندوق‌های ورودی و مرزهای منابع فضای کاری فراهم می‌کند. API ‏HTTP آن می‌تواند در کنار ارسال مستقیم SMTP، درخواست‌های ساخت‌یافته، شناسه‌ها و رویدادها فراهم کند. این کار رفتار سرور مقصد را تغییر نمی‌دهد یا پذیرش SMTP، رسیدن به صندوق ورودی یا تعامل گیرنده را برقرار نمی‌کند.

پرسش‌های متداول

SMTP مخفف چیست؟

SMTP مخفف Simple Mail Transfer Protocol است. این پروتکل تعریف می‌کند که کلاینت‌ها و سرورهای ایمیل چگونه پیام‌های خروجی را از طریق فرمان‌ها، پاسخ‌ها، envelopeها، داده پیام و افزونه‌هایی برای قابلیت‌هایی مانند احراز هویت و TLS ارسال و منتقل می‌کنند.

آیا از SMTP برای خواندن ایمیل از صندوق ورودی استفاده می‌شود؟

خیر. SMTP اساساً برای ارسال و انتقال ایمیل خروجی است. دسترسی به صندوق ورودی از رابط‌های دیگری مانند IMAP، POP، API اختصاصی صندوق ایمیل یک ارائه‌دهنده یا API ایمیل اپلیکیشنی که پیام‌های ورودی ذخیره‌شده را ارائه می‌دهد انجام می‌شود.

تفاوت پورت‌های 25، 587 و 465 چیست؟

پورت 25 طبق عرف برای relay بین سرورها استفاده می‌شود. پورت 587 سرویس استاندارد ارسال پیام (submission) است و معمولاً TLS را مذاکره می‌کند. پورت 465 برای ارسال از طریق TLS ضمنی (implicit TLS) ثبت شده است. به‌جای تغییر آزمایشی پورت‌ها، از endpoint و حالت امنیتی مستند ارائه‌دهنده پیروی کنید.

آیا موفقیت SMTP ثابت می‌کند ایمیل به صندوق ورودی رسیده است؟

خیر. پاسخ موفق فقط ثابت می‌کند که سرور SMTP پاسخ‌دهنده، فرمان مربوط یا مسئولیت پیام را پذیرفته است. سیستم گیرنده همچنان می‌تواند بعداً سیاست اعمال کند، خطای تأخیری تولید کند یا ایمیل پذیرفته‌شده را خارج از صندوق ورودی اصلی دسته‌بندی کند.

آیا اپلیکیشن باید هر پاسخ 4xx در SMTP را دوباره امتحان کند؟

کد 4xx نتیجه منفی گذرا را نشان می‌دهد، اما تلاش‌های مجدد باید از یک صف ماندگار، exponential backoff همراه با jitter، عمر محدود و سقف تلاش با در نظر گرفتن گیرنده استفاده کنند. به‌جای تلاش مجدد بی‌پایان، خطاهای موقت تکراری را بررسی کنید.

آیا یک API ایمیل مبتنی بر HTTP جایگزین SMTP است؟

می‌تواند در کد اپلیکیشن جایگزین SMTP شود، اما ارائه‌دهنده معمولاً همچنان برای ارتباط با سیستم‌های ایمیل گیرنده از SMTP استفاده می‌کند. API بالای لایه انتقال، احراز هویت ساختاریافته، payloadها، محدودسازی منابع، شناسه‌ها و مدیریت رویدادها را اضافه می‌کند.

منابع