保存电子邮件附件(python3,pop3_ssl,gmail)
问题描述:
我试图保存来自Google邮件帐户的电子邮件附件。保存电子邮件附件(python3,pop3_ssl,gmail)
AFAIK,这是可以做到“走”的消息,并获取其有效载荷,
for part in message.walk():
# getting payload, saving attach etc.
,但它不工作。 请参见下面的整个例子:
def test_save_attach(self):
self.connection = poplib.POP3_SSL('pop.gmail.com', 995)
self.connection.set_debuglevel(1)
self.connection.user(USERNAME)
self.connection.pass_(PASS)
emails, total_bytes = self.connection.stat()
print("{0} emails in the inbox, {1} bytes total".format(emails, total_bytes))
# return in format: (response, ['mesg_num octets', ...], octets)
msg_list = self.connection.list()
print(msg_list)
# messages processing
for i in range(emails):
response = self.connection.retr(i+1)
# return in format: (response, ['line', ...], octets)
lines = response[1]
str_message = email.message_from_bytes(b''.join(lines))
print(str_message)
# save attach
for part in str_message.walk():
print(part.get_content_type())
if part.get_content_maintype() == 'multipart':
continue
if part.get('Content-Disposition') is None:
continue
filename = part.get_filename()
if not(filename): continue
fp = open(os.path.join(self.savedir, filename), 'wb')
fp.write(part.get_payload(decode=1))
fp.close
self.connection.quit()
脚本输出是:
*cmd* 'USER **********'
*cmd* 'PASS **********'
*cmd* 'STAT'
*stat* [b'+OK', b'1', b'5301']
1 emails in the inbox, 5301 bytes total
*cmd* 'LIST'
(b'+OK 1 messages (5301 bytes)', [b'1 5301'], 8)
*cmd* 'RETR 1'
[<message headers and body>]
text/plain
*cmd* 'QUIT'
正如我们所看到的,该消息的唯一的部分具有“text/plain的”格式和不包含任何附加信息,尽管消息体确实包含了它,并且可以在调试输出时看到它。
答
response = self.connection.retr(i+1)
raw_message = response[1]
raw_message
不是字符串。 retr以单行列表形式返回消息。你试图将列表转换成一个字符串str(raw_message)
- 这是行不通的。
代替,加入这些线在一起,例如,更换
str_message = email.message_from_string(str(raw_message))
有:
python2:
str_message = email.message_from_string("\n".join(raw_message))
python3:
str_message = email.message_from_bytes(b'\n'.join(raw_message))
编辑://加入我的全部工作的源和输出帮助调试问题
import poplib
import email
import os
class GmailTest(object):
def __init__(self):
self.savedir="/tmp"
def test_save_attach(self):
self.connection = poplib.POP3_SSL('pop.gmail.com', 995)
self.connection.set_debuglevel(1)
self.connection.user("<munged>")
self.connection.pass_("<munged>")
emails, total_bytes = self.connection.stat()
print("{0} emails in the inbox, {1} bytes total".format(emails, total_bytes))
# return in format: (response, ['mesg_num octets', ...], octets)
msg_list = self.connection.list()
print(msg_list)
# messages processing
for i in range(emails):
# return in format: (response, ['line', ...], octets)
response = self.connection.retr(i+1)
raw_message = response[1]
str_message = email.message_from_bytes(b'\n'.join(raw_message))
# save attach
for part in str_message.walk():
print(part.get_content_type())
if part.get_content_maintype() == 'multipart':
continue
if part.get('Content-Disposition') is None:
print("no content dispo")
continue
filename = part.get_filename()
if not(filename): filename = "test.txt"
print(filename)
fp = open(os.path.join(self.savedir, filename), 'wb')
fp.write(part.get_payload(decode=1))
fp.close
#I exit here instead of pop3lib quit to make sure the message doesn't get removed in gmail
import sys
sys.exit(0)
d=GmailTest()
d.test_save_attach()
输出:
python3 thetest.py
*cmd* 'USER <munged>'
*cmd* 'PASS <munged>'
*cmd* 'STAT'
*stat* [b'+OK', b'2', b'152928']
2 emails in the inbox, 152928 bytes total
*cmd* 'LIST'
(b'+OK 2 messages (152928 bytes)', [b'1 76469', b'2 76459'], 18)
*cmd* 'RETR 1'
multipart/mixed
text/plain
test.txt
application/pdf
ADDFILE_0.pdf
*cmd* 'RETR 2'
multipart/mixed
text/plain
test.txt
application/pdf
ADDFILE_0.pdf
我明白了,但此行似乎有“字节”的类型,所以串.join()不起作用。如果我这样做 \t线=响应[1] \t MESSAGE_TEXT = “” \t线路在线路: \t \t MESSAGE_TEXT + = STR(线) 我得到同样的效果 –
啊,你似乎使用python3,我不熟悉(尚未),对不起!您可能需要连接字节,然后使用email.message_from_bytes(这是python 3 afaik中的新增功能) - 但这只是一个猜测 – Gryphius
使用email.message_from_bytes()会得到相同的结果。 –