Código C # para validar la dirección de correo electrónico


461

¿Cuál es el código más elegante para validar que una cadena es una dirección de correo electrónico válida?



99

hay muchas otras validaciones importantes, no solo la cadena, es mejor verificar si el correo electrónico existe en este servidor smtp o si el usuario está ingresando algún correo electrónico, etc. es correcto como ver-email.com
Amr Magdy


Respuestas:


784

¿Qué hay de esto?

bool IsValidEmail(string email)
{
    try {
        var addr = new System.Net.Mail.MailAddress(email);
        return addr.Address == email;
    }
    catch {
        return false;
    }
}

Para aclarar, la pregunta es si una cadena en particular es una representación válida de una dirección de correo electrónico, no si una dirección de correo electrónico es un destino válido para enviar un mensaje. Para eso, la única forma real es enviar un mensaje para confirmar.

Tenga en cuenta que las direcciones de correo electrónico son más indulgentes de lo que podría suponer primero. Estas son todas formas perfectamente válidas:

  • rueda dentada
  • "rueda dentada la naranja" @ example.com
  • 123@$.xyz

Para la mayoría de los casos de uso, un falso "inválido" es mucho peor para sus usuarios y pruebas futuras que un falso "válido". Aquí hay un artículo que solía ser la respuesta aceptada a esta pregunta (esa respuesta se ha eliminado desde entonces). Tiene muchos más detalles y algunas otras ideas sobre cómo resolver el problema.

Proporcionar controles de cordura sigue siendo una buena idea para la experiencia del usuario. Suponiendo que la dirección de correo electrónico es válida, puede buscar dominios de nivel superior conocidos, verificar el dominio en busca de un registro MX, verificar errores ortográficos de nombres de dominio comunes (gmail.cmo), etc. Luego presentar una advertencia al usuario una oportunidad para decir "sí, mi servidor de correo realmente permite 🌮🍳🎁 como dirección de correo electrónico".


En cuanto al uso de manejo de excepciones para la lógica empresarial, estoy de acuerdo en que es algo que debe evitarse. Pero este es uno de esos casos donde la conveniencia y la claridad pueden ser mayores que el dogma.

Además, si hace algo más con la dirección de correo electrónico, probablemente implicará convertirlo en una dirección de correo electrónico. Incluso si no usa esta función exacta, probablemente quiera usar el mismo patrón. También puede verificar si hay tipos específicos de fallas al detectar diferentes excepciones : nulo, vacío o formato no válido.


Según el comentario de Stuart, esto compara la dirección final con la cadena original en lugar de devolver siempre verdadero. MailAddress intenta analizar una cadena con espacios en las partes "Nombre para mostrar" y "Dirección", por lo que la versión original estaba devolviendo falsos positivos.


--- Otras lecturas ---

Documentación para System.Net.Mail.MailAddress

Explicación de lo que constituye una dirección de correo electrónico válida.


23
En realidad, eso no es incorrecto. a @ a es una dirección de correo electrónico válida. Consulte haacked.com/archive/2007/08/21/…. De hecho, este método devuelve resultados incorrectos si utiliza una dirección con comillas.
Cogwheel el

53
+1: Esta es la mejor respuesta si está utilizando las System.Net.Mailclases para enviar correo, que probablemente sea si está utilizando .NET. Tomamos la decisión de utilizar este tipo de validación simplemente porque no tiene sentido aceptar direcciones de correo electrónico, incluso válidas, a las que no podemos enviar correos.
Greg Beech

24
No lo recomiendo Vuelve cierto:IsValidEmail("this is not valid@email$com");
Kakashi

15
Muchos de los problemas parecen deberse a que MailAddress también intenta analizar el DisplayName, por lo que "single space@domain.com" se analiza a DisplayName "single" y Address "space@domain.com". Una solución para esto es: return (addr.Address == email);
Stuart

18
Me gusta esto; No entiendo que la compulsión sea más restrictiva que la especificación real. Los falsos negativos son mucho peores que los falsos positivos ("¿qué quieres decir con que mi correo electrónico no es válido? ")
Casey

242

Esta es una pregunta antigua, pero todas las respuestas que he encontrado en SO, incluidas las más recientes, se responden de manera similar a esta. Sin embargo, en .Net 4.5 / MVC 4 puede agregar la validación de la dirección de correo electrónico a un formulario agregando la anotación [EmailAddress] de System.ComponentModel.DataAnnotations, por lo que me preguntaba por qué no podía usar la funcionalidad incorporada. Neto en general.

Esto parece funcionar, y me parece bastante elegante:

using System.ComponentModel.DataAnnotations;

class ValidateSomeEmails
{
    static void Main(string[] args)
    {
        var foo = new EmailAddressAttribute();
        bool bar;
        bar = foo.IsValid("someone@somewhere.com");         //true
        bar = foo.IsValid("someone@somewhere.co.uk");       //true
        bar = foo.IsValid("someone+tag@somewhere.net");     //true
        bar = foo.IsValid("futureTLD@somewhere.fooo");      //true

        bar = foo.IsValid("fdsa");                          //false
        bar = foo.IsValid("fdsa@");                         //false
        bar = foo.IsValid("fdsa@fdsa");                     //false
        bar = foo.IsValid("fdsa@fdsa.");                    //false

        //one-liner
        if (new EmailAddressAttribute().IsValid("someone@somewhere.com"))
            bar = true;    
    }
}

44
Genial, aunque es decepcionante que MS no pueda hacer que esto esté de acuerdo con su propia documentación . Esto rechaza js@proseware.com9
Casey

13
Tenga en cuenta que EmailAddressAttributees menos permisivo que System.Net.Mail.MailAddress, por ejemplo, MailAddressacepta una dirección para un TLD. Es algo a tener en cuenta si necesita ser lo más permisivo posible.
Aaroninus

55
@ Rueda dentada: si la respuesta se encuentra en algún lugar de los comentarios, probablemente debería agregarse al cuerpo principal de la respuesta.
hofnarwillie

66
@hofnarwillie: está en el cuerpo principal, pero los comentarios son elaborados. Si su objetivo es no enojar a sus usuarios, entonces su validación no debería ser más restrictiva que la especificación. La única forma de verificar realmente si un correo electrónico es válido es enviar un mensaje de prueba.
Rueda dentada

44
Tenga en cuenta que foo.IsValid(null);vuelve true.
urig

62

Utilizo este método de línea única que hace el trabajo por mí.

using System.ComponentModel.DataAnnotations;
public bool IsValidEmail(string source)
{
    return new EmailAddressAttribute().IsValid(source);
}

Según los comentarios, esto "fallará" si source(la dirección de correo electrónico) es nula.

public static bool IsValidEmailAddress(this string address) => address != null && new EmailAddressAttribute().IsValid(address);

1
Esto no funciona para mí; Entiendo, "'Anotaciones de datos' no existe ... ¿falta una referencia de ensamblaje?" ¿Qué referencia necesito agregar?
B. Clay Shannon

Esto devolverá verdadero si la fuente es nula. Consulte msdn.microsoft.com/en-us/library/hh192424 "verdadero si el valor especificado es válido o nulo; de lo contrario, falso".
jao

2
Una versión mejor:public static Boolean IsValidMailAddress(this String pThis) => pThis == null ? false : new EmailAddressAttribute().IsValid(pThis);
Sebastian Hofmann

77
O incluso mejor:public static bool IsValidEmailAddress(this string address) => address != null && new EmailAddressAttribute().IsValid(address);
Patrik Melander

1
No creo que este método de extensión deba regresar silenciosamente falsepara cadenas nulas. Es por eso que proponen la (mejor aún mejor) ++ versión: public static bool IsValidEmailAddress(this string address) => new EmailAddressAttribute().IsValid(address ?? throw new ArgumentNullException());. Ahora iré y encontraré la Iglesia reformada de los versionistas aún mejores.
Marc.2377

41

.net 4.5 agregó System.ComponentModel.DataAnnotations.EmailAddressAttribute

Puede navegar por la fuente de EmailAddressAttribute , esta es la expresión regular que utiliza internamente:

const string pattern = @"^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$";

2
Desafortunadamente, EmaillAddressAttribute permite Ñ, que no es un carácter válido para el correo electrónico
BZ

16
@BZ Sí lo es. ¿Por qué crees que no lo es?
Casey

@Chad Grant: esta es una versión de C #. ¿Puede proporcionar una VB.Net? Porque eso escapará de personajes como \\ to \ o puede proporcionar una cadena literalmente.
Nikhil Agrawal

3
Esto funciona, ¡pero no lo olvides RegexOptions.IgnoreCaseporque este patrón no permite letras mayúsculas explícitamente!
Chris

1
Tenga en cuenta que Regex es muy deliberado: "Este atributo proporciona una validación de correo electrónico del lado del servidor equivalente a jquery validate y, por lo tanto, comparte la misma expresión regular".
Ohad Schneider

38

Tomé la respuesta de Phil del # 1 y creé esta clase. Llámalo así:bool isValid = Validator.EmailIsValid(emailString);

Aquí está la clase:

using System.Text.RegularExpressions;

public static class Validator
{

    static Regex ValidEmailRegex = CreateValidEmailRegex();

    /// <summary>
    /// Taken from http://haacked.com/archive/2007/08/21/i-knew-how-to-validate-an-email-address-until-i.aspx
    /// </summary>
    /// <returns></returns>
    private static Regex CreateValidEmailRegex()
    {
        string validEmailPattern = @"^(?!\.)(""([^""\r\\]|\\[""\r\\])*""|"
            + @"([-a-z0-9!#$%&'*+/=?^_`{|}~]|(?<!\.)\.)*)(?<!\.)"
            + @"@[a-z0-9][\w\.-]*[a-z0-9]\.[a-z][a-z\.]*[a-z]$";

        return new Regex(validEmailPattern, RegexOptions.IgnoreCase);
    }

    internal static bool EmailIsValid(string emailAddress)
    {
        bool isValid = ValidEmailRegex.IsMatch(emailAddress);

        return isValid;
    }
}

55
Solo uno pequeño, pero usaría: return (! String.IsNullOrEmpty (emailAddress)) && ValidEmailRegex.IsMatch (emailAddress);
Marc

Esto es solo horror :)
Alexandru Dicu

31

Personalmente, diría que debes asegurarte de que haya un símbolo @ allí, posiblemente con un. personaje. Hay muchas expresiones regulares que podría usar con una corrección variable, pero creo que la mayoría de ellas omiten las direcciones de correo electrónico válidas o dejan pasar las inválidas. Si las personas desean ingresar una dirección de correo electrónico falsa, ingresarán una dirección falsa. Si necesita verificar que la dirección de correo electrónico es legítima y que la persona tiene el control de esa dirección de correo electrónico, deberá enviarles un correo electrónico con un enlace codificado especial para que puedan verificar que realmente es una dirección real.


66
Personalmente, creo que deberías hacer un poco más de validación que eso. Alguien está obligado a probar la dirección de correo electrónico de Bobby Table o algo peor.
Luke Quinane

31
¿Qué tiene de malo la dirección de correo electrónico de Bobby Table si está utilizando declaraciones preparadas? Estamos hablando de direcciones de correo electrónico válidas, no de otras cosas que no tienen nada que ver con lo que constituye una dirección de correo electrónico válida, como cómo hacer correctamente las consultas SQL para que no tenga problemas de inyección SQL.
Kibbee

Supongo que no sabes lo que alguien pondrá allí, pero una persona maliciosa sabe que el valor eventualmente se puede alimentar a tu sistema de correo. Prefiero ir a la defensa en profundidad y ser un poco más estricto.
Luke Quinane

10
Eso es por lo que debe preocuparse el sistema de correo. No rechazaría direcciones de correo electrónico perfectamente válidas solo porque podría ser un problema de seguridad con algún otro sistema. Si todo lo que necesita su servidor de correo electrónico es una dirección de correo electrónico mal formada para causar problemas de seguridad, probablemente debería cambiar a otro servidor.
Kibbee

44
La defensa en profundidad solo funciona si cada nivel de tu cebolla de seguridad no está podrido. Una capa podrida significa que echas a perder toda la cebolla. Rechazar "foo@example.com.au" porque quiere defenderse de vulnerabilidades en la codificación de la ley µ de Sun no tiene sentido, ¿verdad? No te rías, me ha pasado a mí. La razón por la que estoy comentando aquí es que Medicare Australia no permite direcciones ".au", solo ".com". Lea también Mark Swanson, "Cómo no validar el correo electrónico", mdswanson.com/blog/2013/10/14/…
ManicDee

17

Creo que la mejor manera es la siguiente:

    public static bool EmailIsValid(string email)
    {
        string expression = "\\w+([-+.']\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*";

        if (Regex.IsMatch(email, expression))
        {
            if (Regex.Replace(email, expression, string.Empty).Length == 0)
            {
                return true;
            }
        }
        return false;
    }

Puede tener esta función estática en una clase general.


Esta respuesta no acepta una dirección con un TLD en la parte del dominio.
Simone

15

Código corto y preciso

string Email = txtEmail.Text;
if (Email.IsValidEmail())
{
   //use code here 
}

public static bool IsValidEmail(this string email)
{
  string pattern = @"^(?!\.)(""([^""\r\\]|\\[""\r\\])*""|" + @"([-a-z0-9!#$%&'*+/=?^_`{|}~]|(?<!\.)\.)*)(?<!\.)" + @"@[a-z0-9][\w\.-]*[a-z0-9]\.[a-z][a-z\.]*[a-z]$";    
  var regex = new Regex(pattern, RegexOptions.IgnoreCase);    
  return regex.IsMatch(email);
}

2
Gracias por la solución
Jack Gajanan

Tuve que cambiar el bool estático público IsValidEmail (este correo electrónico de cadena) por el bool estático público IsValidEmail (correo electrónico de cadena) para evitar ESTO: stackoverflow.com/questions/10412233/…
Goner Doug

@Goner Doug, esta funcionalidad funcionará así. (Bool flag = EmailAddress.IsValidEmail ())
Naveen

2
el "ESTE" necesitaba ser eliminado para evitar causar problemas de compilación cuando se agregaba a mi formulario.
Goner Doug

@Goner Doug, su funcionalidad funcionará así. cadena de correo electrónico = "abc@xyz.com"; if (email.IsValidEmail ()) {return false; } else {return true;}
Naveen

14

La forma más elegante es utilizar los métodos integrados de .Net.

Estos métodos:

  • Son probados y probados. Estos métodos se utilizan en mis propios proyectos profesionales.

  • Use expresiones regulares internamente, que son confiables y rápidas.

  • Hecho por Microsoft para C #. No hay necesidad de reinventar la rueda.

  • Devuelve un resultado bool. Verdadero significa que el correo electrónico es válido.

Para usuarios de .Net 4.5 y superior

Agregue esta referencia a su proyecto:

System.ComponentModel.DataAnnotations

Ahora puede usar el siguiente código:

(new EmailAddressAttribute().IsValid("youremailhere@test.test"));

Ejemplo de uso

Aquí hay algunos métodos para declarar:

protected List<string> GetRecipients() // Gets recipients from TextBox named `TxtRecipients`
{
    List<string> MethodResult = null;

    try
    {
        List<string> Recipients = TxtRecipients.Text.Replace(",",";").Replace(" ", "").Split(';').ToList();

        List<string> RecipientsCleaned = new List<string>();

        foreach (string Recipient in RecipientsCleaned)
        {
            if (!String.IsNullOrWhiteSpace(Recipient))
            {
                RecipientsNoBlanks.Add(Recipient);

            }

        }

        MethodResult = RecipientsNoBlanks;

    }
    catch//(Exception ex)
    {
        //ex.HandleException();
    }

    return MethodResult;

}


public static bool IsValidEmailAddresses(List<string> recipients)
{
    List<string> InvalidAddresses = GetInvalidEmailAddresses(recipients);

    return InvalidAddresses != null && InvalidAddresses.Count == 0;

}

public static List<string> GetInvalidEmailAddresses(List<string> recipients)
{
    List<string> MethodResult = null;

    try
    {
        List<string> InvalidEmailAddresses = new List<string>();

        foreach (string Recipient in recipients)
        {
            if (!(new EmailAddressAttribute().IsValid(Recipient)) && !InvalidEmailAddresses.Contains(Recipient))
            {
                InvalidEmailAddresses.Add(Recipient);

            }

        }

        MethodResult = InvalidEmailAddresses;

    }
    catch//(Exception ex)
    {
        //ex.HandleException();

    }

    return MethodResult;

}

... y código que los demuestra en acción:

List<string> Recipients = GetRecipients();

bool IsValidEmailAddresses = IsValidEmailAddresses(Recipients);

if (IsValidEmailAddresses)
{
    //Emails are valid. Your code here

}
else
{
    StringBuilder sb = new StringBuilder();

    sb.Append("The following addresses are invalid:");

    List<string> InvalidEmails = GetInvalidEmailAddresses(Recipients);

    foreach (string InvalidEmail in InvalidEmails)
    {
        sb.Append("\n" + InvalidEmail);

    }

    MessageBox.Show(sb.ToString());

}

Además, este ejemplo:

  • Se extiende más allá de la especificación ya que una sola cadena se usa para contener 0, una o varias direcciones de correo electrónico escritas por un punto y coma ;.
  • Demuestra claramente cómo utilizar el método IsValid del objeto EmailAddressAttribute.

Alternativa, para usuarios de una versión de .Net inferior a 4.5

Para situaciones en las que .Net 4.5 no está disponible, utilizo la siguiente solución:

Específicamente, yo uso:

public static bool IsValidEmailAddress(string emailAddress)
{
    bool MethodResult = false;

    try
    {
        MailAddress m = new MailAddress(emailAddress);

        MethodResult = m.Address == emailAddress;

    }
    catch //(Exception ex)
    {
        //ex.HandleException();

    }

    return MethodResult;

}

public static List<string> GetInvalidEmailAddresses(List<string> recipients)
{
    List<string> MethodResult = null;

    try
    {
        List<string> InvalidEmailAddresses = new List<string>();

        foreach (string Recipient in recipients)
        {
            if (!IsValidEmail(Recipient) && !InvalidEmailAddresses.Contains(Recipient))
            {
                InvalidEmailAddresses.Add(Recipient);

            }

        }

        MethodResult = InvalidEmailAddresses;

    }
    catch //(Exception ex)
    {
        //ex.HandleException();

    }

    return MethodResult;

}

1
@ThomasAyoub No he visto una respuesta EmailAddressAttribute, y no hay una respuesta que use la nueva MailAddress () con una verificación en input == .Address, así que creo que es bastante útil. Sin leer los comentarios, la respuesta aceptada es bastante incorrecta. La nueva MailAddress ("Foobar Some@thing.com") lo demuestra.
Jan

@ Jan fwiw, Manik venció a Knickerless EmailAddressAttributepor poco menos de cuatro meses, aunque este sí capta el nullproblema.
ruffin

7

Para ser honesto, en el código de producción, lo mejor que hago es buscar un @símbolo.

Nunca estoy en un lugar para validar por completo los correos electrónicos. ¿Sabes cómo veo si fue realmente válido? Si fue enviado. Si no lo hizo, es malo, si lo hizo, la vida es buena. Éso es Todo lo que Necesito Saber.


6

Considero que esta expresión regular es una buena compensación entre verificar algo más que solo la marca @ y aceptar casos extraños:

^[^@\s]+@[^@\s]+(\.[^@\s]+)+$

Al menos te hará poner algo alrededor de la marca @, y colocar al menos un dominio de aspecto normal.


Se me ocurrió la misma expresión regular;) Sin embargo, permite caracteres no válidos
Stefan

Esta respuesta no acepta un TLD en la parte del dominio.
Simone

@Simone probablemente nadie tenga direcciones de correo electrónico con el TLD en la parte del dominio, aunque en la práctica: serverfault.com/a/721929/167961 tenga en cuenta en los comentarios que puede estar prohibido en estos días
Matthew Lock

@MatthewLock ¿Podría ser una dirección de intranet? Al igual que bob@companyinternal?
Simone

@Simone, ¿alguien en la vida real usa ese esquema?
Matthew Lock

4

La validación de la dirección de correo electrónico no es tan fácil como parece. En realidad, es teóricamente imposible validar completamente una dirección de correo electrónico utilizando solo una expresión regular.

Consulte mi publicación de blog al respecto para una discusión sobre el tema y una implementación de F # usando FParsec. [/ shameless_plug]


1
Me gustó tu lista de enfoques alternativos; muy interesante.
Luke Quinane

1
Artículo interesante. Pero en serio, ¿quién está poniendo comentarios, y anidados en eso, en las direcciones de correo electrónico?
Matthew Lock

3
@matthew No sé por qué el IETF lo ha permitido, pero es posible , por lo que una validación exhaustiva debe tenerlo en cuenta.
Mauricio Scheffer

4

Aquí está mi respuesta: la solución de Phil falla para dominios de una letra como "someone@q.com". Lo creas o no, eso se usa =) (va a centurylink, por ejemplo).

La respuesta de Phil también funcionará solo con el estándar PCRE ... por lo que C # lo tomará, pero JavaScript va a bombardear. Es demasiado complejo para javascript. Por lo tanto, no puede usar la solución de Phil para los atributos de validación de mvc.

Aquí está mi expresión regular. Funcionará bien con los atributos de validación MVC.
- Todo antes de @ se simplifica, por lo que al menos JavaScript funcionará. Estoy bien relajando la validación aquí, siempre y cuando el servidor de intercambio no me dé un 5.1.3. - Todo después de @ es la solución de Phil modificada para dominios de una letra.

public const string EmailPattern =
        @"^\s*[\w\-\+_']+(\.[\w\-\+_']+)*\@[A-Za-z0-9]([\w\.-]*[A-Za-z0-9])?\.[A-Za-z][A-Za-z\.]*[A-Za-z]$";

Para las personas que sugieren usar system.net.mail MailMessage (), eso es MANERA de ser flexible. Claro, C # aceptará el correo electrónico, pero luego el servidor de Exchange bombardeará con un error de tiempo de ejecución 5.1.3 tan pronto como intente enviar el correo electrónico.


esa parece ser la mejor respuesta más reflexiva / razonable / del mundo real, ¡gracias Ralph!
Fattie

¡Esta es la mejor respuesta hasta ahora! No puedo creer que una mala solución que acepta basket@ballcomo una dirección de correo electrónico válida haya obtenido la respuesta correcta, así como todos esos votos positivos. ¡Gracias de cualquier manera!
disasterkid

Gracias, esta es la mejor solución y se debe aceptar la respuesta.
Bat_Programmer

3

Si realmente quiere decir si quiere saber si una dirección de correo electrónico es válida ... pídale al intercambiador de correo que lo pruebe, no se necesita regex. Puedo proporcionar el código si así lo solicita.

Los pasos generales son los siguientes: 1. ¿la dirección de correo electrónico tiene una parte de nombre de dominio? (índice de @> 0) 2. usando una consulta DNS pregunte si el dominio tiene un intercambiador de correo 3. abra la conexión tcp al intercambiador de correo 4. usando el protocolo smtp, abra un mensaje al servidor usando la dirección de correo electrónico como el receptor 5. analizar la respuesta del servidor. 6. Salga del mensaje si llegó hasta aquí, todo está bien.

Esto es, como puede imaginar, un tiempo muy costoso y depende de smtp, pero funciona.


¿Creaste falsificaciones, stubs y / o simulacros para esas interfaces?
Mark A

1
Eso no funcionará. El protocolo smtp para verificar una dirección de correo electrónico ha quedado DESAPROBADO / no se ha usado. Se considera una mala práctica habilitar eso en los servidores de correo ya que los spammers usan esa funcionalidad.
Chad Grant

Mantendré su sugerencia hasta el punto 2. Mucho más a prueba de futuro que buscar un patrón de nombre de dominio conocido.
Simone

Nitpicking, pero definir "tiene un intercambiador de correo" ? Si no existen registros MX, SMTP debe recurrir al registro A / AAAA, según RFC2821 / 5321. Si existe un registro MX, aún podría no indicar que existe un intercambiador de correo (RFC7505). Realmente, la única forma es enviarles un correo con un enlace de llamado a la acción, y esperar a que respondan ...
jimbobmcgee

2

En términos generales, una expresión regular para validar direcciones de correo electrónico no es algo fácil de inventar; En el momento de escribir este artículo, la sintaxis de una dirección de correo electrónico debe seguir un número relativamente alto de estándares y la implementación de todos ellos dentro de una expresión regular es prácticamente inviable.

Le recomiendo que pruebe nuestro EmailVerify.NET , una biblioteca .NET madura que puede validar las direcciones de correo electrónico siguiendo todos los estándares actuales de IETF (RFC 1123, RFC 2821, RFC 2822, RFC 3696, RFC 4291, RFC 5321 y RFC 5322) , prueba los registros DNS relacionados, comprueba si los buzones de correo de destino pueden aceptar mensajes e incluso puede decir si una dirección determinada es desechable o no.

Descargo de responsabilidad: soy el desarrollador principal de este componente.


¡Impresionante! "Luego, intenta ponerse en contacto con el intercambiador de correo responsable de la dirección de correo electrónico dada y comienza un diálogo SMTP falso con ese servidor, emulando un servidor de correo real. De esta manera se asegura que el servidor pueda manejar los correos electrónicos de la dirección. Muchos servidores SMTP en realidad devolver respuestas falsas positivas como protección contra los spammers: para superar este problema, EmailVerify para .NET finalmente intenta consultar el intercambiador de correo objetivo varias veces con diferentes direcciones fabricadas. "
Matthew Lock

Gracias, @MatthewLock;)
Efran Cobisi

Bien, pero solo veo ediciones pagas. ¿Algún plan para una edición comunitaria / OpenSource?
Ohad Schneider

1
@OhadSchneider Sí: estamos ofreciendo una versión gratuita de nuestra tecnología de validación de correo electrónico a través de Verifalia, nuestro servicio de verificación de correo electrónico SaaS . Verifalia viene con SDK gratuitos y de código abierto para las principales plataformas de desarrollo de software, incluido .NET .
Efran Cobisi

2
For the simple email like goerge@xxx.com, below code is sufficient. 

 public static bool ValidateEmail(string email)
        {
            System.Text.RegularExpressions.Regex emailRegex = new System.Text.RegularExpressions.Regex(@"^([\w\.\-]+)@([\w\-]+)((\.(\w){2,3})+)$");
            System.Text.RegularExpressions.Match emailMatch = emailRegex.Match(email);
            return emailMatch.Success;
        }

No podrá validar a@b.info como una dirección de correo electrónico válida.
Ray Cheng el

2

En caso de que esté utilizando FluentValidation , podría escribir algo tan simple como esto:

public cass User
{
    public string Email { get; set; }
}

public class UserValidator : AbstractValidator<User>
{
    public UserValidator()
    {
        RuleFor(x => x.Email).EmailAddress().WithMessage("The text entered is not a valid email address.");
    }
}

// Validates an user. 
var validationResult = new UserValidator().Validate(new User { Email = "açflkdj" });

// This will return false, since the user email is not valid.
bool userIsValid = validationResult.IsValid;

2

una pequeña modificación a la respuesta de @Cogwheel

public static bool IsValidEmail(this string email)
{
  // skip the exception & return early if possible
  if (email.IndexOf("@") <= 0) return false;

  try
  {
    var address = new MailAddress(email);
    return address.Address == email;
  }
  catch
  {
    return false;
  }
}

Esto no parece ayudar ... Console.WriteLine(MailAddress("asdf@asdf.").Address);genera "asdf @ asdf", que no es válido.
Langdon el

.net parece tener su propia definición de válido. discusión
waitforit

2

Hay muchas respuestas fuertes aquí. Sin embargo, recomiendo que demos un paso atrás. @Cogwheel responde la pregunta https://stackoverflow.com/a/1374644/388267 . Sin embargo, podría ser costoso en un escenario de validación masiva, si muchas de las direcciones de correo electrónico que se validan no son válidas. Sugiero que empleemos un poco de lógica antes de entrar en su bloque try-catch. Sé que el siguiente código podría escribirse usando RegEx, pero eso podría ser costoso para los nuevos desarrolladores. Este es mi valor de dos peniques:

    public static bool IsEmail(this string input)
    {
        if (string.IsNullOrWhiteSpace(input)) return false;

        // MUST CONTAIN ONE AND ONLY ONE @
        var atCount = input.Count(c => c == '@');
        if (atCount != 1) return false;

        // MUST CONTAIN PERIOD
        if (!input.Contains(".")) return false;

        // @ MUST OCCUR BEFORE LAST PERIOD
        var indexOfAt = input.IndexOf("@", StringComparison.Ordinal);
        var lastIndexOfPeriod = input.LastIndexOf(".", StringComparison.Ordinal);
        var atBeforeLastPeriod = lastIndexOfPeriod > indexOfAt;
        if (!atBeforeLastPeriod) return false;

        // CODE FROM COGWHEEL'S ANSWER: https://stackoverflow.com/a/1374644/388267 
        try
        {
            var addr = new System.Net.Mail.MailAddress(input);
            return addr.Address == input;
        }
        catch
        {
            return false;
        }
    }

2

La respuesta más votada de @Cogwheel es la mejor respuesta, sin embargo, he intentado implementar el trim()método de cadena para que recorte todo el espacio en blanco del usuario de principio a fin. Verifique el código a continuación para ver un ejemplo completo:

bool IsValidEmail(string email)
{
    try
    {
        email = email.Trim();
        var addr = new System.Net.Mail.MailAddress(email);
        return addr.Address == email;
    }
    catch
    {
        return false;
    }
}

El riesgo de esto es que está validando una dirección de correo electrónico diferente de la fuente, lo que le hace pensar que puede enviar por correo a la versión no recortada (en este caso) de la dirección de correo electrónico especificada. Un mejor enfoque sería hacer un método separado SanitizeEmail(string email), utilizando el resultado de ese método para validar y enviar el correo electrónico.
Marco de Zeeuw

1
private static bool IsValidEmail(string emailAddress)
{
    const string validEmailPattern = @"^(?!\.)(""([^""\r\\]|\\[""\r\\])*""|"
                                     + @"([-a-z0-9!#$%&'*+/=?^_`{|}~]|(?<!\.)\.)*)(?<!\.)"
                                     + @"@[a-z0-9][\w\.-]*[a-z0-9]\.[a-z][a-z\.]*[a-z]$";

    return new Regex(validEmailPattern, RegexOptions.IgnoreCase).IsMatch(emailAddress);
}

1

Compruebe que la cadena de correo electrónico tenga el formato correcto o incorrecto System.Text.RegularExpressions:

    public static bool IsValidEmailId(string InputEmail)
    {
        Regex regex = new Regex(@"^([\w\.\-]+)@([\w\-]+)((\.(\w){2,3})+)$");
        Match match = regex.Match(InputEmail);
        if (match.Success)
            return true;
        else
            return false;
    }

    protected void Email_TextChanged(object sender, EventArgs e)
    {
        String UserEmail = Email.Text;
        if (IsValidEmailId(UserEmail))
        {
            Label4.Text = "This email is correct formate";
        }
        else
        {
            Label4.Text = "This email isn't correct formate";
        }
    }

1

/ Uso de la expresión regular interna utilizada para crear el "nuevo EmailAddressAttribute ();" componente en .Net4.5 >>> usando System.ComponentModel.DataAnnotations; // Para validar una dirección de correo electrónico ...... Probado y funcionando.

public bool IsEmail(string email)
{
    if (String.IsNullOrEmpty(email))
    {   return false;  }
    try
    {
        Regex _regex = new Regex("^((([a-z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])" +
                "+(\\.([a-z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])+)*)|((\\x22)" +
                "((((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(([\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]|\\x21|[\\x23-\\x5b]|[\\x5d-\\x7e]|" +
                "[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(\\\\([\\x01-\\x09\\x0b\\x0c\\x0d-\\x7f]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\u" +
                "FDF0-\\uFFEF]))))*(((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(\\x22)))@((([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|" +
                "(([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])*([a-z]|\\d|" +
                "[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])))\\.)+(([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(([a-z]|[\\u00A0-\\uD7FF\\uF900" +
                "-\\uFDCF\\uFDF0-\\uFFEF])([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])*([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFF" +
                "EF])))\\.?$", RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture | RegexOptions.Compiled);
        return _regex.IsMatch(email);
    }
    catch (RegexMatchTimeoutException)
    {
        return false;
    }
}

Además, puedes usar esto:

http://msdn.microsoft.com/en-us/library/01escwtf(v=vs.110).aspx


dice verdadero para este correo electrónico: "fulya_42_@hotmail.coö" y arroja un error en la api mandril
MonsterMMORPG

1
Primero, el correo electrónico es válido wrt example@example.co o example@example.com .... El correo electrónico tiene todas las cadenas y criterios válidos, excepto el último carácter "ö" y puede agregar fácilmente una condición simple para validar dicho carácter . En segundo lugar, no estoy seguro acerca de ese error de la API de mandril, es posible que desee verificar su método de uso porque he utilizado esta validación en otro entorno / API y ha sido bueno para mí.
Aina Ademola C

1

He resumido la respuesta de Poyson 1 así:

public static bool IsValidEmailAddress(string candidateEmailAddr)
{
    string regexExpresion = "\\w+([-+.']\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*";
    return (Regex.IsMatch(candidateEmailAddr, regexExpresion)) && 
           (Regex.Replace(candidateEmailAddr, regexExpresion, string.Empty).Length == 0);
}

1

Una forma simple de identificar el correo electrónico es válida o no.

public static bool EmailIsValid(string email)
{
        return Regex.IsMatch(email, @"^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$");
}

1

Hay un problema de cultura en regex en C # en lugar de js. Por lo tanto, necesitamos usar expresiones regulares en modo estadounidense para la verificación de correo electrónico. Si no usa el modo ECMAScript, los caracteres especiales de su idioma están implícitos en AZ con regex.

Regex.IsMatch(email, @"^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9_\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$", RegexOptions.ECMAScript)

1

Terminé usando esta expresión regular, ya que valida con éxito comas, comentarios, caracteres Unicode y direcciones de dominio IP (v4).

Las direcciones válidas serán:

"" @ example.org

(comentario) prueba@ejemplo.org

тест@example.org

ტესტი @ example.org

prueba @ [192.168.1.1]

 public const string REGEX_EMAIL = @"^(((\([\w!#$%&'*+\/=?^_`{|}~-]*\))?[^<>()[\]\\.,;:\s@\""]+(\.[^<>()[\]\\.,;:\s@\""]+)*)|(\"".+\""))(\([\w!#$%&'*+\/=?^_`{|}~-]*\))?@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$";

1

Una simple sin usar Regex (que no me gusta por su poca legibilidad):

bool IsValidEmail(string email)
{
    string emailTrimed = email.Trim();

    if (!string.IsNullOrEmpty(emailTrimed))
    {
        bool hasWhitespace = emailTrimed.Contains(" ");

        int indexOfAtSign = emailTrimed.LastIndexOf('@');

        if (indexOfAtSign > 0 && !hasWhitespace)
        {
            string afterAtSign = emailTrimed.Substring(indexOfAtSign + 1);

            int indexOfDotAfterAtSign = afterAtSign.LastIndexOf('.');

            if (indexOfDotAfterAtSign > 0 && afterAtSign.Substring(indexOfDotAfterAtSign).Length > 1)
                return true;
        }
    }

    return false;
}

Ejemplos:

  • IsValidEmail("@b.com") // false
  • IsValidEmail("a@.com") // false
  • IsValidEmail("a@bcom") // false
  • IsValidEmail("a.b@com") // false
  • IsValidEmail("a@b.") // false
  • IsValidEmail("a b@c.com") // false
  • IsValidEmail("a@b c.com") // false
  • IsValidEmail("a@b.com") // true
  • IsValidEmail("a@b.c.com") // true
  • IsValidEmail("a+b@c.com") // true
  • IsValidEmail("a@123.45.67.89") // true

Se pretende que sea simple y, por lo tanto, no trata casos raros como correos electrónicos con dominios entre corchetes que contienen espacios (generalmente permitidos), correos electrónicos con direcciones IPv6, etc.


1

Aquí hay una respuesta a su pregunta para que la revise.

using System;
using System.Globalization;
using System.Text.RegularExpressions;

public class RegexUtilities
{    
   public bool IsValidEmail(string strIn)
   {
       if (String.IsNullOrEmpty(strIn))
       {
          return false;

       }

       // Use IdnMapping class to convert Unicode domain names.

       try 
       {
          strIn = Regex.Replace(strIn, @"(@)(.+)$", this.DomainMapper, RegexOptions.None, TimeSpan.FromMilliseconds(200));

       }
       catch (RegexMatchTimeoutException) 
       {
           return false;

       }

       if (invalid)
       {
           return false;

       }

       // Return true if strIn is in valid e-mail format.    

       try 
       {
          return Regex.IsMatch(strIn, @"^(?("")("".+?(?<!\\)""@)|(([0-9a-z]((\.(?!\.))|       [-!#\$%&'\*\+/=\?\^`\{\}\|~\w])*)(?<=[0-9a-z])@))(?(\[)(\[(\d{1,3}\.){3}\d{1,3}\])|(([0-9a-z][-\w]*[0-9a-z]*\.)+[a-z0-9][\-a-z0-9]{0,22}[a-z0-9]))$", RegexOptions.IgnoreCase, TimeSpan.FromMilliseconds(250));

       }
       catch (RegexMatchTimeoutException) 
       {
          return false;

       }

   }


   private string DomainMapper(Match match)
   {
      // IdnMapping class with default property values.

      IdnMapping idn = new IdnMapping();

      string domainName = match.Groups[2].Value;

      try 
      {
         domainName = idn.GetAscii(domainName);

      }
      catch (ArgumentException) 
      {
         invalid = true;

      }

      return match.Groups[1].Value + domainName;

   }

}

1

Según la respuesta de @Cogwheel, quiero compartir una solución modificada que funcione para SSIS y el "Componente de script":

  1. Coloque el "Componente de secuencia de comandos" en su conexión de flujo de datos y luego ábralo.
  2. En la sección "Columnas de entrada" establezca el campo que contiene las direcciones de correo electrónico en "ReadWrite" (en el ejemplo 'fieldName').
  3. Vuelva a la sección "Script" y haga clic en "Editar script". Luego debe esperar después de que se abra el código.
  4. Coloque este código en el método correcto:

    public override void Input0_ProcessInputRow(Input0Buffer Row)
    {
        string email = Row.fieldName;
    
        try
        {
            System.Net.Mail.MailAddress addr = new System.Net.Mail.MailAddress(email);
            Row.fieldName= addr.Address.ToString();
        }
        catch
        {
            Row.fieldName = "WRONGADDRESS";
        }
    }

Luego, puede usar una división condicional para filtrar todos los registros no válidos o lo que quiera hacer.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.