如何使用Microsoft Graph发送数字签名电子邮件?(附现有代码)
使用Microsoft Graph发送带数字签名的邮件
要发送带数字签名的S/MIME邮件,Microsoft Graph要求你先在本地完成邮件的S/MIME签名,再将签名后的完整MIME内容通过Message.Raw属性提交,而非使用普通的Message对象构造方式。以下是具体实现步骤和代码:
关键前提
- 发送邮件的用户邮箱已配置有效的S/MIME签名证书(可在Exchange管理中心或本地证书存储中获取)
- 应用已拥有
Mail.Send权限(你当前的代码已满足此条件)
实现步骤及代码
构造并签名邮件为S/MIME格式
使用System.Security.Cryptography.Pkcs命名空间下的类完成签名,生成Base64编码的完整MIME邮件内容。通过Graph发送签名后的邮件
将签名后的Base64内容赋值给Message.Raw,调用SendMail接口发送。
完整代码示例:
using System; using System.Collections.Generic; using System.Security.Cryptography.X509Certificates; using System.Security.Cryptography.Pkcs; using System.Text; using Azure.Identity; using Microsoft.Graph; using Microsoft.Graph.Models; // 1. 获取签名证书(示例从本地证书存储获取,可根据实际情况调整) X509Certificate2 signingCert = GetSigningCertificate(); // 2. 构造原始邮件的MIME内容 string mimeContent = ConstructMimeMessage( "Test Signed Email", "Some text", "sender@domain.com", "somebody@somewhere.com" ); // 3. 对MIME内容进行S/MIME签名 string signedMimeBase64 = SignMimeContent(mimeContent, signingCert); // 4. 使用Graph发送签名后的邮件 ClientSecretCredential credentials = new ClientSecretCredential( "--TenantId--", "--ClientId--", "--Secret--", new TokenCredentialOptions { AuthorityHost = AzureAuthorityHosts.AzurePublicCloud } ); GraphServiceClient graphServiceClient = new GraphServiceClient(credentials); Message signedMessage = new Message { Raw = signedMimeBase64 }; await graphServiceClient .Users["--UserId--"] .SendMail(signedMessage, false) .Request() .PostAsync(); // 辅助方法:获取签名证书 X509Certificate2 GetSigningCertificate() { using X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser); store.Open(OpenFlags.ReadOnly); X509Certificate2Collection certs = store.Certificates.Find( X509FindType.FindBySubjectName, "你的证书主题名称", validOnly: true ); if (certs.Count == 0) throw new InvalidOperationException("未找到有效的签名证书"); return certs[0]; } // 辅助方法:构造基础MIME邮件内容 string ConstructMimeMessage(string subject, string body, string from, string to) { StringBuilder mimeBuilder = new StringBuilder(); mimeBuilder.AppendLine($"From: {from}"); mimeBuilder.AppendLine($"To: {to}"); mimeBuilder.AppendLine($"Subject: {subject}"); mimeBuilder.AppendLine("MIME-Version: 1.0"); mimeBuilder.AppendLine("Content-Type: text/html; charset=utf-8"); mimeBuilder.AppendLine(); mimeBuilder.AppendLine(body); return mimeBuilder.ToString(); } // 辅助方法:对MIME内容进行S/MIME签名 string SignMimeContent(string mimeContent, X509Certificate2 signingCert) { byte[] mimeBytes = Encoding.UTF8.GetBytes(mimeContent); ContentInfo contentInfo = new ContentInfo(mimeBytes); SignedCms signedCms = new SignedCms(contentInfo, detached: false); CmsSigner signer = new CmsSigner(signingCert); signedCms.ComputeSignature(signer); byte[] signedBytes = signedCms.Encode(); return Convert.ToBase64String(signedBytes); }
注意事项
detached: false表示签名是内嵌的,收件人可直接在邮件客户端看到签名验证结果- 确保签名证书的私钥可访问(如果是从文件加载,需确保证书包含私钥)
- 若需要加密+签名,可先签名再加密,或先加密再签名(根据需求选择)
内容的提问来源于stack exchange,提问作者ChronosCZ
相关产品推荐
相关产品推荐

