.NET Framework调用默认邮件应用创建带正文及附件的邮件方法
.NET Framework 唤起默认邮件客户端新建带附件邮件的实现方案
最优实现:调用Windows原生MAPI接口
该方案不依赖特定邮件客户端,兼容所有支持MAPI规范的主流邮件客户端(包括Outlook、Foxmail、Thunderbird等),支持批量添加附件,无需引入第三方依赖。
第一步:封装MAPI调用帮助类
首先通过P/Invoke声明Windows MAPI接口的相关结构和方法,完整代码如下:
using System; using System.Collections.Generic; using System.Runtime.InteropServices; public static class MailHelper { [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] private class MapiFileDesc { public int reserved = 0; public int flags = 0; public int position = 0; public string path = null; public string name = null; public IntPtr type = IntPtr.Zero; } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] private class MapiMessage { public int reserved = 0; public string subject = null; public string body = null; public int receiptRequested = 0; public IntPtr interop = IntPtr.Zero; public string originator = null; public int recipientCount = 0; public IntPtr recipients = IntPtr.Zero; public int fileCount = 0; public IntPtr files = IntPtr.Zero; } [DllImport("MAPI32.DLL", CharSet = CharSet.Ansi)] private static extern int MAPISendMail(IntPtr session, IntPtr hwnd, MapiMessage message, int flags, int reserved); private const int MAPI_LOGON_UI = 0x00000001; private const int MAPI_DIALOG = 0x00000008; private const int SUCCESS_SUCCESS = 0; /// <summary> /// 唤起默认邮件客户端新建带附件的邮件 /// </summary> /// <param name="subject">邮件主题</param> /// <param name="body">邮件正文</param> /// <param name="attachmentPaths">附件文件的本地完整路径列表</param> /// <returns>调用是否成功</returns> public static bool SendMail(string subject, string body, List<string> attachmentPaths) { var message = new MapiMessage { subject = subject, body = body }; // 处理附件 if (attachmentPaths != null && attachmentPaths.Count > 0) { message.fileCount = attachmentPaths.Count; var fileDescPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(MapiFileDesc)) * attachmentPaths.Count); var currentPtr = fileDescPtr; foreach (var path in attachmentPaths) { var fileDesc = new MapiFileDesc { path = path }; Marshal.StructureToPtr(fileDesc, currentPtr, false); currentPtr += Marshal.SizeOf(typeof(MapiFileDesc)); } message.files = fileDescPtr; } try { int result = MAPISendMail(IntPtr.Zero, IntPtr.Zero, message, MAPI_LOGON_UI | MAPI_DIALOG, 0); return result == SUCCESS_SUCCESS; } finally { // 释放非托管内存 if (message.files != IntPtr.Zero) { Marshal.FreeHGlobal(message.files); } } } }
第二步:按钮点击事件中调用
private void btnSendMail_Click(object sender, EventArgs e) { // 示例参数 var attachments = new List<string> { @"C:\Users\Public\Documents\test1.pdf", @"C:\Users\Public\Documents\test2.xlsx" }; MailHelper.SendMail("测试邮件主题", "这是邮件正文内容", attachments); }
注意事项
- 调用前需校验附件文件存在,且当前程序拥有附件的读取权限,否则会调用失败
- 仅极少数小众邮件客户端不支持MAPI协议,这类场景占比极低,常规业务无需额外兼容
- 该实现兼容.NET Framework 4.0及以上所有版本,无需引入额外NuGet包或依赖
内容的提问来源于stack exchange,提问作者George
相关产品推荐
相关产品推荐

