2013-10-06 26 views
3

我試圖在電子郵件中解析兼容的「From:」字段爲RFC 5322兩部分:顯示名稱和電子郵件地址,在Python 2.7中(顯示名稱可以是空的)。熟悉的例子就像解析Python中的電子郵件的「From:」字段

John Smith <[email protected]> 

在上面,John Smith是顯示名稱,[email protected]是電子郵件地址。但下面也是一個有效的「發件人:」字段:

"unusual" <"very.(),:;<>[]\".VERY.\"[email protected]\\ \"very\".unusual"@strange.example.com> 

在本例中,顯示的名稱,返回值是

"unusual" 

"very.(),:;<>[]\".VERY.\"[email protected]\\ \"very\".unusual"@strange.example.com 

是電子郵件地址。

您可以使用語法來解析Perl中的這些問題(如以下問題所述:Using a regular expression to validate an email addressThe recognizing power of 「modern」 regexes),但我想在Python 2.7中執行此操作。我曾嘗試在Python中使用email.parser模塊,但該模塊似乎只能分離那些由冒號區分的字段。所以,如果你這樣做

from email.parser import Parser 
headers = Parser().parsestr('From: "John Smith" <[email protected]>') 
print headers['from'] 

它將返回

"John Smith" <[email protected]> 

而如果你

print headers['display-name'] 

替換最後一行在上面的代碼將返回

None 

我非常感謝提供任何建議和意見。

+0

我建議讓它工作?在任何人可以提供更具體的幫助之前,您需要提供有關該問題的更多信息。 – alexis

+0

謝謝。你是對的。我會盡力澄清。 – user765195

+0

'headers ['display-name']'沒有意義。顯示名稱不是標題的字段,而是From:...標題中的第一個電子郵件地址。 –

回答

3

headers['display-name']不是email.parser api的一部分。

嘗試email.utils.parseaddr:

In [17]: email.utils.parseaddr("[email protected]") 
Out[17]: ('', '[email protected]') 

In [18]: email.utils.parseaddr("(John Smith) [email protected]") 
Out[18]: ('John Smith', '[email protected]') 

In [19]: email.utils.parseaddr("John Smith <[email protected]>") 
Out[19]: ('John Smith', '[email protected]') 

它還可以處理你的不尋常地址:

In [21]: email.utils.parseaddr('''"unusual" <"very.(),:;<>[]\".VERY.\"[email protected]\\ \"very\".unusual"@strange.example.com>''') 
Out[21]: ('unusual', '"very.(),:;<>[]".VERY."[email protected] "very".unusual"@strange.example.com') 
+0

謝謝!太棒了!這正是我所期待的。 – user765195

1

libtld用C寫了這樣一個解析器++。如果你想真正完成,有lex和yacc(儘管我不使用這些工具)。我的C++ code可能會幫助你在python中編寫你自己的版本。

(lex part) 
[-A-Za-z0-9!#$%&'*+/=?^_`{|}~]+           atom_text_repeat (ALPHA+DIGIT+some other characters) 
([\x09\x0A\x0D\x20-\x27\x2A-\x5B\x5D-\x7E]|\\[\x09\x20-\x7E])+   comment_text_repeat 
([\x33-\x5A\x5E-\x7E])+             domain_text_repeat 
([\x21\x23-\x5B\x5D-\x7E]|\\[\x09\x20-\x7E])+       quoted_text_repeat 
\x22                  DQUOTE 
[\x20\x09]*\x0D\x0A[\x20\x09]+           FWS 
.                  any other character 

(lex definitions merged in more complex lex definitions) 
[\x01-\x08\x0B\x0C\x0E-\x1F\x7F]           NO_WS_CTL 
[()<>[\]:;@\\,.]               specials 
[\x01-\x09\x0B\x0C\x0E-\x7F]            text 
\\[\x09\x20-\x7E]              quoted_pair ('\\' text) 
[A-Za-z]                 ALPHA 
[0-9]                 DIGIT 
[\x20\x09]                WSP 
\x20                  SP 
\x09                  HTAB 
\x0D\x0A                 CRLF 
\x0D                  CR 
\x0A                  LF 

(yacc part) 
address_list: address 
      | address ',' address_list 
address: mailbox 
     | group 
mailbox_list: mailbox 
      | mailbox ',' mailbox_list 
mailbox: name_addr 
     | addr_spec 
group: display_name ':' mailbox_list ';' CFWS 
    | display_name ':' CFWS ';' CFWS 
name_addr: angle_addr 
     | display_name angle_addr 
display_name: phrase 
angle_addr: CFWS '<' addr_spec '>' CFWS 
addr_spec: local_part '@' domain 
local_part: dot_atom 
      | quoted_string 
domain: dot_atom 
     | domain_literal 
domain_literal: CFWS '[' FWS domain_text_repeat FWS ']' CFWS 
phrase: word 
     | word phrase 
word: atom 
    | quoted_string 
atom: CFWS atom_text_repeat CFWS 
dot_atom: CFWS dot_atom_text CFWS 
dot_atom_text: atom_text_repeat 
      | atom_text_repeat '.' dot_atom_text 
quoted_string: CFWS DQUOTE quoted_text_repeat DQUOTE CFWS 
CFWS: <empty> 
    | FWS comment 
    | CFWS comment FWS 
comment: '(' comment_content ')' 
comment_content: comment_text_repeat 
       | comment 
       | ccontent ccontent 
+0

謝謝!我試圖避免寫一個解析器。 – user765195

+0

啊!在問題中並不清楚你不想編寫實際的解析器。 8-) –