Pregunta

Tengo una publicación de webhook en un formulario en mi aplicación web y necesito analizar las direcciones de encabezado de correo electrónico.

Aquí está el texto de origen:

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]

Estoy buscando sacar lo siguiente:

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

He estado luchando con Regex todo el día sin suerte.

¿Fue útil?

Solución

Al contrario de algunas de las publicaciones aquí, tengo que estar de acuerdo con MMUTZ, no puede analizar los correos electrónicos con una regex ... ver este artículo:

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

3.4.1. Especificación ADDR-SPEC

Un ADDR-SPEC es un identificador de Internet específico que contiene una cadena interpretada localmente seguida del carácter AT-SIGN ("@", valor ASCII 64) seguido de un dominio de Internet.

La idea de "interpretado localmente" significa que solo se espera que el servidor receptor pueda analizarlo.

Si iba a intentar resolver esto, encontraría el contenido de la línea "para", lo rompería e intentaría analizar cada segmento con 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)
            {
            }
        }
    }

Salida del programa anterior:

testto@domain.com
"Yes, this is valid"@[emails are hard to parse!]
testto1@domain.com
testto2@domain.com

Otros consejos

El correo electrónico de correo electrónico que cumple con RFC 2822 es:

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

Simplemente ejecute su mensaje de texto y obtendrá las direcciones de correo electrónico.

Por supuesto, siempre existe la opción de no usar Regex, donde Regex no es la mejor opción. ¡Pero depende de ti!

No puede usar expresiones regulares para analizar los correos RFC2822, porque su gramática contiene una producción recursiva (fuera de mi cabeza, fue por comentarios (a (nested) comment)) que hace que la gramática no sea regular. Las expresiones regulares (como su nombre lo indica) solo puede analizar regular Gramáticas.

Ver también Regex Match Open Etiquetas excepto XHTML Etiquetas autónomas para más información.

Como sugiere Blindy, a veces puedes analizarlo a la antigua.

Si prefiere hacer eso, aquí hay un enfoque rápido suponiendo que el texto del encabezado de correo electrónico se llama 'encabezado':

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

Puede estar fuera de un byte en la resta, pero puede probar y modificarlo fácilmente. Por supuesto, también tendrá que estar seguro de que siempre tendrá un CC: fila en su encabezado o esto no funcionará.

Hay un desglose de validar los correos electrónicos con Regex aquí, que hace referencia a una implementación más práctica de RFC 2822 con:

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

También parece que solo desea que las direcciones de correo electrónico fuera del campo "para", y también tiene que preocuparse como <>, por lo que es probable que funcione algo como lo siguiente:

^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*))*)

Nuevamente, como otros mencionados, es posible que no desee hacer esto. Pero si quieres regex, que convertirá esa entrada en <testto@domain.com>, testto1@domain.com, testto2@domain.com, eso lo hará.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top