dnl dnl Проверка поля Content-Transfer-Encoding dnl в text/plain и text/html сообщениях dnl dnl для описания поведения MTA используется файл confCONFDIR/access-transfer-encodings dnl в нем хранится информация трех типов: dnl 1. какие charset'ы будут маскироваться звездочкой dnl 2. кодирование различных X-Mailer dnl 3. собственно правила для разных триплетов charset/transfer-encoding/mailer dnl dnl charset'ы указываются в виде: dnl charset=<название charset'а> dnl dnl например: dnl charset=koi8-r dnl charset=windows-1251 dnl dnl для сообщений с этими charset'ами будут использованы правила, у которых в качестве charset dnl будет указана звездочка. обычно необходимо перечислить все кириллические (8-битные) charset'ы dnl dnl значение полей X-Mailer кодируется в виде регулярного выражения с префиксом "mailer=": dnl \N^(?i)mailer=$\N : dnl dnl кодовое название мейлера mailer_name не должно содержать пробельных символов и символа ":" dnl dnl пример: dnl \N^(?i)mailer=SquirrelMail\s*\(.+\)$\N : squirrelmail dnl dnl т. е. для сообщений со значением X-Mailer, соответствующим регулярному выражению dnl /^SquirrelMail\s*\(.+\)$/, будут применяться все правила, у которых в триплете в качестве dnl mailer'а будет указано "squirrelmail" dnl dnl собственно, сами правила указываются в виде: dnl || : <действие> : <сообщение> dnl dnl 1. в качестве charset может быть указан либо конкретный charset, либо звездочка. тогда dnl правило будет применено для charset'ов, указанных с префиксом "charset=" dnl 2. в качестве transfer-encoding'а можно использовать "7bit", "8bit" или пустое значение, dnl которое воспринимается как отсутствие поля Content-Transfer-Encoding dnl 3. в качестве mailer'а указывается то кодовое название mailer'а, которое было описано с dnl префиксом "mailer=" dnl указание mailer'а может быть опущено вместе с предшествующим разделителем "|". тогда правило dnl будет применено ко сообщениям без учета поля X-Mailer dnl dnl в качестве "действия" могут выступать: dnl ok - принимать сообщения с данным transfer-encoding-ом dnl warn - добавлять в заголовки сообщения поле X-Warn-Charset dnl текст значения поля может быть указан через двоеточие dnl reject - не принимать сообщения с данным charset-ом dnl текст сообщения об ошибке может быть указан через двоеточие dnl deny - синоним для reject dnl fakereject - возврат отправителю ошибки 5xx с продолжением обработки сообщения dnl quarantine - сообщение будет сохранено в карантине и не будет доставлено получателю dnl dnl действие quarantine можно указывать вместе с reject или deny через пробел dnl dnl примеры: dnl dnl отвергнуть все сообщения с charset=windows-1251 и Content-Transfer-Encoding: 7bit dnl для остальных проверяемых charset-ов добавляется поле X-Warn-Encoding:, dnl кроме собщений, отосланных с помощью X-Mailer: PocoMail dnl \N^(?i)mailer=PocoMail\s.+$\N : pocomail dnl *|7bit|pocomail : ok dnl windows-1251|7bit : deny : 5.7.1 broken Content-Transfer-Encoding detected dnl *|7bit : warn dnl dnl отвергать все сообщения с charset=windows-1251 без поля Content-Transfer-Encoding dnl для остальных проверяемых charset-ов вставлять поле X-Warn-Encoding: со значением dnl этого поля по умолчанию dnl для сообщений с X-Mailer: SquirrelMail вставляется поле X-Warn-Encoding: с отдельным dnl значением dnl dnl \N^(?i)mailer=SquirrelMail\s*\(.+\)$\N : squirrelmail dnl *||squirrelmail : warn : squirrelmail does not add field Content-Transfer-Encoding :-( dnl windows-1251| : deny : 5.7.1 Content-Transfer-Encoding field expected dnl *| : warn : Content-Transfer-Encoding field expected dnl # Проверка поля Content-Transfer-Encoding # в text/plain и text/html сообщениях # правила приведены в access-transfer-encodings # извлекаем значение charset-а из поля Content-Type для text/plain и text/html сообщений warn set acl_m0 = ${lc:${if match{$header_Content-Type:}\ {\N(?i)^text\/(plain|html) *;[\r\n]*[\t ]*charset="?([a-z][a-z0-9\-]+)"?\N}\ {$2}{}}} # если charset определен, идем его в списке проверяемых warn condition = ${if eq{$acl_m0}{}{no}{yes}} set acl_m0 = ${lookup{charset=${lc:$acl_m0}}\ lsearch{CONFDIR/access-transfer-encodings}{$acl_m0}{}} # если charset определен, определяем mailer и ищем для него кодовое название warn condition = ${if eq{$acl_m0}{}{no}{yes}} set acl_m1 = ${lookup{mailer=$h_X-Mailer:}\ wildlsearch{CONFDIR/access-transfer-encodings}{$value}{\ ${lookup{mailer=$h_User-Agent:}\ wildlsearch{CONFDIR/access-transfer-encodings}{$value}{}}\ }} # если charset определен, ищем действие по триплету charset|transfer-encoding|mailer # порядок поиска: # charset|transfer-encoding|mailer # *|transfer-encoding|mailer # charset|transfer-encoding # *|transfer-encoding warn condition = ${if eq{$acl_m0}{}{no}{yes}} set acl_m1 = ${lookup{$acl_m0|$h_Content-Transfer-Encoding:|$acl_m1}\ lsearch{CONFDIR/access-transfer-encodings}{$value}{\ ${lookup{*|$h_Content-Transfer-Encoding:|$acl_m1}\ lsearch{CONFDIR/access-transfer-encodings}{$value}{\ ${lookup{$acl_m0|$h_Content-Transfer-Encoding:}\ lsearch{CONFDIR/access-transfer-encodings}{$value}{\ ${lookup{*|$h_Content-Transfer-Encoding:}\ lsearch{CONFDIR/access-transfer-encodings}{$value}{\ }}\ }}\ }}\ }} set acl_m2 = ${lc:${extract{1}{:}{$acl_m1}}} set acl_m2 = ${sg{${sg{$acl_m2}{\N^\s+\N}{}}}{\N\s*$\N}{}} set acl_m1 = ${extract{2}{:}{$acl_m1}} set acl_m1 = ${sg{${sg{$acl_m1}{\N^\s+\N}{}}}{\N\s*$\N}{}} # если для данного триплета выбрано действие warn warn condition = ${if eq{$acl_m0}{}{no}{yes}} condition = ${if eq{$acl_m2}{warn}{yes}{no}} log_message = ${if eq{$h_Content-Transfer-Encoding:}{}\ {Content-Transfer-Encoding field expected (charset: $acl_m0; X-Mailer: $header_X-Mailer:)}\ {broken Content-Transfer-Encoding detected (charset: $acl_m0; X-Mailer: $header_X-Mailer:)}\ } message = X-Warn-Encoding: \ ${if eq{$acl_m1}{}\ {${if eq{$h_Content-Transfer-Encoding:}{}\ {Content-Transfer-Encoding field expected}\ {broken Content-Transfer-Encoding detected}\ }}\ {${sg{$acl_m1}{\N^\d+\.\d+\.\d+\s*\N}{}}}\ } # если для данного триплета выбрано действие deny или reject без quarantine deny condition = ${if eq{$acl_m0}{}{no}{yes}} condition = ${if match{$acl_m2}{\N^.*(deny|reject)\N}{yes}{no}} condition = ${if eq{$acl_m2}{fakereject}{no}{yes}} condition = ${if match{$acl_m2}{\N^.*quarantine\N}{no}{yes}} log_message = ${if eq{$h_Content-Transfer-Encoding:}{}\ {Content-Transfer-Encoding field expected (charset: $acl_m0; X-Mailer: $header_X-Mailer:)}\ {broken Content-Transfer-Encoding detected (charset: $acl_m0;\ Content-Transfer-Encoding: $h_Content-Transfer-Encoding:; X-Mailer: $header_X-Mailer:)}\ } message = ${if eq{$acl_m1}{}\ {5.7.1 ${if eq{$h_Content-Transfer-Encoding:}{}\ {Content-Transfer-Encoding field expected}\ {broken Content-Transfer-Encoding detected}\ }}\ {$acl_m1}\ } (${message_id}) logwrite = original recipients: $recipients # если для данного триплета выбрано действие deny или reject с quarantine warn condition = ${if eq{$acl_m0}{}{no}{yes}} condition = ${if match{$acl_m2}{\N^.*(deny|reject)\N}{yes}{no}} condition = ${if eq{$acl_m2}{fakereject}{no}{yes}} condition = ${if match{$acl_m2}{\N^.*quarantine\N}{yes}{no}} control = fakereject/${if eq{$acl_m1}{}\ {5.7.1 ${if eq{$h_Content-Transfer-Encoding:}{}\ {Content-Transfer-Encoding field expected}\ {broken Content-Transfer-Encoding detected}\ }}\ {$acl_m1}\ } (${message_id}) log_message = message quarantined: ${if eq{$h_Content-Transfer-Encoding:}{}\ {Content-Transfer-Encoding field expected (charset: $acl_m0; X-Mailer: $header_X-Mailer:)}\ {broken Content-Transfer-Encoding detected (charset: $acl_m0;\ Content-Transfer-Encoding: $h_Content-Transfer-Encoding:; X-Mailer: $header_X-Mailer:)}\ } message = X-Quarantine-Encoding: \ ${if eq{$acl_m1}{}\ {${if eq{$h_Content-Transfer-Encoding:}{}\ {Content-Transfer-Encoding field expected}\ {broken Content-Transfer-Encoding detected}\ }}\ {${sg{$acl_m1}{\N^\d+\.\d+\.\d+\s*\N}{}}}\ } set acl_m17 = quarantined # если для данного триплета выбрано действие fakereject warn condition = ${if eq{$acl_m0}{}{no}{yes}} condition = ${if eq{$acl_m2}{fakereject}{yes}{no}} control = fakereject/${if eq{$acl_m1}{}\ {5.7.1 ${if eq{$h_Content-Transfer-Encoding:}{}\ {Content-Transfer-Encoding field expected}\ {broken Content-Transfer-Encoding detected}\ }}\ {$acl_m1}\ } (${message_id}) log_message = fakerejected: ${if eq{$h_Content-Transfer-Encoding:}{}\ {Content-Transfer-Encoding field expected (charset: $acl_m0; X-Mailer: $header_X-Mailer:)}\ {broken Content-Transfer-Encoding detected (charset: $acl_m0;\ Content-Transfer-Encoding: $h_Content-Transfer-Encoding:; X-Mailer: $header_X-Mailer:)}\ } message = X-Warn-Encoding: \ ${if eq{$acl_m1}{}\ {${if eq{$h_Content-Transfer-Encoding:}{}\ {Content-Transfer-Encoding field expected}\ {broken Content-Transfer-Encoding detected}\ }}\ {${sg{$acl_m1}{\N^\d+\.\d+\.\d+\s*\N}{}}}\ } logwrite = original recipients: $recipients # если для данного триплета выбрано действие quarantine без reject или deny warn condition = ${if eq{$acl_m0}{}{no}{yes}} condition = ${if match{$acl_m2}{\N^.*(deny|reject)\N}{no}{yes}} condition = ${if eq{$acl_m2}{quarantine}{yes}{no}} log_message = message quarantined: \ ${if eq{$h_Content-Transfer-Encoding:}{}\ {Content-Transfer-Encoding field expected (charset: $acl_m0; X-Mailer: $header_X-Mailer:)}\ {broken Content-Transfer-Encoding detected (charset: $acl_m0; X-Mailer: $header_X-Mailer:)}\ } message = X-Quarantine-Encoding: \ ${if eq{$acl_m1}{}\ {${if eq{$h_Content-Transfer-Encoding:}{}\ {Content-Transfer-Encoding field expected}\ {broken Content-Transfer-Encoding detected}\ }}\ {${sg{$acl_m1}{\N^\d+\.\d+\.\d+\s*\N}{}}}\ } set acl_m17 = quarantined