Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Problemy z kodowaniem w IMAP

264 views
Skip to first unread message

Paweł

unread,
Dec 4, 2010, 2:26:07 PM12/4/10
to
Witam !

Usiłuję wyświetlić e-maila (ISO-8859-2) pobranego przez IMAP ale mam
problem ze znakami narodowymi.
Strona HTML na której umieszczam zawartość e-maila ma kodowanie UTF-8
Robię coś takiego:

$body = imap_fetchbody($inbox,$id, 1);
$struckture = imap_fetchstructure($inbox, $id);
$coding = $struckture->parts[1]->encoding;

$coding jest NULL lub jest równe 0.
Próbowałem użyć imap_utf8($body) ale nie ma polskich znaków.
Testowo zrobiłem mb_convert_encoding($body,"UTF-8", "ISO-8859-2")
Jest dużo lepiej ale części znaków nadal brak.
Co trzeba zrobić aby poprawnie wyświetlać e-maila ?

Paweł


porneL

unread,
Dec 4, 2010, 2:51:58 PM12/4/10
to
On Sat, 04 Dec 2010 19:26:07 -0000, Paweł <pawe...@neostrada.pl> wrote:

> Testowo zrobiłem mb_convert_encoding($body,"UTF-8", "ISO-8859-2")
> Jest dużo lepiej ale części znaków nadal brak.
> Co trzeba zrobić aby poprawnie wyświetlać e-maila ?

ISO jest w stanie przedstawić tylko ok. 200 znaków z ok. 100000, które
obsługuje UTF-8. Konwersja Unicode na archaiczne kodowanie zawsze wiąże
się z ryzykiem utraty znaków.

Najlepiej przestaw stronę na UTF-8 (konwersja ISO → UTF-8 jest bezstratna).

W HTML da się uratować sytuację za pomocą encji: htmlentities($txt,
ENT_QUOTES, 'UTF-8');

--
http://pornel.net
this.author = new Geek("porneL");

Paweł

unread,
Dec 4, 2010, 3:29:40 PM12/4/10
to

> Najlepiej przestaw stronę na UTF-8 (konwersja ISO → UTF-8 jest bezstratna).
>

Stronę HTML mam UTF-8. Generuje ja w skrypcie PHP
header ("Content-type: text/html; charset=UTF-8");
...
echo '<head><meta http-equiv="Content-Type" content="text/html;
charset=UTF-8" /></head>';


> W HTML da się uratować sytuację za pomocą encji: htmlentities($txt,
> ENT_QUOTES, 'UTF-8');
>

Zrobiłem teraz:
$body = imap_fetchbody($inbox,$id, 1);
$body=htmlentities($body, ENT_QUOTES, 'UTF-8');
echo nl2br($body);

Nadal nie ma polskich znaków
Jeśli zrobię imap_body($inbox,$id) zamiast imap_fetchbody($inbox,$id,
1); to na początku otrzymuję:


This is a multi-part message in MIME format.
--------------080706030701080000000507
Content-Type: text/plain; charset=windows-1250; format=flowed
Content-Transfer-Encoding: 8bit


Testowo przepuściłem to przez skrypt zamieniający znaki "windows-1250"
->UTF-8 i polskie znaki się pojawiły.


Paweł

pakalk

unread,
Dec 4, 2010, 3:33:50 PM12/4/10
to
1. Co robi funkcja imap_utf8()?
2. Co to jest encoding?

porneL

unread,
Dec 4, 2010, 5:14:32 PM12/4/10
to
On Sat, 04 Dec 2010 20:29:40 -0000, Paweł <pawe...@neostrada.pl> wrote:

> Stronę HTML mam UTF-8. Generuje ja w skrypcie PHP
> header ("Content-type: text/html; charset=UTF-8");

Ah, sorry. Źle przeczytałem.


Jak wyglądają niedziałające znaki? Nagłówek content-type jest w e-mailu?

pakalk

unread,
Dec 4, 2010, 5:32:12 PM12/4/10
to
On 4 Gru, 21:33, pakalk <pak...@gmail.com> wrote:
> 1. Co robi funkcja imap_utf8()?
> 2. Co to jest encoding?

Ekhm...

Paweł

unread,
Dec 5, 2010, 3:27:14 AM12/5/10
to

>> Stronę HTML mam UTF-8. Generuje ja w skrypcie PHP
>> header ("Content-type: text/html; charset=UTF-8");
>
> Ah, sorry. Źle przeczytałem.
>
>
> Jak wyglądają niedziałające znaki? Nagłówek content-type jest w e-mailu?
>
Pobrałem e-mail instrukcją $body =imap_body($inbox,$id);

$body na początku zawiera coś takiego:


This is a multi-part message in MIME format.
--------------080706030701080000000507
Content-Type: text/plain; charset=windows-1250; format=flowed
Content-Transfer-Encoding: 8bit

------ Wiadomo�� oryginalna ------


W przeglądarce (FF) wygląda to identycznie jak w tym e-mailu. Brak "ś",
"ć" w wyrazie "Wiadomość". Zamiast nich jest prostokąt z FF,FD.
Jak już pisałem wcześniej jeśli zawienię kody znaków narodowych w $body
z windows-1250 na UTF-8 to jest OK.
Dodanie instrukcji:
$body=htmlentities($body, ENT_QUOTES, 'UTF-8');
Zupełnie nic nie zmienia.
E-maile wysyłane jako tekstowe nie zawierają nagłówka i z nimi nie
mailem problemów.

Paweł

pakalk

unread,
Dec 5, 2010, 7:14:27 AM12/5/10
to
On 5 Gru, 09:27, Paweł <pawel....@neostrada.pl> wrote:
> "Usiłuję wyświetlić e-maila (ISO-8859-2) "
> Content-Type: text/plain; charset=windows-1250; format=flowed

Dostrzegasz jakiś trop, Szerloku?

> Jak już pisałem wcześniej jeśli zawienię kody znaków narodowych w $body
> z windows-1250 na UTF-8 to jest OK.

Coś Ty? To jaki masz problem?

Poza tym, chrząkanie moje nawet nie pomogło... więc właściwie to sobie
idę :)

Paweł

unread,
Dec 5, 2010, 10:56:29 AM12/5/10
to
W dniu 2010-12-05 13:14, pakalk pisze:

> On 5 Gru, 09:27, Paweł<pawel....@neostrada.pl> wrote:
>> "Usiłuję wyświetlić e-maila (ISO-8859-2)"
>> Content-Type: text/plain; charset=windows-1250; format=flowed
>
> Dostrzegasz jakiś trop, Szerloku?
>
>> Jak już pisałem wcześniej jeśli zawienię kody znaków narodowych w $body
>> z windows-1250 na UTF-8 to jest OK.
>
> Coś Ty? To jaki masz problem?

Czy metoda przedstawiona poniżej będzie dobra ?

1. odczytać nagłówek przez imap_fetchheader
2. przeszukać nagłówek pod kątem występowania ciągów znaków
określających różne sposoby kodowania.
3. odczytać e-maila przez imap_fetchbody
4. pozamieniać odpowiednio kody znaków

Paweł


pakalk

unread,
Dec 5, 2010, 11:09:30 AM12/5/10
to
On 5 Gru, 16:56, Paweł <pawel....@neostrada.pl> wrote:
>
> Czy metoda przedstawiona poni ej b dzie dobra ?
>
> 1. odczyta nag wek przez imap_fetchheader
> 2. przeszuka nag wek pod k tem wyst powania ci g w znak w
> okre laj cych r ne sposoby kodowania.
> 3. odczyta e-maila przez imap_fetchbody
> 4. pozamienia odpowiednio kody znak w
>

Nie da się ukryć, że odczytanie treści maila a potem konwersja
kodowania jest dobrym sposobem. Tylko, że atrybut encoding nie ma nic
wspólnego z UTF8, CP1250 ani ISO-8859-2. Co prawda mógłbym napisać od
razu o co mi chodzi, ale mi się nie chce, skoro Tobie nie chce się
zajrzeć do manuala i przeczytać opis tych funkcji.

Masz jakieś pomysły, dlaczego to nie działa? ;)

pakalk

unread,
Dec 5, 2010, 11:54:00 AM12/5/10
to
Zresztą nie chce mi się...

Treść maila jest zakodowana w np. CP1250, ale później jest jeszcze w
jakiś sposób kodowana, np. quoted printable i to jest wysyłane jako
mail.

Aby to prawidłowo odczytać, to należy odkodowac w drugą stronę, więc:

QP CP1250 -> CP1250

To kodowanie transmisji (Body transfer encoding) określane jest
właśnie w atrybucie encoding.

Transfer encodings (may vary with used library)
0 7BIT
1 8BIT
2 BINARY
3 BASE64
4 QUOTED-PRINTABLE
5 OTHER

Więc po ściągnięciu wiadomości, trzeba najpierw to odkodować za pomocą
np. http://www.php.net/manual/en/function.imap-qprint.php. Druga
popularna metoda kodowania, np. załączników to base64.

Jeśli mówisz, że tam masz zero, tzn. że masz to w 8-bit, a co za tym
idzie to sobie poszukaj, np. tu http://msdn.microsoft.com/en-us/library/ms526992(EXCHG.10).aspx

Kodowanie znaków natomiast kryje się w parametrze charset i jest to, o
ile dobrze pamiętam, w tablicy właśnie parameters. Zrób sobie
var_dumpa tego, co zwraca imap_fetchstructure, to będziesz wiedział. W
Twoim przypadku charset powinien być równy windows-1250 (cp1250). Za
pomocą iconv() możesz to sobie zamienić na utf-8, ale! z konwersją z
cp1250 mogą być kłopoty (parę razy mi się zdarzyło, że dostawałem
nulla), więc lepiej staraj się wysyłać maile w ISO, albo UTF - jeśli
masz na to wpływ.

Generalnie, to zabawa z mailami jest dużo trudniejsza niż to się
wydaje - głównie chodzi o masę maili niespełniającą standardów.

pakalk

unread,
Dec 5, 2010, 12:02:28 PM12/5/10
to
Sorry... 0 to oczywiście 7bit.

Null natomiast to zje*any mail ;]

Paweł

unread,
Dec 5, 2010, 12:25:17 PM12/5/10
to
W dniu 2010-12-05 18:02, pakalk pisze:

> Sorry... 0 to oczywiście 7bit.
>
> Null natomiast to zje*any mail ;]
>

W sieci są setki bardzo podobnych przykładów.
Dla wartości zero we wszystkich jest do odkodowania użyta funkcja
imap_7bit. Jednak w nowszych wersjach PHP już jej nie ma
Metodą prób i błędów doszedłem, że trzeba użyć imap_qprint lub
quoted_printable_decode

Paweł

unread,
Dec 5, 2010, 12:38:39 PM12/5/10
to
W dniu 2010-12-05 18:02, pakalk pisze:
> Sorry... 0 to oczywi�cie 7bit.

>
> Null natomiast to zje*any mail ;]
>

To co napisa�e� bardzo mi pomog�o. Skrypt ju� dzia�a.
Cho� nie wiem czy zawsze imap_fetchheader zwr�ci tekst, z kt�rego b�dzie
mo�na uzyska� informacj� o kodowaniu.

Te e-maile, dla kt�rych encoding jest NULL to klasyczne wiadomo�ci tekstowe.

Paweďż˝

Paweł

unread,
Dec 5, 2010, 12:57:51 PM12/5/10
to
W dniu 2010-12-05 18:02, pakalk pisze:
> Sorry... 0 to oczywiście 7bit.
>
> Null natomiast to zje*any mail ;]
>

Zdradź jeszcze jak pewnie uzyskać informację o zastosowanym kodowaniu.
Właśnie odebrałem e-maila gdzie imap_fetchheader zwraca tekst, w którym
nie ma ciągu określającego kodowanie.

Paweł

pakalk

unread,
Dec 5, 2010, 2:24:36 PM12/5/10
to
On 5 Gru, 18:57, Paweł <pawel....@neostrada.pl> wrote:
>
> Zdrad jeszcze jak pewnie uzyska informacj o zastosowanym kodowaniu.
> W a nie odebra em e-maila gdzie imap_fetchheader zwraca tekst, w kt rym
> nie ma ci gu okre laj cego kodowanie.
>

Nie da się. Ale można strzelać z mb_detect_encoding();

pakalk

unread,
Dec 5, 2010, 2:26:48 PM12/5/10
to
On 5 Gru, 18:38, Paweł <pawel....@neostrada.pl> wrote:
>
> Te e-maile, dla kt rych encoding jest NULL to klasyczne wiadomo ci tekstowe.

Pokaż takiego przykładowego maila. Możesz zamazać treść i nadawców/
odbiorców.

Nie musisz wykrywać kodowania za pomocą parsowania nagłówków (choć
możesz) - w zwrotce imap_fetchstructure() jest atrybut parameters (i
dparameters czy coś tam) - to jest tablica z parametrami, jeden z nich
to charset (pisane tak jak w mailu, czyli albo charset albo CHARSET, a
jak ktos ma fantazje to i charSET itp.).

Paweł

unread,
Dec 5, 2010, 3:03:16 PM12/5/10
to

> Pokaż takiego przykładowego maila. Możesz zamazać treść i nadawców/
> odbiorców.
>

E-maila można wysłać jako HTML lub jako tekst.
W pierwszym przypadku funkcja imap_body na początku zwraca np. coś takiego:

This is a multi-part message in MIME format.
--------------080706030701080000000507
Content-Type: text/plain; charset=windows-1250; format=flowed
Content-Transfer-Encoding: 8bit

Dalej jest zawartość wiadomości (tekst).
W drugim przypadku jest tylko zawartość wiadomości. Nie ma nic więcej.
Zauważyłem, że dla tych tekstowych wiadomości
$struckture->parts[1]->encoding zwraca NULL.
Trochę inaczej również wygląda również to co zwraca imap_fetchheader.

Jak trzeba to mogę coś przesłać jednak nie wiem co dokładnie mam zrobić.

>w zwrotce imap_fetchstructure() jest atrybut parameters (i
> dparameters czy coś tam) - to jest tablica z parametrami, jeden z nich
> to charset (pisane tak jak w mailu, czyli albo charset albo CHARSET, a
> jak ktos ma fantazje to i charSET itp.).

Zrobiłem to tak:
$struct = imap_fetchstructure($inbox,$id);
$charset =$struct->parts[0]->parameters[0]->value;

Wszytko działa.
Bardzo dziękuję za pomoc.

Paweł

bo...@nano.pl

unread,
Dec 6, 2010, 4:21:27 AM12/6/10
to

To jest bardziej pokręcone. Możesz mieć zagnieżdżenia partów. Więc
trzeba rekurencyjnie to sprawdzać. W dodatku każdy part może mieć osobne
kodowanie. Tak ogólnie to bajzel na kółkach, w dodatku każdy klient mail
(szczególnie webmaile) tworzą radosną twórczość dzieci kalekich.

--
wer <",,)~~
http://szumofob.eu

0 new messages