Разбор заголовка письма с Regex в C # - PullRequest
2 голосов
/ 27 апреля 2011

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

Вот исходный текст:

Thread-Topic: test subject
Thread-Index: AcwE4mK6Jj19Hgi0SV6yYKvj2/HJbw==
From: "Lastname, Firstname" <firstname_lastname@domain.com>
To: <testto@domain.com>, testto1@domain.com, testto2@domain.com
Cc: <testcc@domain.com>, test3@domain.com
X-OriginalArrivalTime: 27 Apr 2011 13:52:46.0235 (UTC) FILETIME=[635226B0:01CC04E2]

Я хочу вытащить следующее:

<testto@domain.com>, testto1@domain.com, testto2@domain.com

Я боролся с Regex весь день без всякой удачи.

Ответы [ 5 ]

5 голосов
/ 27 апреля 2011

Вопреки некоторым постам здесь, я должен согласиться с mmutz, вы не можете анализировать электронные письма с регулярным выражением ... см. Эту статью:

http://tools.ietf.org/html/rfc2822#section-3.4.1

3.4.1. Спецификация Addr-спецификации

addr-spec - это конкретный интернет идентификатор, который содержит локально интерпретируемая строка, за которой следует символ знака ("@", значение ASCII 64), за которым следует интернет-домен.

Идея «локально интерпретируемого» означает, что только принимающий сервер сможет его проанализировать.

Если бы я попытался решить эту проблему, я бы нашел содержимое строки «Кому», разбил ее на части и попытался проанализировать каждый сегмент с помощью System.Net.Mail.MailAddress.

    static void Main()
    {
        string input = @"Thread-Topic: test subject
Thread-Index: AcwE4mK6Jj19Hgi0SV6yYKvj2/HJbw==
From: ""Lastname, Firstname"" <firstname_lastname@domain.com>
To: <testto@domain.com>, ""Yes, this is valid""@[emails are hard to parse!], testto1@domain.com, testto2@domain.com
Cc: <testcc@domain.com>, test3@domain.com
X-OriginalArrivalTime: 27 Apr 2011 13:52:46.0235 (UTC) FILETIME=[635226B0:01CC04E2]";

        Regex toline = new Regex(@"(?im-:^To\s*:\s*(?<to>.*)$)");
        string to = toline.Match(input).Groups["to"].Value;

        int from = 0;
        int pos = 0;
        int found;
        string test;

        while(from < to.Length)
        {
            found = (found = to.IndexOf(',', from)) > 0 ? found : to.Length;
            from = found + 1;
            test = to.Substring(pos, found - pos);

            try
            {
                System.Net.Mail.MailAddress addy = new System.Net.Mail.MailAddress(test.Trim());
                Console.WriteLine(addy.Address);
                pos = found + 1;
            }
            catch (FormatException)
            {
            }
        }
    }

Вывод из вышеуказанной программы:

testto@domain.com
"Yes, this is valid"@[emails are hard to parse!]
testto1@domain.com
testto2@domain.com
1 голос
/ 27 апреля 2011

Регулярное выражение электронной почты, соответствующее RFC 2822:

(?:[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])+)\])

Просто введите текст и получите адреса электронной почты.

Конечно, всегда есть возможностьне использовать регулярное выражение, где регулярное выражение не лучший вариант.Но до вас!

0 голосов
/ 27 апреля 2011

Существует разбивка проверки писем с помощью регулярного выражения здесь , что указывает на более практическую реализацию RFC 2822 с:

[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?

Выглядит так, как будто вы хотите, чтобы адреса электронной почты были только из поля «Кому», и вам также нужно беспокоиться о <>, так что может сработать что-то вроде следующего:

^To: ((?:\<?[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\>?,?(?:\s*))*)

Опять же, как уже упоминали другие, вы, возможно, не захотите этого делать. Но если вам нужно регулярное выражение, которое превратит этот ввод в <testto@domain.com>, testto1@domain.com, testto2@domain.com, это будет сделано.

0 голосов
/ 27 апреля 2011

Как подсказывает Блинди, иногда вы можете просто разобрать это по старинке.

Если вы предпочитаете это делать, вот быстрый подход, предполагающий, что текст заголовка письма называется «заголовок»:

int start = header.IndexOf("To: ");
int end = header.IndexOf("Cc: ");
string x = header.Substring(start, end-start);

Я могу быть выключен байтом на вычитании, но вы можете очень легко проверить и изменить это. Конечно, вы также должны быть уверены, что в заголовке всегда будет строка Cc: или это не сработает.

0 голосов
/ 27 апреля 2011

Вы не можете использовать регулярные выражения для синтаксического анализа писем RFC2822, потому что их грамматика содержит рекурсивную продукцию (вне головы, это было для комментариев (a (nested) comment)), что делает грамматику нерегулярной.Регулярные выражения (как следует из названия) могут анализировать только регулярные грамматики.

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

...