2010-07-10 27 views
53

He escrito una función para agregar correos electrónicos a la base del boletín. Hasta que agregué la validez de verificación del correo electrónico enviado, funcionaba sin problemas. Ahora, cada vez recibo un "correo electrónico incorrecto" a cambio. ¿Alguien puede ver algún error aquí? La expresión regular utilizada es:Verificación de la validez del correo electrónico en django/python

\b[\w\.-][email protected][\w\.-]+\.\w{2,4}\b y es 100% válida (http://gskinner.com/RegExr/), pero puede estar usando mal, o puede haber algún error lógico:

def newsletter_add(request): 
    if request.method == "POST": 
     try: 
      e = NewsletterEmails.objects.get(email = request.POST['email']) 
      message = _(u"Email is already added.") 
      type = "error" 
     except NewsletterEmails.DoesNotExist: 
      if validateEmail(request.POST['email']): 
       try: 
        e = NewsletterEmails(email = request.POST['email']) 
       except DoesNotExist: 
        pass 
       message = _(u"Email added.") 
       type = "success" 
       e.save() 
      else: 
       message = _(u"Wrong email") 
       type = "error" 

import re 

def validateEmail(email): 
    if len(email) > 6: 
     if re.match('\b[\w\.-][email protected][\w\.-]+\.\w{2,4}\b', email) != None: 
      return 1 
    return 0 
+4

100% valido? No coincidirá con 'foo + bar @ example.com', no coincidirá con' foo @ museum.com', y toneladas más. – Kos

+0

100% válido? Tu expresión regular coincidirá con 'a .. @ .............. a'. – Zenadix

Respuesta

131

ACTUALIZACIÓN 2017: el código de abajo es de 7 años de edad y fue modificado desde entonces, fija y ampliado. Para cualquier persona que desee hacer esto ahora, el código correcto vive por aquí: https://github.com/django/django/blob/master/django/core/validators.py#L168-L180

aquí es parte de django.core.validators que puede resultar interesante :)

class EmailValidator(RegexValidator): 

    def __call__(self, value): 
     try: 
      super(EmailValidator, self).__call__(value) 
     except ValidationError, e: 
      # Trivial case failed. Try for possible IDN domain-part 
      if value and u'@' in value: 
       parts = value.split(u'@') 
       domain_part = parts[-1] 
       try: 
        parts[-1] = parts[-1].encode('idna') 
       except UnicodeError: 
        raise e 
       super(EmailValidator, self).__call__(u'@'.join(parts)) 
      else: 
       raise 

email_re = re.compile(
    r"(^[-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*" # dot-atom 
    r'|^"([\001-\010\013\014\016-\037!#-\[\]-\177]|\\[\001-011\013\014\016-\177])*"' # quoted-string 
    r')@(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+[A-Z]{2,6}\.?$', re.IGNORECASE) # domain 
validate_email = EmailValidator(email_re, _(u'Enter a valid e-mail address.'), 'invalid') 

por lo que si no lo hace desea utilizar formularios y campos de formulario, puede importar email_re y usarlo en su función, o incluso mejor - importar validate_email y usarlo, capturando posible ValidationError.

def validateEmail(email): 
    from django.core.validators import validate_email 
    from django.core.exceptions import ValidationError 
    try: 
     validate_email(email) 
     return True 
    except ValidationError: 
     return False 

Y aquí se utiliza Mail::RFC822::Address regexp en Perl, si realmente necesita ser paranoico.

+0

Gracias, tenía una importación con email_re (ese es el fragmento en la web) pero su segundo bloque de código hizo el truco –

+2

Esto ya no es válido con las próximas nuevas extensiones de dominio de nivel superior (más de 6 caracteres para las extensiones creo) http : //mashable.com/2011/06/21/icann-top-level-domains-change/ – jptsetung

+0

Creo que puede haber un error en la expresión 'email_re'. Específicamente en la línea de cadena citada, supongo que la intención es que '\ 001-011' en realidad debería ser' \ 001- \ 011'. ¿Alguna idea? – kalefranz

46

Ick, no, por favor, don No intente validar las direcciones de correo electrónico usted mismo. Es una de esas cosas que las personas nunca entienden bien.

Su opción más segura, ya que usted está usando Django, es simplemente aprovechar su validación de formulario para correo electrónico. Por los documentos (http://docs.djangoproject.com/en/dev/ref/forms/fields/):

>>> from django import forms 
>>> f = forms.EmailField() 
>>> f.clean('[email protected]mple.com') 
u'[email protected]' 
>>> f.clean(u'[email protected]') 
u'[email protected]' 
>>> f.clean('invalid e-mail address') 
... 
ValidationError: [u'Enter a valid e-mail address.'] 
+9

[Aquí hay un pequeño módulo de Python basado en este método] (https://gist.github.com/3683902). Simplemente use 'isEmailAddressValid (address)' para realizar la validación. –

+0

Como la pregunta es sobre Django, esta es la mejor respuesta. +1 para alentar la reutilización y simplicidad del código. –

7

lo tienes mal, pero es una tarea que no se puede hacer de todos modos. Hay una y solo una forma de saber si una dirección RFC 2822 es válida, y eso es para enviarle un correo y obtener una respuesta. Hacer cualquier otra cosa no mejora el contenido de información de su dato ni siquiera por un bit fraccionario.

También tornillo el factor humano y la aceptación de propiedad, ya que cuando le das validateEmail mi dirección de

[email protected] 

y usted me dice que he hecho un error, le digo adiós a su aplicación.

+0

Afortunadamente, esta expresión regular no es mía :) ¿Así que también estás para el método normal de EmailField? – muntu

+0

No hablo django, pero el argumento se aplica a cualquier intento de validación sintáctica de una dirección. http://code.djangoproject.com/ticket/3344 Parece que ni siquiera EmailField puede estar a la altura de la tarea (pero no parecía realmente difícil) – msw

+0

ese ticket en particular está marcado como fijo desde el 07/04/07, y error que había en el manejo de Unicode del mensaje de error traducido. Creo que el uso de validadores Django es relativamente seguro ahora. – cji

0

cambiar su código de esto:

re.match ('\ b [\ w .-] + @ [\ w .-] + \ w {2,4} \ b.', correo electrónico)

a esto:

re.match (r '\ b [\ w .-] + @ [\ w .-] + \ w {2,4} \ b. ', correo electrónico)

funciona bien conmigo.

92
from django.core.exceptions import ValidationError 
from django.core.validators import validate_email 
try: 
    validate_email("[email protected]") 
except ValidationError as e: 
    print "oops! wrong email" 
else: 
    print "hooray! email is valid" 
+2

Esta solución no estaba disponible cuando las preguntas se formularon originalmente, pero definitivamente es la mejor respuesta. – keithhackbarth

+0

¡Y sigue siendo la mejor respuesta en 2017 ..! Reenviar a 2018 ..! Esta debe ser definitivamente una respuesta aceptada según el flujo actual. – Jay

0

Esta expresión regular validará una dirección de correo electrónico con una precisión razonable.

\w[\w\.-]*@\w[\w\.-]+\.\w+ 

Permite caracteres alfanuméricos, _, . y -.

Cuestiones relacionadas