You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 06:21:31