Электронная почта: "From" и "mail from". Памятка веб-разработчикам.
Как следует из заголовка статьи, в основном, это касается разработчиков Web-сервисов, но проблема может встречаться и в других случаях, потому про различие "From" и "envelope from" следует знать всем, кто использует электронную почту. Если Ваше электронное сообщение куда-то не доставлено, а вы не знаете почему, то эта статья объяснит наиболее вероятную причину, почему Вы это не знаете.
В последние годы стали массово появляться web-сервисы с формами обратной связи. При этом, значительное количество web-разработчиков не задумывается о том, как именно работает электронная почта. В основном, внимание уделяется полям сообщения, и совсем не уделяется параметрам smtp-конверта (envelope), а именно, важному параметру "envelope from" (задаётся командой "mail from" в smtp-сессии). Почтовые сервера в своей работе ориентируются именно на smtp-конверт, а не на поля сообщения "From", "To" и "Cc". Классический почтовый клиент формирует "envelope from" из значения поля "From", скрывая различие от пользователя, а вот при написании своего кода это следует учитывать. Например, рассмотрим вариант с PHP. Функция PHP mail() не умеет формировать "envelope from", по-этому, при её использовании по-умолчанию, "envelope from" формируется почтовым агентом сервера из имени хоста и имени пользователя, из-под которого работает web-сервер. Как правило, это получается несуществующий E-Mail на несуществующем почтовом сервере.
Правила передачи электронной почты подразумевают, что сообщение не должно быть потеряно бесследно. Сообщение либо должно быть доставлено получателю, либо отправителю формируется так называемое bounce-сообщение с уведомлением о недоставке и причинах. Это сообщение формируется с использованием того, что содержится в "envelope from", а, отнюдь, не в "From" самого письма. Если "envelope from" содержит мусор, по которому невозможно доставить сообщение (сервер не отвечает), то это сообщение остаётся в спуле сервера, сформировавшего сообщение, на интервал времени (несколько суток), который предусмотрен в RFC 5321/1123 (раздел 4.5.4.1. Sending Strategy). Достаточно большое количество таких сообщений в спуле может привести к проблемам в работе почтового сервера. Несмотря на то, что предпочтительной настройкой почтовых серверов сейчас является принятие решения на этапе SMTP-сессии (когда формирование bounce перекладывается на сервер отправителя), существуют ситуации, когда сообщение приходится сначала принимать, а уже потом проверять возможность доставки. Почтовый сервер может быть защищён от этого проверкой smtp callback (кроме того, это ещё и один из вариантов защиты от спама). В этой ситуации сообщение с веб-формы не будет доставлено получателю, а отправитель ничего не узнает, так как и его собственный сервер не отошлёт уведомление. Вероятно, это сообщение может увидеть администратор web-сервера, но это только в том случае, если он проверяет почту локальных пользователей, чего, как правило, на площадках web-хостинга никто не делает. В случае PHP mail() следует использовать пятый (необязательный) параметр, который передаётся, как есть, в bin/sendmail, где следует задать envelope from способом, который поддерживает ПО сервера. Как правило, это "-f e-mail". При написании кода сайта на других языках следует учитывать написанное аналогичным образом.
Отдельную группу составляют те, кто пишет в "mail from" несуществующие E-Mail вида "noreply@..." ("...@undeliverable....", и т.п.), не понимая, что ПО почтового сервера не обладает интеллектом и не читает написанное. Оно, точно так же, будет формировать bounce в случае необходимости, а проверка smtp callback, если она используется, не пропустит такое сообщение на почтовый сервер получателя. Единственно верное решение в том случае, если не хочется разбирать возвращающиеся bounce, это использовать специальное значение, описанное в RFC 5321/2821/821 (команда имеет вид "mail from:<>"). Хотя это предназначено для формирования специальных сообщений (включая bounce), для цели отправки без получения сообщений о проблемах доставки данный вариант использовать предпочтительнее, нежели несуществующий E-Mail (в упомянутой сеции 4.5.5 RFC 5321 даже прямо написано: all other types of messages SHOULD be sent with a valid reverse-path). Для уже упомянутой функции PHP mail() пятый параметр, в таком случае, должен иметь вид '-f"<>"' . Данная конструкция ("mail from:<>"), кроме того, описана в RFC 1123, являющемся частью STD 3, и обязана поддерживаться всеми почтовыми серверами (хотя и тут бывают нарушения, но сервера, нарушающие даже не RFC, а STD можно не принимать во внимание).
Проблему усугубляет то, что недостатком квалифицированных кадров в этой области сейчас страдают даже очень крупные компании.
Попавшийся образец мнения (домены и название хостинг-провайдера изменены):
quicktask@example.com Данный адрес, отлично работает на почтовых клиентах, mail.ru yandex.ru, Gmail а также с моим доменом example.com если поставить адреса данных провайдеров, ВСЕ РАБОТАЕТ НА УРА, В ТАКИХ КРУПНЫХ КОМПАНИЯХ, КАК ЯНДЕКС ГУГЛ и вы сообщаете что у хостинг провайдера ABCD проблема.
Человек даже не понял, о чём речь, и что он сам (а вовсе не хостинг-провайдер ABCD) допустил ошибку в формировании сообщения с сайта, не позаботившись о правильном "envelope from" и напрасно понадеявшись на CMS. То, что где-то такие сообщения принимаются, никак не означает, что они будут приниматься везде. Следует изучать технологии, а не ориентироваться на уровне интуиции и "там работает", зачастую ошибочно.
Про некоторые популярные CMS (ищется поисковыми системами по словам "<название CMS> set envelope from"): Bitrix: http://dev.1c-bitrix.ru/community/webdev/user/224396/blog/11743/ WordPress: http://abdussamad.com/archives/567-Fixing-the-WordPress-Email-Return-Path-Header.html
|