System.Net.MailMessage допускает некоторые недопустимые форматы адресов электронной почты.

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

Если вы посмотрите на http://en.wikipedia.org/wiki/Email_address#Local_part , вы увидите, что точка в начале или конце локальной части не допускается. Два последовательных периода также не допускаются. Однако следующий тест NUnit доказывает, что System.Net.MailMessage позволяет создавать экземпляр объекта MailMessage для некоторых недопустимых форматов адресов электронной почты.

[Test]
[TestCase(@"foobar@exampleserver")] //technically valid from the wiki article
[TestCase(@"jsmith@[192.168.2.1]")] //technically valid from the wiki article
[TestCase(@"[email protected]")] //vanilla email address
[TestCase(@"[email protected]")] //also standard
[TestCase(@"[email protected]")] //long with lots of periods
[TestCase(@"[email protected]")] //disposable with the + symbol
[TestCase(@"[email protected]")] //period and dash in local part
[TestCase(@"[email protected]")] //lots of hyphens
[TestCase(@"!#$%&'*+-/=?^_`{|}[email protected]")] //all these symbols are allowed in local part
[TestCase(@"ër_%لdev@gكňil.com")] //characters outside the ascii range are permitted
[TestCase(@"""abcdefghixyz""@example.com")] //technically valid
//[TestCase(@"abc.""defghi""[email protected]")] //technically valid, but .NET throws exception
public void CanCreateMailMessageObjectTest(string emailAddress)
{
     var mailMessage = new System.Net.Mail.MailMessage("[email protected]", emailAddress);  
}

Все вышеперечисленные тестовые случаи проходят, кроме последнего.

[Test]
[TestCase(@"[email protected]")] //leading period
[TestCase(@"[email protected]")] //period at end of local part <---FAIL
[TestCase(@"[email protected]")] //double period in local part <---FAIL
[TestCase(@"foobar@example!#$%^&*()=server.com")] //special characters in domain part
[TestCase(@"Abc.example.com")] //No @ separating local and domain part
[TestCase(@"A@b@[email protected]")] //more than one @ symbol
[TestCase(@"just""not""[email protected]")] //quoted strings must be dot separated
[TestCase(@"a""b(c)d,e:f;g<h>i[j\k][email protected]")] //special symbols "(),:;<>@[\] not inside quotes
[TestCase(@"[[email protected]")] //leading special symbol in local part
[TestCase(@"this is""not\[email protected]")] //spaces not in quotes
[TestCase(@"this\ still\""not\\[email protected]")] //backslashes not in quotes
[ExpectedException(typeof (System.FormatException))]
public void CannotCreateMailMessageObjectTest(string emailAddress)
{
    var mailMessage = new System.Net.Mail.MailMessage("[email protected]", emailAddress);
}

С какой стати [email protected] и [email protected] не выдают исключение System.FormatException? Кто здесь не прав, Майкрософт или Википедия? Существуют ли какие-либо адреса электронной почты, которые устарели, чтобы разрешить конечную точку или двойную точку? Должна ли моя проверка разрешать их? У меня есть надлежащая обработка исключений, позволяющая моей службе доставки электронной почты продолжать работу в течение дня, если возникает исключение, но я хотел бы отбрасывать адреса электронной почты, которые либо недействительны, либо гарантированно вызывают исключение.


person jreancsu    schedule 19.09.2014    source источник


Ответы (2)


Нет никакого объяснения, почему, но документы MSDN на System.Net.Mail.MailAddress указывает, что этот формат адреса поддерживается:

Класс MailAddress поддерживает следующие форматы почтовых адресов:

...

  • Последовательные и завершающие точки в именах пользователей. Например, пользователь...имя..@хост.

Так что это не ошибка в классе MailAddress — эта форма явно поддерживается. Но я не знаю, в чем причина их поддержки. Я предполагаю, что, возможно, некоторые системы действительно принимают их, и MS считает необходимым поддерживать этот сценарий.

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

person Michael Burr    schedule 19.09.2014
comment
может быть обычная опечатка --› Точно. Я терплю неудачу по этой причине. В основном я просто хочу отклонить адреса, которые а) явно недействительны или б) я знаю, что они не будут доставлены, потому что MailAddress/MailMessage выдает исключение (которое я обрабатываю, но все же...). - person jreancsu; 08.10.2014

Что ж, поскольку RFC определяют Стандарт, это будет неправильной реализацией Microsoft.

Если вы хотите улучшить проверку, попробуйте валидатор, который я разместил в этом ответе на вопрос Проверка адреса электронной почты C#.

Он должен должным образом (и строго) проверять почти любой «обычный» адрес электронной почты в формате local-part@domain, с которым вы можете столкнуться, хотя он не будет иметь дело с новым стилем, отличным от ASCII. это разрешено. Я не гарантирую, что немного гниения не произошло с тех пор, как ему исполнилось несколько лет, и RFC для электронной почты были обновлены с тех пор, как я его написал.

local-part не должен быть заключен в кавычки: он не поддерживает заключенные в кавычки локальные части или метки в кавычках.

Что касается доменной части, то мой валидатор не поддерживает литералы IPv4 или IPv6 (хотя добавить это будет несложно).

Если вы хотите разрешить любые/все RFC-совместимые адреса, это становится намного сложнее.

person Nicholas Carey    schedule 19.09.2014
comment
Спасибо за публикацию вашего 3 1/2-летнего решения, но это не совсем то, что я искал. Я могу получить регулярное выражение от FluentValidation и Microsoft или написать свое собственное, но проблема в том, что все они разные. Этот пост не запрашивает регулярное выражение, но задает вопрос, почему MailMessage не вызывает FormatException. - person jreancsu; 19.09.2014