2012-01-03 9 views
8

(Ponieważ jest to moje pierwsze pytanie SO, pozwól mi tylko powiedzieć, że mam nadzieję, że nie jest to zbyt specyficzne dla Zend, o ile mogę to stwierdzić, nie powinno być Problem, chociaż mogłem opublikować go na forum specyficznym dla Zend, wydaje mi się, że jestem tak samo prawdopodobny, aby uzyskać dobrą odpowiedź tutaj, zwłaszcza, że ​​odpowiedź może obejmować zagadnienia związane z MIME, które wykraczają poza Zend Framework. Zasadniczo próbuję zrozumieć, czy problem, który napotykam, powinien być uważany za błąd ZF, czy też coś nie rozumiem lub go niewłaściwie wykorzystuję.)Nie mogę zrozumieć, dlaczego Zend_Mail :: addHeader() rozbiera znaki nowej linii

Używam Zend_Mail do budowania wiadomości MIME, która dostaje wysyłane za pośrednictwem SendGrid, usługi dystrybucji poczty e-mail. Ich platforma umożliwia wysyłanie wiadomości e-mail za pośrednictwem ich serwera SMTP, ale zapewnia dodatkowe funkcje, gdy używany jest specjalny nagłówek (X-SMTPAPI), którego wartość jest zakodowanym w JSON ciągiem zastrzeżonych parametrów, które mogą być dość długie.

Ostatecznie nagłówek, przez który przechodziłem, był zbyt długi (chyba 1000 znaków) i pojawiły się błędy. Byłem zdezorientowany, ponieważ wiedziałem, że przechodzi on przez natywną funkcję wordwrap() PHP, zanim przekazałem wartość do Zend_Mail :: addHeader(), więc pomyślałem, że długość linii nigdy nie powinna stanowić problemu.

Okazuje się, że addHeader() rozbiera newlines bardzo celowo, bez szczególnego wyjaśnienia poprzez komentarze.

// In Zend_Mail::addHeader() 
$value = $this->_filterOther($value); 


// In Zend_Mail::_filterOther() 
$rule = array("\r" => '', 
       "\n" => '', 
       "\t" => '', 
); 
return strtr($data, $rule); 

OK, wydawało się to rozsądne na początku - może ZF chce mieć pełną kontrolę nad formatowaniem i zawijaniem linii. Kolejna metoda nazywa się Zend_Mail :: AddHeader() jest

$value = $this->_encodeHeader($value); 

Sposób ten koduje wartość (albo quoted-druku lub base64 odpowiednio) i fragmenty go na linii odpowiedniej długości, ale tylko jeśli zawiera "znaki niedrukowalne", określone przez Zend_Mime :: isPrintable (wartość $).

Patrząc na tę metodę, znaki nowej linii (\ n) są rzeczywiście uważane za znaki niedrukowalne! Więc jeśli nie zostałyby usunięte z łańcucha w poprzednim wywołaniu metody, długi nagłówek zostałby zakodowany jako QP i pocięty na linie 72-znakowe, a wszystko działałoby dobrze. W rzeczywistości zrobiłem test, w którym skomentowałem wywołanie funkcji _filterOther(), a długi nagłówek zostaje zakodowany i przechodzi bez problemu. Ale teraz zrobiłem bezmyślny hack do ZF, nie rozumiejąc dokładnie celu, z którego usunąłem linię, więc nie może to być rozwiązanie długoterminowe.

Moim średnioterminowym rozwiązaniem było rozszerzenie Zend_Mail i stworzenie nowej metody, addHeaderForceEncode(), która zawsze zakoduje wartość nagłówka, a zatem zawsze będzie dzielona na krótkie linie. Ale nadal nie jestem zadowolony, ponieważ nie rozumiem, dlaczego to wezwanie "FilterOther" było w ogóle konieczne - może nie powinienem w ogóle pracować nad tym.

Czy ktoś może mi wytłumaczyć, dlaczego istnieje takie zachowanie polegające na zdzieraniu nowych linii? Wydaje się nieuchronnie prowadzić do sytuacji, w których nagłówek może stać się zbyt długi, jeśli nie zawiera żadnych "niedrukowalnych znaków" innych niż znaki nowej linii.

Zrobiłem kilka różnych wyszukiwań na ten temat i przejrzałem niektóre raporty błędów ZF, ale nie widziałem nikogo, kto o tym mówił. Zaskakująco wydaje się, że jest to naprawdę niejasny problem. FYI Pracuję z ZF 1.11.11.


Aktualizacja: W przypadku ktoś chce śledzić ZF problem I otwarty na ten temat, to jest tutaj: Zend_Mail::addHeader() UNfolds long headers, then throws exception

+1

StackOverflow może odpowiedzieć na wszystkie pytania;) +1 Na pierwsze pytanie tutaj. – Flavius

+0

Dzięki za to, że poczułam się mile widziana. – LinusR

Odpowiedz

6

Pewnie działa na kilka rzeczy. Za RFC 2821, linie tekstu w SMTP nie może przekraczać 1000 znaków:

linia tekstu

Maksymalna łączna długość linii tekstu w tym jest 1000 znaków (nie licząc kropką duplikowane dla przejrzystości). Liczba ta może zostać zwiększona za pomocą rozszerzeń usługi SMTP .

Nagłówek nie może zawierać znaków nowego wiersza, więc pewnie dlatego Zend je rozbiera. W przypadku długich nagłówków często wstawia się podział wiersza (CRLF w SMTP) i kartę, aby je "zawinąć".

Fragment RFC 822:

Każde pole nagłówka może być postrzegana jako pojedynczy logiczny linii znaków ASCII, zawierające nazwę polową i pole-ciało. Dla wygody, część ciało-ciało tej konceptualnej jednostki można podzielić na reprezentację wieloliniową; to nazywa się "składaniem". Ogólna reguła jest taka, że ​​wszędzie tam, gdzie może być liniowo-białą spacją (nie tylko LWSP-znakami), CRLF bezpośrednio po AT LEAST jeden LWSP-char może zamiast tego być wstawiony.

Powiedziałbym, że funkcja _encodeHeader() powinien ewentualnie spojrzeć na długości linii, a jeśli nagłówek jest dłuższy niż jakiejś magicznej wartości, wykonaj „wrap i zakładka” mieć ona obejmować wiele wierszy.

+2

Sprawdziłem również i nie wygląda na to, że Zend_Mail obsługuje składanie nagłówków, ani nie daje sposobu na dodanie "nieprzetworzonego nagłówka", który nie jest przetwarzany. Wygląda na to, że ta modyfikacja byłaby najlepiej wykonana w metodzie '_prepareHeaders'' Zend_Mail_Transport_Abstract'. Jeśli przekażesz trzeci parametr '$ append' do' addHeader', to spisze on dołączone dane, ale także doda przecinek na końcu wiersza, który prawdopodobnie złamałby twój JSON. Może to być warte stworzenia [wydania] (http://framework.zend.com/issues/secure/Dashboard.jspa). – drew010

+0

@tomlogic Nie rozumiem, dlaczego powiedziałeś "Nagłówek nie może zawierać znaków nowej linii, więc prawdopodobnie Zend je usuwa", ponieważ znaki nowej linii jako część CRLF są niezbędne do zwijania (jak również wskazano w RFC 822) . Ale ogólnie rzecz biorąc rozumiem, że brakuje pewności w addHeader() lub _encodeHeader()? – LinusR

+0

@LinusR: Myślę, że Zend nie oczekuje złożonego nagłówka, i dlatego rozbiera nowe linie. Moim zdaniem, Zend powinien zaakceptować złożony nagłówek (gdzie każda CRLF jest podążana za białymi znakami, bez nagiego CR lub LF) lub spróbuj spasować długie nagłówki. – tomlogic

Powiązane problemy