Сведения о вопросе

Electro Full

22:20, 22nd August, 2020

Теги

php   email    

анализ сырой email в php

Просмотров: 490   Ответов: 14

Я ищу good/working/simple, чтобы использовать код php для разбора raw email на части.

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

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

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

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



  Сведения об ответе

DO__IT

09:46, 25th August, 2020

Что вы надеетесь получить в конце концов? Тело,предмет, отправитель, вложение? Вы должны потратить некоторое время с RFC2822 , чтобы понять формат почты, но вот самые простые правила для хорошо сформированного email:

HEADERS\n
\n
BODY

То есть первая пустая строка (двойная новая строка) является разделителем между HEADERS и BODY. Заголовок выглядит следующим образом:

HSTRING:HTEXT

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

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

Итак, в очень простых, примерно 1982 RFC822 терминах, email выглядит следующим образом:

HEADER: HEADER TEXT
HEADER: MORE HEADER TEXT
  INCLUDING A LINE CONTINUATION
HEADER: LAST HEADER

THIS IS ANY
ARBITRARY DATA
(FOR THE MOST PART)

Однако большинство современных email более сложны, чем это. Заголовки могут быть закодированы для кодировок или RFC2047 MIME-слов, или тонны других вещей, о которых я сейчас не думаю. Тела действительно трудно свернуть свой собственный код для этих дней, если вы хотите, чтобы они были значимыми. Почти все email, которые генерируются MUA, будут кодироваться MIME . Что может быть в кодировке uuencode текст, это может быть html, это может быть в кодировке uuencode excel таблицы.

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


  Сведения об ответе

DINO

06:52, 6th August, 2020

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

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


  Сведения об ответе

Chhiki

08:35, 17th August, 2020

Я собрал это вместе, какой-то код не мой, но я не знаю, откуда он взялся... Позже я принял более надежный "MimeMailParser", но это работает нормально, я передаю ему свой default email с помощью 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());
}
?>


  Сведения об ответе

FAriza

03:55, 19th August, 2020

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


  Сведения об ответе

lourence

13:05, 5th August, 2020

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


  Сведения об ответе

fo_I_K

15:40, 6th August, 2020

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

Статический метод parseMessage() можно использовать для разбора полного MIME email сообщение в том же формате, что и 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
);


  Сведения об ответе

prince

19:10, 6th August, 2020

Это 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


  Сведения об ответе

FAriza

01:38, 8th August, 2020

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

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

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

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

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


  Сведения об ответе

#hash

09:58, 1st August, 2020

Вам, вероятно, будет не очень весело писать свой собственный парсер MIME. Причина, по которой вы находите "overdeveloped mail handling packages", заключается в том, что MIME-это действительно сложный набор rules/formats/encodings. MIME части могут быть рекурсивными, что является частью удовольствия. Я думаю, что вам лучше всего написать лучший обработчик MIME, который вы можете, разобрать сообщение, выбросить все, что не является текстом / обычным или text/html,, а затем заставить команду в входящей строке быть префиксом COMMAND: или что-то подобное, чтобы вы могли найти его в грязи. Если вы начинаете с таких правил, у вас есть неплохие шансы справиться с новыми поставщиками, но вы должны быть готовы настроить их, если появится новый поставщик (или, черт возьми, если ваш текущий поставщик решит изменить свою архитектуру обмена сообщениями).


  Сведения об ответе

PROGA

21:06, 1st October, 2020

Я не уверен, что это поможет вам - надеюсь, что да, - но это наверняка поможет другим заинтересованным в том, чтобы узнать больше о email. Маркус Бойнтон сделал одну из лучших презентаций под названием "Mail() и жизнь после Mail()" на Лондонской конференции PHP в марте этого года, и слайды и MP3 находятся в интернете. Он говорит с некоторым авторитетом, много работая с email и PHP на глубоком уровне.

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

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


  Сведения об ответе

pumpa

03:48, 6th August, 2020

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

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

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

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

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

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

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

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


  Сведения об ответе

fo_I_K

05:41, 9th August, 2020

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

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


  Сведения об ответе

DO__IT

21:06, 1st October, 2020

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

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

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


  Сведения об ответе

DAAA

05:53, 16th August, 2020

Простой 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);


Ответить на вопрос

Чтобы ответить на вопрос вам нужно войти в систему или зарегистрироваться