Email processing: различия между версиями

Материал из MoodleDocs
Перейти к:навигация, поиск
Нет описания правки
Строка 205: Строка 205:
[[Категория:Администратору]]
[[Категория:Администратору]]
[[Категория:Разработчику]]
[[Категория:Разработчику]]
[[en:Email processing]]

Версия от 17:29, 21 апреля 2010

Возможности

Moodle использует протокол SMTP для электронной почты и технологии, известной как Нефиксированный Путь Возвращения Посылки (VERP, Variable Envelope Return Path).

  • Работает на большинстве современных почтовых серверах (по крайней мере в системах UNIX).
  • Вся обработка возвратов и ответов защищаются с использованием HMAC-MD5-8.
  • Возвраты обрабатываются корректно, увеличивая счетчик "вредной почты" пользователя.
  • Теперь адрес noreply@host находится в поле Reply-to, исключая тем самым случайное {загрязнение} адресной книги пользователя.
  • noreply@host содержит автоответчик
  • Облегчает модулям посылку электронной почты с подписанным VERP reply-to.
  • Обработка получения VERP-ответов: проверка правильности подписи HMAC-MD5-8 и отправка зашифрованных данных соответствующему модулю

Конфигурация Moodle

Стандартные настройки php для почты

Unix и некоторые другие платформы могут использовать стандартную php-ю программу электронной почты. Почтовая программа может использовать файл config.php для установки строки from всех исходящих писем. Однако спам-фильтры не будут анализировать письма с IP в поле from, а сразу отправят их в папку для спама. Поэтому замените %CFG->wwwroot на зарегистрированный DNS-адрес. Например:

$CFG->wwwroot ='http://192.168.0.1/Moodle' ;

можно заменить на:

$CFG->wwwroot ='http://www.mydomain.org/Moodle' ;


Активация обработки возвратов

Отредактируйте config.php для активации обработки возвратов, и сконфигурируйте Moodle так, чтобы он соответствовал конфигурации почтового сервера. Ниже показано, как. Раскомментируйте эти строки в config.php (если Вы не можете найти их, то скопируйте из config-dist.php):

// как только handlebounces станет true, мы будем использовать VERP, как адрес возврата для каждого отправленного письма
$CFG->handlebounces = true;
// допускаемый минимум возвратов на одного пользователя
$CFG->minbounces = 10;
// отношение плохих сообщений к общему количеству посланных
// если мы получим больше 20% возвратов
// для конкретного пользователя, его/ее письмо будет помечено, как плохое
$CFG->bounceratio = .20;
// Префикс для идентификации Вашего сайта ДОЛЖЕН СОДЕРЖАТЬ РОВНО 3 символа
$CFG->mailprefix = 'mdl';
// Домен, принимающий электронную почту для обработки
$CFG->maildomain = 'bounces.my.domain';

Отредактируйте строку $CFG->maildomain и одну из строк $CFG->mailprefix (ту, которая соответствует Вашему почтовому серверу).

Убедитесь, что у Вашего сервера есть PHP-интерпретатор командной строки, и что он может подключиться к mysql (или postgre, если используется он). Если Вы можете запустить cron.php из командной строки или его вкладки, то с PHP все в порядке.

Отредактируйте скрипт process_email.php так, чтобы он указывал путь к бинарнику Вашего php. Обычно это /usr/bin/php.

Почтовые слова для подтверждения и регистрации и их редактирование.

  • Студенты получают сообщение о необходимости подтверждения регистрации после создания учетной записи. Его текст можно найти в файле lang/?/moodle.php как "переменную" emailconfirmation.
  • Студенты получают сообщение приветствия, когда они регистрируются на курсе. Его текст можно найти в файле lang/?/moodle.php как "переменную" welcometocoursetext.
  • Если Вы чувствуете необходимость отредактировать этот текст, лучше всего можно сделать это, зайдя в Администрирование Сайта -> Редактирование Языков (Site Administration -> Language editing) и кликнув на необходимой строке. Как только Вы сделаете это, нажмите "Переключить каталог языка" ("Switch lang directory") и осуществите Вашу правку.
  • Если же Вам очень хочется сделать все вручную, с помощью редактирования moodle.php - будьте внимательны, открывайте этот файл только в простых текстовых редакторах типа Блокнот или Wordpad.
  • Совет: будьте внимательны с разметкой - во время редактирования Вам может понадобиться использовать " ", например, в гиперссылках, заголовках и адресатах. Вы ДОЛЖНЫ экранировать их вставкой \ перед каждой ". Если Вы не будете этого делать, результирующая страница окажется пустой. Например, гиперссылки обычно размечаются так:
    • <a href="http://www.blah_blah">кликните здесь</a> Если Вы сделаете так в moodle.php, то отредактированный Вами текст не появится.
    • Используйте <a href=\"http://www.blah_blah\">кликните здесь</a>
  • Используйте \ перед каждой " когда размечаете что-то типа target=\"_blank\" и title=\"Бла бла\" и другой подобный код.
  • Если Вам кажется, что действительно необходимо отредактировать moodle.php вручную, сделайте копию файла в его собственном каталоге (скопируйте и вставьте файл в одном и том же каталоге. В случае, если что-то пойдет не так, все, что надо сделать - удалить испорченный файл и переименовать 'Копия moodle.php' ('copy of moodle.php') обратно в 'moodle.php' и Вы вернетесь в начальное состояния без каких-либо проблем).
  • Подытожив все сказанное выше, наилучшим способом осуществить все необходимое редактирование является использование web-интерфейса, зайдя в Администрирование Сайта -> Редактирование Языков (Site Administration -> Language editing), и нажав там на строке, которую необходимо изменить.
Ошибка создания миниатюры: Не удаётся сохранить эскиз по месту назначения

Установка под Postfix

Добавьте строку к Вашему файлу псевдонимов. Это строка должна содержать трехбуквенный префикс, к которому добавляется '|' и путь к скрипту. Например, для префикса 'mdl' и moodle'а, установленного в /var/www/moodle, мы имеем в файле псевдонимов:

   mdl:     |/var/www/moodle/admin/process_email.php
   noreply: |/var/www/moodle/admin/process_email.php

Если Вы используйте виртуальные домены, проконсультируйтесь с администратором Вашего сервера насчет правильного конфигурирования. Скорее всего, оно будет связано с редактированием транспортов и отображением Вашего адреса на один из "канальных" транспортов.

Установка под Qmail

В зависимости от Вашей конфигурации, Ваши псевдонимы будут контролироваться одним из

  • /etc/aliases
  • /var/qmail/alias/.qmail-PREFIX

При редактировании /etc/aliases добавьте строку типа этой (для префикса 'mdl'):

   mdl:     |/var/www/moodle/admin/process_email.php
   noreply: |/var/www/moodle/admin/process_email.php

Если Вы создаете /var/qmail/alias/.qmail-PREFIX, просто сделайте

 echo "|/var/www/moodle/admin/process_email.php" > /var/qmail/alias/.qmail-mdl
 echo "|/var/www/moodle/admin/process_email.php" > /var/qmail/alias/.qmail-noreply

К трехсимвольному префиксу мы добавляем '-' при отправке и приеме сообщений. Детальнее об этом можно прочесть в руководстве по dot-qmail.

Установка под Exim

Откройте /etc/exim/exim.conf и добавьте к trusted_users пользователя Apache и cron.php, запускаемый как (обычно "www-data" или "nobody").

Добавьте строку к Вашему файлу псевдонимов. Это строка должна содержать трехбуквенный префикс, к которому добавляется '+' и путь к скрипту. Например, для префикса 'mdl' мы имеем в файле псевдонимов:

   mdl:     |/var/www/moodle/admin/process_email.php
   noreply: |/var/www/moodle/admin/process_email.php

Если Вы используйте виртуальные домены, проконсультируйтесь с администратором Вашего сервера насчет правильного конфигурирования. Скорее всего, оно будет связано с редактированием транспортов и отображением Вашего адреса на один из "канальных" транспортов.

Дополнительную документацию по Exim можно найти здесь.

Вы скорее всего должны будете заставить Exim не преобразовывать строки в локальной части Вашей конфигурации exim'а в нижний регистр. Это можно сделать в маршрутизаторе, который обрабатывает почту для Вашего файла псевдонимов, с помощью: caseful_local_part = true

Информация для разработчиков

Изменения в функциях:

  • email_to_user() устанавливает отправителя посылки в специально обрабатываемый адрес возврата (основанный на параметрах $CFG)
  • email_to_user() принимает (и устанавливает) заголовок reply-to, генерируемый вызывающим функцию модулем.
  • изменения/дополнения в связанных строках

Новые функции:

  • generate_email_processing_address() - ВСЕГДА используйте ее для генерации заголовка reply-to. Заголовок reply-to выглядит примерно так: (ЛИМИТ: всего 64 символа) префикс - РОВНО 4 кодированных символа, флаг упаковки, id модуля [moduleid] (0 для ядра) (2 символа), до 42 символов для модулей для размещения всего, что они захотят (может содержать id пользователя [userid] (или, например для форума, id постов [postids] для ответа), или что-нибудь еще, 42 символа - это действительно АБСОЛЮТНЫЙ ЛИМИТ) 16-символьный хеш (половина md5) первой части адреса вместе с "секретным значением" сайта
  • moodle_process_email() - любая внемодульная обработка почты происходит здесь (в настоящее время используется для обработки возвратов)

Новые файлы:

admin/process_email.php

Этот скрипт необходимо вызывать Вашим почтовым сервером для всего, что начинается с 3-символьного префикса, описанного выше (и, опционально, для адреса noreply).

Как он работает? Скрипт разбивает и декодирует email-адрес в id модуля, проверяет половину md5-хеша и вызывает $modname_process_email (если он существует). Аргументы этой функции: $modargs (любая часть email-адреса, не являющаяся префиксом, id модуля или хешем) и содержимое email'а (читается из STDIN).

Письмо дублируется автоответчиком для адреса noreply, если Вы также сконфигурировали его для этого адреса. Отвечающим дружелюбным сообщением "данный адрес электронной почты не существует".

Авторам Модулей

Изучите новые функции moodle_process_email() и generate_email_processing_address() в moodlelib.php на предмет того, как

  • кодировать и декодировать аргументы, которые должен обрабатывать Ваш модуль
  • что делать со множественными "действиями" для любого имеющегося модуля.

Пользователи могут отправлять письма Moodle'у из nutshell'а, используя специальные динамические адреса. Эти письма могут вызвать обращение к функции модуля в форме modulename_process_email($str, $bodyofemail). Частью $str будет до 42 символа данных, сгенерированных Moodle'ом (скорее всего Вашим собственным модулем), а часть $bodyofemail является содержимым письма (полученного путем чтения STDIN - обычно генерируемых с помощью пользовательских MUA).

42 символа берутся из "локальной части" адреса письма (часть до знака @), который может быть длиною до 64 символов. Из этих 64 символов Moodle использует 22, оставляя Вам 42 для кодирования данных.

Как используются эти 22 символа? Четыре идет на префикс, с помощью которого почтовый сервер определяет, что он должен отправить письмо нашему скрипту. Два используются для идентификации ID модуля, благодаря чему становится ясно, какой из модулей сгенерировал сообщение (и таким образом запрос перенаправляется этому модулю). Оставшиеся 16 - это сигнатура (HMAC-MD5-8), которая используется для подтверждения подлинности сообщения.

Сорок два символа - немного (хотя и достаточно, чтобы стать ответом жизни, Вселенной и всему!), поэтому убедитесь, что Вы используйте их мудро.

Самый эффективный найденный нами способ закодировать полный диапазон идентификаторов базы данных (чтобы разместить их в адресе электронной почты) является base64_encode(pack('V',2147483647)), возвращающее "////fw==". Два конечных "==" являются избыточными и Вы можете отбросить их (Вы должны будете повторно добавить их после извлечения Ваших данных). Для повышения эффективности присоединяйте Ваши параметры как закодированные идентификаторы в позиционные слоты.

При извлечении Ваших данных используйте substr() для их разделения, а следом - unpack('V',base64_decode($str)). Заметьте, что будет возвращен одноэлементный массив.

Помните:

Использование 'V' устанавливает предел 2147483647, половину диапазона INT mySQL'а. Еще 'V' ведет себя как знаковое значение, вместо того, чтобы быть беззнаковым, поэтому я подозреваю наличие ошибки в документации PHP по pack() (проблема, видимо, в том, что в pack() поступают значения, уже переведенные во внутреннем формате в php'ный int, а он как раз себя так и ведет, как UINT может вести себя php'ный float или string- прим. перев.).

С каждым ID'ом, использующим 6 символов (8, если будет найден путь использовать весь диапазон 'V'), имеется ограниченное число параметров. Если необходимо закодировать больше информации, сохраните ее в БД и отправьте письмо, указывающее на сохраненные данные. Помните про необходимость очищать эти временные данные после безопасного промежутка времени.

Помните:

Не пытайтесь использовать кодирование переменной длины для размещения ID'ов, т.к. срабатывая на малых инсталляциях, оно приводит к ошибкам на больших.

Проблемы безопасности

Любой код в modulename_process_email() ДОЛЖЕН иметь возможность приема повторных ответов и изящную их обработку. Определение 'изящную' зависит от того, что делает код.

Серверы электронной почты (MTA) могут иногда повторно отправлять письмо, если будут неуверенны, что принимающий MTA получил его - и сисадмины могут иногда переотправлять целую почтовую очередь, если что-то пошло не так. В этом случае тело этих писем будет идентично, немного отличаясь заголовками.

В некоторых случаях пользователь может 'ответить' на письмо дважды. Возможно по ошибке, возможно специально. Что делать, зависит от определенного сценария.

Мы /могли/ поддерживать лучшую защищенность на уровне оболочки, отслеживая каждый отсылаемый нами reply-to адрес. Однако мы решили отказаться от этого, потому что (а) воздействие на производительность может быть весомо (б) мы хотим, чтобы первый слой было легко и просто изменить в случае, если нам это понадобится.

Поэтому модули в первоначальной реализации должны предоставлять функции, которые корректно обрабатывают подобные 'ответы'. Если позже мы захотим предоставить дополнительные функции, мы можем добавить такое отслеживание, как опциональную возможность. Было бы ужасно получать все это из всех писем, отправляемых Moodle'ом.

Экспериментальная обработка почты, ожидаемая в 1.9/2.0

Авторам Модулей

Интерфейс электронной почты предоставляет возможность позволить пользователям отвечать на письма, посланные через Ваш модуль и затрагивающие изменения в нем. Основная идея - каждое письмо однозначно связано с почтовой сессией, которая переносит в нем полезную информацию. Эта полезная информация хранится в БД и не может быть изменена пользователем. Ответы обрабатываются модульным кодом Вашей lib.php библиотеки - modulename_process_email($payload, $body) - которому передается полезная информация сессии и тело полученного сообщения (вместе с заголовками), для предпочитаемого Вами парсинга. Для облегчения этой операции доступны некоторые вспомогательные функции.

Вот примерная схема использования:

  • Перед отправкой письма пользователю с помощью функции email_to_user() модуль должен проверить, активирована ли конфигурационная переменная $CFG->emailinterface. (По умолчанию ее значение - off)
  • После проверки доступности почтового интерфейса следует вызвать функцию generate_email_verp_address($moduleid, $payload, $userid) для создания "почтовой сессии". Полезная информация может включать любые данные, которые необходимо использовать в Вашей процедуре обработки, такие, как id пользователя, или с какой частью интерфейса он взаимодействует. Функция возвращает строку, содержащую id сессии данного письма.
  • Далее следует обычный вызов email_to_user(), где в качестве 11 параметра используется id сессии. Имейте в виду, что Вам вероятно также может потребоваться изменить текст или html письма, чтобы указать, что активирован почтовый интерфейс.
  • Должна быть написана функция с именем [modulename]_process_email($payload, $body), которая будет находится в файле lib.php Вашего модуля. Эта функция является обработчиком, который вызывается, когда получен ответ на письмо. Это функция может просматривать содержимое полезной информации из полученного письма, а потом парсить его тело для извлечения данных. Параметр $body содержит все письмо, включая заголовки.

Следует отметить, что на каждое электронное письмо можно ответить лишь один раз - e-mail сессия будет уничтожена после получения письма. Если есть желание получать многократные ответы от пользователя, можно каждый раз создавать новую сессию (и новое письмо). Таблица сессий электронной почты также регулярно очищается, настройки по умолчанию позволяют сессиям храниться в течении одного месяца.

Также в admin/process_email.php определены такие полезные сервисные функции:

  • get_email_subject($fullemail) - возвращает тему письма
  • strip_email_headers($fullemail) - извлекает все заголовки из письма
  • email_is_multipart($fullemail) - определяет, является ли письмо многослойным сообщением
  • seperate_multipart($multipartmsg) - разбивает многослойное сообщение в массив частей, каждая из которых имеет заголовок и тело.
  • get_multipart_content_type($part) - определяет тип содержимого многослойного сообщения, обычно text/plain или text/html.
  • multipart_is_quoted_printable($part) - определяет, было ли часть многослойного письма закодирована с применением кавычко-печатаемого кодирования - некоторые почтовые клиенты имеют тенденцию делать это с html.
  • decode_quoted_printable($partdata) - декодирует письмо, закодированное с использованием кавычко-печатаемого кодирования - это необходимо выполнить для секции данных части многослойного письма (strip_email_headers можно использовать для отделения её заголовков).
  • strip_email_reply($body, $ishtml, $identifier) - извлекает все несоответствующие строки письма, основанного на уникальном идентификаторе, внедренном в оригинальное письмо. Это используется для определения того, что является пользовательским вводом, а что - несоответствующими данными, добавленными почтовым клиентом.
  • strip_email_reply_multi($body, $ishtml, $identifier) - то же, только учитываются возможную многократность секций пользовательского ввода в одном письме.

Примеры использования этих функций можно увидеть в обработчике в модуле форума. Следующей после обработки ответа функциями извлечения заголовков идеей являет то, что оригинально письмо содержит уникальный идентификатор, такой, как строка из 10 случайных символов. Он внедряется в строку с инструкциями для пользователя, говорящими, что писать необходимо между ними, например:

 \/ Please put your response here [ABCDEFGHIJ] \/
 <Пользовательские данные>
 /\ Please put your response here [ABCDEFGHIJ] /\

Это необходимо из-за большого различия между web-почтой и почтовыми клиентами при обработке кавычек и приписываемых к письму-ответу даты/времени. Имейте в виду, что у текстовых электронных писем есть 80-символьное ограничение ширины строки, которое должно также включать кавычку, добавленную почтовым клиентом, таким образом любая строка текстового электронного письма с этим идентификатором должна быть сохранена по крайней мере в 77 символах, чтобы избежать ее обрезания почтовым клиентом. Этот уникальный идентификатор может быть легко сохранен, как полезная информация. Многократные секции ввода обрабатываются так же - в конец идентификатора добавляется число, например [ABCDEFGHIJ1] для указания первой секции ввода. Функция strip_email_reply_multi возвращает массив, содержащий отображение каждой пронумерованной секции, найденной ею, на строку, содержащую данные это секции.

Информация для разработчика

Заголовок reply-to теперь кодируется с помощью base32 вместо base64, чтобы учесть регистро-нечувствительные почтовые сервера. Функция generate_email_processing_address оставили, как заглушку для обратной совместимости, теперь вместо нее модули должны использовать функцию generate_email_verp_address.

Почтовые сессии были созданы так, чтобы иметь дело с нехваткой доступного для закодированного base32 заголовка пространства, полезная информация хранится в новой таблице mdl_email_sessions, и идентифицируется уникальным base32 ключом, который внедряется в заголовок reply-to. Каждая запись имеет timestamp, и таблица сокращается во время очистки cron'а в admin/cron.php.

Обнаружение возвратов теперь объединено с почтовым интерфейсом - оно включено в admin/process_email.php. Также, чтобы помочь в настройке этих изменений, были введены некоторые новые конфигурационные переменные - $CFG->emailinterface и $CFG->emailsessiontime - обе добавлены в конфигурацию сервера страницы администратора.