Как я могу извлечь канонический адрес электронной почты, учитывая адрес, который включает BATV или другие теги?

Наше веб-приложение имеет функцию, которая позволяет пользователям импортировать данные, отправляя электронные письма на определенный адрес электронной почты. Когда письма принимаются нашим приложением, они обрабатываются по-разному в зависимости от того, кто их отправил. Мы смотрим на поле "отправитель" электронного письма и сопоставляем его с пользователем в нашей базе данных. Как только пользователь, отправивший электронное письмо, будет определен, мы обрабатываем это электронное письмо в соответствии с его личными настройками.

Обычно это работает нормально для большинства пользователей. Однако некоторые пользователи жаловались, что их электронные письма не обрабатывались. Когда мы изучили это, мы обнаружили, что их почтовый сервер добавляет информацию к адресу электронной почты отправителей, и это привело к тому, что адрес электронной почты не соответствовал тому, что было в нашей таблице пользователей в базе данных. Например, электронная почта пользователя может быть testuser@example.com в базе данных, но поле "отправитель" в электронном письме, которое мы получили, было бы что-то вроде btv1==502867923ab==testuser@example.com, Некоторые исследования показали, что это было вызвано тем, что сервер отправителя использовал проверку Bounce Address Tag Validation (BATV).

Нам нужно иметь возможность извлечь канонический адрес электронной почты из предоставленного нам поля "отправитель", чтобы мы могли сопоставить его с нашей таблицей пользователей. Один из других разработчиков здесь написал для этого функцию и отправил ее мне для проверки кода. Вот что он написал (C#):

private static string SanitizeEmailSender(string sender)
{
    if (sender == null)
        return null;
    return System.Text.RegularExpressions.Regex.Replace(
        sender, 
        @"^((btv1==.{11}==)|(prvs=.{9}=))", 
        "", 
        System.Text.RegularExpressions.RegexOptions.None);
} 

Шаблон регулярных выражений здесь охватывает конкретные случаи, которые мы видели в наших журналах электронной почты. Я обеспокоен тем, что регулярное выражение может быть слишком конкретным. Являются btv1 а также prvs единственные префиксы, используемые в этих тегах? Всегда ли точно 9 символов после prvs=? Существуют ли другие схемы тегирования отправителей электронной почты, кроме BATV, на которые нам нужно обратить внимание? Чего я не хочу, так это чтобы это исправление было запущено в производство, чтобы в следующем месяце выяснить, что нам нужно исправить это снова, поскольку были другие случаи, которые мы не рассматривали.

Мой инстинкт инстинкта состоял в том, чтобы просто урезать адрес электронной почты, чтобы включить только часть после последнего =, Тем не менее, исследования показывают, что = является действительным символом в адресах электронной почты и, следовательно, может являться частью канонического адреса электронной почты пользователя. Лично я никогда не видел = используется в адресе электронной почты вне какой-либо схемы тегов или субадресации, но вы никогда не знаете. Закон Мерфи предполагает, что в ту минуту, когда я предполагаю, что у пользователя никогда не будет определенного символа в его адресе электронной почты, кто-то с таким адресом немедленно зарегистрируется.

Мой вопрос: существует ли общепринятый надежный способ извлечения канонического адреса электронной почты пользователя с использованием более длинного адреса, который может включать BATV или другие теги? Если это не удастся, есть ли, по крайней мере, более надежный способ, чем у нас до сих пор? Или то, что у нас есть на самом деле достаточно?

2 ответа

Являются ли btv1 и prvs единственными префиксами, используемыми в этих тегах?

prvs является префиксом, который соответствует "метасинтаксису", определенному в RFC. btv1 является перезаписью Invalid Spoof Suppression устройства Barracuda, которая не соответствует стандарту BATV (отсюда и двойной знак равенства).

Регулярное выражение, которое просто соответствует всем локальным частям BATV, будет

[0-9A-Za-z\-]+=[0-9A-Za-z\-]+=.+@.+]

Но это не поймает Барракуда btv1 переписывает (и другие переписывает)

Всегда ли точно 9 символов после prvs=?

Нет, в спецификации сказано, что их 10, но в дикой природе это чаще всего 9

Существуют ли другие схемы тегирования отправителей электронной почты, кроме BATV, на которые нам нужно обратить внимание?

Да, смотрите ниже.

существует ли общепринятый надежный способ извлечения канонического адреса электронной почты пользователя с использованием более длинного адреса, который может включать BATV или другие теги?

нет

Глядя на различные базы кода, похоже, что каждый реализует свое собственное решение. Некоторая сложность проистекает из того факта, что существуют

Вот модульный тест, содержащий список возможных переписанных примеров отправителя, и вот несколько примеров синтаксисов, найденных в дикой природе.

Если это не удастся, есть ли, по крайней мере, более надежный способ, чем у нас до сих пор? Или то, что у нас есть на самом деле достаточно?

Похоже, что лучший подход - обратиться к каждому из условий так, как это делают ezmlm-idx и rspamd.

Используемое вами регулярное выражение не распространяется

  • првс с loc-core а также tag-val обратная
  • Prvs, которые следуют спецификации с 10 символов вместо 9
  • SRS
  • Гугл форварды

Поскольку информации, добавляемой BATV, всегда предшествует тег BATV и разграничение информации между двумя == строки, это то, что я должен использовать:

((btv1|prvs)==([^=]|=[^=])*==))

Конечно, вы правы в том смысле, что = знак допускается в качестве допустимого символа в адресах электронной почты, но именно поэтому необходимо использовать эту последовательность (для формирования действительного адреса электронной почты).

Если вы попытаетесь немного больше покопаться в RFC, относящихся к электронной почте, вы увидите, что MIME добавляет некоторые конструкции, чтобы разрешить использование символов, не являющихся символами ascii, на адрес электронной почты с помощью функции для печати в кавычках. Немного чтения RFC необходимо, чтобы выбрать, как правильно справляться с этими вещами.

Наконец, чтобы ответить на ваш вопрос, почтовые серверы имеют право изменять / перезаписывать адреса конвертов - это адреса в протоколе управления SMTP, используемом для маршрутизации почтовых сообщений --- (sendmail может делать это даже в почте поля заголовка) Правильный ответ на ваш вопрос заключается в том, что нет надежного способа (принятого или нет) для извлечения канонического адреса электронной почты отправителя. Адреса переписываются по мере продвижения сообщения к целевому получателю, и информация теряется в пути. Вы не можете восстановить исходный адрес.

И последнее, чтобы проиллюстрировать немного:

  • Поле отправителя добавляется конечным получателем SMTP, чтобы включить в электронное письмо адрес отправителя конверта (адрес, используемый как FROM: <sender@address.com> в исходном сообщении протокола SMTP)
  • Поле From добавляется исходным почтовым клиентом для определения источника сообщения. Это поведение может быть изменено наличием полей Resent-from или Resent-sender в случае повторной отправки сообщения. Они идентифицируют повторную отправку сообщений.
  • Наконец, отправитель может использовать заголовок Reply-to, чтобы указать ответы, которые будут отправлены на этот адрес.

Чтобы получить представление о том, как работает протокол SMTP, ознакомьтесь с документами RFC-2821 (протокол SMTP) и RFC-2822 (формат сообщений электронной почты в Интернете).

Другие вопросы по тегам