使用Gmail API读取邮件触发'parts'错误的排查咨询
解决Gmail API读取邮件时的'parts'错误
错误原因
你遇到的'parts'错误,核心原因是并非所有邮件的payload都包含parts字段:
- 纯文本格式的邮件,payload里没有
parts,直接通过payload['body']存储内容 - 带附件/多格式的邮件(比如同时有HTML和纯文本)才会有
parts数组
和邮件语种、是否包含图片没有直接关系,只是这类邮件更可能是多格式结构,而纯文本邮件触发了无parts的情况
修复后的代码
修改代码,先判断payload是否存在parts,再分别处理:
import base64 from googleapiclient.discovery import build from googleapiclient.errors import HttpError SCOPES = ['https://www.googleapis.com/auth/gmail.readonly', 'https://www.googleapis.com/auth/gmail.modify'] try: # Call the Gmail API service = build('gmail', 'v1', credentials=creds) results = service.users().messages().list(userId='me', labelIds=['INBOX']).execute() messages = results.get('messages', []) if not messages: print('No messages found.') else: for message in messages: msg = service.users().messages().get(userId='me', id=message['id'], format='full').execute() # 获取发件人 from_name = None for header in msg['payload']['headers']: if header['name'] == 'From': from_name = header['value'] break # 处理邮件内容 def extract_body(payload): if 'parts' in payload: # 遍历多部分内容,优先取纯文本 for part in payload['parts']: if part['mimeType'] == 'text/plain': if 'data' in part['body']: data = part['body']['data'] byte_code = base64.urlsafe_b64decode(data) return byte_code.decode('utf-8', errors='replace') # 递归处理嵌套的parts(比如multipart/alternative里的子部分) elif part['mimeType'].startswith('multipart/'): nested_text = extract_body(part) if nested_text: return nested_text else: # 纯文本邮件直接取body if 'data' in payload['body']: data = payload['body']['data'] byte_code = base64.urlsafe_b64decode(data) return byte_code.decode('utf-8', errors='replace') return '无法提取邮件内容' email_text = extract_body(msg['payload']) print(f'邮件来自: {from_name} - 内容: {email_text}') except HttpError as error: print(f'An error occurred: {error}') except Exception as error: print(f'An error occurred: {error}')
关键改进点
- 新增
extract_body函数,递归处理邮件的嵌套结构(比如multipart类型的邮件) - 优先提取
text/plain类型内容,避免HTML格式干扰 - 用
decode('utf-8', errors='replace')处理非英文编码邮件,防止解码失败 - 先判断
parts是否存在再遍历,避免KeyError - 优化发件人获取逻辑,找到后直接终止循环,减少不必要的遍历
内容的提问来源于stack exchange,提问作者Michael
相关产品推荐
相关产品推荐

