【问题标题】:Parsing "From:" field of an e-mail message in Python在 Python 中解析电子邮件的“发件人:”字段
【发布时间】:2013-10-13 10:02:37
【问题描述】:

我正在尝试将电子邮件消息中符合RFC 5322 的“发件人:”字段解析为两部分:Python 2.7 中的显示名称和电子邮件地址(显示名称可以是空的)。熟悉的例子是这样的

John Smith <jsmith@example.org>

在上面,John Smith 是显示名称,jsmith@example.org 是电子邮件地址。但以下也是有效的“发件人:”字段:

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

在本例中,display-name 的返回值为

"unusual" 

"very.(),:;<>[]\".VERY.\"very@\\ \"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" <jsmith@example.org>')
print headers['from'] 

它会返回

"John Smith" <jsmith@example.com> 

如果将上面代码中的最后一行替换为

print headers['display-name']

它会返回

None

我将非常感谢任何建议和 cmets。

【问题讨论】:

  • 我建议让它工作?您需要提供有关该问题的更多信息,然后才能有人提供更具体的帮助。
  • 谢谢。你说得对。我会尽力澄清。
  • headers['display-name'] 没有意义。显示名称不是标头的字段,而是 From: ... 标头中的第一个电子邮件地址。

标签: python email


【解决方案1】:

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

试试 email.utils.parseaddr:

In [17]: email.utils.parseaddr("jsmith@example.com")
Out[17]: ('', 'jsmith@example.com')

In [18]: email.utils.parseaddr("(John Smith) jsmith@example.com")
Out[18]: ('John Smith', 'jsmith@example.com')

In [19]: email.utils.parseaddr("John Smith <jsmith@example.com>")
Out[19]: ('John Smith', 'jsmith@example.com')

它还处理您的不寻常地址:

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

【讨论】:

  • 谢谢!太棒了!这正是我想要的。
【解决方案2】:

我用 C++ 在libtld 中编写了这样一个解析器。如果你想真正完整的话,还有 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

【讨论】:

  • 谢谢!我试图避免编写解析器。
  • 啊!问题中并不清楚您不想编写实际的解析器。 8-)
猜你喜欢
  • 2022-12-17
  • 1970-01-01
  • 2014-04-09
  • 2010-10-07
  • 2023-01-11
  • 1970-01-01
  • 1970-01-01
  • 2016-10-20
  • 2017-11-07
相关资源
最近更新 更多