首页 > 解决方案 > 使用错误编码保存赎回文件(可能)

问题描述

我目前的项目是一个使用 Redemption 和 MimeKit 的电子邮件解密程序。这是一条漫长的道路,但在大多数情况下,它正在为我们的客户服务。

但是,对于一个外部公司的消息,生成的消息已损坏。输出消息成功保存到磁盘,当电子邮件在 Windows 资源管理器预览窗格中预览时,它呈现良好。但在 Outlook 中打开时,该消息似乎将扩展 ascii 字符转换为十六进制格式 (ISO-8859-1),即“ü”变为“=FC”。

这似乎发生在所有非标准 ascii 字符上,但仅来自一个特定的发件人 only(current)

这些电子邮件可见的另一个问题是互联网标题在邮件中可见。以下是解密电子邮件的(部分保护客户端)屏幕截图:

使用 Redemption 保存的解密电子邮件的屏幕截图

应该注意的是,当解密的消息通过兑换在 C# 中重新加载时,HTMLBody 属性的格式似乎正确。

解密代码:

// "attach" object is the RDOAttachment (smime.p7m file)

DebugLog.Log($"Attachment Display name resembles that of an encrypted email");

// Is SMIME

byte[] decrypted;
DebugLog.Log($"Saving attach to disk");

attach.SaveAsFile(sourcePath + "-smime.p7m");
DebugLog.Log($"File exists: {File.Exists(sourcePath + "-smime.p7m").ToString()}");

MimeEntity entity = null;
DebugLog.Log($"MimeEntity: entity init");

MimeEntity finalOutput = null;
DebugLog.Log($"MimeEntity: finalOutput init");

using (MemoryStream ms = new MemoryStream())
//using (StreamWriter sw = new StreamWriter(ms))
using (FileStream file = new FileStream(sourcePath + "-smime.p7m", FileMode.Open, FileAccess.Read))
{
    DebugLog.Log($"Copying file to memory");

    file.CopyTo(ms);

    CryptographyContext.Register(typeof(WindowsSecureMimeContext));
    DebugLog.Log($"Registering CryptographicContext with typeof WindowsSecureMimeContext");

    ApplicationPkcs7Mime p7m = new ApplicationPkcs7Mime(SecureMimeType.EnvelopedData, ms);
    DebugLog.Log($"Creating new ApplicationPkcs7Mime object");

    var ctx = new WindowsSecureMimeContext(StoreLocation.CurrentUser);
    DebugLog.Log($"Printing available EncryptionAlgorithms");
    foreach (EncryptionAlgorithm alg in ctx.EnabledEncryptionAlgorithms)
    {
        DebugLog.Log($"Alg: {alg.ToString()}");
    }
    DebugLog.Log($"Setting context to CurrentUser");

    DebugLog.Log($"If p7m is not null and is envelope data");

    if (p7m != null && p7m.SecureMimeType == SecureMimeType.EnvelopedData)
    {
        try
        {
            //var y = p7m.Verify(ctx, out MimeEntity yeet);

            DebugLog.Log($"Attempting decrypt");

            entity = p7m.Decrypt(ctx);
        }
        catch (Exception e)
        {
            DebugLog.Log($"Error decrypting", e);
            DebugLog.Log($"Trying old method");
            try
            {
                using (var message = new MsgDecrypt.Message(sourcePath))
                {
                    message.SaveDecryptedCopyAs(destinationPath);
                    return;
                }
            }
            catch (Exception ex)
            {
                DebugLog.Log($"Error using old method:", ex);
                if (!(ex is CryptographicException))
                    throw ex;
            }

            if (!(e is CryptographicException))
                throw e;
            //throw e;
        }
    }
}

文件保存代码:

PrintObjectInfo(finalOutput);
DebugLog.Log(finalOutput.ContentType?.MimeType);
DebugLog.Log($"true");
try
{
    DebugLog.Log($"write to eml");
    using (FileStream fs = new FileStream(destinationPath + "-out.eml", FileMode.Create,
        FileAccess.ReadWrite))
    {
        finalOutput.WriteTo(fs);
    }

    DebugLog.Log($"success");

    Marshal.ReleaseComObject(attach);
    DebugLog.Log($"create empty message file ");

    var final = Session.CreateMessageFromMsgFile(destinationPath, "IPM.Note", msg.BodyFormat);

    final.Sent = true;
    //var x = File.ReadAllText("RTF.txt");

    final.Import(destinationPath + "-out.eml", rdoSaveAsType.olRFC822);

    if (final.Attachments.Count == 1)
    {
        if (final.Attachments.Item(1).DisplayName == "Untitled Attachment")
        {
            DebugLog.Log("Specific Attachment Delete Scenario has occured");
            final.Attachments.Clear();
        }
    }

    if (string.IsNullOrEmpty(final.HTMLBody) && !string.IsNullOrEmpty(final.RTFBody))
    {
        var x = final.RTFBody;
        final.RTFBody = x;
    }
    //final.HTMLBody = "";
    final.ReceivedByName = msg.ReceivedByName;

    final.Sender = msg.Sender;
    final.SenderEmailAddress = msg.SenderEmailAddress; // Fix empty name
    final.SenderName = msg.SenderName?.Replace("\"", "");

    final.Subject = msg.Subject;
    final.Recipients = msg.Recipients;
    final.SentOn = msg.SentOn;

    DebugLog.Log($"Save File");
    PrintObjectInfo(final);
    final.SaveAs(destinationPath, rdoSaveAsType.olMSGUnicode);

    var finalDis = final as IDisposable;
    finalDis.Dispose();
    try
    {
        var entDis = entity as IDisposable;
        entDis.Dispose();
    }
    catch (Exception)
    {

    }
    Marshal.ReleaseComObject(final);

    GC.Collect();
    GC.WaitForPendingFinalizers();
    File.Delete(destinationPath + "-out.eml");

    if (!File.Exists(destinationPath))
    {
        throw new Exception("File couln't be saved...");
    }
}
catch (Exception saveException)
{
    throw new Exception("Error saving new file", saveException);
}

如果您需要更多代码片段,请告诉我。

不幸的是,由于程序围绕着解密和人们的安全证书/凭证,调试这个问题是一个真正的痛苦。因此,解决此问题的任何帮助都将是巨大的帮助!

标签: c#encryptionoutlookoutlook-redemptionmimekit

解决方案


=FC-style 编码是quoted-printable在标头中指定的编码Content-Transfer-Encoding

从您问题中提供的屏幕截图来看,它似乎在text/plain部件中设置正确。

也就是说,该text/plain部分的内容看起来像它的开头被截断(是否为保护客户信息而进行了编辑?)而且它看起来也是 CSS/HTML 而不是纯文本。


推荐阅读