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

Expo应用中expo-mail-composer带附件时Gmail真机发送异常问题

Expo Mail Composer 真机Gmail带附件发送异常问题

问题现象

  • 模拟器Gmail发送带附件邮件:流程顺畅,可正常收到邮件
  • 真机Gmail发送带附件邮件:邮件被存入草稿箱且附件丢失
  • 无附件邮件发送:一切正常
  • 测试场景:Expo Go、打包APK均出现此问题;真机使用其他邮件应用或模拟器Gmail则正常

代码片段

const sendDebugEmail = (inMemoryDatas: InMemoryData[], dataInBody = false) => {
    createFilesFromString(inMemoryDatas) // 生成文件列表并返回URI
        .then(async (attachmentsUris: string[]) => {
                await MailComposer.composeAsync({
                    recipients: ["anEmail@domain.com"],
                    subject: "Data",
                    attachments: attachmentsUris,
                    body: "mail body"
                });
            }
        )
}

解决方案

1. 修正文件URI格式与存储路径

真机Gmail对附件URI的兼容性要求更严格,需确保文件存放在公共可访问目录(Expo内部缓存目录可能不被Gmail识别),且URI以file://开头。修改createFilesFromString函数:

import * as FileSystem from 'expo-file-system';

const createFilesFromString = async (datas) => {
  const externalDir = await FileSystem.getExternalStorageDirectoryAsync();
  const attachments = [];
  
  for (let i = 0; i < datas.length; i++) {
    const fileName = `debug_${i}.txt`; // 按实际文件类型修改扩展名
    const filePath = `${externalDir}${fileName}`;
    
    await FileSystem.writeAsStringAsync(filePath, datas[i].content, {
      encoding: FileSystem.EncodingType.UTF8,
    });
    
    attachments.push(`file://${filePath}`);
  }
  
  return attachments;
};

2. 明确指定附件MIME类型

给每个附件指定对应MIME类型,避免Gmail无法识别附件格式:

await MailComposer.composeAsync({
  recipients: ["anEmail@domain.com"],
  subject: "Data",
  attachments: attachmentsUris.map(uri => ({
    uri: uri,
    mimeType: 'text/plain', // 按实际文件类型调整,如application/json、image/png等
    name: uri.split('/').pop()
  })),
  body: "mail body"
});

3. 申请必要的存储权限

在app.json中添加Android存储权限:

{
  "expo": {
    "android": {
      "permissions": [
        "READ_EXTERNAL_STORAGE",
        "WRITE_EXTERNAL_STORAGE"
      ]
    }
  }
}

代码中动态申请权限(适配Android 13+需对应调整权限类型):

import * as Permissions from 'expo-permissions';

const requestPermissions = async () => {
  const { status } = await Permissions.askAsync(Permissions.MEDIA_LIBRARY);
  if (status !== 'granted') {
    alert('需要存储权限才能发送附件');
    return false;
  }
  return true;
};

// 发送邮件前先校验权限
const sendDebugEmail = async (inMemoryDatas: InMemoryData[], dataInBody = false) => {
  const hasPermission = await requestPermissions();
  if (!hasPermission) return;
  
  const attachmentsUris = await createFilesFromString(inMemoryDatas);
  await MailComposer.composeAsync({
    // ...原有配置
  });
};

4. 切换到Gmail兼容的存储目录

可尝试将文件存到Download文件夹,提升Gmail识别概率:

const downloadDir = `${await FileSystem.getExternalStorageDirectoryAsync()}Download/`;
// 在createFilesFromString中使用此路径生成文件

内容的提问来源于stack exchange,提问作者minioim

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 18:57:23