如何通过Gmail API获取多次转发邮件的原始内容?
问题:通过Gmail API获取转发邮件原始内容时无法过滤额外文本
我尝试通过Gmail API获取转发至当前账户的原始邮件内容,但输出里不仅带有转发头信息,原始消息还多次重复,无法得到纯净的原始内容。
我的代码:
import lxml.html from bs4 import BeautifulSoup import base64 # 原代码遗漏此导入,需补充 myid = "18147a05aba83e45" # service 是访问Gmail API所需的服务对象,此处省略获取service的代码 txt = service.users().messages().get(userId='me', id=myid).execute() try: if 'INBOX' in txt['labelIds']: payload = txt['payload'] parts = payload.get('parts')[0] data = parts['body']['data'] data = data.replace("-","+").replace("_","/") decoded_data = base64.b64decode(data) soup = BeautifulSoup(decoded_data , "lxml") body = soup.body() body = str(body) body = body[1:-1] my_msg = lxml.html.fromstring(body).text_content() print(my_msg) except Exception as e: print('exception', e)
原始邮件内容:
Hshhsjshshhsbsbhs d dddd 1.5.5.5 2. D d. Sbsh
代码输出:
-----Forwarded message----- From: NiKHiL Date: Mon, Jul 11, 2822, 12:42 PM Subject: 0eiginal sub To: nikhilchauhanxd@gmail.com Hshhsjshshhsbsbhs d dddd 1.5.5.5 2. D d. Sbsh , Date: Mon, Jul 11, 2022, 12:42 PM Subject: Oeiginal sub To: nikhilchauhanxd@gnail.com Hshhsjshshhsbsbhs d dddd 1.5.5.5 2. D d. Sbsh , Hshhsjshshhsbsbhs d dddd 1.5.5.5 2. D d. Sbsh
解决方案
问题根源在于你直接读取邮件的第一个part,未处理转发邮件的嵌套结构或文本分隔特征,以下是两种可靠的处理方式:
方式一:通过MIME结构提取原始邮件
转发邮件在Gmail API中通常会以message/rfc822类型的嵌套part存储原始邮件,遍历parts即可精准提取:
import base64 import email myid = "18147a05aba83e45" # 获取原始格式邮件,便于解析MIME结构 txt = service.users().messages().get(userId='me', id=myid, format='raw').execute() try: # 解码原始邮件数据 raw_data = txt['raw'].replace("-","+").replace("_","/") decoded_raw = base64.b64decode(raw_data) msg = email.message_from_bytes(decoded_raw) # 遍历查找嵌套的原始邮件 for part in msg.walk(): if part.get_content_type() == 'message/rfc822': original_msg = email.message_from_bytes(part.get_payload(decode=True)) # 提取原始邮件的纯文本内容 if original_msg.is_multipart(): for sub_part in original_msg.walk(): if sub_part.get_content_type() == 'text/plain': print(sub_part.get_payload(decode=True).decode()) break else: print(original_msg.get_payload(decode=True).decode()) break else: # 未找到嵌套结构时,用文本分隔符处理 for part in msg.walk(): if part.get_content_type() == 'text/plain': body = part.get_payload(decode=True).decode() if '-----Forwarded message-----' in body: # 跳过转发头,取第一个空行后的内容 original_content = body.split('-----Forwarded message-----')[-1].split('\n\n', 1)[-1].strip() print(original_content) else: print(body) break except Exception as e: print('exception', e)
方式二:文本分割过滤(简单场景适用)
如果邮件是纯文本格式,直接通过Gmail默认的转发分隔符分割文本,快速提取原始内容:
修改原代码的解码后处理逻辑:
# ... 原代码中解码部分 decoded_data = base64.b64decode(data) body_text = decoded_data.decode() if '-----Forwarded message-----' in body_text: # 分割并提取原始内容 forwarded_section = body_text.split('-----Forwarded message-----')[-1] original_content = forwarded_section.split('\n\n', 1)[-1].strip() print(original_content) else: print(body_text)
注意事项:
- 原代码遗漏
base64库导入,必须补充否则会报错。 - 邮件可能同时包含HTML和纯文本版本,优先处理
text/plain部分更稳定。 - 不同邮箱的转发分隔符可能有差异,Gmail默认使用
-----Forwarded message-----,其他邮箱需对应调整。
内容的提问来源于stack exchange,提问作者NiKHiL
相关产品推荐
相关产品推荐

