Письма от Moodle в кривой кодировке??
Moodle успешно работает уже более года. Как-то незаметно мы пересекли эту границу. За это время более-менее разобрались с основным функционалом, сейчас потихоньку работаем над увеличением предоставляемых возможностей и устранением имеющихся “шероховатостей”. Всё-таки это очень жизнеспособная платформа. Немного удивляют периодические предложения сделать из учебного портала гламурный сайт =) Почему-то забывают об общей концепции системы, её назначении, хотят из кареты сделать тыкву. От таких посягательств пока что успешно отбиваемся.
Хотя, положив руку на сердце, пора бы уже что-то решить с дизайном. Используемый стандартный шаблон давно отстал от современных требований эргономики. Не те цвета, не там кнопки, да и просто криво интерпретируется браузерами. Устарел он. Тут съехало, там поплыло.. и без валидатора всё понятно =)
Но это заметки на будущее. Сейчас разговор пойдёт об отправляемых системой Moodle письмах. А точнее их кодировке. Moodle может использовать оповещение пользователей учебного портала посредством электронной почты. Может это делать в зависимости от событий: размещение новых материалов в курсе, новости портала, новое личное сообщение в профиле. При этом может сыпать несколькими письмами, либо одним “дайджестом” за день. Всё логично.
Настраивается это в панели администрирования: Сервер ▶ Email и частично в профиле пользователя (если разрешите =). Всё очень грамотно раскидано. Кроме одного – пункт Character set (да-да, административная панель только на первый взгляд русифицированная).
Вроде присутствует UTF-8. В общем случае это означает, что не должно быть проблем с русским языком. Однако, всплыла проблема кривого отображения писем от учебного портала на базе Moodle в корпоративном веб-интерфейсе на базе OpenWebMail. При этом для отображения кириллицы интерфейс использует кодировку KOI8-r. Как вы думаете как выглядит UTF8-письмо в подобном интерфейсе?? Правильный ответ – криво. Будет время – выложу скрины.
Конечно, в OpenWebMail при просмотре тела письма присутствует преобразователь кодировки письма, но какому пользователю интересно вручную выбирать преобразование UTF-8 > KOI8-R?? Поверьте, ещё менее увлекательно объяснять это по телефону любознательным пользователям.
В общем-то понятно, что эта проблема настигает любой веб-интерфейс который отображается не в UTF-8. Например, много раз сталкивался с рекомендациями принудительно переводить RoundCube c UTF на CP1251. Да, там свой механизм конвертации, но всё-таки, надо осознавать зачем вы это делаете и чем это грозит. При этом стационарная почтовая программа-клиент (Thunderbird, TheBat, M2 OperaMail etc, Outlook etc) корректно распознают UTF и соответственно никаких проблем нет.
Логично, что стационарные клиенты без проблем разгребут и любую другую кодировку, а вот интерфейс будет корректно отображать исключительно письма в KOI8-R. Это ключевой момент в решении проблемы. Кодировка отправляемых учебным порталом Moodle писем должна быть KOI8-R. А в административной панели такого варианта нет =) В этом и засада.
Давайте разбираться. Возможные кодировки письма хранятся в переменной sitemailcharset. Разработчики Moodle хорошие люди, поэтому подписывают наклоненным мелким сереньким шрифтом имя переменной к каждому объекту интерфейса, содержащему сколь-нибудь значащие данные. Обычно немного ниже основной подписи к полю/форме/кнопке/списку. Эта фишка очень сильно упрощает жизнь, поэтому хорошо о ней знать и всегда помнить
Далее производим поиск по исходникам по вхождению sitemailcharset. Более всего меня заинтересовал файл lib/moodlelib.php. А именно код с достаточно красноречивыми комментариями:
/// If we are running under Unicode and sitemailcharset or allowusermailcharset are set, convert the email
/// encoding to the specified one
if ((!empty($CFG->sitemailcharset) || !empty($CFG->allowusermailcharset))) {
/// Set it to site mail charset
$charset = $CFG->sitemailcharset;
/// Overwrite it with the user mail charset
if (!empty($CFG->allowusermailcharset)) {
if ($useremailcharset = get_user_preferences('mailcharset', '0', $user->id)) {
$charset = $useremailcharset;
}
}
/// If it has changed, convert all the necessary strings
$charsets = get_list_of_charsets();
unset($charsets['UTF-8']);
if (in_array($charset, $charsets)) {
/// Save the new mail charset
$mail->CharSet = $charset;
/// And convert some strings
$mail->FromName = $textlib->convert($mail->FromName, 'utf-8', $mail->CharSet); //From Name
foreach ($mail->ReplyTo as $key => $rt) { //ReplyTo Names
$mail->ReplyTo[$key][1] = $textlib->convert($rt[1], 'utf-8', $mail->CharSet);
}
$mail->Subject = $textlib->convert($mail->Subject, 'utf-8', $mail->CharSet); //Subject
foreach ($mail->to as $key => $to) {
$mail->to[$key][1] = $textlib->convert($to[1], 'utf-8', $mail->CharSet); //To Names
}
$mail->Body = $textlib->convert($mail->Body, 'utf-8', $mail->CharSet); //Body
$mail->AltBody = $textlib->convert($mail->AltBody, 'utf-8', $mail->CharSet); //Subject
}
}
Последующий код не имеет значения для решения задачи. Отметим, что по умолчанию письма генерируются в UTF-8, затем выставленная кодировка (в административной панели или профиле пользователя, если разрешено) сверяется с массивом доступных кодировок $charsets и происходит конвертация.
Если Вы экстремал, можете втихую потрещать и кастрировать код прямо в функции convert, заменив $mail->CharSet на угодную кодировку (у вас должен отвалиться функционал выбора кодировки в административной панели). За результат не ручаюсь, я не отношу себя к экстремалам, поэтому обратил внимание на функцию get_list_of_charsets(). В этом же файле, только ниже.
Собственно, после незначительной правки функция приняла вид:
/**
* Returns a list of charset codes. It's hardcoded, so they should be added manually
* (cheking that such charset is supported by the texlib library!)
*
* @return array And associative array with contents in the form of charset => charset
*
* KOI8-R support for Moodle added and tested by www.it-mutant.ru
*/
function get_list_of_charsets() {
$charsets = array(
'EUC-JP' => 'EUC-JP',
'ISO-2022-JP'=> 'ISO-2022-JP',
'ISO-8859-1' => 'ISO-8859-1',
'SHIFT-JIS' => 'SHIFT-JIS',
'GB2312' => 'GB2312',
'GB18030' => 'GB18030', // gb18030 not supported by typo and mbstring
'UTF-8' => 'UTF-8',
'KOI8-R' => 'KOI8-R');
asort($charsets);
return $charsets;
}
Теперь лезем в админку и.. Чудо!! Появилась возможность выбрать кодировку KOI8-R для отправлемых писем =) С чего бы это
Работает железно. Судя из авторских комментариев крайне желательно чтобы добавляемая кодировка поддерживалась расширением mbstring (если у вас PHP < 5.0 – сочувствую, скорее всего вообще недоступно) и редактором typo. Если кого-то интересует CP1251 – не парьтесь, всё в норме. Насчет других – проверьте, мало ли.
Для проверки корректности работы я использовал внутреннюю систему сообщений Moodle, при этом не забудьте в профиле пользователя указать время после которого высылается сообщение (я поставил 1 минуту) и учтите что отсылка сработает по крону (который вы должны были установить для портала после установки
.
Если кто-то захочет набросать плагин для установки дополнительных кодировок на основе данной информации, дайте знать, можем потрудиться совместно