c# - Outlook 无法打开 s/mime 签名的邮件
问题描述
我需要使用 s/mime 对电子邮件进行数字签名。我为我的附件创建了一个分离的签名,但 Outlook 无法打开它:“无法打开此项目。基础安全系统无法找到您的数字 ID 名称”。证书已安装在此 PC 上,并且需要在此代码中进行调整:
const int CHARS_IN_LINE = 64;
StringBuilder message = new StringBuilder();
message.AppendLine("Content-Type: multipart/signed; protocol=\"application/pkcs7-signature\";");
message.AppendLine(" boundary=\"__multipart-signed-boundary__\"");
message.AppendLine("Content-Transfer-Encoding: 7bit");
message.AppendLine("MIME-Version: 1.0");
message.AppendLine("Subject: " + tbMessageSubject.Text);
message.AppendLine();
message.AppendLine("--__multipart-signed-boundary__");
message.AppendLine("Content-Type: text/xml; charset=\"windows - 1251\"");
message.AppendLine("Content-Disposition: attachment; ");
message.AppendLine(" filename=\"" + Path.GetFileName(filename) + "\"");
message.AppendLine("Content-Transfer-Encoding: base64");
message.AppendLine();
var dataToSign = File.ReadAllBytes(filePath);
var base64Data = Convert.ToBase64String(dataToSign, Base64FormattingOptions.None);
var base64DataSb = new StringBuilder(base64Data);
for (int i = CHARS_IN_LINE; i < base64DataSb.Length; i += CHARS_IN_LINE + 2) // \r\n
base64DataSb.Insert(i, "\r\n");
message.AppendLine(base64DataSb.ToString());
message.AppendLine("--__multipart-signed-boundary__");
message.AppendLine("Content-Type: application/pkcs7-signature; name=\"smime.p7m\"");
message.AppendLine("Content-Transfer-Encoding: base64");
message.AppendLine("Content-Disposition: attachment; filename=smime.p7s");
message.AppendLine();
CmsSigner signer = new CmsSigner(clientCert);
SignedCms cms = new SignedCms(new ContentInfo(dataToSign), true);
cms.ComputeSignature(signer);
var signature = cms.Encode();
var base64Signature = Convert.ToBase64String(signature, Base64FormattingOptions.None);
var base64Sb = new StringBuilder(base64Signature);
for (int i = CHARS_IN_LINE; i < base64Sb.Length; i += CHARS_IN_LINE + 2) // \r\n
base64Sb.Insert(i, "\r\n");
message.AppendLine(base64Sb.ToString());
message.AppendLine();
message.AppendLine("--__multipart-signed-boundary__--");
message.AppendLine(".");
var stream = new MemoryStream(Encoding.ASCII.GetBytes(message.ToString()));
MailMessage mail = new MailMessage();
mail.From = new MailAddress(tbEmailFrom.Text);
mail.To.Add(new MailAddress(tbEmailTo.Text));
AlternateView alternateView = new AlternateView(stream, "application/pkcs7-mime; smime-type=signed-data; name=smime.p7m");
alternateView.TransferEncoding = TransferEncoding.SevenBit;
mail.AlternateViews.Add(alternateView);
SmtpClient client = new SmtpClient(host, port);
client.EnableSsl = chbUseSSL.Checked;
client.Send(mail);
解决方案
最后,问题出在 AlternateView 中指定的 mediaType 中,正确的方法是:
AlternateView alternateView = new AlternateView(stream, "multipart/signed; protocol=\"application/pkcs7-signature\"; boundary=\"__multipart-signed-boundary__\"");
alternateView.TransferEncoding = TransferEncoding.SevenBit;
并且感谢jdweng,我需要签署的不是附件,而是带有标题的附件(首先__multipart-signed-boundary
带有附件)
推荐阅读
- ios - 在 Swift 如何识别音频文件中的多个声音?
- asp.net-core - 通过比较原始图和修改图 EF Core 来更新实体状态的通用解决方案
- r - 安装 R 时出错
- mysql - django.db.utils.OperationalError: (2002, "Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2)")
- amazon-web-services - 如何将 AWS Cognito 用户与 DynamoDB 同步
- reactjs - 如何在 React .jsx 文件中包含标准 html?
- javascript - 为什么点击事件只适用于一个元素?
- c# - Microsoft office Interop word 文档从模板创建并关闭不工作
- c++ - 在 C++ 中使用智能指针在成员函数中构造的嵌套类
- php - Laravel ZIP 目录和子目录