Uniвсячина

понемножку о Linux и программировании

Отсылка почты в Rails через Sendmail

В Rails, ActionMailer предлагает нам два метода для отправки электронной почты: smtp и sendmail. Настройка метода отправки производится в config.action_mailer.delivery_method. Как следует из названий методов, отправка письма в MTA идёт либо через протокол SMTP, либо через вызов команды sendmail на сервере.

Если у вас включена отправка через sendmail и вы работает с Rails 3.x, есть тонкий момент. actionmailer версии >= 3.0 работает через гем mail, а гем mail отсылает письмо через sendmail, по умолчанию формируя такую команду:

sendmail -i -t [email protected] [email protected] ...

Ключ -i означает, что текст письма будет читаться из потока stdin, пока не дойдет до символа конца файла (EOF). Ключ -t говорит, что адреса на которые будет отправляться письмо нужно взять из текста письма. Вроде бы всё в порядке и всё должно работать как надо. Однако, давайте посмотрим, что пишут про ключ -t в таком MTA, как Exim:

When Exim is receiving a locally-generated, non-SMTP message on its standard input, the -t option causes the recipients of the message to be obtained from the To:, Cc:, and Bcc: header lines in the message instead of from the command arguments. The addresses are extracted before any rewriting takes place and the Bcc: header line, if present, is then removed.

If the command has any arguments, they specify addresses to which the message is not to be delivered. That is, the argument addresses are removed from the recipients list obtained from the headers. This is compatible with Smail 3 and in accordance with the documented behaviour of several versions of Sendmail, as described in man pages on a number of operating systems (e.g. Solaris 8, IRIX 6.5, HP-UX 11). However, some versions of Sendmail add argument addresses to those obtained from the headers, and the O’Reilly Sendmail book documents it that way. Exim can be made to add argument addresses instead of subtracting them by setting the option extract_addresses_remove_arguments false.

Пишут тут, что любые аргументы команды трактуются, как адреса, которые будут удалены из списка адресов взятых в самом письме. А так как гем mail передает команде sendmail те же самые адреса, что и в самом письме, мы получаем пустой список адресов. И закономерно получаем отлуп, нижеприведенного вида:

Subject: Mail failure - no recipient addresses

A message that you sent using the -t command line option contained no
addresses that were not also on the command line, and were therefore
suppressed. This left no recipient addresses, and so no delivery could
be attempted.

Самое просто решение в этой ситуации — убрать ключ -t из команды sendmail. Пишем в config/environments/production.rb:

....
  config.action_mailer.sendmail_settings = { :arguments => "-i" }
....

Делаем для себя вывод: либо используем ключ -t, либо передаем список адресов, как аргументы команде sendmail, но ни в коем случае не делаем это одновременно.

Comments