python3/email:解析带有嵌入式逗号的电子邮件地址列表?

python3/email: parsing a list of email addresses with embedded commas?

我知道如何使用 email.utils.parseaddr() 解析电子邮件地址。但是,我想解析一个包含多个电子邮件地址的列表,例如这个 header:

的地址部分
Cc: "abc" <foo@bar.com>, "www, xxyyzz" <something@else.com>

一般来说,我知道我可以拆分像 \s*,\s* 这样的正则表达式来获取各个地址,但在我的示例中,其中一个地址的名称部分包含一个逗号,因此该正则表达式将header 拆分不正确。

我知道如何手动编写 state-machine-based 代码以将该地址正确地分成多个部分,而且我还知道如何编写一个复杂的正则表达式来匹配每个电子邮件地址。我不是在寻求帮助来编写这样的代码。相反,我想知道是否有任何现有的 python 模块可用于正确拆分此电子邮件地址列表,因此我不必 "re-invent the wheel".

提前致谢。

这一点也不优雅,我相信有人会对此进行改进。但是,这对我有用,希望能让您了解如何做到这一点。

我相信 split 方法就是您在这里寻找的方法。用最简单的术语来说,您使用字符串并选择 split 上的字符。这会将字符串分隔成一个列表,您可以在假设找到拆分键选择的情况下对其进行迭代。如果未找到,则该字符串是一个单元素列表。

emails = 'Cc: "abc" <foo@bar.com>, "www, xxyyzz" <something@else.com>'
emails
Out[37]: 
'Cc: "abc" <foo@bar.com>, "www, xxyyzz" <something@else.com>'
In [38]:
emails = emails.split(' ')
new_emails = []
for e in emails:
    if '@' in e:
        new_email = e.replace('<', '')
        new_email = new_email.replace('>', '')
        new_email = new_email.replace(',', '')
        new_emails.append(new_email)
print(new_emails)
['foo@bar.com', 'something@else.com']

如果你想使用正则表达式来做这件事,比我聪明的人会提供帮助。

借用这个问题的答案

msg = 'Cc: "abc" <foo@bar.com>, "www, xxyyzz" <something@else.com>'

import email.utils

print(email.utils.getaddresses([msg]))

产生:

[('abc', 'foo@bar.com'), ('www, xxyyzz', 'something@else.com')]

我知道我可以做类似下面的事情,但同样,我希望已经有一个现有的包可以为我做这件事...

#!/usr/bin/python3         

import email.utils

def getaddrs(text):
    def _yieldaddrs(text):
        inquote = False
        curaddr = ''
        for x in text:
            if x == '"':
                inquote = not inquote
                curaddr += x
            elif x == ',':
                if inquote:
                    curaddr += x
                else:
                    yield(curaddr)
                    curaddr = ''
            else:
                curaddr += x
        if curaddr:
            yield(curaddr)
    return [email.utils.parseaddr(x) for x in _yieldaddrs(text)]

addrstring = '"abc" <foo@bar.com>, "www, xxyyzz" <something@else.com>'
print('{}'.format(getaddrs(addrstring)))
# Prints this ...
#   [('abc', 'foo@bar.com'), ('www, xxyyzz', 'something@else.com')]