Autor Zpráva
maarlin
Profil
Zdravím,
mám následující string (odpověď IMAP serveru):
--001485f3c1f82c29a1046d17d944
Content-Type: text/plain
 ... Hlavička: obsah ...
.. zde je odřádkování \n\r ..
libovolný obsah
.. opět \n\r ..
--001485f3c1f82c29a1046d17d94b
Content-Type: image/png
 ... Hlavička: obsah ...
.. zde je odřádkování \n\r ..
base64-coded obsah přílohy


Řeším, jak z té odpovědi vyparsovat zvlášť:
1) jednotlivé ID zpráv (dle dvojité pomlčky a 28bitového řetězce [0-9a-f]{28})
2) hlavičky (klidně célé hlavičky ve stringu, s tím už si dokážu pohrát
3) obsah (ať už MIME-coded textový obsah mailu, nebo base64-coded obsah přílohy)

Použil bych preg_match_all() a v reguláru modifikátor "s", ovšem dosud mi není jasné, jak v reguláru zmínit přímo ten nový řádek (\n\r).
/(.*)\n\r/is
nevyhoví,
/(.*)\\n\\r/is
taky ne, co s tím udělat, jak to escapovat, aby to vyhovělo?

Moje ideální (doufám že ne idealistická) představa je, že bych z toho dokázal dostat něco následujícího:
array (
	[0]	=>	array (
				['id']	=>	"001485f3c1f82c29a1046d17d944",
				['headers']	=>	"Content-Type: text/html\nContent-Transfer-Encoding: ....",
				['content']	=>	"testovac=ED obsah textov=E9ho mailu"
			),
	[1]	=>	array (
				['id']	=>	"001485f3c1f82c29a1046d17d94b",
				['headers']	=>	"Content-Type: image/png\nContent-Transfer-Encoding: ....",
				['content']	=>	"iVBORw0KGgoAAAANSUhEUgAAAJEAAAA0CAIAAA..."
			)
);


Pokud někdo případně znáte nějakou knihovnu na práci s IMAP (bez PHP IMAP extension), která umí takto parsovat maily, zmiňte se o ní, prosím. S vyjímkou této: http://www.phpclasses.org/browse/file/9635.html kterou částečně využívám, ovšem ta prakticky neumí pracovat s přílohami a bídně s textem mailu.
Díky za každou radu.
Jan Tvrdík
Profil
maarlin:
Celé jsem to nestudoval, ale zkus nahradit /(.*)\n\r/is za /(.*?)\n\r/is. Třeba ti to pomůže alespoň trochu.
Yur4Y
Profil
Myslím, že nový riadok bude \r\n, nie \n\r.
PCRE
Profil *
A co /^(.*)$/is - modifikátor s by měl způsobit ukotvení na začátek a konec řádku
Aesir
Profil
maarlin:
Pokud někdo případně znáte nějakou knihovnu

Mrkněte na PEAR knihovny, obzvláště Mail_mimeDecode, jsou trochu staršího data, ale poměrně spolehlivé.
lordfrikk
Profil
Dej mi kus testovacího textu (ne ten pseudo s vysvětlivkami nahoře) a jak chceš aby to vypadalo, a já ti tady ten regex napíšu.
maarlin
Profil
2lordfrikk:
Beru tě za slovo, tady máš nějaký skutečný testovací text:
--0016363b9c86b8b081046d1b0639
Content-Type: multipart/alternative; boundary=0016363b9c86b8b072046d1b0637

--0016363b9c86b8b072046d1b0637
Content-Type: text/plain; charset=ISO-8859-2
Content-Transfer-Encoding: quoted-printable

Tady m=E1=B9 v=B9echny obr=E1zky.

--0016363b9c86b8b072046d1b0637
Content-Type: text/html; charset=ISO-8859-2
Content-Transfer-Encoding: quoted-printable

Tady m=E1=B9 v=B9echny obr=E1zky.

--0016363b9c86b8b072046d1b0637--
--0016363b9c86b8b081046d1b0639
Content-Type: image/jpeg; name="image.jpg"
Content-Disposition: attachment; filename="image.jpg"
Content-Transfer-Encoding: base64
X-Attachment-Id: f_fwc9l7fo0

/9j/4AAQSkZJRgABAQEASABIAAD/2wBDAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB
AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/2wBDAQEBAQEBAQEBAQEBAQEBAQEBAQEB
AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/wgARCACAAHUDAREA
AhEBAxEB/8QAHgAAAQQDAQEBAAAAAAAAAAAACAUGBwkCAwQBCgD/xAAdAQABBQEBAQEAAAAAAAAA
/* zkrácený base64-coded text */
--0016363b9c86b8b081046d1b0639


Každá příloha (0016363b9c86b8b081046d1b0639) má evidentně své ID z obou stran (na začátku i na konci) - něco jako párový tag.
Samotné textové zprávy (0016363b9c86b8b072046d1b0637) mají identifikátor jen na začátku. Pravděpodobně příloha vždy přísluší konkrétní zprávě dle konkrétního ID (ačkoliv nevím proč se musí vázat, když těžko pošlu přes běžného mailového klienta více než jednu zprávu ve dvou formátech plain/html). Čili všechny přílohy asi začínají identifikátorem zprávy odděleným z obou stran dvěma pomlčkami:
--0016363b9c86b8b072046d1b0637--

Jinak ještě každý celý element (tj. příloha nebo textová zpráva) je oddělen od dalšího \n\r, jak už jsem zmínil.

Moje představa je dostat přibližně toto (je jedno jak budou pole seřazené a různě vnořené, s tím už si pohraju):
array (
    [0]    =>    array (
                ['id']    =>    "0016363b9c86b8b081046d1b0639",
                ['headers']    =>    "Content-Type: multipart/alternative; boundary=0016363b9c86b8b072046d1b0637",
                ['content']    =>    ""
            ),
    [1]    =>    array (
                ['id']    =>    "0016363b9c86b8b072046d1b0637",
                ['headers']    =>    "Content-Type: text/plain; charset=ISO-8859-2\nContent-Transfer-Encoding: quoted-printable",
                ['content']    =>    "Tady m=E1=B9 v=B9echny obr=E1zky."
            )
    [2]    =>    array (
                ['id']    =>    "0016363b9c86b8b072046d1b0637",
                ['headers']    =>    "Content-Type: text/html; charset=ISO-8859-2\nContent-Transfer-Encoding: quoted-printable",
                ['content']    =>    "Tady m=E1=B9 v=B9echny obr=E1zky."
            )
    [3]    =>    array (
                ['id']    =>    "0016363b9c86b8b081046d1b0639",
                ['headers']    =>    "Content-Type: image/jpeg; name="image.jpg"\nContent-Disposition: attachment; filename="image.jpg"\nContent-Transfer-Encoding: base64\nX-Attachment-Id: f_fwc9l7fo0",
                ['content']    =>    "/9j/4AAQSkZJRgABAQEASABIAAD/2wBDAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB..."
            )
);

Doufám, že zkrácený base64 text nevadí, jelikož podstatu už snad vystihuje dostatečně a nerad bych diskuzi rozvinul na dalších X stránek :)
MrVain
Profil
Keep It Simple ;)
http://us3.php.net/manual/en/function.explode.php
maarlin
Profil
2MrVain: Kdyžtak Keep It Smart and Simple => KISS ... ;-)
Znám fci explode a napadlo mě její použití, ale co mě nenapadlo, je podle čeho to spolehlivě rozsekat? Dvě pomlčky? Co když náhodou bude v těle emailu třeba zrovna v podpisu --? Třeba Gmail to tam s oblibou dává... O rozsekání přes \r\n ani nemluvím, to by v těle mailu klidně mohlo být...
Čili asi nejspolehlivější řešení bude přes reguláry - dvě pomlčky a přesná definice 28bit kódu [0-9a-f]{28} zakončená \n, potom hlavičky zakončené asi prázdným řádkem, pak obsah a čekání na další definici 28bit kódu [0-9a-f]{28} zakončenou \n.
Aesir
Profil
A jak jsem psal v [#5], tak už je to dávno hotové a vymyšlené, stačí zavolat jednu metodu.
maarlin
Profil
2Aesir: Nevím zda jsi tu knihovnu zkoušel použít...
Prakticky neumí pracovat s přílohama...
Nakonec jsem jednotlivé zprávy/elementy rozsekal přes
split ("\r\n--[^\n-.]{28}\n?\r?", $content);
MrVain
Profil
[#9] boundary MUSIS poznat vzdy uz davno predtym podla specifikacie takze regexp dost blbost. ;)

mail@dxin.org
Aesir
Profil
maarlin
2Aesir: Nevím zda jsi tu knihovnu zkoušel použít...
Ano, používám ji aktivně, jinak bych ani nehodnotil její spolehlivost :)

Prakticky neumí pracovat s přílohama...
Ano a ani to nemá v popisu práce, jen rozseká na jednotlivé části hlavičky a jejich těla e-mailu podle oddělovačů, najít si v nich přílohu už musíte sám. Dělá vysloveně jen to, co jste vyžadoval od prvního příspěvku.
Přílohy následně nacházím normálně podle content-type a content-disposition hlaviček.
maarlin
Profil
Aesir
Nechtěl jsem ani od knihovny, aby mi "zpracovávala" přílohy v tom smyslu, že je nějak hned nabídne ke stažení, dokáže z nich udělat stažitelný soubor, soupis všech příloh v podobě odkazů apod...
Problém byl bohužel v tom, že pokud jsem třídě předal kompletně celý řetězec (odpověď od IMAP serveru) - tj. všechny zprávy, tak dokázala vrátit jen první element - definici boundary a jednu, popř. dvě textové zprávy (text/plain, text/html), ovšem samotná/é příloha/y (s base64-encoded obsahem) jakoby pro něj neexistovaly.
Nakonec, jak jsem psal výše, vyřešil jsem to tak, že elementy rozsekávám přes split() dle toho reguláru a pak jednotlivé části teprve předávám knihovně pro zpracování... a pokud zjistím, že jde o přílohu (dle patřičných hlaviček), přihodím ji do pole a pak to pole následně přes foreach() zpracovávám...

MrVain
Asi máš pravdu, když se nad tím trochu zamyslím, teoreticky by se to dalo řešit via explode(), ale asi by to bylo na delší lokte a testování... takhle když hned na začátku mám - spolehlivě - rozsekané jednotlivé elementy, mám o starost míň a můžu si to dál zpracovávat... U explode bych to řekněme rozdělil přes \r\n, pak každou část ještě znova rozdělit na řádky přes \n, první řádek bude identifikátor, zbytek hlavičky. Ovšem co se mezitím stalo se samotným textem mailu? ten může být klidně rozsekaný na 5 částí... a teď bych zase musel dávat ty části dohromady, zkoumat, jestli fakt první řádek je identifikátor a ne jen pokračování textu mailu... čili by stejně opět došlo na reguláry... potřebuju vědět, jestli na první řádku je tvar "dvě pomlčky" a 28 jakýchkoliv znaků kromě pomlčky a \n, což určitě přes explode neudělám...
Nebo bys to řešil jinak? Pochopil jsem tvou úvahu špatně?
Aesir
Profil
maarlin:
ovšem samotná/é příloha/y (s base64-encoded obsahem) jakoby pro něj neexistovaly

V tom případě jste nejspíš nenastavil parametr include_bodies na true, jak se píše v dokumentaci.
maarlin
Profil
Aesir
Aha, trochu jsem přehlédl definici té hlavní metody decode()... konkrétně tuto část...
$this->_include_bodies = isset($params['include_bodies']) ?
	                             $params['include_bodies'] : false;

Původně jsem totiž viděl konstruktor:
function Mail_mimeDecode($input)
    {
        list($header, $body)   = $this->_splitBodyHeader($input);

        $this->_input          = $input;
        $this->_header         = $header;
        $this->_body           = $body;
        $this->_decode_bodies  = true;
        $this->_include_bodies = true;
    }

, podle kterého bych tipoval, že bude _include_bodies nastaveno na true při každém volání třídy... jenže tyhle hodnoty by se použily asi jen v případě, kdy bych tu metodu volal staticky...
Moje chyba... Moje blbost...

Nakonec jsem ale i pro mime-decoding použil jinou, vyGooglenou třídu, která uměla (i bez PEARu) vše, co potřebuji, jen jsem ji lépe předhodil rozsekané zvlášť ty elementy a měla i nějakou základní podporu příloh, kterou jsem taky upravil trochu k obrazu svému...
http://www.weberdev.com/get_example-1607.html Takže s tímto řešením víceméně spokojenost... :-)

Díky všem za váš čas a rady. ;)
MrVain
Profil
Myslel som rozsekat podla boundary a netreba ti triedu. Specifikacie su dobry pomocnik, vela sa tam clovek dozvie. ;)
http://tools.ietf.org/html/rfc2046#section-5.1.1

Ozaj tvoja trieda pouziva stary "nebezpecny" posix aby si potom v buducnosti neprepisoval opat. ;)
http://sk2.php.net/manual/en/intro.regex.php

Niet zaco. :D

mail@dxin.org

Vaše odpověď

Mohlo by se hodit


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm: