Python和imaplib:获取附件名称或正文,而无需下载完整的电子邮件

时间:2012-12-12 20:12:31

标签: python imaplib

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

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

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

我的具体含义是:假设我有一封30Mb的电子邮件,其中包含一行文本和两个15Mb附件。我想获得附件名称和文本行而不下载完整的30Mb正文。

谢谢

2 个答案:

答案 0 :(得分:4)

假设你问我认为你在问什么,这是做什么的:

首先,获取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])是第一个真正的附件,您就可以下载-text body通过获取(BODY[1]),并且您从结构中获得了附件的名称。

很抱歉这里没有代码。我不认为imaplib或任何stdlib与MIME和邮件相关的模块都会为你做难题(解释结构),但我实际上没有检查过,所以我会看那里首先,如果没有,请转到PyPI以查看是否有其他人已经编写过代码。

嗯,实际上,首先我只需要获取BODYSTRUCTURE(BODY ENVELOPE)(BODY[3])来获取特定消息,以确保gmail在编写完整的代码之前得到完全支持... < / p>

PS,如果最糟糕的情况发生,如果您的用例与您所描述的一样简单和严格,您可以随时获取BODYSTRUCTURE(BODY[1]),如果最差,则回退到RFC822失败,并通过在结构上运行hacky regexp而不是真正的解析来获取附件名称。除了一次性脚本或快速和简单的原型以了解gmail之外,我不会写这些内容,但对于那些情况,我可能会这样做。

答案 1 :(得分:4)

[编辑]

好的,我们去=)

>>> 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。

然后如here所述。

  

例如,由文本和a组成的两部分消息            BASE64编码的文本附件可以具有以下的主体结构:            ((“TEXT”“PLAIN”(“CHARSET”“US-ASCII”)NIL NIL“7BIT”1152            23)(“TEXT”“PLAIN”(“CHARSET”“US-ASCII”“NAME”“cc.diff”)            “&LT; 960723163407.20117h@cac.washington.edu>” “编译器差异”            “BASE64”4554 73)“MIXED”)

另请参阅this postthis one。最后一个链接看起来就像你想要做的那样。