Делегирование обслуживания почтового домена: часть 2. Отправка почты через localhost (настройка Exim4 в Debian)

Настройка и PHP mail() на примере Linux

Чтобы решить проблему отказа серверов Gmail от обслуживания  при отправке большого числа писем на несуществующие адреса, используем для отправки почты из скриптов сайта локальный почтовый -сервер (MTA). Локальный сервер будет выступать в качестве mail relay. В дополнение мы откажемся от подключения из скрипта к удаленному серверу, что может быть медленно. Локальные подключения всегда должны быть быстрее и стабильнее.

Локальный сервер мы будем использовать только для отправки писем. Причем, не важно, как будет происходить отправка: непосредственно через SMTP, или с помощью MUA. Получение почты по-прежнему будет происходить с серверов Gmail.

В дистрибутиве Debian 5 по умолчанию устанавливается MTA Exim4. Он отлично подойдет для наших задач. Причем его настройка производится с помощью мастера и невероятно проста. Настроить сервер требуется на прием соединений исключительно с локального соединения. При этом не нужно поручать ему обслуживание доменов, кроме дефолтного локального (localhost).

Итак, если Exim у вас не установлен, то установим его:

# aptitude install exim4

Далее запускаем его конфигурацию:

# dpkg-reconfigure exim4-config

1. На первом шаге необходимо выбрать конфигурацию сервера. В Exim есть несколько стандартных конфигураций, предназначенных для разных случаев. Подробнее о них в мануале. Нам нужна конфигурация “ site; mail is sent and received directly using SMTP”.

2. Далее укажите имя сервера. Оно будет передаваться в SMTP-протоколе в команде HELLO, т.е. будет видно получателям вашей почты. Лучше всего, чтобы это имя совпадало с доменом, с которого шлется почта. Например, valera.ws.

Если у вас на сервере несколько сайтов с разными доменами (см. ниже), то лучше это имя сделать нейтральным, чтобы «не палиться». Например, можно выбрать local-mail-agent.

3. Далее требуется указать, какие интерфейсы должен слушать Exim. В нашем случае удаленные подключения мало того, что не нужны, так еще и опасны: кто угодно сможет рассылать почту через ваш сервер. Указываем только 127.0.0.1.

4. Далее спрашивается, какие домены должен обслуживать сервер. Т.е. для каких доменов не нужно пересылать письма на удаленные SMTP-сервера, пользователь заберет их с этого сервера. Нам не нужно обслуживание наших доменов. Можно указать только localhost, т.к. его больше обслужить некому.

Не указывайте здесь адрес вашего сервера (подставляется по умолчанию), т.к. его обслуживание делегировано Gmail. Если его указать, то письма, отправленные на ящики вашего домена, в Gmail не попадут и останутся на сервере. Это не нужно.

5. Далее можно указать, для каких доменов сервер должен служить релеем (список через точку с запятой). Здесь не указываем ничего, так как на следующем шаге мы разрешим себе релей для всех доменов. Можете указать список ваших доменов.

6. Здесь укажем 127.0.0.1, чтобы раз-решить релей для всех запросов с локального .

При этой конфигурации есть один негативный момент. Если ваш сайт поломают, то злоумышленники смогут слать почту с любых доменов через ваш сервер. Если на сервере 1—2 сайта, то лучше на этом шаге оставить поле пустым, а на предыдущем шаге внести список этих доменов (для возврата на шаг назад нажмите кнопку “Cancel”). При появлении новых доменов не забывайте их заносить в конфиг. Если вы считаете свои надежными, то проще всего указывать здесь 127.0.0.1.

7. Дале уточняется, является ли для нас проблемой постоянные DNS-запросы при отправке каждого письма. В 99,9% это не проблема, так что выбираем ответ на вопрос “Keep number of DNS-queries minimal (Dial-on-Demand)?” “No”.

8. Где хранить локальную почту (помните, мы указали серверу обслуживать домен localhost?) нам по сути не важно, так как этим как правило никто не пользуется. Можно выбрать вариант по умолчанию: складывать все в /var/mail.

9. Предпоследний шаг — выбор конфигурации. Хранить все в одном файле, или раскидать по множеству мелких файлов. В большой файл проще вносить большие изменения, а с мелкими проще работать в случае мелких правок. Выберите вариант на свой вкус. Я выбрал “unsplit configuration” (ответ “No”).

10. На последнем шаге укажем на какой аккаунт реального пользователя системы пересылать сообщения, отправленные на служебные аккаунты postmaster, root и т.д. Здесь имеет смысл указать ваше имя пользователя в системе.

Переконфигурировать Exim в любой момент можно тем же способом. Мастер подставит в значения по умолчанию текущие значения вашей конфигурации.

Правильная настройка SPF

Если кратко, то SPF — это способ борьбы со спамом.

Мы собираемся отправлять почту с сервера, PTR IP которого не равен одной из MX-записей сервера, а так же в большинстве случаев PTR IP не равен самому нашему домену (не всегда хостеры соглашаются менять PTR). В этом случае вероятность попадания писем в спам повышается. Но есть хороший способ ее понизить: указать правильно запись SPF нашего домена.

SPF-запись — это обыкновенная запись доменной зоны, имеющая тип TXT. Узнать текущее ее значение для домена можно с помощью команды host в Linux:

$ host -t TXT valera.ws
valera.ws TXT record currently not present

В данном примере SPF-запись не задана. Зададим ее. С моего домена почта может отправляться с серверов Gmail и с моего сервера. Для начала узнаем, какой PTR моего сайта (valera.ws):

$ nslookup valera.ws
Server:      194.224.52.4
Address:     194.224.52.4#53

Non-authoritative answer:
Name:     valera.ws
Address:  93.174.6.118

IP-адрес моего сервера 93.174.6.118. Узнаем PTR:

$ nslookup 93.174.6.118
Server:      194.224.52.4
Address:     194.224.52.4#53

Non-authoritative answer:
118.6.174.93.in-addr.arpa name = server.valera.ws.

Видно, что PTR IP, к которому привязан мой домен (IP моего сервера) — server.valera.ws.

v=spf1 a mx ptr include:_spf.google.com ~all

По порядку:

  • v=spf1 — версия SPF (первая);
  • a — разрешение отправлять почту с IP, указанного в A-записи домена (собственно с сервера, на который ваш домен ссылается);
  • mx — разрешение отправлять почту с IP, указанных в MX-записях домена (в нашем случае сервера Gmail);
  • ptr — разрешение отправлять почту с IP, PTR-запись которых содержит ваш домен (т.е. сам домен и поддомены);
  • include:_spf.google.com — подключение разрешений для серверов отправки почту Gmail (совсем не обязательно почта будет слаться с серверов, указанных в MX-записи);
  • ~all — нейтральная реакция на всю остальную почту; здесь можно указать -all, что будет значить, что почта, не попадающая под эти , — спам.

Если вы хотите отправлять почту с сервера, не попадающего под все эти правила, его можно указать по IP или домену PTR, например:

v=spf1 a mx ptr ptr:example.com include:_spf.google.com ~all

Запись указывается для вашего домена соответствующим образом, который определяет владелец DNS-сервера. Обычно сервером заведует хостер и предоставляет возможность вносить изменения в DNS-зоны через панель хостинга. Либо сам по запросу в саппорт меняет запись. В зональном файле должна появиться запись вида:

valera.ws.      TXT      v=spf1 a mx ptr include:_spf.google.com ~all

После обновления зоны host выдаст следующее:

$ host -t TXT valera.ws
valera.ws      TXT      «v=spf1 a mx ptr include:_spf.google.com ~all»

PHP mail()

После всей этой настройки функция mail() в PHP начнет слать почту через ваш локальный сервер на законных основаниях для антиспам-ботов. Но косяк будет в том, что в поле отправителя будет фигурировать адрес системного пользователя www-data@localdomain. Нас это не устраивает. Чтобы почта правильно слалась из mail(), необходимо использовать ее дополнительный параметр.

bool mail ( string $to , string $subject , string $message [, string $additional_headers [, string $additional_parameters ]] )

Именно $additional_parameters нас и интерисует. В него надо передавать реального отправителя:

mail($to, $subject, $message, $additional_headers, $additional_parameters.» -frealsender@valera.ws»);

Указывается отправитель слитно с параметром -f.

Теперь отправленные через mail() письма будут абсолютно адекватны (при условии, что вы указываете все нужные SMTP-заголовки, вроде “FROM:”, “TO:” и т.д.).

А если несколько сайтов с разными IP (настройка Exim для отправки писем с разных IP)?

Мы хотим использовать локальный SMTP-сервер для отправки почты со всех сайтов на сервере. Никаких проблем нет, если настроен Exim правильно (см. выше). Но проблема появляется, если разные сайты работают на разных IP. Мы не хотим в почте «палить» то, что все наши сайты живут на одном сервере. Но Exim по умолчанию шлет всю почту с основного (первого) IP сетевого интерфейса, а этот IP всем получателям в SMTP-заголовках “Received:” письма. Кроме того, там указывается и имя сервера, которые мы в случае с разными сайтами на сервере выбрали нейтральными.

Чтобы не «палить» IP сервера, нужно отсылать письмо на удаленный сервер с IP, равного A-записи домена сайта. Делается это несложно путем изменения конфига Exim. Внесем изменения в настройки транспорта SMTP Exim. Если вы выбрали монолитный конфиг, то нужно отредактировать файл:

# nano /etc/exim4/exim4.conf.template

Находим в файле строку “remote_smtp:” (поиск в nano — F6). Добавляем в конец этого блока:

interface = «${lookup{$sender_address_domain}lsearch{/usr/share/exim4/domain2ip}{$value}}»
helo_data = «$sender_address_domain»

Это значит, что при отправке письма нужно определить домен отправителя почты (для sender@valera.ws это valera.ws) и отправить почту с IP, к которому этот домен привязан. Само собой разумеется, что домен должен быть привязан к серверу, где установлен Exim.

Так же нужно создать файл в любом месте файл привязки доменов к IP (у домена может быть несколько IP, так что просто lookup-ить его не прокатит). Я выбрал для файла место: /usr/share/exim4/domain2ip

# nano /usr/share/exim4/domain2ip

Туда вводим наши домены по шаблону:

valera.ws: 123.123.123.123
vasya.ws: 123.123.123.124

Не забудьте дописать домен в файл в случае появления нового сайта.
Кстати, строку helo_data = «$sender_address_domain» можно добавить в файл даже если у вас один IP на все сайты. Тогда в команде HELLO SMTP-протокола (а, следовательно, и в заголовках писем) будет фигурировать ваш домен.

Идея с указанием интерфейса взята отсюда: http://www.directadmin.com/forum/showthread.php?t=36468

Проверка

Остается проверить, чтобы все ваши настройки работали верно. Для этого просто отправим письмо с локального сервера через консоль.

$ mail -a «From:feedbee@valera.ws» -s Test feedbee@gmail.com — -ffeedbee@valera.ws
Test <Ctrl-D>
Cc:

Проверяем отосланное письмо в ящике получателя:

А вот текст SMTP-протокола:

Delivered-To: feedbee@gmail.com
Received: by 10.236.109.139 with SMTP id s11cs13826yhg;
Wed, 24 Nov 2010 02:18:14 -0800 (PST)
Received: by 10.227.145.134 with SMTP id d6mr9025492wbv.195.1290593893066;
Wed, 24 Nov 2010 02:18:13 -0800 (PST)
Return-Path: feedbee@valera.ws
Received: from valera.ws (server.valera.ws [93.174.6.118])
by mx.google.com with ESMTP id b7si11085685wer.164.2010.11.24.02.18.12;
Wed, 24 Nov 2010 02:18:12 -0800 (PST)
Received-SPF: pass (google.com: domain of feedbee@valera.ws designates 93.174.6.118 as permitted sender) client-ip=93.174.6.118;
Authentication-Results: mx.google.com; spf=pass (google.com: domain of feedbee@valera.ws designates 93.174.6.118 as permitted sender) smtp.mail=feedbee@valera.ws
Received: from root by server.valera.ws with local (Exim 4.69)
(envelope-from <feedbee@valera.ws>)
id 1PLCQW-0006KD-Pc
for feedbee@gmail.com; Wed, 24 Nov 2010 10:18:12 +0000
To: feedbee@gmail.com
Subject: Test
From:feedbee@valera.ws
Message-Id: E1PLCQW-0006KD-Pc@server.valera.ws
Date: Wed, 24 Nov 2010 10:18:12 +0000

Test

P.S. Чтобы отправленная почта не попадала в спам, отправляйте письма только от имени реально существующих на серверах Gmail адресов на ваших доменах. Туда же повалятся уведомления о недоставках.

Делегирование обслуживания почтового домена: часть 2. Отправка почты через localhost (настройка Exim4 в Debian): 2 комментария

  1. Добавлю про helo_data на нескольких IP. Если домен отправителя найден в списке domain2ip, то он попадет в helo_data. А вот если он там не найден, то в helo_data будет пустота. А это плохо. Чтобы избежать пустоты, нужно сделать проверку:

    helo_data = ${if >{${strlen:$sender_address_domain}}{0} \
    {$sender_address_domain} \
    {$primary_hostname}}

    Вместо $primary_hostname можно просто написать свой хост.

  2. Привет! Хорошая статься, но к сожалению мой недуг не помогла решить!
    Не подскажешь куда копать?

    Получаю такую запись в логе Exim-a:

    2012-10-28 03:12:12 1TSGU7-0005HS-OD ** zekefast@gmail.com R=dnslookup T=remote_smtp: SMTP error from remote mail server after end of data: host gmail-smtp-in.l.google.com [74.125.143.26]: 550-5.7.1 [109.87.135.214] The IP you’re using to send mail is not authorized to\n550-5.7.1 send email directly to our servers. Please use the SMTP relay at your\n550-5.7.1 service provider instead. Learn more at\n550 5.7.1 http://support.google.com/mail/bin/answer.py?answer=10336 sk9si4285420lab.41
    2012-10-28 03:12:12 1TSGU8-0005HV-HJ <= R=1TSGU7-0005HS-OD U=Debian-exim P=local S=1663
    2012-10-28 03:12:12 1TSGU7-0005HS-OD Completed

    Отправляю так:

    mail -a «From:zekefast@server.zekefast.org» -s Test zekefast@gmail.com-fzekefast@server.zekefast.org
    Test
    Cc:

    SPF и PTR имеются.

Добавить комментарий