PHP
August 2011 18

Обработка входящей почты на PHP

Хочу поделиться рецептом, как совместить php-скрипт и почтовый сервер Postfix для автоматической обработки входящей почты.

С помощью такой связки мы собираем статистику по количеству возвратов bounce-писем:Undelivered Mail Returned to Sender.

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

Как это сделать

  1. Для начала убедитесь, что у вас есть работающий почтовый сервер.

    Можно сделать отдельный почтовик в поддомене, достаточно внести 2 записи в DNS:
    rob.mydomain.ru. A ip-вашего-сервера
    rob.mydomain.ru. MX rob.mydomain.ru.
    

  2. Отредактируйте файл с алиасами /etc/aliases:
    добавьте туда строку:
    robot: "|php -q /путь/к/скрипту.php"
    robot — это название почтового ящика;
    /путь/к/скрипту.php — скрипт обрабатывающий входящие.

    после редактирования выполните команду newaliases

  3. в настройках postfix main.cf рекомендую добавить параметр:
    recipient_delimiter = +

    тогда в адресе можно будет кодировать дополнительную информацию:robot+someId@rob.mydomain.ru

    Все письма на такие адреса будет также обрабатывать наш скрипт.
    someId может быть идентификатором пользователя или любыми другими данными.
  4. создайте скрипт-обработчик писем:
    <?php
    
    /**
     * Скрипт для автоматической обработки входящих писем
     *
     * Все данные smtp-конверта письма RECIPIENT, SENDER и другие postfix 
     * передает через окружение $_ENV; полный перечень переменных:
     * http://www.postfix.org/local.8.html секция EXTERNAL COMMAND DELIVERY 
     */
    
    //текст сообщения считываем из STDIN
    $msg = file_get_contents("php://stdin");
    
    //отправитель письма
    $sender = getenv('SENDER');
    
    //получатель письма
    $recipient = getenv('RECIPIENT');
    
    //парсинг сообщения
    list($header, $body) = explode("\n\n", $msg, 2);
    
    //выделим строки с Subject: и From:
    $subject = '';
    $from = '';
    $headerArr = explode("\n", $header);
    foreach ($headerArr as $str) {
      if (strpos($str, 'Subject:') === 0) {
        $subject = $str;
      }
      if (strpos($str, 'From:') === 0) {
        $from = $str;
      }
    }
    
    //для отладки сохраняем полученное сообщение в лог:
    $logMsg = "=== MSG ===\n";
    $logMsg .= "SENDER: $sender\n";
    $logMsg .= "RECIPIENT: $recipient\n";
    $logMsg .= "$from\n";
    $logMsg .= "$subject\n\n";
    $logMsg .= "$msg\n";
    file_put_contents('/tmp/inb.log',$logMsg, FILE_APPEND);
    
  5. отправьте письмо на адрес robot@rob.mydomain.ru и загляните в лог /tmp/inb.log

Готово!


+51
30.5k 213
Comments 43