验证电子邮件本地组件

时间:2012-09-10 04:38:46

标签: python regex django email-validation

我正在编写一个只需要接受所需电子邮件地址的本地组件的注册表单。域组件已固定到站点。我试图通过有选择地复制Django为validators.validate_email提供的EmailField来验证它:

email_re = re.compile(
    r"(^[-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*"  # dot-atom
    # quoted-string, see also http://tools.ietf.org/html/rfc2822#section-3.2.5
    r'|^"([\001-\010\013\014\016-\037!#-\[\]-\177]|\\[\001-\011\013\014\016-\177])*"'
    r')@((?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+[A-Z]{2,6}\.?$)'  # domain
    r'|\[(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}\]$', re.IGNORECASE)  # literal form, ipv4 address (SMTP 4.1.3)
validate_email = EmailValidator(email_re, _(u'Enter a valid e-mail address.'), 'invalid')

以下是我的代码。我的主要问题是我无法适应正则表达式。此时我只是在http://www.pythonregex.com/的正则表达式测试中对它进行测试,但是它失败了:

^([-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*)$

这似乎传递了不受欢迎的字符,例如?

我的Field的整个代码,在这个阶段不一定相关,但我不介意对它进行一些评论:

class LocalEmailField(CharField):    
    email_local_re = re.compile(r"^([-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*)$", re.IGNORECASE)
    validate_email_local = RegexValidator(email_re, (u'Enter a valid e-mail username.'), 'invalid')
    default_validators = [validate_email_local]

编辑:为了澄清,用户只在@之前输入文本,因此我无需在验证器中验证@domain.com

编辑2:因此表单字段和标签将如下所示:

所需的电子邮件地址:[--- type-able area ---] @ domain.com

4 个答案:

答案 0 :(得分:2)

你说“?”之类的“不受欢迎的字符”,但我认为你错误地认为哪些字符是可取的。原始的正则表达式允许问号。

请注意,您还可以定义自己的验证程序,该验证程序不使用大量正则表达式,并且稍后可能会对逻辑进行解码。

答案 1 :(得分:1)

  

有些人在遇到问题时会想:“我知道,我会用   正则表达式。“现在他们有两个问题。 - Jamie Zawinski

通过正则表达式进行检查是一种浪费时间的练习。最好的方法是尝试交付;这样,您不仅可以验证电子邮件地址,还可以验证邮箱是否实际处于活动状态并且可以接收电子邮件。

否则,您将最终进入一个不可能希望匹配所有rules的每个扩展正则表达式。

"Haha boo hoo woo woo!"@foo.com是有效地址,qwerterukeriouo@gmail.com

也是

相反,提供几乎标准的“请点击我们发送到blahblah@goo.com的电子邮件中的链接来验证您的地址。”方法。

如果您想创建电子邮件地址,那么您可以编写自己的规则,了解可以作为电子邮件组件的一部分;它们可以是RFC中官方允许的字符的一部分。

例如,保守规则(不使用正则表达式):

allowed_chars = [string.digits+string.letters+'-']

if len([x in user_input if x not in allowed_chars]):
   print 'Sorry, invalid characters'
else:
   if user_input[0] in string.digits+'-':
      print 'Cannot start with a number or `-`'
   else:
      if check_if_already_exists(user_input):
         print 'Sorry, already taken'
      else:
         print 'Congratulations!'

答案 2 :(得分:1)

我还是Django和Python的新手,但为什么要重新发明轮子并保持自己的正则表达式呢?如果除了希望用户只输入其电子邮件地址的本地部分之外,您对Django的内置EmailField感到满意,您可以非常轻松地对其进行子类化并稍微调整验证逻辑:

DOMAIN_NAME = u'foo.com'


class LocalEmailField(models.EmailField):
    def clean(local_part):
        whole_address = '%s@%s' % (local_part, DOMAIN_NAME)
        clean_address = super(LocalEmailField, self).clean(whole_address)
        # Can do more checking here if necessary
        clean_local, at_sign, clean_domain = clean_address.rpartition('@')
        return clean_local

您是否查看了Form and Field Validation.clean() method的文档?

答案 3 :(得分:0)

如果你想用正则表达式100%正确地完成它,你需要使用一种带有某种形式的扩展正则表达式的引擎,它允许匹配嵌套的括号。

Python的默认引擎不允许这样做,所以你最好用一个非常简单(允许)的正则表达式来妥协。