Flutter Windows端如何打开默认邮件应用并附加txt文件发送?
Flutter Windows端调用默认邮件应用并附加文件的实现方案
mailto协议本身不支持附件参数,因此你之前用url_launcher走mailto协议的方案无法实现附加文件的需求,Windows平台可以通过调用MAPI(Messaging Application Programming Interface)接口实现调用默认邮件应用携带附件的功能,具体实现如下:
1. 引入所需依赖
将以下依赖添加到项目的pubspec.yaml文件中:
dependencies: flutter: sdk: flutter win32: ^5.0.0 # 用于调用Windows系统API ffi: ^2.1.0 # 用于处理C语言类型转换 path_provider: ^2.1.0 # 可选,用于获取应用沙盒内文件的绝对路径
2. 封装带附件发邮件的调用方法
import 'dart:ffi'; import 'package:ffi/ffi.dart'; import 'package:win32/win32.dart'; import 'dart:io'; /// 调用Windows默认邮件应用发信 /// [to] 收件人邮箱 /// [subject] 邮件主题 /// [body] 邮件正文 /// [attachments] 附件文件列表,必须传入绝对路径的文件 /// 返回0代表调用成功,其他值为错误码 int sendEmailWithAttachment({ required String to, required String subject, required String body, required List<File> attachments, }) { return using((Arena arena) { // 加载Windows MAPI模块 final mapiLib = DynamicLibrary.open('mapi32.dll'); final sendMailFunc = mapiLib.lookupFunction< Int32 Function(Pointer<Void> session, Pointer<Void> hwnd, Pointer<MapiMessage> message, Uint32 flags, Uint32 reserved), int Function(Pointer<Void> session, Pointer<Void> hwnd, Pointer<MapiMessage> message, int flags, int reserved) >('MAPISendMailW'); // 构造收件人信息 final recipient = arena<MapiRecipDesc>(); recipient.ref.ulRecipClass = MAPI_TO; recipient.ref.lpszName = to.toNativeUtf16(allocator: arena).cast(); recipient.ref.lpszAddress = 'SMTP:${to}'.toNativeUtf16(allocator: arena).cast(); // 构造附件列表 final mapiAttachments = arena<MapiFileDesc>(attachments.length); for (var i = 0; i < attachments.length; i++) { final filePath = attachments[i].absolute.path.toNativeUtf16(allocator: arena); mapiAttachments[i].ulReserved = 0; mapiAttachments[i].flFlags = 0; mapiAttachments[i].nPosition = 0xFFFFFFFF; mapiAttachments[i].lpszPathName = filePath.cast(); mapiAttachments[i].lpszFileName = filePath.cast(); mapiAttachments[i].lpFileType = nullptr; } // 构造邮件主体 final message = arena<MapiMessage>(); message.ref.ulReserved = 0; message.ref.lpszSubject = subject.toNativeUtf16(allocator: arena).cast(); message.ref.lpszNoteText = body.toNativeUtf16(allocator: arena).cast(); message.ref.nRecipCount = 1; message.ref.lpRecips = recipient; message.ref.nFileCount = attachments.length; message.ref.lpFiles = mapiAttachments; // 触发系统邮件应用弹窗 return sendMailFunc(nullptr, nullptr, message, MAPI_LOGON_UI | MAPI_DIALOG, 0); }); }
3. 调用示例
// 调用前先判断当前平台为Windows if (Platform.isWindows) { final testTxt = File('C:/用户/公共/测试文件.txt'); // 必须传入绝对路径的文件 sendEmailWithAttachment( to: 'test@example.com', subject: '测试带附件邮件', body: '这是邮件正文内容', attachments: [testTxt], ); }
注意事项
- 该方案仅适用于Windows平台,调用前必须做平台判断,避免其他平台运行报错
- 若用户设备未安装任何邮件客户端,调用后会弹出系统引导提示,让用户选择/安装默认邮件应用
- 附件必须传入绝对路径,若需要发送应用沙盒内的文件,可先通过
path_provider获取文件的绝对路径后再传入
内容的提问来源于stack exchange,提问作者Andrew Klement Winarto
相关产品推荐
相关产品推荐

