Dart/Flutter中如何解析Gmail邮件消息获取纯文本内容
核心原因
你当前直接读取payload.body.data的写法,仅能兼容结构最简单的单段纯文本邮件。Gmail API返回full格式的邮件时,绝大多数日常邮件都是多段(multipart)结构:纯文本正文、HTML格式正文、附件分别存放在payload.parts数组的不同子项中,部分嵌套结构的邮件还会出现子项本身又是多段类型的情况,顶层payload的body字段大多是空值,直接读自然拿不到完整内容,甚至偶尔会读到HTML片段。
实现逻辑
- 拉取邮件时保留
format: "full"参数即可,不需要更换其他格式 - 递归遍历整个payload的所有子段,不能只读取顶层字段
- 筛选所有
mimeType == "text/plain"的片段,跳过text/html、附件类的非文本片段 - 对筛选出的纯文本片段做base64Url解码、utf8转码,拼接后就是完整的纯文本正文
- 补全base64字符串末尾缺失的
=padding,避免部分返回值不规范导致解码报错
可直接运行的代码
首先写一个提取纯文本的公共方法,处理嵌套结构和边界情况:
import 'dart:convert'; import 'package:flutter/foundation.dart'; import 'package:googleapis/gmail/v1.dart'; String? extractFullPlainText(Message email) { final List<String> textFragments = []; // 递归处理嵌套的多段结构 void iterateParts(List<MessagePart> parts) { for (final part in parts) { final mime = part.mimeType ?? ''; // 遇到嵌套多段结构就继续往下遍历 if (mime.startsWith('multipart/')) { if (part.parts != null) iterateParts(part.parts!); continue; } // 只提取纯文本片段 if (mime == 'text/plain') { final rawData = part.body?.data; if (rawData == null || rawData.isEmpty) continue; // 补全base64必需的padding位 final paddedData = rawData.padRight((rawData.length + 3) ~/ 4 * 4, '='); final decoded = base64Url.decode(paddedData); textFragments.add(utf8.decode(decoded, allowMalformed: true)); } } } final payload = email.payload; if (payload == null) return null; // 兼容顶层就是纯文本的简单邮件 if (payload.mimeType == 'text/plain' && payload.body?.data != null) { final rawData = payload.body!.data!; final paddedData = rawData.padRight((rawData.length + 3) ~/ 4 * 4, '='); return utf8.decode(base64Url.decode(paddedData), allowMalformed: true); } // 遍历所有子段 if (payload.parts != null) iterateParts(payload.parts!); return textFragments.join('\n').trim(); }
替换你原有逻辑里的解码部分即可:
final mailList = await gmailApi.users.messages.list("me", maxResults: 10, q:"subject:receipt"); for (var msgMeta in mailList.messages!) { final fullMsg = await gmailApi.users.messages.get( _currentUser!.id, msgMeta.id ?? "", format: "full" ); // 这里拿到的就是和snippet同源、但内容完整的纯文本正文 final fullPlainContent = extractFullPlainText(fullMsg); if (kDebugMode) print(fullPlainContent); }
注意事项
- 少部分营销邮件、系统自动通知可能不会提供
text/plain版本的正文,仅返回HTML内容,这种场景如果需要纯文本,需要额外引入HTML转纯文本的工具做二次处理 - 解码时加
allowMalformed: true是为了兼容部分编码不规范的垃圾邮件、转发邮件,避免解码异常直接导致程序崩溃 - 不要尝试解码
text/html类型的片段,否则拿到的就是带HTML标签的内容,和需求不符
内容的提问来源于stack exchange,提问作者Alan Karanja
相关产品推荐
相关产品推荐

