Как разобрать отформатированный адрес электронной почты в отображаемое имя и адрес электронной почты?

Учитывая адрес электронной почты: «Джим» ‹[email protected]

Если я попытаюсь передать это в MailAddress, я получу исключение:

Указанная строка не соответствует форме, необходимой для адреса электронной почты.

Как преобразовать этот адрес в отображаемое имя (Jim) и адрес электронной почты ([email protected]) в C#?

РЕДАКТИРОВАТЬ: я ищу код С# для его анализа.

EDIT2: я обнаружил, что MailAddress выдает исключение, потому что у меня есть пробел в начале строки адреса электронной почты.


person Dylan    schedule 02.10.2008    source источник
comment
Могу я предложить MimeKit? Это очень совместимая со стандартами библиотека, способная правильно анализировать адреса электронной почты.   -  person Roy Tinker    schedule 01.09.2016
comment
Возможный дубликат How To Parse String in format Name ‹Email›   -  person Michael Freidgeim    schedule 30.01.2017


Ответы (13)


Если вы хотите разобрать адрес электронной почты вручную, прочтите RFC2822 (https://tools.ietf.org/html/rfc822.html#section-3.4). Раздел 3.4 говорит о формате адреса.

Но правильно анализировать адреса электронной почты непросто, и MailAddress должен справиться с большинством сценариев.

Согласно документации MSDN для MailAddress:

http://msdn.microsoft.com/en-us/library/591bk9e8.aspx

Он должен иметь возможность анализировать адрес с отображаемым именем. Они приводят "Tom Smith <[email protected]>" в качестве примера. Может дело в цитатах? Если это так, просто удалите кавычки и используйте MailAddress для анализа остальных.

string emailAddress = "\"Jim\" <[email protected]>";

MailAddress address = new MailAddress(emailAddress.Replace("\"", ""));

Разбирать RFC2822 вручную не стоит, если этого можно избежать.

person Brannon    schedule 02.10.2008
comment
Круто! Никогда бы не подумал, что можно просто отправить «Имя ‹[email protected]›»! Я как раз собирался написать еще одну функцию разделения строк :) - person TimS; 05.11.2009
comment
Может быть, это кому-то поможет, мне пришлось использовать его с этой небольшой разницей, потому что он не принимал пустой символ, потому что каждое возможное значение для типа char имеет длину в один символ. MailAddress address = new MailAddress(emailAddress.Replace("\"", "")); - person Soph; 11.06.2012

Работает на меня:

string s = "\"Jim\" <[email protected]>";
System.Net.Mail.MailAddress a = new System.Net.Mail.MailAddress(s);
Debug.WriteLine("DisplayName:  " +  a.DisplayName);
Debug.WriteLine("Address:  " + a.Address);

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

person Joe    schedule 02.10.2008

Пытаться:

"Jimbo <[email protected]>"
person Codewerks    schedule 02.10.2008

try: "Jim" ‹[email protected]› не уверен, что это сработает, но именно так я обычно вижу это в почтовых клиентах.

person Sekhat    schedule 02.10.2008

если вы предполагаете, что между 2 всегда есть пробел, вы можете просто использовать String.Split(' ') чтобы разделить его на пробелы. Это даст вам массив с разделенными частями.

так что можно так:

string str = "\"Jimbo\" [email protected]"
string[] parts = str.Trim().Replace("\"","").Split(' ')

Проблема с этим, которую нужно проверить, заключается в том, что если в отображаемом имени есть пробел, оно будет разделено на 2 или более элементов в самом массиве, но электронная почта всегда будет последней.

Редактировать - вам также может понадобиться отредактировать скобки, просто добавьте замены на них.

person Carlton Jenke    schedule 02.10.2008

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

Много возможностей для улучшения, но мне нужно уйти на работу :)

class Program
{
    static void Main(string[] args)
    {
        string email = "\"Jimbo\" <[email protected]>";
        Console.WriteLine(parseEmail(email));
    }

    private static string parseEmail(string inputString)
    {
        Regex r = 
            new Regex(@"^((?:(?:(?:[a-zA-Z0-9][\.\-\+_]?)*)[a-zA-Z0-9])+)\@((?:(?:(?:[a-zA-Z0-9][\.\-_]?){0,62})[a-zA-Z0-9])+)\.([a-zA-Z0-9]{2,6})$");

        string[] tokens = inputString.Split(' ');

        foreach (string s in tokens)
        {
            string temp = s;
            temp = temp.TrimStart('<'); temp = temp.TrimEnd('>');

            if (r.Match(temp).Success)
                return temp;
        }

        throw new ArgumentException("Not an e-mail address");
    }
}
person FlySwat    schedule 02.10.2008

Это немного "грубо и готово", но будет работать для приведенного вами примера:

        string emailAddress, displayname;
        string unparsedText = "\"Jimbo\" <[email protected]>";
        string[] emailParts = unparsedText.Split(new char[] { '<' });

        if (emailParts.Length == 2)
        {
            displayname = emailParts[0].Trim(new char[] { ' ', '\"' });
            emailAddress = emailParts[1].TrimEnd('>');
        }
person Rob    schedule 02.10.2008

new MailAddress("[email protected]", "Jimbo");

чтобы разобрать строку, которую вы дали:

string input = "\"Jimbo\" [email protected]";
string[] pieces = input.Split(' ');
MailAddress ma = new MailAddress(pieces[1].Replace("<", string.Empty).Replace(">",string.Empty), pieces[0].Replace("\"", string.Empty));
person Wayne    schedule 02.10.2008

Чтобы обрабатывать встроенные пробелы, разделите скобки следующим образом:

string addrin = "\"Jim Smith\" <[email protected]>";
char[] bracks = {'<','>'};
string[] pieces = addrin.Split(bracks);
pieces[0] = pieces[0]
  .Substring(0, pieces[0].Length - 1)
  .Replace("\"", string.Empty);
MailAddress ma = new MailAddress(pieces[1], pieces[0]);
person b w    schedule 02.10.2008

Итак, вот что я сделал. Это немного быстро и грязно, но, кажется, работает.

string emailTo = "\"Jim\" <[email protected]>";
string emailRegex = @"(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|""(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*"")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])";
string emailAddress = Regex.Match(emailTo.ToLower(), emailRegex).Value;
string displayName = null;

try
{
    displayName = emailTo.Substring(0, emailTo.ToLower().IndexOf(emailAddress) - 1);
}
catch 
{
    // No display name 
}

MailAddress addr = new MailAddress(emailAddress, displayName);

Комментарии?

person Dylan    schedule 02.10.2008

Я не пишу код на этом языке, но вижу две проблемы, которые вы, возможно, захотите проверить:

1- Вы точно не знаете, почему он был отклонен. На ближайшую вероятность было то, что у него есть черный список, например, например.com.

2- Реальное решение, которое вы хотите, это, вероятно, реализовать строгий валидатор. Stack Overflow, вероятно, хорошее место для разработки, потому что есть много людей с практическим опытом.

Вот пара вещей, которые вам нужны:

  1. обрезать пробелы и, очевидно, мусор.
  2. разобрать на отдельные части (отображаемое имя, левая часть адреса, правая часть адреса).
  3. проверьте каждый из них с помощью специального валидатора структуры данных. Например, справа должно быть действительное полное доменное имя (или неполное имя хоста, если вы используете либеральную почтовую систему).

Это лучший долгосрочный подход к решению этой проблемы.

person Community    schedule 02.10.2008

Я могу предложить свое решение на основе регулярных выражений для декодирования значений полей адреса электронной почты («От», «Кому») и значения поля «Тема».

https://www.codeproject.com/Tips/1198601/Parsing-and-Decoding-Values-of-Some-Email-Message

person CSharpCoder    schedule 26.07.2017

person    schedule
comment
Я знаю, как вызвать MailAddress, мне нужен код для разбора данного адреса. - person Dylan; 02.10.2008