парсинг темы почты по IMAP

Discussion in 'PHP' started by Snyper, 12 Nov 2016.

  1. Snyper

    Snyper New Member

    Joined:
    23 May 2008
    Messages:
    2
    Likes Received:
    0
    Reputations:
    0
    Всем привет, такой вопрос:
    Как распарсить тему почты если она состоит из 2х частей?

    так например:

    =?UTF-8?Q?=D0=A2=D0=B5=D0=BC=D0=B0=20=D0=BD=D0=B0=20=D1=80=D1=83?= =?UTF-8?Q?=D1=81=D1=81=D0=BA=D0=BE=D0=BC=20=D0=B8=20=D0=B0=D0=BD=D0=B3?= =?UTF-8?Q?=D0=BB=D0=B8=D0=B9=D1=81=D0=BA=D0=BE=D0=BC=20=D1=8F=D0=B7=D1=8B?= =?UTF-8?Q?=D0=BA=D0=B0=D1=85=20korp-m=2Ecom?=

    так например в данной теме начало "=?UTF-8?Q?" встречается 4 раза

    В дркгом письме данная тема будет кодирована один раз.

    в итоге как правильно читать?
    Использовать костыль типа:
    первый раз отловить "=?UTF-8?Q?" что бы понять кодировку и метод шифрования, второй раз удалить все вхождения "=?UTF-8?Q?" и удалить их, и потом расшифровывать или все таки есть какой то метод проще?
     
  2. bologer

    bologer Member

    Joined:
    25 Nov 2016
    Messages:
    62
    Likes Received:
    18
    Reputations:
    3
    Немного не понятно того, что ты хочешь сделать.
    Для начала, я бы посчитал сколько что-то встречается. В твоей варианте - это "=?UTF-8?Q?" с помощью регулярного выражения, а точнее http://php.net/manual/en/function.preg-match-all.php.
    Далее делаешь if условия и разбираешь строку подетально как тебе нужно опять же с регулярками. Других вариантов я не вижу. Может быть кто-то еще подскажет.
     
  3. t0ma5

    t0ma5 Reservists Of Antichat

    Joined:
    10 Feb 2012
    Messages:
    829
    Likes Received:
    815
    Reputations:
    90
    Code:
    ~$ cat /tmp/x.pl
    use URI::Encode;
    $str = '=?UTF-8?Q?=D0=A2=D0=B5=D0=BC=D0=B0=20=D0=BD=D0=B0=20=D1=80=D1=83?= =?UTF-8?Q?=D1=81=D1=81=D0=BA=D0=BE=D0=BC=20=D0=B8=20=D0=B0=D0=BD=D0=B3?= =?UTF-8?Q?=D0=BB=D0=B8=D0=B9=D1=81=D0=BA=D0=BE=D0=BC=20=D1=8F=D0=B7=D1=8B?= =?UTF-8?Q?=D0=BA=D0=B0=D1=85=20korp-m=2Ecom?=';
    $uri = URI::Encode->new( { encode_reserved => 0 } );
    while($str=~/[^\?]+\?=([^?]+)\?=/g)
    { 
        $str2 = $1;
        $str2=~s/\=/\%/g;
        print $uri->decode("$str2")."\n";
    }
    ~$ perl /tmp/x.pl
    D0�ема на ру
    D1�ском и анг
    D0�ийском язы
    D0�ах korp-m.com
    
    формат заголовков почты это отдельный изврат, даже знать не хочу как точно и по каким правилам он формируется, рекомендую читать маны
     
    _________________________
  4. pas9x

    pas9x Elder - Старейшина

    Joined:
    13 Oct 2012
    Messages:
    423
    Likes Received:
    585
    Reputations:
    52
    Гг. Когда-то тоже с этим сталкивался. Формат заголовков письма, на самом деле, не сложный. Он описан а RFC2047. Такое кодирование относится не только к теме, но и к другим заголовкам. В заголовках куски текста содержащие нестантартные символы должны кодироваться в таком формате:
    =?кодировка?формат?закодированный_текст?=
    Где:
    кодировка - кодовая таблица (например utf-8, windows-1251)
    формат - буква B или Q
    B означает способ кодирования base64
    Q означает способ кодирования quoted printable
    Других форматов кроме B и Q нет, о чём нам говорит раздел 4 из RFC.

    Заголовки следует обрабатывать как простой текст, но всё что находится внутри =?кодировка?формат?закодированный_текст?= нужно раскодировать. Так как внутри этих блоков может быть текст в любой кодировке, например utf-8 а снаружи них стандартный ASCII то для простоты можно конвертировать декодированный текст этих блоков в какую-нибудь однобайтовую кодировку, например в windows-1251.

    Пример кода для расшифровки твоего текста:
    PHP:
    <?php

    function decodeSubject($subject$adjustToCp1251 true)
    {
        
    $result '';
        
    $split preg_split('/\s+/s'$subject);
        foreach (
    $split as $particle) {
            if (
    $particle === '') {
                continue;
            }
            if (!
    preg_match('/^\=\?([a-z0-9\_\.\-]{2,50})\?([bq])\?(.*)\?\=$/i'$particle$matches)) {
                
    $result .= $particle;
                continue;
            }
            
    $charset $matches[1];
            
    $encoding strtoupper($matches[2]);
            
    $encodedText $matches[3];
            if (
    $encoding === 'B') {
                
    $decodedText base64_decode($encodedText);
            } elseif (
    $encoding === 'Q') {
                
    $decodedText quoted_printable_decode($encodedText);
            } else {
                throw new 
    Exception('WTF?');
            }
            if (
    $adjustToCp1251) {
                
    $result .= iconv($charset'CP1251'$decodedText);
            } else {
                
    $result .= $decodedText;
            }
        }
        return 
    $result;
    }

    $subj '=?UTF-8?Q?=D0=A2=D0=B5=D0=BC=D0=B0=20=D0=BD=D0=B0=20=D1=80=D1=83?= =?UTF-8?Q?=D1=81=D1=81=D0=BA=D0=BE=D0=BC=20=D0=B8=20=D0=B0=D0=BD=D0=B3?= =?UTF-8?Q?=D0=BB=D0=B8=D0=B9=D1=81=D0=BA=D0=BE=D0=BC=20=D1=8F=D0=B7=D1=8B?= =?UTF-8?Q?=D0=BA=D0=B0=D1=85=20korp-m=2Ecom?=';
    $text decodeSubject($subj);
    echo 
    $text;

     
    mr_Coder and t0ma5 like this.