Autor | Zpráva | ||
---|---|---|---|
truefriend-cz Profil |
#1 · Zasláno: 28. 5. 2019, 05:58:05
Ahoj. Mám script, který se připojuje na server IMAP Gmailu a zobrazuje zprávy. Ale některé z nich jsou "rozsypaný text".
Když příjde mail s kódováním: Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: base64 Když však příjde: Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: quoted-printable tak se ukáže původní text "Dobrý den, soidugsodugoauíášýěířěýšř" jako "��7^��"v�,�۠���M}P�@��@���m��ݭ�ޘƫi'���O���rٚ�[h��ڱ�r&j)\�". Na internetu jsem našel script2.php, který by měl tohle řešit ale nedaří se mi ho začlenit do script1.php tak, aby fungoval. Pomohl by mi někdo s tím? Jinak výsledný požadavek je takový, aby když přijde email ať s TEXT/HTML nebo TEXT/PLAIN obsahem tak aby se zobrazoval jen jako prostý text ve formátu "Jméno odesílatele, Datum odeslání zprávy, a Tělo zprávy". (což momentální verze script1.php dělá) i když těžko říct, protože HTML emaily co mám ve schránce přímo od Google mají "Content-Type: text/plain". Akorát to tedy zlobí s tím rozsypáním textu. script1.php: <?php $hostname = '{imap.gmail.com:993/imap/ssl}INBOX'; $username = '*******@gmail.com'; $password = '***********'; $imap_client = imap_open($hostname, $username, $password); if (!$imap_client) { echo imap_last_error(); exit; } $emails = imap_search($imap_client, 'ALL'); if (empty($emails)) { echo 'Ve schránce se nenacházejí zprávy.'; } else { foreach ($emails as $email_id) { $text = imap_fetchbody($imap_client, $email_id, '1'); $text = base64_decode($text); $header = imap_header($imap_client, $email_id,'1'); echo '<div class="container"><div class="container-in from">' . imap_utf8($header->fromaddress) . '</div>' . ' <div class="container-in date">(' . date("d. m. Y", $header->udate) . ')</div></div>'; echo '<div class="body">⋙ ' . $text. '</div>'; echo '<br><br>'; } } imap_close($imap_client); ?> script2.php: <?php function getBody($uid, $imap) { $body = get_part($imap, $uid, "TEXT/HTML"); // if HTML body is empty, try getting text body if ($body == "") { $body = get_part($imap, $uid, "TEXT/PLAIN"); } return $body; } function get_part($imap, $uid, $mimetype, $structure = false, $partNumber = false) { if (!$structure) { $structure = imap_fetchstructure($imap, $uid, FT_UID); } if ($structure) { if ($mimetype == get_mime_type($structure)) { if (!$partNumber) { $partNumber = 1; } $text = imap_fetchbody($imap, $uid, $partNumber, FT_UID); switch ($structure->encoding) { case 3: return imap_base64($text); case 4: return imap_qprint($text); default: return $text; } } // multipart if ($structure->type == 1) { foreach ($structure->parts as $index => $subStruct) { $prefix = ""; if ($partNumber) { $prefix = $partNumber . "."; } $data = get_part($imap, $uid, $mimetype, $subStruct, $prefix . ($index + 1)); if ($data) { return $data; } } } } return false; } function get_mime_type($structure) { $primaryMimetype = array("TEXT", "MULTIPART", "MESSAGE", "APPLICATION", "AUDIO", "IMAGE", "VIDEO", "OTHER"); if ($structure->subtype) { return $primaryMimetype[(int)$structure->type] . "/" . $structure->subtype; } return "TEXT/PLAIN"; } ?> |
||
Kajman Profil |
#2 · Zasláno: 28. 5. 2019, 07:51:28
Zkuste nahradit řádky
$text = imap_fetchbody($imap_client, $email_id, '1'); $text = base64_decode($text); $text = getBody($email_id, $imap_client) Funkce ze script2 je potřeba nějak načíst, např. na začátku skriptu1 příkazem require_once("script2.php"); |
||
truefriend-cz Profil |
truefriend-cz, Kajman:
bohužel to nepomohlo. Začalo to vypisovat chybu, kterou to dělat nemá, protože by měla být ošetřená. Chyba je Fatal error: Uncaught Error: Using $this when not in object context in script.php:64 Stack trace: #0 script.php(148): getBody(1, Resource id #2) #1 {main} thrown in script.php on line 64
Jinak vložil jsem ten obsah script2.php do toho souboru jen jako funkci. Nebudu to volat ještě z jiných scriptů. Jinak řádkem 63 začíná "function getBody($uid, $imap) {". Před tímto řádkem mám jen CSS styl. Zkusil jsem najít novější (snad lepší) verzi těch funkcí (odstraněné je jen to "$this->"): function getBody($uid, $imap) { $body = get_part($imap, $uid, "TEXT/HTML"); // if HTML body is empty, try getting text body if ($body == "") { $body = get_part($imap, $uid, "TEXT/PLAIN"); } return $body; } function get_part($imap, $uid, $mimetype, $structure = false, $partNumber = false) { if (!$structure) { $structure = imap_fetchstructure($imap, $uid, FT_UID); } if ($structure) { if ($mimetype == get_mime_type($structure)) { if (!$partNumber) { $partNumber = 1; } $text = imap_fetchbody($imap, $uid, $partNumber, FT_UID); switch ($structure->encoding) { case 3: return imap_base64($text); case 4: return imap_qprint($text); default: return $text; } } // multipart if ($structure->type == 1) { foreach ($structure->parts as $index => $subStruct) { $prefix = ""; if ($partNumber) { $prefix = $partNumber . "."; } $data = get_part($imap, $uid, $mimetype, $subStruct, $prefix . ($index + 1)); if ($data) { return $data; } } } } return false; } function get_mime_type($structure) { $primaryMimetype = array("TEXT", "MULTIPART", "MESSAGE", "APPLICATION", "AUDIO", "IMAGE", "VIDEO", "OTHER"); if ($structure->subtype) { return $primaryMimetype[(int)$structure->type] . "/" . $structure->subtype; } return "TEXT/PLAIN"; } function truncate($str,$n_chars='240',$crop_str=' ... <div class="info">(text byl zkrácen)</div>') { $buff=strip_tags($str); if(strlen($buff) > $n_chars) { $cut_index=strpos($buff,' ',$n_chars); $buff=substr($buff,0,($cut_index===false? $n_chars: $cut_index+1)).$crop_str; } return $buff; } Warning: imap_fetchstructure(): Bad message number in script.php on line 11 (číslo řádku jsem upravil pro použití tady). Jinak když jsem si nechal ve funkci před řádkem 11 vypsat na stránce přes echo hodnotu $uid tak ji to normálně přiděluje správně. |
||
Kajman Profil |
#4 · Zasláno: 29. 5. 2019, 09:26:40
Když ty funkce používají k číslování UID, tak by i imap_search měl být volaný s příznakem, aby to používal.
$emails = imap_search($imap_client, 'ALL', SE_UID); |
||
truefriend-cz Profil |
Vyzkoušel jsem to a až na několik chybových zpráv okolo se načítá i obsah ale neumí to zobrazit HTML e-maily jako prostý text. Respektive zobrazuje to jako prostý text ale ne ten text na stránce jako když to bylo z původního script1.php
Zobrazuje se včetně CSS, aj. obsahu v HTML mailu. "@media only screen and (max-width: 767px){ .body_wrapper{min-width:100vw !important;} .device_txt{font-size:26px!imp"... Zkoušel jsem ve funkci vyměnit imap_base64, imap_qprint, za (původně fungující u HTML e-mailů) base64_decode ale to problém neřeší (rozházeně zobrazuje jak HTML maily tak i maily v prostém textu). V této úrovni jsem nenašel jak nějakou funkci tak třídy, které by byli schopny reálně pracovat s diakritikou tak aby výsledkem bylo co požaduji. A další chyba, že se u emailů začalo objevovat datum odeslání 01. 01. 1970. Zkouším ještě na netu hledat nějaké řešení ve směru "mail to rss", které by se dalo pro to co chci možná lépe použít. Pokud víte o něčem takovém existujícím o čem víte, že by mělo nebo funguje s češtinou bylo by to fajn. Z toho co jsem našel například: github.com/vekin03/Mail2RSS Zjišťuji, že to co je na netu je mnohdy staré a nefunguje to kvůli zastaralosti a nevěnování se chybám v kódu (podpora autorů těch scriptů nereaguje). Zmíněné chyby jsou (zde z uvedeného jako script1.php): Warning: imap_header(): Bad message number in script.php on line 23 Notice: Trying to get property 'fromaddress' of non-object in script.php on line 24 Notice: Trying to get property 'udate' of non-object in script.php on line 24 Po čarou: Nikdy jsem netušil, že taková hovadina typu zobrazit e-maily v úplně základní variantě textu bude taková patálie. Už se s tím **** týden. Hledám stále nějaké classy, postupuji podle českých návodů "krok za krokem" a nechápu jak tihle experti i na profesionálních webech kde jsou ty průvodci opomíjejí takové základy aby se vůbec text zobrazil ve správné codepage, apod. Cca ze 80% vůbec nějaké kódování nebo řazení podle nějakého parametru jako datumu, apod. naprosto neberou v úvahu. A když člověk něco takového najde, tak nakonec musí překopat celý kód, protože to nestaví tak, aby to bylo pokud možno integrované na další funkce. Ty peníze za reklamu na těch webech bych jim narval kamsi... |
||
Kajman Profil |
#6 · Zasláno: 30. 5. 2019, 10:09:18
truefriend-cz:
„Ty peníze za reklamu na těch webech bych jim narval kamsi“ Ano, to je také možnost, nabídnout jim peníze za zakázku na míru s jasným zadáním a placenou podporou po nějakou dobu od předání. |
||
Tomášeek Profil |
#7 · Zasláno: 30. 5. 2019, 11:13:10
truefriend-cz:
Proč se rozčiluješ, že někdo nenabízí podporu k něčemu, co ve svém volném čase napsal a dal volně na internet k užití? Ty sám jsi někdy zadarmo na internet pověsil něco, co bylo k užitku i ostatním? A po letech, když ti někdo napsal mail, že něco nefunguje, jsi nechal veškeré práce, sedl ke stroji a během hodiny, dne, týdne danou funkcionalitu někomu na míru připravil? Zdarma samozřejmě? Asi ne, že? Nic ti nebrání nabrat potřebné zkušenosti a napsat vlastní třídu, která bude fungovat dokonale. Nebo si najmout někoho, kdo to napíše za tebe, pokud na to sám nemáš. Řešíš úplně základní chyby špantého formátování data (předpokládám, že datum je ve zprávách správné), non-object, atd. Čílíš se, že ti funguje jen HTML výpis, ale ne plaintext. Plaintext se z HTML zprávy dá udělat i bez užití nějaké třídy, zabralo mi to asi tak půl minuty. |
||
Davex Profil |
Moderátor Davex: Přesunuto z duplicitního smazaného tématu.
E-maily mohou být poskládané různými způsoby nebo různě zakódované, takže nikdy nemůžeš spoléhat na to, že v části 1 bude vždy text zakódovaný v base64. Z obálek je nejdřív potřeba vyčíst strukturu pomocí imap_fetchstructure a v ní najít správnou část a způsob jak získat obsah.
Jinak to nemá smysl řešit takto nízkoúrovňově, když existují knihovny jako třeba PhpImap. |
||
N71 Profil * |
Odborná poznámka k původnímu tématu: IMAP, respektive v tomto případě MIME, je jedna z nejstarších široce používaných internetových komunikačních norem – A v takové je zhruba taky kondici. Bezchybnou implementaci neumí udělat už vlastně nikdo, ten formát se už dávno vymknul kontrole a kompatibilita je samozřejmě víc než norma. Obecně je to tedy úkol netriviální a rozhodně bych radši hledal hotovou knihovnu, než se pokoušel o cokoliv sám.
Moderátor Kajman: Vlákno je promazáno od nesouvisejících blábolů uživatele truefriend-cz a reakcí na ně. Pokud bude uživatel truefriend-cz nadále spamovat diskuzi výlevy mimo zaměření diskuze a zakládat duplicitní vlákna, dostane ban.
|
||
Časová prodleva: 6 let
|
0