Перевод выполнен Алексеем Паутовым в рамках некоммерческого проекта RussianLDP (http://www.rldp.ru/). Именно на этом сайте и надлежит искать новые версии, если таковые будут.
Многие конфигурационные опции Exim содержат списки доменов, узлов, email-адресов или локальных частей почтового адреса. Например, опция hold_domains содержит список доменов, для которых доставка на данный момент временно приостановлена. Эти списки также используются как данные в списках управления доступом (см. главу 39) и как параметры к условиям раскрытия, типа match_domain.
Каждый элемент в одном из этих списков шаблон, проверяемый на соответствие домену, узлу, email-адресу или локальной части почтового адреса, соответственно. В секциях ниже описаны различные типы шаблонов для каждого случая, но сначала мы затронем некоторые общие средства, которые применяются для всех четырех типов списков.
Каждый список раскрывается как одиночная строка перед использованием. Результатом раскрытия должен быть список, возможно, содержащий пустые элементы, разделённый на отдельные элементы для совпадения. По умолчанию символ-разделитель двоеточие, но в случае необходимости он может быть изменён. Смотрите разделы 6.19 и 6.20 для деталей о синтаксисе списка: по второй ссылке обсуждается способ определения пустых элементов списка.
При неудачном раскрытии строки Exim ведет себя так, будто тестируемый элемент (домен, узел, адрес или локальная часть почтового адреса) не в списке. Другие отказы раскрытия приводят к временным ошибкам.
Если элемент списка регулярное выражение, знак обратного слэша, знак доллара и, возможно, другой спецсимвол в выражении, он должен быть защищен от неправильной интерпретации функцией раскрытия. Самый простой способ это сделать: использовать особенность раскрытия \N, чтобы обозначить, что содержимое регулярного выражения не должно раскрываться. Например, в списке управления доступом Вы можете указать:
deny senders = \N^\d{8}\w@.*\.baddomain\.example$\N : \ ${lookup{$domain}lsearch{/badsenders/bydomain}} |
Первый элемент это регулярное выражение, защищенное от раскрытия указанием \N, а второй использует раскрытие для получения списка нежелательных отправителей на основе домена получателя.
Элемент в списке может быть положительным или отрицательным. Отрицательные элементы идентифицируются предшествующим знаком восклицания, за которым может следовать пробел. Список определяет набор элементов. Когда Exim обрабатывает один из этих списков, он пытается найти домен, узел, адрес или локалую часть почтового адреса в наборе, определенном списком. Это работает так:
Список сканируется слева направо. Если совпадает положительный элемент, проверяется, установлена ли тема: если совпадает отрицательный, тема не устанавливается. Если достигнут конец списка и не было совпадения темы ни с одним шаблоном, она устанавливается в последний элемент списка, если последний элемент был отрицательным, либо не устанавливается, если он был положительным.
domainlist relay_domains = !a.b.c : *.b.c |
domainlist relay_domains = !a.b.c |
Другой способ подумать о положительных и отрицательных элементах списков: это читать соединитель как "или" после положительных элементов и как "и" после отрицательных.
Если элемент списка доменов, хостов, адресов или локальных частей почтового адреса является абсолютным именем файла (начинается со знака слеша), каждая строка файла читается и обрабатывается так, как если бы это был независимый элемент списка, за исключением того, что не допускаются дальнейшие имена файлов, раскрытие данных из файла не происходит. Пустые строки файла игнорируются, файл также может содержать строки комментариев:
not#comment@x.y.z # but this is a comment |
Указание имени файла в списке имеет такой эффект, как вставка каждой строки файла в качестве элемента в список (пустые строки и комментарии исключаются). Тем не менее есть одно важное отличие: файл читается при каждой обработке списка, таким образом, если его содержимое периодически меняется, изменяется и поведение Exim.
Если имени файла предшествует восклицательный знак, значение любых совпадений с файлом инвертируется. Например, если:
hold_domains = !/etc/nohold-domains |
!a.b.c *.b.c |
Как будет описано в следующих секциях, поиски могут использоваться в списках для обеспечения индексированных методов проверки списка членов. Было некоторое количество путанницы о способе работы lsearch со списками. Поскольку файл lsearch содержит простой текст и сканируется последовательно, то некоторые думают, что в него можно ставить групповые символы и другие переменные шаблоны. Это не так. Ключи в файле lsearch всегда фиксированные строки так же, как и для любого другого одноключевого поиска.
Если Вы хотите использовать файл, содержащий подстановочные шаблоны, являющиеся частью списка, просто дайте самостоятельное имя файла без типа поиска, как описано в предыдущей секции.
Списку доменов, хостов, e-mail-адресов или локальных частей адреса можно дать название, которое используется для обращения к списку в другом месте конфигурации. Это особенно удобно, если один и тот же список нужно использовать в нескольких различных местах. Например, часто задают спосок доменов, называемый local_domains, для всех локальных доменов, обрабатываемых на этой машине с использованием конфигурационной строки типа:
domainlist local_domains = localhost:my.dom.example |
На именованный список можно ссылаться, давая его имя с предшествующим ему знаком +, например, роутер, предназначенный для обработки локальных доменов, был бы сконфигурирован со строкой:
domains = +local_domains |
Первый роутер в конфигурации обычно тот, который обрабатывает все домены, кроме локальных, используя конфигурацию с инвертированным элементом, как этот:
dnslookup: driver = dnslookup domains = ! +local_domains transport = remote_smtp no_more |
Четыре вида именованных списков создаются конфигурационными строками, начинающимися со слов domainlist, hostlist, addresslist или localpartlist, соответственно. Задаваемые Вами списки помещайте после них. Например:
hostlist relay_hosts = 192.168.23.0/24 : my.friend.example addresslist bad_senders = cdb;/etc/badsenders |
Именованный список может обращаться к другим именованным спискам:
domainlist dom1 = first.example : second.example domainlist dom2 = +dom1 : third.example domainlist dom3 = fourth.example : +dom2 : fifth.example |
Внимание: Если последний элемент в списке на который ссылаются, отрицательный (инвертированный), то может быть вовсе не тот эффект, который Вы ожидали, поскольку отрицание не передаётся на следующий (более высокий) уровень. Например, рассмотрите:
domainlist dom1 = !a.b domainlist dom2 = +dom1 : *.b |
Второй список задан в списке dom1 или *.b. Первый список задаёт только не a.b, таким образом, домен x.y совпадает с ним. Это означает, что он также соответствует и второму списку. Эффект не такой же, как:
domainlist dom2 = !a.b : *.b |
domains = +local_domains |
По умолчанию может быть до 16 именованных списков каждого типа. Этот предел может быть увеличен изменением компиляционной переменной. Использование списков хостов и доменов рекомендуется для концепции типа локальных доменов, релейных доменов и релейных хостов. В конфигурации по умолчанию так и установлено.
На первый взгляд, как могло бы показаться, в файле конфигурации именованные списки неотличимы от макросов. Однако, макрос лишь текстовая замена. Если Вы напишете:
ALIST = host1 : host2 auth_advertise_hosts = !ALIST |
auth_advertise_hosts = !host1 : host2 |
Заметьте, что второе имя хоста не инвертировано. Однако, если Вы используете список хостов и напишете:
hostlist alist = host1 : host2 auth_advertise_hosts = ! +alist |
auth_advertise_hosts = !host1 : !host2 |
При обработке сообщения exim кэширует результат проверки именованного списка, если есть уверенность, что список статический. Практически это означает, что кэширование работает только, если список не содержит символов $, что гарантирует, что список не будет изменяться при раскрытии. Однако, иногда Вы можете иметь раскрываемый список, про который знаете, что это в пределах одного сообщения будет тот же самый список при каждой проверке. Например:
domainlist special_domains = \ ${lookup{$sender_host_address}cdb{/some/file}} |
Это обеспечивает список доменов, который зависит лишь от IP-адреса хоста отправителя. Если этот список доменов используется неоднократно (например, в нескольких строках ACL или в нескольких роутерах), по умолчанию результат не кэшируется, поскольку exim не знает, что каждую проверку это будет один и тот же список.
Добавив _cache к domainlist, Вы можете сказать exim, что результат можно кэшировать. Например:
domainlist_cache special_domains = ${lookup{... |
Если Вы сделаете это, то должны быть абсолютно уверены, что кэшированный результат будет верен во всех случаях. Если сомневаетесь, не делайте этого.
Списки доменов содержат шаблоны, не совпадающие с почтовыми доменами. Следующие типы элементов могут использоваться в списках доменов:
Поиск MX, соответствующей образцу, выполняется с опциями ресолвера для отключения раскрытия имён. Таким образом, например, однокомпонентный домен не будет раскрыт ресолвером добавлением домена по умолчанию. Смотрите опции qualify_single и search_parents роутера dnslookup для подробной информации о раскрытии домена.
Иногда можно игнорировать определённые IP-адреса при использовании одного из этих шаблонов. Вы можете задать их сразу за образцом при помощи /ignore=<ip list>, где <ip list> список IP-адресов. При обработке шаблона эти адреса игнорируются (сравните с опцией ignore_target_hosts в роутере). Например:
domains = @mx_any/ignore=127.0.0.1 |
Этот пример совпадает с любым доменом, имеющим MX-запись, указывающую на один из IP-адресов локальной машины, за исключением 127.0.0.1.
Список IP-адресов обрабатывается тем же самым кодом, который обрабатывает список хостов, таким образом тут можно писать сети в виде CIDR, а также тут могут находится негативные элементы.
Поскольку список IP-адресов является подсписком внутри списка доменов, Вы должны быть осторожны при использовании разделителей, если тут больше одного адреса. Как и в любом другом списке, разделитель по умолчанию может быть заменён. Таким образом, можно сделать так:
domains = @mx_any/ignore=<;127.0.0.1;0.0.0.0 : \ an.other.domain : ... |
domains = <? @mx_any/ignore=<;127.0.0.1;::1 ? \ an.other.domain ? ... |
domains = cdb;/etc/mail/local_domains.cdb |
Соответсвующий тип поиска производится по файлу с использованием доменного имени как ключа. В большинстве случаев данные, которые ищутся, не нужны, exim интересует, лишь есть или нет ключ в файле. Однако, при использовании поиска для опции domains в роутере или в выражении domains ACL, данные сохраняются в переменной $domain_data и могут быть использованы в других опциях роутера или в утверждениях в той же самой ACL.
domains = partial-dbm;/partial/domains |
hold_domains = mysql;select domain from holdlist \ where domain = '$domain'; |
domainlist funny_domains = @ : lib.unseen.edu : \ *.foundation.fict.example : \ \N^[1-2]\d{3}\.fict\.example$\N : \ partial-dbm;/opt/data/penguin/book : \ nis;domains.byname : \ nisplus;[name=$domain,status=local],domains.org_dir |
Тут очевидна обработка в различных режимах соответствия. Использование звёздочки быстрей, чем регулярного выражения (имеется ввиду по трудоёмкости, то есть процессорным ресурсам) и внесение в список нескольких имён, очевидно, тоже. Использование поиска по БД или файлу дорого (опять-таки по процессорому времени), но это может оказаться единственным вариантом, если используются сотни имён. Поскольку шаблоны проверяются по порядку, имеет смысл поместить самые вероятные (совпадающие чаще всего) выше.
Списки хостов используются для контроля, что можно делать удалённым хостам. Например, некоторым хостам можно разрешить релей через локальную машину, а некоторым может быть разрешено использовать команду SMTP ETRN. Хосты могут быть идентифицированы двумя различными путями: по имени или IP-адресу. В списке хостов некоторые типы шаблонов совпадают с именем хоста, а некоторые совпадают с IP-адресом. Вы должны быть особенно осторожны при использовании одноключевых поисков и гарантировать, что используется правильный ключ.
Если элемент списка хостов пустая строка, то она совпадает только, когда не используется удалённый хост. Так происходит при получении сообщения от локального процесса, используя SMTP на стандартном вводе, то есть когда не используется соединение TCP/IP.
Специальный шаблон * в списке хостов совпадает с любым хостом или ни с каким хостом Фактически, ни имя, ни Ip-адрес не просматриваются.
Если хост IPv4 соединяется с хостом IPv6, и запрос принимается на сокет IPv6, входящий адрес на хосте IPv6 фигурирует как ::ffff:<v4address>. Когда такой адрес проверяется в списке хостов, он сначала преобразуется в традиционный адрес IPv4. Не все операционные системы принимают вызовы IPv4 на сокеты IPv6, поскольку были проблемы с безопасностью. Следующие типы шаблонов в списках хостов проверяют удалённый хост, просматривая его IP-адрес:
accept hosts = 127.0.0.1 : 10.45.23.56accept hosts = @[] |
192.168.23.236/31 |
recipient_unqualified_hosts = 192.168.0.0/16: \ 3ffe::ffff::836f::::/48 |
recipient_unqualified_hosts = /opt/exim/unqualnets |
172.16.0.0/123ffe:ffff:836f::/48 |
recipient_unqualified_hosts = <; 172.16.0.0/12; \ 3ffe:ffff:836f::/48 |
Когда хост идентифицируется по одноключевому поиску его полного IP-адреса, шаблон принимает такой вид:
net-<single-key-search-type>;<search-data> |
Например:
hosts_lookup = net-cdb;/hosts-by-ip.db |
Текстовая форма IP-адреса хоста используется как ключ поиска. Адреса IPv6 конвертируются к несокращённой форме с использованием строчных букв с точками в качестве разделителей, поскольку двоеточие ограничитель ключа в файлах lsearch. Двоеточия могут использоваться внутри ключа в файлах lsearch, если поместить ключ в кавычки, но это было добавлено позже. Данные, возвращённые поиском, не используются.
Одноключевые поиски также могут выполняться с использованием IP-адресов с маской, используя шаблон такой формы:
net<number>-<single-key-search-type>;<search-data> |
Например:
net24-dbm;/networks.db |
IP-адрес хоста замаскирован, используя <number> в качестве длины маски. Текстовая строка создаётся из скрытого маской значения, сопровождаемого маской, и это иcпользуется как ключ поиска. Например, если у хоста IP-адрес 192.168.34.6, то ключ для вышеупомянутого примера 192.168.34.0/24. Адреса IPv6 конвертируются в текстовый вид с использованием строчных букв и точек вместо двоеточия в качестве разделителей, поскольку двоеточие признак конца ключа в файлах lsearch. Всегда используются полные адреса IPv6, а не аббревиатуры.
Внимание: Специфические net32-(для адреса IPv4) или net128-(для адреса IPv6) не то же самое, что и специфическое net-без номера. В предыдущем случае ключевые строки включают значение маски, тогда как в последнем IP-адрес используется самостоятельно.
Существует несколько типов шаблонов требующих, чтобы exim знал имя удалённого хоста. Они являются подстановочными шаблонами или поиском по имени. Если полное имя хоста даётся без какого-либо подстановочного знака, оно используется для поиска соответствующего IP-адреса, как описано выше в секции 10.11.
Если при столкновении exim с одним из этих шаблонов, удалённое имя хоста неизвестно, оно будет найдено по IP-адресу. Хотя многие серверы интернета являются вполне добросовестными и имеют обратные DNS-записи, есть много хостов у которых их нет. Следовательно, имя не всегда может быть найдено, а это может привести к нежелательным эффектам. Позаботьтесь об этом при конфигурировании списков хостов с подстановочными шаблонами. Рассмотрите вариант, если имя не может быть найдено.
Из-за проблем с разрешением имён хостов по IP-адресам, соответствие имён хостов не такое же, как совпадение IP-адресов. По умолчанию для нахождения имени хоста exim делает обратный DNS-поиск: если в DNS имя не найдено, пробуются системные функции gethostbyaddr() или getipnodebyaddr(), какая доступна. Порядок, в котором производится поиск, может быть изменён установками опции host_lookup_order.
Есть несколько опций, управляющих поведением в случае, если имя хоста не найдено. Они описаны ниже в разделе 10.14. В результате алиасинга хосты могут иметь более одного имени. При обработке любого из следующих типов шаблонов, все имена хостов проверяются:
^(a|b)\.c\.d$ |
sender_unqualified_hosts = \N^(a|b)\.c\.d$\N : .... |
Предупреждение: Если Вы хотите соответствия полному имени хоста, то должны включить символ $ закрывающий метасимвол в регулярном выражении, как в вышеупомянутом примере. Без этого будет подходить всё, с совпадаюшим именем хоста.
Когда обрабатывается список хостов, exim может понадобиться найти IP-адрес по имени (смотрите секцию 10.11) или имя хоста по IP-адресу (смотрите секцию 10.13). В любом случае при невозможности найти информацию поведение одинаковое.
По умолчанию exim ведёт себя так, будто хост не совпадает со списком. Это не всегда совпадает с тем, что Вам нужно. Для изменения поведения exim есть специальные элементы: +include_unknown или +ignore_unknown, которые могут появляться в списке (на верхнем уровне, они не признаются в списках файлов).
host_reject_connection = +include_unknown:*.enemy.ex |
accept hosts = +ignore_unknown : friend.example : \ 192.168.4.5 |
Оба элемента, +include_unknown и +ignore_unknown, могут появляться в одном списке. Эффект от каждого длится до следующего или до конца списка.
Заметьте: Эта секция применяется к постоянным ошибкам поиска. Она не применяется к временным ошибкам DNS. Они всегда вызывают задержку сообщения (кроме тех случаев, когда dns_again_means_nonexist преобразовывает их в постоянные ошибки).
Если шаблон имеет форму
<single-key-search-type>;<search-data> |
dbm;/host/accept/list |
Напоминание: С этим видом шаблона Вы должны иметь имена хостов как ключи в файле, а не IP-адреса. Если Вам нужно сделать поиск основанный на IP-адресах, необходимо предварить тип поиска префиксом net- (смотрите секцию 10.12). Однако, ничто не препятствует использовать два элемента в одном списке, один для поиска адреса, другой для поиска имени с использованием обоими одного и того же файла.
Если шаблон имеет форму
<query-style-search-type>;<query> |
hosts_lookup = pgsql;\ select ip from hostlist where ip='$sender_host_address' |
Значение переменной $sender_host_address для адреса IPv6 содержит двоеточия. Если необходимо, можете использовать элемент раскрытия sg для изменения этого. Если хотите использовать адреса с маской, можете использовать оператор раскрытия mask.
Если запрос содержит ссылку на $sender_host_name, exim автоматически ищет имя хоста, если это не было сделано раньше. Смотрите секцию 10.13 для подробностей о поиске имён хостов.
Историческое примечание: до релиза 4.30 exim всегда пытался найти имя хоста перед выполнением запроса, если типу поиска не предшествовало net-. Сейчас это не так. Для обратной совместимости net- распознаётся при поиске в стиле запроса, но его присутствие или отсутствие не имеет никакого эффекта. Разумеется, для одноключевых поисков net- является важным. Смотрите секцию 10.12.
Если Вы используете поиск имени или безразличного имени хоста и IP-адреса в одном списке хостов, то должны размещать IP-адреса в начале. Например, в ACL Вы могли бы иметь:
accept hosts = 10.9.8.7 : *.friend.example |
Причина этого в том, что exim обрабатывает списки слева направо. Это позволяет проверить IP-адрес без запроса DNS, а при достижении элемента, требующего разрешения имени в адрес, происходит ошибка, если невозможно найти имя хоста для сравения с шаблоном. Если вышеупомянутый список был бы в обратном порядке, утверждение accept было бы неудачно для хоста, имя которого найти невозможно, даже если его IP-адрес 10.9.8.7.
Если же Вам действительно необходимо проверять первыми имена и продолжить проверять IP-адреса, то Вы можете переписать эту ACL таким образом:
accept hosts = *.friend.example accept hosts = 10.9.8.7 |
Если первый accept неудачен, exim продолжает проверять второе утверждение. Смотрите секцию 39 для получения подробной информации об ACL.
Списки адресов содержат шаблоны, совпадающие с почтовыми адресами. Есть лишь один специальный случай: адрес отправителя для рикошета всегда пустой. Вы можете проверить это, задав пустой элемент в списке адресов. Например, Вы могли бы установить опцию маршрутизатора для обработки рикошетов:
senders = : |
Присутствие двоеточия означает пустой элемент. Если никаких данных нет, то список пуст и не соответствует вообще ничему. Пустой отправитель также может быть обнаружен регулярным выражением, соответствующим пустой строке, и поиском в стиле запросов, успешному в случае, если переменная $sender_address пуста. Непустые элементы списка адресов могут быть прямыми адресами электронной почты. Например:
senders = jbc@askone.example : hs@anacreon.example |
Разрешается некоторое число шаблонов. Если шаблон содержит символ @, но он не регулярное выражение и не начинается с типа поиска, заканчивающегося точкой с запятой (описано ниже), локальная часть адреса сравнивается с локальной частью шаблона, которая может начинатся со звёздочки. Если локальная часть совпадает, проверяется точно таким же образом для шаблона списка доменов. Например, домен может быть безразличным, обращаясь к именованному списку, или быть поиском:
deny senders = *@*.spamming.site:\ *@+hostile_domains:\ bozo@partial-lsearch;/list/of/dodgy/sites:\ *@dbm;/bad/domains.db |
Если локальная часть начинается с восклицательного знака, требуется, чтобы это было определено как регулярное выражение, поскольку в противном случае восклицательный знак, как обычно в списках, будет воспринят как символ отрицания.
Если непустой шаблон не регулярное выражение, или поиск не содержит символ @, это сравнивается с доменной частью адреса. Так понимаются только два формата: литеральный домен (домен в виде IP-адреса) или шаблон домена, начинающийся со звёздочки. В обоих случаях эффект точно такой же, как будто *@ предшествовала шаблону. Например:
deny senders = enemy.domain : *.enemy.domain |
Следующие виды более сложных шаблонов списков адресов могут совпадать с любым адресом, включая пустой адрес, являющийся характеристикой отправителей рикошета:
deny senders = \N^.*this.*@example\.com$\N : \ \N^\d{8}.+@spamhaus.example$\N : ... |
deny senders = cdb;/etc/blocked.senders : \ mysql;select address from blocked where \ address='${quote_mysql:$sender_address}' |
Могут использоваться одноключевой стиль и стиль запросов. Для одноключевого типа exim использует полный адрес как ключ. Однако, пустые ключи не поддерживаются одноключевым поиском, таким образом, сравнение с пустым адресом всегда будет неудачно. Это ограничение не применяется к поиску в стиле запросов.
Частичное соответствие для одноключевых поисков (раздел 9.7) не может использоваться и игнорируется, если задано с записью в журнал событий (paniclog). Однако, Вы можете сконфигурировать параметры поиска по умолчанию, как описано в секции 9.6, но это полезно лишь для значений по умолчанию, типа *@. Например, с этим поиском:
accept senders = lsearch*@;/some/file |
user1@domain1.example *@domain2.example |
nimrod@jaeger.example *@jaeger.example * |
Предупреждение 1: Не включайте строку * в ключевой файл, поскольку это означало бы соответствие любому адресу, делая эту проверку бесполезной.
Предупреждение 2: Не путайте эти два вида элементов:
deny recipients = dbm*@;/some/file deny recipients = *@dbm;/some/file |
Первый по умолчанию производит полный поиск адреса, как описано, поскольку он начинается с типа поиска. Второй сравнивается с локальной и доменной частью независимо, как описано ниже.
Следующие виды шаблонов списков адресов могут совпадать лишь с непустыми адресами. Если адрес пуст, сравнение с любым из этих типов шаблонов неудачно.
deny senders = @@dbm;/etc/reject-by-domain |
baddomain.com: !postmaster : * |
aol.com: spammer1 : spammer2 : ^[0-9]+$ : spammer3 : spammer4 |
aol.com: spammer1 : spammer 2 : >* xyz.com: spammer3 : >* *: ^\d{8}$ |
senders = +my_list |
Домены в e-mail-адресах всегда обрабатываются регистронезависимо, но для локальных частей на некоторых системах это может быть существенно (смотрите caseful_local_part для разъяснения того, как exim работает с этими адресами при роутинге). Однако, RFC 2505 (Anti-Spam Recommendations for SMTP MTAs) предлагает, чтобы соответствие адресов спискам заблокированных было сделано в регистронезависимой манере. Так как большинство списков адресов в exim используется для этого вида управления, exim пытается сделать регистронезависимый поиск по умолчанию.
Доменная часть адреса всегда переводится в нижний регистр до сравнения её со списком адресов. Локальная часть по умолчанию переводится в нижний регистр, а любые производимые сравнения строки делаются регистронезависимо. Это значит, что данные непосредственно в списках адресов, в файлах, включающих простые имена файлов, и в любых файлах, в которых производится поиск с использованием механизма @@, могут быть в любом регистре. Однако, ключи в файлах, поиск в которых производится по типу, отличному от lsearch (который выполняется регистронезависимо), должны быть в строчных буквах, поскольку в них поиск регистрозависим.
Для разрешения регистрозависимого совпадения в списках адресов, если элемент списка адресов является строкой +caseful, оригинальный регистр локальной части восстанавливается для любого проводимого сравнения, а сравнения строк становятся регистрозависимы. Это не затрагивает домен, остающийся в нижнем регистре. Однако, хотя независимые сравнения доменов остаются регистронезависимы, регулярные выражения, производящие сравнение со всем адресом, становятся регистрозависимыми после того, как был обнаружен пункт +caseful.
Чувствтительность к регистру в списках локальных частей обрабатывается таким же образом для списков адресов, как только что описано. Элемент +caseful может использоваться по необходимости. В установке опции local_parts в роутере с установленным в false пунктом caseful_local_part адрес в строчных буквах и изначально сравнивается регистронезависмо. В этом случае +caseful восстановит регистрозависимое сравнение в списках локальных частей, но не в других местах роутера. Если в роутере опция caseful_local_part установлена в true, сравнение в опции local_parts регистрозависимо с начала маршрутизатора.
Если список локальных частей расположен в файле (смотрите секцию 10.3), комментарии обрабатываются так же, как и списки адресов: они распознаются лишь в случае, если символу # предшествует пустой символ или символ начала новой строки. Иначе, списки локальных частей сравниваются точно так же, как и списки доменов, за исключением специальных элементов, относящихся к локальному хосту (@, @[], @mx_any, @mx_primary и @mx_secondary), которые не распознаются. Обратитесь к секции 10.8 для получения дополнительных деталей о других доступных типах элементов.