Проблема: не доходят письма, которые должны были быть отправлены с вашего сервера. Почтовый сервер Postfix попал под сомнение. Но вы уверены что проблем с почтовым сервером нет.

Как исключить сомнения и доказать, что проблема не в почтовом сервере, а в той программе, которая должна была отправлять письма? То есть, показать, что потерявшиеся письма вовсе не поступали в обработку и на доставку к Postfix.

Что есть?

В логах Postfix записывается факт обработки какого-то письма, отправитель, получатель, время обработки. Например, по каждому письму в логах можно найти такие записи:

postfix/pickup[1098]: DDAD1E0021: uid=1001 from=<webmaster@example.com>
postfix/cleanup[4212]: DDAD1E0021: message-id=<20121234561000.DDAD1E0021@mx.example.com>
opendkim[5327]: DDAD1E0021: DKIM-Signature field added (s=mx, d=example.com)
postfix/qmgr[2410]: DDAD1E0021: from=<webmaster@example.com>, size=1024, nrcpt=1 (queue active)
postfix/smtp[2576]: DDAD1E0021: to=<me@test.ru>, relay=mx.test.ru[192.168.1.192]:25, delay=7.3, delays=0.04/0.05/2.2/5, dsn=2.0.0, status=sent (250 OK id=123456)
postfix/qmgr[2410]: DDAD1E0021: removed

В какой-то ситуации такие строки могут служить веским доказательством обработки какого-то письма. В другой ситуации не всё однозначно: может быть это было какое-то другое письмо тому же получателю?

Все сомнения можно было бы устранить, если бы в логе были видны не только какие-то базовые данные о письмах, но и дополнительная информация. Например, это может быть тема письма. Если по теме нельзя сказать, о чём письмо, или если тема идёт в закодированном виде, то удобней было бы видеть в логе какие-то идентифицирующие письмо заголовки.

Что можно сделать?

Если отправитель писем будет указывать в заголовках письма технические идентификаторы для сообщения (вид письма, объекты в БД, к которым относится то или иное письмо, какие-то другие идентификаторы), то можно будет записывать их в почтовый лог в общем порядке.

Это задачу нам поможет выполнить директива header_checks.

  1. Создадим файл с правилами проверки заголовков. Пусть это будет /etc/postfix/header_checks с таким содержимым:

     /^X-Message-(.*)$/ INFO $1
    
  2. Проверим, что мы не ошиблись с форматом файла:

    postmap -q "X-Message-Testing: 12345" pcre:/etc/postfix/header_checks
    

    Должно вывести:

    INFO Testing: 12345
    
  3. Включим использование этого файла в Postfix:

    postconf -e header_checks=pcre:/etc/postfix/header_checks
    postfix reload
    

Итого

Теперь для всех писем, что содержат заголовок вида X-Message-..., в лог будет писаться последняя часть заголовка и, собственно, содержимое заголовка.

Проверим, отправив письмо самому себе:

echo "Example" | bsd-mailx me@test.ru -s "Test" -a "X-Message-Testing: 98765"

Поиском по идентификатору 98765 легко находим письмо:

$ grep 98765 /var/log/mail.log
postfix/cleanup[2882]: 110FDE0111: info: header X-Message-Testing: 98765 from local; from=<webmaster@example.com>: Testing: 98765

Затем, по ID из очереди, находим все оставшиеся строки, относящиеся к письму:

$ grep 110FDE0111 /var/log/mail.log
postfix/pickup[2827]: 110FDE0111: uid=1001 from=<example.com>
postfix/cleanup[2882]: 110FDE0111: info: header X-Message-Testing: 98765 from local; from=<webmaster@example.com>: Testing: 98765
postfix/cleanup[2882]: 110FDE0111: message-id=<20121234561000.110FDE0111@mx.example.com>
opendkim[5327]: 110FDE0111: DKIM-Signature field added (s=mx, d=example.com)
postfix/qmgr[2273]: 110FDE0111: from=<webmaster@example.com>, size=474, nrcpt=1 (queue active)
postfix/smtp[2576]: 110FDE0111: to=<me@test.ru>, relay=mx.test.ru[192.168.1.192]:25, delay=2, delays=0.01/0/0.85/1.1, dsn=2.0.0, status=sent (250 2.0.0 OK id=123456)
postfix/qmgr[2823]: 110FDE0111: removed

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

/^Subject:/    INFO
/^X-Message-/  INFO

В таком варианте будет записываться только сам заголовок, без второй части:

info: header X-Message-Testing: 12345 from local; from=<webmaster@example.com>
info: header Subject: Test from local; from=<webmaster@example.com>

Эта же директива header_checks приходит на помощь если нужно скрыть IP адреса авторизованных пользователей — отправителей писем.