【问题标题】:Validate email local component验证电子邮件本地组件
【发布时间】:2012-09-02 22:45:48
【问题描述】:

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

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]+)*)$

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

我的领域的整个代码,在这个阶段不一定相关,但我不介意对此发表评论:

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:所以表单字段和标签将如下所示:

所需的电子邮件地址:[---可键入区域---] @domain.com

【问题讨论】:

  • 为什么不正常验证邮件,然后检查是否email.endswith('@domain.com')
  • 用户没有输入@domain.com,它将被设置为表单中字段之后的标签。用户只需在@ 之前输入电子邮件字段的第一部分
  • 所以基本上"[^@]*" ?
  • 我的问题显然写得很糟糕,尽管我不知道如何改进它。用户在任何时候都不会输入文本@domain.com,他们只输入电子邮件的用户名。
  • 你明确地允许 '?'在那个正则表达式中(你确定 ? 不是电子邮件用户名部分的有效部分......我认为规则非常宽松......)

标签: python regex django email-validation


【解决方案1】:

您说“不受欢迎的字符,例如?”,但我认为您误解了哪些字符是可取的。原始正则表达式允许使用问号。

请注意,您还可以定义自己的不使用大量正则表达式的验证器,并有机会稍后解码逻辑。

【讨论】:

  • 电子邮件的有效用户部分非常开放......我同意另一个答案,即正则表达式可能不合适......当然不是一个疯狂的大问题
  • 由于这是用于创建电子邮件帐户,也许我们可以简单地限制允许的字符超出规范允许的范围,然后编写一个更简单的验证器。另外,天哪!
【解决方案2】:

有些人在遇到问题时会想,“我知道,我会用 常用表达。”现在他们有两个问题。 - 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!'

      

【讨论】:

  • 这是用于创建电子邮件帐户,而不是用于验证
  • 那么你可以编写你自己的规则,说明在一个漂亮的简短正则表达式中不允许什么......不需要那个怪物......
  • 是的,我认为这是要走的路,我们可以以简单的名义合理地否认这些角色。
  • 如果是这种情况,那么只需 valid_chars = [string.letters+string.digits+'-'] 然后搜索。
  • 或者可能更好 invalid_chars_re = "[^?@#]*" 并且只允许特定字符而不是允许一大堆...
【解决方案3】:

我还是 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 的文档?

【讨论】:

  • 好像很多人都漏掉了自定义字段的要求,也就是只输入想要的邮箱的用户名部分,比如USER@DOMAIN.COM,用户只会输入USER。你是对的,尽管我应该研究字段验证并更多地了解 clean 方法:)
  • 除非我遗漏了一些重要的东西,否则这应该完全符合您的要求。但是,它并没有跳过箍来准确定义有效用户名的构成,而是采用(对我而言)更简单的方法,接受USER 作为表单输入,附加@DOMAIN.COM,使用Django 的内置字段验证整个地址,然后返回USER
【解决方案4】:

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

Python 的默认引擎不允许这样做,因此您最好使用一个非常简单(宽松的)正则表达式。

【讨论】:

  • 正则表达式根据定义不能匹配嵌套的任何东西......你需要一个堆栈(或某种形式的内存)......是否有任何 python 正则表达式模块可以匹配嵌套项目?
  • 你真的需要匹配括号才能知道它是否是一个有效的地址吗?
  • @JoranBeasley:是的,“扩展正则表达式”指的是允许您执行此操作的 .NET 或类似 Perl 的引擎。我不确定 Python 正则表达式是否有类似 PCRE 的接口?
  • 好吧,我只是不知道有什么,我喜欢关注这样的事情:)
猜你喜欢
  • 2014-06-12
  • 1970-01-01
  • 2019-03-04
  • 2015-12-08
  • 2011-05-15
  • 2018-03-13
  • 2011-09-02
  • 2013-02-20
  • 2014-03-12
相关资源
最近更新 更多