in

regex – ¿Cómo puedo validar una dirección de correo electrónico usando una expresión regular?

apple touch icon@2

Utilice la siguiente expresión regular para la validación de entrada:

([-!#-'*+/-9=?A-Z^-~]+(.[-!#-'*+/-9=?A-Z^-~]+)*|"([]!#-[^-~ t]|(\[t -~]))+")@[0-9A-Za-z]([0-9A-Za-z-]{0,61}[0-9A-Za-z])?(.[0-9A-Za-z]([0-9A-Za-z-]{0,61}[0-9A-Za-z])?)+

Direcciones que coinciden con esta expresión regular:

  • tener una parte local (es decir, la parte antes del signo @) que cumpla estrictamente con RFC 5321/5322,
  • tener una parte de dominio (es decir, la parte después del signo @) que sea un nombre de host con al menos dos etiquetas, cada una de las cuales tenga un máximo de 63 caracteres.

La segunda restricción es una restricción en RFC 5321/5322.

El uso de una expresión regular que reconozca las direcciones de correo electrónico podría ser útil en varias situaciones: por ejemplo, para buscar direcciones de correo electrónico en un documento, para validar la entrada del usuario o como una restricción de integridad en un depósito de datos.

Sin embargo, debe tenerse en cuenta que si desea saber si la dirección realmente se refiere a un buzón existente, no hay sustituto para enviar un mensaje a la dirección. Si solo desea verificar si una dirección es gramaticalmente correcta, puede usar una expresión regular, pero tenga en cuenta que ""@[] es una dirección de correo electrónico gramaticalmente correcta que ciertamente no se refiere a un buzón de correo existente.

La sintaxis de las direcciones de correo electrónico se ha definido en varios RFC, más destacado RFC 822 y RFC 5322. RFC 822 debe verse como el estándar «original» y RFC 5322 como el estándar más reciente. La sintaxis definida en RFC 822 es la más indulgente y los estándares posteriores han restringido la sintaxis cada vez más, donde los sistemas o servicios más nuevos deben reconocer la sintaxis obsoleta, pero nunca producirla.

En esta respuesta, tomaré «dirección de correo electrónico» para significar addr-spec como se define en las RFC (es decir, jdoe@example.org, pero no "John Doe"<jdoe@example.org>, ni some-group:jdoe@example.org,mrx@exampel.org;).

Hay un problema al traducir las sintaxis RFC a expresiones regulares: ¡las sintaxis no son regulares! Esto se debe a que permiten comentarios opcionales en direcciones de correo electrónico que se pueden anidar infinitamente, mientras que el anidamiento infinito no se puede describir mediante una expresión regular. Para buscar o validar direcciones que contienen comentarios, necesita un analizador o expresiones más potentes. (Tenga en cuenta que los lenguajes como Perl tienen construcciones para describir gramáticas libres de contexto de una manera similar a una expresión regular). En esta respuesta, ignoraré los comentarios y solo consideraré las expresiones regulares adecuadas.

Las RFC definen sintaxis para mensajes de correo electrónico, no para direcciones de correo electrónico como tales. Las direcciones pueden aparecer en varios campos de encabezado y aquí es donde se definen principalmente. Cuando aparecen en los campos de encabezado, las direcciones pueden contener (entre tokens léxicos) espacios en blanco, comentarios e incluso saltos de línea. Sin embargo, semánticamente esto no tiene importancia. Al eliminar este espacio en blanco, etc. de una dirección, obtiene un equivalente semánticamente representación canónica. Así, la representación canónica de first. last (comment) @ [3.5.7.9] es first.last@[3.5.7.9].

Deben usarse diferentes sintaxis para diferentes propósitos. Si desea buscar direcciones de correo electrónico en un documento (posiblemente muy antiguo), puede ser una buena idea usar la sintaxis tal como se define en RFC 822. Por otro lado, si desea validar la entrada del usuario, puede usar el sintaxis como se define en RFC 5322, probablemente solo acepte representaciones canónicas. Debe decidir qué sintaxis se aplica a su caso específico.

Utilizo expresiones regulares POSIX «extendidas» en esta respuesta, asumiendo un conjunto de caracteres compatible con ASCII.

RFC 822

Llegué a la siguiente expresión regular. Los invito a todos a intentar romperlo. Si encuentra falsos positivos o falsos negativos, publíquelos en un comentario e intentaré corregir la expresión lo antes posible.

([^][()<>@,;:\". x00-x1Fx7F]+|"(n|(\r)*([^"\rn]|\[^r]))*(\r)*")(.([^][()<>@,;:\". x00-x1Fx7F]+|"(n|(\r)*([^"\rn]|\[^r]))*(\r)*"))*@([^][()<>@,;:\". x00-x1Fx7F]+|[(n|(\r)*([^][\rn]|\[^r]))*(\r)*])(.([^][()<>@,;:\". x00-x1Fx7F]+|[(n|(\r)*([^][\rn]|\[^r]))*(\r)*]))*

Creo que es totalmente compatible con RFC 822, incluido el erratas. Solo reconoce las direcciones de correo electrónico en su forma canónica. Para una expresión regular que reconoce (plegamiento) espacios en blanco, consulte la derivación a continuación.

La derivación muestra cómo llegué a la expresión. Enumero todas las reglas gramaticales relevantes del RFC exactamente como aparecen, seguidas de la expresión regular correspondiente. Cuando se ha publicado una errata, doy una expresión separada para la regla gramatical corregida (marcada como «errata») y uso la versión actualizada como subexpresión en las siguientes expresiones regulares.

Como se indica en el párrafo 3.1.4. de RFC 822 se puede insertar un espacio en blanco lineal opcional entre los tokens léxicos. Cuando corresponde, he ampliado las expresiones para adaptarlas a esta regla y he marcado el resultado con «opt-lwsp».

CHAR        =  <any ASCII character>
            =~ .

CTL         =  <any ASCII control character and DEL>
            =~ [x00-x1Fx7F]

CR          =  <ASCII CR, carriage return>
            =~ r

LF          =  <ASCII LF, linefeed>
            =~ n

SPACE       =  <ASCII SP, space>
            =~  

HTAB        =  <ASCII HT, horizontal-tab>
            =~ t

<">         =  <ASCII quote mark>
            =~ "

CRLF        =  CR LF
            =~ rn

LWSP-char   =  SPACE / HTAB
            =~ [ t]

linear-white-space =  1*([CRLF] LWSP-char)
                   =~ ((rn)?[ t])+

specials    =  "(" / ")" / "<" / ">" / "@" /  "," / ";" / ":" / "" / <"> /  "." / "[" / "]"
            =~ [][()<>@,;:\".]

quoted-pair =  "" CHAR
            =~ \.

qtext       =  <any CHAR excepting <">, "" & CR, and including linear-white-space>
            =~ [^"\r]|((rn)?[ t])+

dtext       =  <any CHAR excluding "[", "]", "" & CR, & including linear-white-space>
            =~ [^][\r]|((rn)?[ t])+

quoted-string  =  <"> *(qtext|quoted-pair) <">
               =~ "([^"\r]|((rn)?[ t])|\.)*"
(erratum)      =~ "(n|(\r)*([^"\rn]|\[^r]|(rn)?[ t]))*(\r)*"

domain-literal =  "[" *(dtext|quoted-pair) "]"
               =~ [([^][\r]|((rn)?[ t])|\.)*]
(erratum)      =~ [(n|(\r)*([^][\rn]|\[^r]|(rn)?[ t]))*(\r)*]

atom        =  1*<any CHAR except specials, SPACE and CTLs>
            =~ [^][()<>@,;:\". x00-x1Fx7F]+

word        =  atom / quoted-string
            =~ [^][()<>@,;:\". x00-x1Fx7F]+|"(n|(\r)*([^"\rn]|\[^r]|(rn)?[ t]))*(\r)*"

domain-ref  =  atom

sub-domain  =  domain-ref / domain-literal
            =~ [^][()<>@,;:\". x00-x1Fx7F]+|[(n|(\r)*([^][\rn]|\[^r]|(rn)?[ t]))*(\r)*]

local-part  =  word *("." word)
            =~ ([^][()<>@,;:\". x00-x1Fx7F]+|"(n|(\r)*([^"\rn]|\[^r]|(rn)?[ t]))*(\r)*")(.([^][()<>@,;:\". x00-x1Fx7F]+|"(n|(\r)*([^"\rn]|\[^r]|(rn)?[ t]))*(\r)*"))*
(opt-lwsp)  =~ ([^][()<>@,;:\". x00-x1Fx7F]+|"(n|(\r)*([^"\rn]|\[^r]|(rn)?[ t]))*(\r)*")(((rn)?[ t])*.((rn)?[ t])*([^][()<>@,;:\". x00-x1Fx7F]+|"(n|(\r)*([^"\rn]|\[^r]|(rn)?[ t]))*(\r)*"))*

domain      =  sub-domain *("." sub-domain)
            =~ ([^][()<>@,;:\". x00-x1Fx7F]+|[(n|(\r)*([^][\rn]|\[^r]|(rn)?[ t]))*(\r)*])(.([^][()<>@,;:\". x00-x1Fx7F]+|[(n|(\r)*([^][\rn]|\[^r]|(rn)?[ t]))*(\r)*]))*
(opt-lwsp)  =~ ([^][()<>@,;:\". x00-x1Fx7F]+|[(n|(\r)*([^][\rn]|\[^r]|(rn)?[ t]))*(\r)*])(((rn)?[ t])*.((rn)?[ t])*([^][()<>@,;:\". x00-x1Fx7F]+|[(n|(\r)*([^][\rn]|\[^r]|(rn)?[ t]))*(\r)*]))*

addr-spec   =  local-part "@" domain
            =~ ([^][()<>@,;:\". x00-x1Fx7F]+|"(n|(\r)*([^"\rn]|\[^r]|(rn)?[ t]))*(\r)*")(.([^][()<>@,;:\". x00-x1Fx7F]+|"(n|(\r)*([^"\rn]|\[^r]|(rn)?[ t]))*(\r)*"))*@([^][()<>@,;:\". x00-x1Fx7F]+|[(n|(\r)*([^][\rn]|\[^r]|(rn)?[ t]))*(\r)*])(.([^][()<>@,;:\". x00-x1Fx7F]+|[(n|(\r)*([^][\rn]|\[^r]|(rn)?[ t]))*(\r)*]))*
(opt-lwsp)  =~ ([^][()<>@,;:\". x00-x1Fx7F]+|"(n|(\r)*([^"\rn]|\[^r]|(rn)?[ t]))*(\r)*")((rn)?[ t])*(.((rn)?[ t])*([^][()<>@,;:\". x00-x1Fx7F]+|"(n|(\r)*([^"\rn]|\[^r]|(rn)?[ t]))*(\r)*")((rn)?[ t])*)*@((rn)?[ t])*([^][()<>@,;:\". x00-x1Fx7F]+|[(n|(\r)*([^][\rn]|\[^r]|(rn)?[ t]))*(\r)*])(((rn)?[ t])*.((rn)?[ t])*([^][()<>@,;:\". x00-x1Fx7F]+|[(n|(\r)*([^][\rn]|\[^r]|(rn)?[ t]))*(\r)*]))*
(canonical) =~ ([^][()<>@,;:\". x00-x1Fx7F]+|"(n|(\r)*([^"\rn]|\[^r]))*(\r)*")(.([^][()<>@,;:\". x00-x1Fx7F]+|"(n|(\r)*([^"\rn]|\[^r]))*(\r)*"))*@([^][()<>@,;:\". x00-x1Fx7F]+|[(n|(\r)*([^][\rn]|\[^r]))*(\r)*])(.([^][()<>@,;:\". x00-x1Fx7F]+|[(n|(\r)*([^][\rn]|\[^r]))*(\r)*]))*

RFC 5322

Llegué a la siguiente expresión regular. Los invito a todos a intentar romperlo. Si encuentra falsos positivos o falsos negativos, publíquelos en un comentario e intentaré corregir la expresión lo antes posible.

([-!#-'*+/-9=?A-Z^-~]+(.[-!#-'*+/-9=?A-Z^-~]+)*|"([]!#-[^-~ t]|(\[t -~]))+")@([-!#-'*+/-9=?A-Z^-~]+(.[-!#-'*+/-9=?A-Z^-~]+)*|[[t -Z^-~]*])

Creo que es totalmente compatible con RFC 5322, incluido el erratas. Solo reconoce las direcciones de correo electrónico en su forma canónica. Para una expresión regular que reconoce (plegamiento) espacios en blanco, consulte la derivación a continuación.

La derivación muestra cómo llegué a la expresión. Enumero todas las reglas gramaticales relevantes del RFC exactamente como aparecen, seguidas de la expresión regular correspondiente. Para las reglas que incluyen espacios en blanco semánticamente irrelevantes (plegables), doy una expresión regular separada marcada como «(normalizada)» que no acepta este espacio en blanco.

Ignoré todas las reglas «obs-» del RFC. Esto significa que las expresiones regulares solo coinciden con direcciones de correo electrónico que cumplen estrictamente con RFC 5322. Si tiene que hacer coincidir direcciones «antiguas» (como lo hace la gramática más flexible, incluidas las reglas «obs-«), puede utilizar una de las expresiones regulares RFC 822 del párrafo anterior.

VCHAR           =   %x21-7E
                =~  [!-~]

ALPHA           =   %x41-5A / %x61-7A
                =~  [A-Za-z]

DIGIT           =   %x30-39
                =~  [0-9]

HTAB            =   %x09
                =~  t

CR              =   %x0D
                =~  r

LF              =   %x0A
                =~  n

SP              =   %x20
                =~  

DQUOTE          =   %x22
                =~  "

CRLF            =   CR LF
                =~  rn

WSP             =   SP / HTAB
                =~  [t ]

quoted-pair     =   "" (VCHAR / WSP)
                =~  \[t -~]

FWS             =   ([*WSP CRLF] 1*WSP)
                =~  ([t ]*rn)?[t ]+

ctext           =   %d33-39 / %d42-91 / %d93-126
                =~  []!-'*-[^-~]

("comment" is left out in the regex)
ccontent        =   ctext / quoted-pair / comment
                =~  []!-'*-[^-~]|(\[t -~])

(not regular)
comment         =   "(" *([FWS] ccontent) [FWS] ")"

(is equivalent to FWS when leaving out comments)
CFWS            =   (1*([FWS] comment) [FWS]) / FWS
                =~  ([t ]*rn)?[t ]+

atext           =   ALPHA / DIGIT / "!" / "#" / "$" / "%" / "&" / "'" / "*" / "+" / "-" / "/" / "=" / "?" / "^" / "_" / "`" / "{" / "|" / "}" / "~"
                =~  [-!#-'*+/-9=?A-Z^-~]

dot-atom-text   =   1*atext *("." 1*atext)
                =~  [-!#-'*+/-9=?A-Z^-~]+(.[-!#-'*+/-9=?A-Z^-~]+)*

dot-atom        =   [CFWS] dot-atom-text [CFWS]
                =~  (([t ]*rn)?[t ]+)?[-!#-'*+/-9=?A-Z^-~]+(.[-!#-'*+/-9=?A-Z^-~]+)*(([t ]*rn)?[t...

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Java: serialización

gfg 200x200 min

SQL | Comandos DDL, DQL, DML, DCL y TCL