Информация
На главную Главная

Мой t-cards.ru
Войти Войти
Зарегистрироваться Регистрация

Разное
Форум Форум
Вернуться Форумы на t-cards.ru> Hard"n"Soft
Логин
Пароль
Регистрация Участники Поиск >> FAQ


Сообщения в теме: "Exim - сортировка писем "на лету" по папкам IMAP п..."
10.04.2006 11:53
Admin

Регистрация: 05.10.2005
Проживание: Москва
Сообщения: 284
По умолчаниюExim - сортировка писем "на лету" по папкам IMAP по пользовательским правилам

Таак. Здесь опишу процесс настройки доставки писем прямо в указанные папки.

1. Заводим в базе 2 дополнительные таблицы для хранения правил, там будут типы правил и сами правила. Типов пока 4 - по заголовкам from, to и subject и еще по пометке "спам" (скрипты дл создания в следующем посте). Описание таблицы юзеров (dbmail_users) не привожу, ранее писал про нее, она используется в запросе.

2. Переходим к настройке exim. Первое, что надо сделать, это сделать так, чтоб после завершения процесса проверки письма при переходе его в состояние локальной доставки сохранились значения заголовков From: To: Subject:. Для этого используем глобальные переменные типа $acl_cx (x - от 0 до 9, итого 10 переменных можно заюзать). В цепочке "acl_check_message:" запомним эти переменные (перекодируя заголовки в нормальный вид перловой функцией header_decode, описание которой есть в предыдущем посте про перл).
warn message =
set acl_c0 = ${perl{header_decode}{$rheader_from:}}
set acl_c1 = ${perl{header_decode}{$rheader_to:}}
set acl_c2 = ${perl{header_decode}{$rheader_subject:}}
set acl_c3 = $spam_score_int

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

address_delivery1:
driver = appendfile
create_directory = true
directory_mode = 700
directory = /var/mail/${domain}/${local_part}/${lookup mysql{SELECT r.folder FROM rules r INNER JOIN dbmail_users u ON r.user_id = u.id INNER JOIN rules_types rt ON rt.id = r.type WHERE lower(u.userid) = lower("$local_part") AND lower(u.domen) = lower("$domain") AND ((rt.type = "from" AND "${sg {$acl_c0}{"}{""}}" LIKE CONCAT("%",r.val,"%")) OR (rt.type = "to" AND "${sg {$acl_c1}{"}{""}}" LIKE CONCAT("%",r.val,"%")) OR (rt.type = "subject" AND "${sg {$acl_c2}{"}{""}}" LIKE CONCAT("%",r.val,"%")) OR (rt.type = "spam" AND CAST("$acl_c3" AS SIGNED) >= r.val)) ORDER BY r.ord LIMIT 1}}
user = mail
group = mail
delivery_date_add
envelope_to_add
return_path_add
maildir_format = true
mode = 660

Пусть не пугает сложность запроса - ничего сложного нет, общий смысл - если подпало под какое-нить правило письмо согласно заголовкам, то запрос выберет имя папки, если нет - выберет NULL и письмо придет в INBOX.
Можно было вместо LIKE заюзать RLIKE и искать совпадение по регулярному выражению, но сделано LIKE с учетом того, что пользователи смогут через веб редактировать свои правила сами, и они же не знают что есть регулярное выражение.
Если папка не существует - она будет создана, но потом пользователю надо будет на нее подписаться.

3. Ну вот в принципе и все, остается теперь пользователям заводить свои правила в базу, для этого можно либо веб-морду написать, либо еще что... А, важный момент - в базу имя папки должно уже попадать в закодированном виде. По стандарту - это жутчайшее сочетание utf7 и utf16, функция для кодировки в посте ниже (пример мой на пхп).
10.04.2006 11:53
Admin

Регистрация: 05.10.2005
Проживание: Москва
Сообщения: 284
По умолчаниюExim - сортировка писем "на лету" по папкам IMAP по пользовательским правилам

Заполнение БД:

CREATE TABLE `rules` (
`id` int(11) NOT NULL auto_increment,
`user_id` int(11) default NULL,
`type` int(11) default NULL,
`val` varchar(255) default NULL,
`folder` varchar(255) default NULL,
`ord` int(11) default "1",
PRIMARY KEY (`id`),
KEY `user_id_ord` (`user_id`,`ord`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1

CREATE TABLE `rules_types` (
`id` int(11) NOT NULL auto_increment,
`type` varchar(10) default NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1

INSERT rules_types (type) SELECT "from"
INSERT rules_types (type) SELECT "to"
INSERT rules_types (type) SELECT "subject"
INSERT rules_types (type) SELECT "spam"
10.04.2006 11:54
Admin

Регистрация: 05.10.2005
Проживание: Москва
Сообщения: 284
По умолчаниюExim - сортировка писем "на лету" по папкам IMAP по пользовательским правилам

Функция на php для кодировки имени папки в соответствии со стандартом:

function folder_encode($str){
$str_ar = explode(".",$str);
$res_arr = array();
foreach ($str_ar as $val){
$res_arr[] = str_replace("+","&",imap_utf7_encode(mb_convert_encoding($val,"UTF-7","windows-1251")));
}
return implode(".",$res_arr);
}


И до кучи - функции для раскодтировки папки обратно в нормальный вид (глотает заглавную букву "Р", не могу ничего с этим поделать

function folder_decode($str){
$str_decoded = imap_utf7_decode($str);
$str_ar = explode(".",$str_decoded);
foreach ($str_ar as $key=>$val){
$ar = explode(" ", $val);
foreach ($ar as $key1=>$val1) {
if (strcasecmp(trim(mb_detect_encoding($val1)), "UTF-8") == 0) {
$ar[$key1] = mb_convert_encoding($val1,"windows-1251", "UTF-16");
}
else {
$ar[$key1] = $val1;
}
}
$str_ar[$key] = implode(" ", $ar);
}
return implode(".",$str_ar);
}