Wiadomość zostaje wysłana i dociera jako zażółć. Albo jako za???. Albo z małymi prostokątami w miejscach, gdzie powinny stać polskie litery. Trzy różne obrazy, trzy różne przyczyny — i tylko jedną z nich da się jeszcze naprawić, gdy wiadomość już leży u odbiorcy.
Co właściwie ustala zestaw znaków
Po łączu płyną bajty, czyli liczby od 0 do 255. To, jaki znak przedstawia dany ciąg liczb, nie wynika z niego samego — stoi w umowie, którą trzeba zakomunikować osobno.
W wiadomości pocztowej ta umowa stoi w Content-Type, i to osobno w każdej części wiadomości:
Content-Type: text/plain; charset=UTF-8
Gdy deklaracji brakuje, program odbierający zgaduje. A zgaduje różnie, zależnie od pochodzenia i ustawień domyślnych.
Skąd bierze się Å
UTF-8 przedstawia ż jako dwa bajty, C5 BC. Program biorący te same bajty za Windows-1252 — starszy zestaw znaków z dokładnie jednym znakiem na bajt — odczytuje z nich dwa znaki: Å i ¼.
Według tego schematu powstaje cała znajoma rodzina:
| Zamierzone | Bajty | Odczytane błędnie |
|---|---|---|
| ą | C4 85 | Ä… |
| ć | C4 87 | ć |
| ę | C4 99 | Ä™ |
| ł | C5 82 | Å‚ |
| ż | C5 BC | ż |
| ó | C3 B3 | ó |
Wiodące Ä i Å nie są przypadkiem: polskie znaki diakrytyczne zaczynają się w UTF-8 od bajtu C4 albo C5, a te w Windows-1252 to właśnie Ä i Å. Widok takiego ciągu od razu mówi, czego szukać.
Znaki zapytania i prostokąty to co innego
Trzy objawy z pierwszego akapitu nie są trzema odcieniami tego samego błędu.
ż— odczytane błędnie. Bajty są nienaruszone, błędna jest tylko interpretacja. Da się to cofnąć: po ustawieniu właściwego zestawu znaków tekst wraca.?— utracone. Tekst przekonwertowano na zestaw, który tego znaku nie zna. Zżzrobił się znak zapytania, a ze znaku zapytania nie da się już niczego odtworzyć. To jedyny przypadek nieodwracalny.- Prostokąty albo romby. Zestaw znaków i bajty się zgadzają, ale użyty krój pisma nie zawiera rysunku tego znaku. Tekst jest nieuszkodzony i da się go skopiować; zawodzi wyłącznie wyświetlanie.
To rozróżnienie decyduje o tym, czy warto poprosić o oryginał jeszcze raz, czy nie.
Nagłówek ma własne reguły
Temat, nazwa wyświetlana i nazwy plików załączników stoją w nagłówku wiadomości, a ten według pierwotnego standardu może zawierać wyłącznie ASCII. Dlatego istnieje tam osobne przepisanie:
Subject: =?UTF-8?Q?Zam=C3=B3wienie?=
To poprawnie zakodowany temat „Zamówienie": deklaracja zestawu znaków, metoda, treść. Program, który to rozumie, pokazuje tekst. Jeśli odbiorca widzi taki ciąg otwartym tekstem, system wysyłający wybrał złą kolejność — zakodował tam, gdzie nie należało, albo odwrotnie.
To kodowanie jest niezależne od charset treści wiadomości. Stąd częsty przypadek, że temat jest zniekształcony, a treść w porządku, albo na odwrót. To dwa osobne place budowy. Jak wiadomość dzieli się na części w całości, opisuje artykuł o MIME.
Zakodowane podwójnie
Najbardziej uporczywy jest przypadek, w którym tekst już zniekształcony zostaje przekonwertowany po raz drugi. Z ż robi się wtedy ż — ciąg rośnie z każdym przebiegiem.
Zdarza się to zwykle w łańcuchach kilku systemów: formularz dostarcza UTF-8, baza danych jest ustawiona na latin1, program wysyłkowy zakłada UTF-8. Każda stacja robi po swojemu rzecz właściwą, a na końcu wychodzi bezsens.
Naprawić da się to wyłącznie idąc łańcuchem wstecz i znajdując miejsce, w którym po raz pierwszy zinterpretowano błędnie. Wszystko po nim jest już następstwem.
Reguły, które problem likwidują
- Wszędzie UTF-8, bez wyjątku. Formularz, aplikacja, baza danych, wysyłka, wiadomość. Jeden jedyny punkt z innym ustawieniem wystarcza na cały efekt.
- Zestaw znaków deklarować, nie zakładać.
charset=UTF-8należy do każdej części tekstowej. Bez deklaracji odbiorca zgaduje, a program, który przez lata zgadywał trafnie, kiedyś zgadnie inaczej. - Nagłówki zostaw bibliotece. Składanie zakodowanych słów własnoręcznie jest podatne na błędy, a każda poważna biblioteka wysyłkowa robi to poprawnie.
- Przy bazie danych pilnuj kodowania połączenia, nie tylko tabeli. Kolumna
utf8mb4nic nie da, gdy połączenie stoi nalatin1— dokładnie tam rodzi się podwójne kodowanie. - Testuj prawdziwymi znakami. Przebieg testowy ze słowem „test" nie dowodzi niczego. Przebieg ze zdaniem „zażółć gęślą jaźń, Grüße, Ελλάδα" dowodzi bardzo wiele.
Ostatni punkt jest najtańszy i najpewniej zapominany. Błąd ujawnia się wyłącznie na znakach, których w danych testowych zwykle nie ma — a potem u klienta, który akurat nazywa się Żółtowski.