Intereting Posts

разбор сырой электронной почты в php

Я ищу хороший / рабочий / простой в использовании PHP-код для разбора сырой электронной почты на части.

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

И прежде чем я укажу на PEAR / PECL, мне нужен реальный код. У моего хоста есть какая-то жуткая конфигурация или что-то в этом роде, я, похоже, никогда не смогу правильно построить .so. Если я действительно получаю .so сделал, некоторые различия в path / environment / php.ini не всегда делают его доступным (apache vs cron vs cli).

О, и последнее, я разбираю текст сырой электронной почты, НЕ POP3, и НЕ IMAP. Он передается в скрипт php через перенаправление электронной почты .qmail.

Я не ожидаю, что SOF напишет это для меня, я ищу несколько советов / отправных точек, чтобы сделать это «правильно». Это одна из тех «колесных» проблем, которые, как я знаю, уже решены.

На что вы надеетесь попасть в конце? Тело, субъект, отправитель, привязанность? Вы должны провести некоторое время с RFC2822, чтобы понять формат почты, но вот простейшие правила для хорошо сформированной электронной почты:

HEADERS\n \n BODY 

То есть первая пустая строка (double newline) является разделителем между HEADERS и BODY. ГОЛОВА выглядит так:

 HSTRING:HTEXT 

HSTRING всегда начинается в начале строки и не содержит пробелов или двоеточий. HTEXT может содержать большое количество текста, включая новые строки, если символ новой строки сопровождается пробелами.

«BODY» – это просто данные, которые следует за первой двойной новой строкой. (Существуют разные правила, если вы отправляете почту через SMTP, но обрабатываете ее по каналу, о котором вам не нужно беспокоиться).

Таким образом, в действительно простых, приблизительно в 1982 году условиях RFC822 , электронное письмо выглядит так:

 HEADER: HEADER TEXT HEADER: MORE HEADER TEXT INCLUDING A LINE CONTINUATION HEADER: LAST HEADER THIS IS ANY ARBITRARY DATA (FOR THE MOST PART) 

Однако большинство современных электронных писем более сложны. Заголовки могут быть закодированы для charsets или RFM2047 mime words, или тонны других вещей, о которых я сейчас не думаю. Органам действительно сложно катить свой код на эти дни, если вы хотите, чтобы они были значимыми. Почти вся электронная почта, созданная MUA, будет кодироваться MIME . Это может быть uuencoded текст, это может быть html, это может быть электронная таблица uuencoded excel.

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

Попробуйте парсер PHP Plancake PHP: https://github.com/plancake/official-library-php-email-parser

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

Я купил это вместе, какой-то код не мой, но я не знаю, откуда он пришел … Я позже принял более надежный «MimeMailParser», но это отлично работает, я транслирую по умолчанию письмо по электронной почте с помощью cPanel, и он работает Великий.

 #!/usr/bin/php -q <?php // Config $dbuser = 'emlusr'; $dbpass = 'pass'; $dbname = 'email'; $dbhost = 'localhost'; $notify= 'services@.com'; // an email address required in case of errors function mailRead($iKlimit = "") { // Purpose: // Reads piped mail from STDIN // // Arguements: // $iKlimit (integer, optional): specifies after how many kilobytes reading of mail should stop // Defaults to 1024k if no value is specified // A value of -1 will cause reading to continue until the entire message has been read // // Return value: // A string containing the entire email, headers, body and all. // Variable perparation // Set default limit of 1024k if no limit has been specified if ($iKlimit == "") { $iKlimit = 1024; } // Error strings $sErrorSTDINFail = "Error - failed to read mail from STDIN!"; // Attempt to connect to STDIN $fp = fopen("php://stdin", "r"); // Failed to connect to STDIN? (shouldn't really happen) if (!$fp) { echo $sErrorSTDINFail; exit(); } // Create empty string for storing message $sEmail = ""; // Read message up until limit (if any) if ($iKlimit == -1) { while (!feof($fp)) { $sEmail .= fread($fp, 1024); } } else { while (!feof($fp) && $i_limit < $iKlimit) { $sEmail .= fread($fp, 1024); $i_limit++; } } // Close connection to STDIN fclose($fp); // Return message return $sEmail; } $email = mailRead(); // handle email $lines = explode("\n", $email); // empty vars $from = ""; $subject = ""; $headers = ""; $message = ""; $splittingheaders = true; for ($i=0; $i < count($lines); $i++) { if ($splittingheaders) { // this is a header $headers .= $lines[$i]."\n"; // look out for special headers if (preg_match("/^Subject: (.*)/", $lines[$i], $matches)) { $subject = $matches[1]; } if (preg_match("/^From: (.*)/", $lines[$i], $matches)) { $from = $matches[1]; } if (preg_match("/^To: (.*)/", $lines[$i], $matches)) { $to = $matches[1]; } } else { // not a header, but message $message .= $lines[$i]."\n"; } if (trim($lines[$i])=="") { // empty line, header section has ended $splittingheaders = false; } } if ($conn = @mysql_connect($dbhost,$dbuser,$dbpass)) { if(!@mysql_select_db($dbname,$conn)) mail($email,'Email Logger Error',"There was an error selecting the email logger database.\n\n".mysql_error()); $from = mysql_real_escape_string($from); $to = mysql_real_escape_string($to); $subject = mysql_real_escape_string($subject); $headers = mysql_real_escape_string($headers); $message = mysql_real_escape_string($message); $email = mysql_real_escape_string($email); $result = @mysql_query("INSERT INTO email_log (`to`,`from`,`subject`,`headers`,`message`,`source`) VALUES('$to','$from','$subject','$headers','$message','$email')"); if (mysql_affected_rows() == 0) mail($notify,'Email Logger Error',"There was an error inserting into the email logger database.\n\n".mysql_error()); } else { mail($notify,'Email Logger Error',"There was an error connecting the email logger database.\n\n".mysql_error()); } ?> 

Есть функции Mailparse, которые вы могли бы попробовать: http://php.net/manual/en/book.mailparse.php , но не в php conf.

Существует библиотека для разбора сырого сообщения электронной почты в php-массив – http://flourishlib.com/api/fMailbox#parseMessage .

Статический метод parseMessage () можно использовать для анализа полного сообщения электронной почты MIME в том же формате, который возвращает fetchMessage (), минус ключ uid.

$ parsed_message = fMailbox :: parseMessage (file_get_contents ('/ path / to / email'));

Ниже приведен пример анализируемого сообщения:

 array( 'received' => '28 Apr 2010 22:00:38 -0400', 'headers' => array( 'received' => array( 0 => '(qmail 25838 invoked from network); 28 Apr 2010 22:00:38 -0400', 1 => 'from example.com (HELO ?192.168.10.2?) (example) by example.com with (DHE-RSA-AES256-SHA encrypted) SMTP; 28 Apr 2010 22:00:38 -0400' ), 'message-id' => '<4BD8E815.1050209@flourishlib.com>', 'date' => 'Wed, 28 Apr 2010 21:59:49 -0400', 'from' => array( 'personal' => 'Will Bond', 'mailbox' => 'tests', 'host' => 'flourishlib.com' ), 'user-agent' => 'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.9) Gecko/20100317 Thunderbird/3.0.4', 'mime-version' => '1.0', 'to' => array( 0 => array( 'mailbox' => 'tests', 'host' => 'flourishlib.com' ) ), 'subject' => 'This message is encrypted' ), 'text' => 'This message is encrypted', 'decrypted' => TRUE, 'uid' => 15 ); 

Этот https://github.com/zbateson/MailMimeParser работает для меня и не нуждается в расширении mailparse.

 <?php echo $message->getHeaderValue('from'); // user@example.com echo $message ->getHeader('from') ->getPersonName(); // Person Name echo $message->getHeaderValue('subject'); // The email's subject echo $message->getTextContent(); // or getHtmlContent 

Pear lib Mail_mimeDecode написан на простом PHP, который вы можете увидеть здесь: Mail_mimeDecode source

Вероятно, вам не будет весело писать собственный MIME-парсер. Причина, по которой вы находите «чрезмерно развитые пакеты обработки почты», заключается в том, что MIME представляет собой действительно сложный набор правил / форматов / кодировок. Части MIME могут быть рекурсивными, что является частью удовольствия. Я считаю, что лучше всего написать лучший обработчик MIME, который вы можете, разобрать сообщение, выбросить все, что не является текстовым / plain или text / html, а затем заставить команду в входящей строке префикс COMMAND: или что-то подобное так что вы можете найти его в гадости. Если вы начнете с таких правил, у вас будет неплохой шанс обратиться к новым провайдерам, но вы должны быть готовы к настройке, если появится новый провайдер (или, если ваш текущий провайдер решит изменить свою архитектуру обмена сообщениями).

Разбор электронной почты на PHP не является невыполнимой задачей. Я имею в виду, что для этого вам не нужна команда инженеров; она достижима как индивидуум. На самом деле самая сложная часть, которую я нашел, это создание FSM для анализа результата IMAP BODYSTRUCTURE. Нигде в Интернете я не видел этого, поэтому написал свои собственные. Моя подпрограмма в основном создает массив вложенных массивов из выходного файла команды, а глубину в массиве примерно соответствует номеру (-ам), необходимым для выполнения поиска. Таким образом, он очень грамотно обрабатывает вложенные MIME-структуры.

Проблема в том, что функции imap_ * по умолчанию PHP не обеспечивают большую детализацию … поэтому мне пришлось открыть сокет на порт IMAP и написать функции для отправки и получения необходимой информации (IMAP FETCH 1 BODY.PEEK [1.2] например), и это связано с рассмотрением документации RFC.

Вам предоставлена ​​кодировка данных (кавычки, base64, 7bit, 8bit и т. Д.), Длина сообщения, тип контента и т. Д. для вложений, текста, html и т. д. Возможно, вам придется выяснить нюансы вашего почтового сервера, так как не все поля всегда реализованы на 100%.

Драгоценный камень – это FSM … если у вас есть фон в Comp Sci, это может быть действительно забавно сделать это (они являются ключом к тому, что скобки не являются регулярной грамматикой;)); в противном случае это будет борьба и / или результат уродливого кода, используя традиционные методы. Также вам нужно некоторое время!

Надеюсь это поможет!

Я не уверен, что это поможет вам – надеюсь, что так – но это, безусловно, поможет другим, заинтересованным узнать больше об электронной почте. Marcus Bointon сделал одну из лучших презентаций под названием «Mail () и life after Mail ()» на конференции в Лондоне в Лондоне в марте этого года, а слайды и MP3 – онлайн. Он говорит с некоторыми авторитетами, много работая с электронной почтой и PHP на глубоком уровне.

Мое восприятие заключается в том, что вы находитесь в мире боли, пытаясь написать действительно общий парсер.

EDIT – файлы, кажется, были удалены на сайте PHP London; нашел слайды на собственном сайте Маркуса: Часть 1 Часть 2 Не мог видеть MP3 в любом месте, хотя

да, ive удалось написать базовый парсер, основанный на том, что rfc и некоторые другие базовые учебники. но его многопартийные вложенные границы, которые мешают мне.

Я узнал, что сообщения MMS (не SMS), отправленные с моего телефона, являются стандартными сообщениями электронной почты, поэтому у меня есть система, которая читает входящее письмо, проверяет его (только для моего телефона) и использует часть тела для запуска разных команд на моем сервере. его вроде как пульт дистанционного управления по электронной почте.

потому что система предназначена для отправки изображений, у нее есть куча по-разному закодированных частей. часть mms.smil.txt, текстовая / обычная (что бесполезно, просто говорит «это html-сообщение»), часть приложения / smil (какая часть телефона будет нарисовать), часть text / html с рекламой моего оператора, затем мое сообщение, но все завернутые в html, а затем, наконец, вложение в текстовое приложение с моим простым сообщением (которое является частью, которую я использую) (если я запишу изображение в качестве вложения в сообщении, его вложение 1, base64, затем моя часть текста прикреплена как вложение 2)

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

У меня есть другие проекты, к которым я хотел бы расширить эту систему phone-> mail-> parse-> command, но мне нужно иметь стабильный / сплошной / общий синтаксический анализатор, чтобы вывести разные части из почты, чтобы использовать их.

моя конечная цель состояла бы в том, чтобы иметь функцию, в которой я мог бы загружать необработанную почтовую почту, и возвращать большой массив с ассоциативными подмассивами заголовков var: val pairs и один для основного текста в виде целой строки

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

я думаю, что мне придется укусить пулю и просто тщательно написать что-то свое.

Эта библиотека работает очень хорошо:

http://www.phpclasses.org/package/3169-PHP-Decode-MIME-e-mail-messages.html

Я встретил ту же проблему, поэтому написал следующий класс: Email_Parser. Он берет необработанное письмо и превращает его в хороший объект.

Он требует PEAR Mail_mimeDecode, но его следует легко установить через WHM или прямо из командной строки.

Получите его здесь: https://github.com/optimumweb/php-email-reader-parser

Простой PhpMimeParser https://github.com/breakermind/PhpMimeParser Юо может вырезать mime-сообщения из файлов, строки. Получите файлы, html и встроенные изображения.

 $str = file_get_contents('mime-mixed-related-alternative.eml'); // MimeParser $m = new PhpMimeParser($str); // Emails print_r($m->mTo); print_r($m->mFrom); // Message echo $m->mSubject; echo $m->mHtml; echo $m->mText; // Attachments and inline images print_r($m->mFiles); print_r($m->mInlineList);