Как преобразовать форматированный адрес электронной почты в отображаемое имя и адрес электронной почты?
Учитывая адрес электронной почты: "Джим"
Если я пытаюсь передать это 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 имеет закрытый метод, который анализирует адрес электронной почты. Не знаю, насколько это хорошо, но я бы скорее использовал это, чем писал свое.
Если вы сделаете предположение, что между двумя всегда есть пробел, вы можете просто использовать String.Split(' '), чтобы разделить его на пробелы. Это даст вам массив с разделением частей.
так что может быть так:
string str = "\"Jimbo\" jim@example.com"
string[] parts = str.Trim().Replace("\"","").Split(' ')
Проблема с этим для проверки заключается в том, что если отображаемое имя содержит пробел, оно будет разбито на 2 или более элементов в самом массиве, но электронное письмо всегда будет последним.
Редактировать - вам также может понадобиться отредактировать скобки, просто добавьте замену на них.
Я не пишу код на этом языке, но вижу две проблемы, которые вы, возможно, захотите проверить:
1- Вы не знаете точно, почему это было отклонено. По немедленной возможности оказалось, что у него есть черный список для example.com.
2- Реальное решение, которое вы хотите, это, вероятно, реализовать строгий валидатор. Stack Overflow, вероятно, является хорошим местом для разработки этого, потому что есть много людей с практическим опытом.
Вот пара вещей, которые вам нужны:
- обрезать пробелы и явно бесполезно.
- разбить на отдельные части (отображаемое имя, левая сторона адреса, правая сторона адреса).
- проверить каждый из них с помощью специального валидатора структуры данных. Например, правая часть должна быть действительным полным доменным именем (или неквалифицированным именем хоста, если вы работаете в либеральной почтовой системе).
Это лучший долгосрочный подход к решению этой проблемы.
Попробуйте: "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));