My current project is an email decryption program using Redemption and MimeKit. It's been a long road but for the most part it is working for our client.
However for one external companies messages, the resultant message is corrupted. The output message is saved to the disk successfully, when the email is previewed in Windows Explorers preview pane, it renders fine. But when opened in outlook the message seems to convert extended-ascii characters into a hex format (ISO-8859-1) i.e. "ü" becomes "=FC".
This seems to happen for all non-standard ascii characters But only from one specific sender only(currently).
Another issue that is visible with these emails is that the internet headers are visible on the message. Below is a (Partial to protect client) screen shot of the decrypted email:
It should be noted that when the decrypted message is re-loaded in C# via redemption, the HTMLBody property appears to be formatted correctly.
Decryption Code:
// "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;
}
}
}
File saving code:
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);
}
If you need anymore code snippets please let me know.
Unfortunately as the program revolves around decryption and peoples secure certificates/credentials, debugging this issue is a real pain. So any help working around this issue would be a massive help!