2

我在 Django 中有一个电子邮件客户端。目前支持使用 imaplib 的 GMail 帐户。

我的问题是:我想获得附件名称而无需下载完整的电子邮件。目前,为了获取附件名称或电子邮件正文,我需要使用带有参数(RFC822)的 fetch 函数下载整个电子邮件。

我知道我只能使用 HEADER.FIELDS 获取特定字段,例如主题,来自 cc。但是有没有办法在不下载整个电子邮件的情况下获取附件名称或电子邮件正文?

我的具体意思是:假设我有一封 30Mb 的电子邮件,正文中有一行文本和两个 15Mb 的附件。我想在不下载完整的 30Mb 正文的情况下获取附件名称和那一行文本。

谢谢

4

2 回答 2

3

假设您要问我认为您要问的问题,请执行以下操作:

首先,获取BODYSTRUCTURE. 假设 gmail 的 IMAP 服务器支持这个,你会得到这样的结果:

(("TEXT" "PLAIN" ("CHARSET" "UTF-8") NIL NIL "QUOTED-PRINTABLE" 56 1 NIL NIL NIL NIL)
 ("TEXT" "HTML" ("CHARSET" "UTF-8") (NAME "") NIL NIL "BASE64" 12345 NIL 
  ("attachment" ("FILENAME" "")) NIL NIL) 
 ("IMG" "JPEG" (NAME "funny picture") NIL NIL "BASE64" 56789 NIL
  ("attachment" ("FILENAME" "image.jpg")) NIL NIL))
 "MIXED" ("BOUNDARY" "----_=_NextPart_001_1234ABCD.56789EF0") NIL NIL NIL)

然后获取(BODY ENVELOPE)是结构有一个。

如果您查看RFC3501 7.4.2,它解释了如何处理这些。

一旦您确定(BODY[1])(BODY[2])是主要内容的纯文本和 HTML 版本,并且(BODY[3])是第一个真正的附件,您可以通过 fetching 下载纯文本正文(BODY[1]),并且您从结构体。

抱歉,这里没有代码。我认为imaplibstdlib MIME 和邮件相关模块中的任何一个或任何一个都不会为你做最困难的部分(解释结构),但我还没有真正检查过,所以我先看看那里,如果不行,去 PyPI 看看有没有其他人已经写过代码了。

好吧,实际上,首先我只是 fetch BODYSTRUCTURE(BODY ENVELOPE)(BODY[3])针对特定消息确保 gmail 在编写一大堆代码之前得到完全支持……</p>

PS,如果最坏的情况变得最糟,如果您的用例像您描述的那样简单和严格,您可以随时获取BODYSTRUCTUREand ,如果失败则(BODY[1])回退,并通过在结构上运行 hacky 正则表达式而不是获取附件名称RFC822真正的解析。除了一次性脚本或快速&肮脏的原型来了解 gmail 之外,我不会写这个,但对于那些情况,我可能会。

于 2012-12-12T20:25:25.117 回答
3

[编辑]

好的,我们开始 =)

>>> import imaplib, email
>>> mail = imaplib.IMAP4_SSL('imap.gmail.com')
>>> mail.login('emailaddr@gmail.com', 'password')
('OK', ['emailaddr@gmail.com Inget Namn authenticated (Success)'])
>>> mail.select('inbox')
('OK', ['14'])
>>> result, data = mail.uid('search', None, 'ALL')
>>> uids=data[0].split()
>>> result, data = mail.uid('fetch', uids[-1], 'BODYSTRUCTURE')
>>> print data
['14 (UID 340 BODYSTRUCTURE ((("TEXT" "PLAIN" ("CHARSET" "ISO-8859-1") NIL NIL "7BIT" 17 1 NIL NIL NIL)("TEXT" "HTML" ("CHARSET" "ISO-8859-1") NIL NIL "7BIT" 17 1 NIL NIL NIL) "ALTERNATIVE" ("BOUNDARY" "20cf3071d16a5a877b04d0adcc43") NIL NIL)("APPLICATION" "PDF" ("NAME" "attiny40.pdf") NIL NIL "BASE64" 8429956 NIL ("ATTACHMENT" ("FILENAME" "attiny40.pdf")) NIL) "MIXED" ("BOUNDARY" "20cf3071d16a5a878104d0adcc45") NIL NIL))']
>>>

此消息的附件名为“attiny40.pdf”,您可以在 BODYSTRUCTURE 中清楚地看到该名称。剩下的就是解析 BODYSTRUCTURE。

该代码几乎直接取自下面的最后一个链接。

[/编辑]

您需要将 fetch 的参数从 RFC822 更改为 BODYSTRUCTURE。

然后例如这里描述的。

例如,由文本和 BASE64 编码文本附件组成的两部分消息的正文结构可以是: (("TEXT" "PLAIN" ("CHARSET" "US-ASCII") NIL NIL "7BIT" 1152 23 )("TEXT" "PLAIN" ("CHARSET" "US-ASCII" "NAME" "cc.diff") "960723163407.20117h@cac.washington.edu" "编译器差异" "BASE64" 4554 73) "MIXED")

另见这篇文章这篇文章。最后一个链接看起来就像你正在尝试做的一样。

于 2012-12-12T20:33:08.773 回答