ПриветУ меня SquirrelMail не показывает заголовки писем с opennet'а. Сегодня посмотрел внимательнее - они не соответствуют RFC2047. Например из сегодняшнего письма:
Subject: =?KOI8-R?Q?=D5=D4=C9=CC=C9=D4=C1 su =C9=CC=C9 =C4=CF=D3=D4=D5=D0 =CB =D0=D2=C1=D7=C1=CD root =CF=C2=D9=DE=CE=CF=CD=D5 =D0=CF=CC=D8=DA=CF=D7=C1=D4=C5=CC=C0?=
тут две проблемы:
1) в токенах недопустимы пробелы, они должны заменятся на подчеркивание или =20;
2) длина одной строки ограничена 76 символами, включая имя хедера и указание кодировки; потом обязан быть перенос на новую строку.Если интересно, то могу запостить правильную реализацию на PHP, десяток строчек (не мое, где-то в Инете нашел).
Для кодирования у меня используется Perl модуль MIME::Words. Сейчас посмотрел, а в одном месте вместо "encode_mimewords" написано "encode_mimeword", поправил.
>Для кодирования у меня используется Perl модуль MIME::Words. Сейчас посмотрел, а в
>одном месте вместо "encode_mimewords" написано "encode_mimeword", поправил.Тот глюк исчез, но теперь он кодировку неправильную подставил:
Subject: =?ISO-8859-1?Q?=E2=C1=C7?= =?ISO-8859-1?Q?=D7?= subject'=?ISO-8859-1?Q?=C1=CD=C9?= =?ISO-8859-1?Q?=D0=C9=D3=C5=CD?=
>Тот глюк исчез, но теперь он кодировку неправильную подставил:Исправил.
>>Тот глюк исчез, но теперь он кодировку неправильную подставил:
>
>Исправил.Еще один остался:
Subject: =?KOI8-R?Q?=E2=C1=C7?= =?KOI8-R?Q?=D7?= subject'=?KOI8-R?Q?=C1=CD=C9?= =?KOI8-R?Q?=D0=C9=D3=C5=CD?=
Показывается как:
Багвsubject'амиписем
Пробелы должны явно входить в токен как подчеркивания, т.к. по RFC рядом стоящие токены склеиваются.
>Показывается как:
>Багвsubject'амиписем
>Пробелы должны явно входить в токен как подчеркивания, т.к. по RFC рядом
>стоящие токены склеиваются.Хм, обновил версию модуля MIME::Words, все равно поведение с пробелами не изменилось.
Почитал RFC, там действительно определено что пробелы между закодированными блоками не отображаются, а между закодированным и не закодированным - вставляются. Получается проблема в MIME::Words, попытаюсь найти альтернативный модуль соблюдающий стандарт.
PS. Посмотрел пару webmail на перл, там таже проблема.
>Хм, обновил версию модуля MIME::Words, все равно поведение с пробелами не изменилось.Угу, у него и в документации написано, что не полностью соответствует.
>Почитал RFC, там действительно определено что пробелы между закодированными блоками не отображаются,
>а между закодированным и не закодированным - вставляются. Получается проблема в
>MIME::Words, попытаюсь найти альтернативный модуль соблюдающий стандарт.
>
>PS. Посмотрел пару webmail на перл, там таже проблема.Накидал такую функцию, мои тесты она проходит. Лицензия - "все_пофиг" :)
#!/usr/local/bin/perl
use strict;
use vars;sub rfc2047conv
{
my $str = shift; # чего кодировать
my $charset = uc(shift); # какую кодировку приписать
my $init_len = shift || 0; # длина того, что планируется добавить потом в начало строкиmy $len = length($str);
return '' unless($len);
my $begin = "=?$charset?Q?";
my $res = $begin;
my $count = $init_len + length($begin);
foreach my $c (split(//, $str)) {
my ($repl, $repl_len);if($c eq '?' || $c eq '_' || $c eq '=' || $c lt ' ' || $c gt '~') {
$repl = sprintf("=X", ord($c));
$repl_len = 3;
}
elsif($c eq ' ') {
$repl = '_';
$repl_len = 1;
}
else {
$repl = $c;
$repl_len = 1;
}if($count + $repl_len > 72) {
$res .= "?=\r\n " . $begin;
$count = 1 + length($begin);
}$res .= $repl;
$count += $repl_len;
}
$res .= '?=';return $res;
}printf("[%s]\n", rfc2047conv("some very very long test subject = длинный тестовый сабжект", 'KOI8-R', length('Subject: ')));
>Накидал такую функцию, мои тесты она проходит. Лицензия - "все_пофиг" :)Добавил ее вместо MIME::Words.
огромное спасибо автору функции
искал именно что-то подобное и нашел в этом форуме
>огромное спасибо автору функции
>искал именно что-то подобное и нашел в этом форумеПроще взять из CPAN модуль
MIME::AltWords. Там попутно и другие ошибки поправлены.
Спасибо автору!
Полезная функция. Но
в процессе эксплуатации заметил, что при переносе длинных строк, символы на границе строк могут быть перенесены некорректно, иногда разбиваются по середине, и пол символа остается на одной строке, а вторая половина переносится на следую строку. Например, у меня была строка, в которой было слово 'найдено', и вот, как оно разбилось на части.
Буква 'д' , после кодирования должна превращаться в '=D0=B4' . Так вот '=D0' осталось на одной строке, а '=B4' перенеслось на следующую, и как следствие, при чтении этого письма в почтовом клиенте, вместо буквы д были два знака вопроса......=D0=BD=D0=B0=D0=B9=D0?=
=?UTF-8?Q?=B4=D0=B5=D0=BD=D0=BE=A?=