Кратко

  • RFC 5231 добавил упорядоченные сравнения :value и подсчёт :count к существовавшим в Sieve тестам address, envelope и header. Результат :count зависит от того, какой именно тест разбирает сообщение.
  • Тест address считает почтовые ящики, envelope — транспортные адреса, а header — экземпляры полей, а не адреса внутри них. envelope :count для to намеренно показывает только текущего пользователя.

«Сколько получателей?» — не один вопрос

На первый взгляд, чтобы посчитать получателей, достаточно взглянуть на строку To:. Два почтовых ящика — значит, два адресата. Но почтовый фильтр работает не с визуальным впечатлением от строки. Он может обращаться к заголовку сообщения, SMTP-конверту и уже разобранным структурам адресов — у каждой поверхности свой смысл и свои границы доступа.

Опубликованная в январе 2008 года RFC 5231 добавила реляционные сравнения к существовавшим тестам Sieve address, envelope и header. Скрипт получил возможность спрашивать не только о совпадении, но и о том, больше ли значение, меньше, равно или не равно другому. Расширение ввело два типа сопоставления: :value сравнивает значения с помощью компаратора, возвращающего сведения о порядке, а :count сначала считает выбранные элементы и лишь затем сравнивает число.

Операторы — gt, ge, lt, le, eq и ne. В :value значение из сообщения стоит слева от отношения, а значение из списка ключей скрипта — справа. Если с любой стороны несколько значений, достаточно одной пары, удовлетворяющей отношению, чтобы тест сработал. Порядок задаётся выбранным компаратором, а не универсальным естественно-языковым смыслом слов «больше» и «меньше». Реализация обязана поддерживать i;ascii-numeric как минимум для 32-битных беззнаковых целых; отрицательные числа этот компаратор не представляет.

Особенно наглядно различие проявляется в :count. Допустим, в To: указаны два адреса почтовых ящиков, а в Cc: — один. Тест address :count для to и cc посчитает три элемента почтовых ящиков. Название группы в счёт не входит, но ящики внутри группы входят. Тест header :count для to и cc посчитает экземпляры полей заголовка. В обычном сообщении, соответствующем RFC 2822, с одним полем To: и одним Cc: результат равен двум, а не числу людей.

envelope :count считает ещё одну сущность: адреса в выбранных частях транспортного конверта. В части конверта to всегда одна запись — адрес пользователя, чей скрипт Sieve сейчас исполняется. Спецификация требует этого ограничения, чтобы пользователь не мог узнать, было ли письмо доставлено кому-то ещё. Для from число равно нулю, если команда SMTP MAIL FROM пуста, и единице в остальных случаях. Поэтому «посчитать получателей» может означать видимые в заголовке ящики, доступные скрипту адреса конверта или строки заголовка. Одно название теста не выбирает вариант.

Это различие влияет и на объединение условий. Подсчёт адресов сразу по to и cc складывает число ящиков в обоих полях. Если правило должно означать «не менее трёх в To или не менее трёх в Cc», нужны два отдельных сравнения внутри anyof. Общий подсчёт отвечает на иной вопрос: «не менее трёх в обоих полях вместе?». В примере RFC два адреса в To и один в Cc дают суммарно три, но не достигают ни одного из отдельных порогов в три.

RFC 5231 не создала реляционные тесты Sieve с нуля. RFC 3431 от 2002 года уже ввела расширение и оба типа сопоставления; RFC 5231 заменила её. Новая версия обновила ссылку на компаратор по RFC 4790, исправила примеры, уточнила, какие элементы RFC 2822 считает COUNT, и убрала собственное требование обрезать пробелы после того, как более широкое правило вошло в базовую спецификацию Sieve. В реестре IANA расширение RFC 5231 зарегистрировано как возможность relational.

Однако действие расширения заканчивается на проверке. Оно не меняет неявное действие KEEP и явные действия вроде fileinto, redirect или reject. Предикат может выбрать ветвь скрипта, но не доказывает, что именно разобрал сервер, правильно ли он выполнил ветвь и куда в итоге попало письмо. Практическая граница такова: для точного сравнения нужно отдельно знать единицу, компаратор и поведение конкретной реализации.

Источники