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

Учитывая адрес электронной почты: "Джим"

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

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

Как мне разобрать этот адрес в отображаемое имя (Jim) и адрес электронной почты (jim@example.com) в C#?

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

РЕДАКТИРОВАТЬ 2: Я обнаружил, что MailAddress генерирует исключение, потому что у меня был пробел в начале строки адреса электронной почты.

14 ответов

Решение

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

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

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

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

Он должен быть в состоянии проанализировать адрес с отображаемым именем. Они дают "Tom Smith <tsmith@contoso.com>" В качестве примера. Может быть, кавычки являются проблемой? Если это так, просто удалите кавычки и используйте MailAddress для анализа остальных.

string emailAddress = "\"Jim\" <jim@example.com>";

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

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

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

string s = "\"Jim\" <jim@example.com>";
System.Net.Mail.MailAddress a = new System.Net.Mail.MailAddress(s);
Debug.WriteLine("DisplayName:  " +  a.DisplayName);
Debug.WriteLine("Address:  " + a.Address);

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

Пытаться:

"Jimbo <jim@example.com>"

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

так что может быть так:

string str = "\"Jimbo\" jim@example.com"
string[] parts = str.Trim().Replace("\"","").Split(' ')

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

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

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

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

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

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

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

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

Попробуйте: "Jim" не уверен, что это будет работать, но я обычно так вижу в почтовых клиентах.

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

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

class Program
{
    static void Main(string[] args)
    {
        string email = "\"Jimbo\" <jim@example.com>";
        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");
    }
}
string inputEmailString = "\"Jimbo\" <jim@example.com>";
string[] strSet =  inputEmailString.Split('\"','<','>');   

MailAddress mAddress = new MailAddress(strSet[0], strSet[2]);

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

string emailTo = "\"Jim\" <jim@example.com>";
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);

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

Если вы используете MailKit, как рекомендуется , вы можете использовать методы Parse и TryParse из MimeKit.MailboxAddress. Вот пример.

      [Test]
public void Should_Parse_EmailAddress_With_Alias()
{
    //Arrange
    var expectedAlias = "Jim";
    var expectedAddress = "jim@example.com";
    string addressWithAlias = "\"Jim\" <jim@example.com>";

    //Act
    var mailboxAddressWithAlias = MimeKit.MailboxAddress.Parse(addressWithAlias);

    //Assert
    Assert.AreEqual(expectedAddress, mailboxAddressWithAlias.Address);
    Assert.AreEqual(expectedAlias, mailboxAddressWithAlias.Name);
}

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

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

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

Для обработки встроенных пространств разбейте скобки следующим образом:

string addrin = "\"Jim Smith\" <jim@example.com>";
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]);

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

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

new MailAddress("jim@example.com", "Jimbo");

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

string input = "\"Jimbo\" jim@example.com";
string[] pieces = input.Split(' ');
MailAddress ma = new MailAddress(pieces[1].Replace("<", string.Empty).Replace(">",string.Empty), pieces[0].Replace("\"", string.Empty));
Другие вопросы по тегам