2012-09-10 526 views
-1

我在寫一個註冊表單,只需要接受所需電子郵件地址的本地組件。域組件固定在該站點上。我試圖從validators.validate_email其中Django提供選擇性複製爲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]+)*)$ 

這似乎是通過這樣的不良分子爲?

我的現場,這是不是整個代碼在這個階段一定相關性,但我不會介意一些關於它的評論是:

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

+0

爲什麼不正常驗證電子郵件,然後檢查email.endswith('@ domain.com')'? – Blender

+0

用戶沒有輸入@ domain.com,它將在表單中的字段後面設置爲一個標籤。用戶只是輸入電子郵件字段的第一部分,在@ – DanH

+2

之前這麼基本'''[^ @] *「'? –

回答

2

有人當遇到問題時,請考慮「我知道,我將使用 正則表達式。」現在他們有兩個問題。 - Jamie Zawinski

通過正則表達式檢查是一個浪費時間的練習。最好的方法是嘗試交付;這樣,您不僅可以驗證電子郵件地址,還可以驗證郵箱是否處於活動狀態並可以接收電子郵件。

否則,您將最終在每擴展正則表達式,不可能希望匹配所有rules

"Haha boo hoo woo woo!"@foo.com是一個有效的地址,所以是[email protected]

相反,提供了幾乎標準「請點擊我們發送到[email protected]驗證您的地址的郵件中的鏈接。」方法。

如果你想創建電子郵件地址,那麼你可以編寫自己的規則,可以成爲電子郵件組件的一部分;並且它們可以是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!' 
+0

這是我最喜歡的引號之一... –

+0

這是創建一個電子郵件帳戶,不用於驗證 – DanH

+1

那麼你可以寫出你自己的規則,關於什麼是不允許在一個很好的簡單的正則表達式...沒有這個怪物需要... –

2

你說「不受歡迎的人物,如?」,但我覺得你是錯誤的哪些字符是可取的。原始的正則表達式允許問號。

請注意,您也可以定義您自己的驗證程序,該驗證程序不使用大量的正則表達式,並稍後有機會解碼邏輯。

+0

電子郵件的有效用戶部分是相當開放的...我同意其他答案一個正則表達式可能不適合......並且肯定不是一個瘋狂的大問題 –

+0

因爲這是爲了創建電子郵件帳戶,所以我們可以簡單地限制允許的字符數量超過規範允許的範圍,然後編寫一個更簡單的驗證器。另外,德哦! – DanH

0

如果你想用正則表達式100%完成它,你需要使用一種擴展正則表達式的引擎,它允許匹配嵌套括號。

Python的默認引擎不允許這樣做,所以你最好用一個非常簡單的(寬鬆的)正則表達式來妥協。

+0

regex按定義cant match嵌套任何東西...你需要一個堆棧(或某種形式的內存)...是否有任何可以匹配嵌套項目的Python正則表達式模塊? –

+0

你是否真的需要配對括號來知道它是否是一個有效的地址? –

+0

@JoranBeasley:是的,通過「擴展正則表達式」,我指的是允許你這樣做的.NET或類似Perl的引擎。我不確定是否有Python正則表達式的PCRE類接口? – porges

1

我還對Django和Python很陌生,但爲什麼要重新發明輪子並維護自己的正則表達式?如果,除了希望用戶只需輸入自己的電子郵件地址的本地部分,你滿意的Django的內置EmailField,你可以很容易地繼承它並調整驗證邏輯了一下:

DOMAIN_NAME = u'foo.com' 


class LocalEmailField(models.EmailField): 
    def clean(local_part): 
     whole_address = '%[email protected]%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的文檔?

+0

似乎很多人都缺少自定義字段的要求,也就是說,它只是用於輸入所需的電子郵件地址的用戶名部分例如,在「USER @ DOMAIN.COM」中,用戶只能輸入「USER」。你是對的,雖然我應該看看字段驗證,並讓我的頭清理方法更多:) – DanH

+0

除非我錯過了重要的東西,這應該完全符合您的要求。儘管如此,我們更簡單的方法是接受「USER」作爲表單輸入,附加「@ DOMAIN.COM」,驗證整個地址使用Django的內置字段,然後返回「USER」。 – akshayshah