2

The text file attached to the email is received with additional characters which I believe is the signature and the email client says the email is not signed.

Should I be using an AlternativeView for both the signature and the encryption? Have I messed up the content types?

From various examples this is what I've come up with so far:

var buffer = new StringBuilder();
buffer.Append("MIME-Version: 1.0\r\n");
buffer.Append("Content-Type: multipart/mixed; boundary=unique-boundary-1\r\n");
buffer.Append("\r\n");
buffer.Append("This is a multi-part message in MIME format.\r\n");
buffer.Append("--unique-boundary-1\r\n");
buffer.Append("Content-Type: text/plain\r\n");  
buffer.Append("Content-Transfer-Encoding: 7Bit\r\n\r\n");
buffer.Append(bodyText);
if (!bodyText.EndsWith("\r\n"))
    buffer.Append("\r\n");
buffer.Append("\r\n\r\n");

buffer.Append("--unique-boundary-1\r\n");
buffer.Append("Content-Type: application/octet-stream; file=" + outputFileName + "\r\n");
buffer.Append("Content-Transfer-Encoding: base64\r\n");
buffer.Append("Content-Disposition: attachment; filename=" + outputFileName + "\r\n");
buffer.Append("\r\n");

var memoryStream = new MemoryStream();
var writer = new StreamWriter(memoryStream);
writer.Write(_exportString);
writer.Flush();
writer.Dispose();

var binaryData = memoryStream.ToArray();

var base64Value = Convert.ToBase64String(binaryData, 0, binaryData.Length);
var position = 0;
while (position < base64Value.Length)
{
    var chunkSize = 100;
    if (base64Value.Length - (position + chunkSize) < 0)
        chunkSize = base64Value.Length - position;
    buffer.Append(base64Value.Substring(position, chunkSize));
    buffer.Append("\r\n");
    position += chunkSize;
}
buffer.Append("\r\n");

var body = buffer.ToString();

var messageData = Encoding.ASCII.GetBytes(body);

//add digital signature:
var signedCms = new SignedCms(new ContentInfo(messageData));
var signerCertificate = GetOurCertificate();
var signer = new CmsSigner(SubjectIdentifierType.SubjectKeyIdentifier, signerCertificate);
signedCms.ComputeSignature(signer);
var signedBytes = signedCms.Encode();
////

//Encrypt
var content = new ContentInfo(signedBytes);
var envelopedCms = new EnvelopedCms(content);

message.To.Add(new MailAddress("yyy@xxx.com"));
var recipientCertifcate = GetCertificate("C544FD2E80BD2B3994D43DBDB820DBE3A3A29922");
var recipient = new CmsRecipient(SubjectIdentifierType.IssuerAndSerialNumber, recipientCertifcate );

envelopedCms.Encrypt(recipient);
var encryptedBytes = envelopedCms.Encode();
////

var stream = new MemoryStream(encryptedBytes);
var view = new AlternateView(stream, "application/pkcs7-mime; smime-type=enveloped-data;name=smime.p7m");
message.AlternateViews.Add(view);


SmtpClient mailClient = new SmtpClient("localhost", 25);
mailClient.Send(message);
Alan S
  • 439
  • 3
  • 13
  • Apologies for the wall of code but I'm unsure if the body or attachments might be causing the problem. – Alan S Nov 08 '17 at 14:40
  • You might have more luck using [MimeKit](https://github.com/jstedfast/MimeKit) and [MailKit](https://github.com/jstedfast/MailKit) as I've implemented S/MIME support there to make it dead simple to do. If you have any questions, I would be happy to help answer them. – jstedfast Nov 10 '17 at 02:36
  • @jstedfast I did take a look at MimeKit. In this scenario the to and from addresses will never change. I wasn't keen to implement a db to act as a certificate store for just 2 addresses. I would rather use the Windows certificate store. – Alan S Nov 10 '17 at 10:11
  • You can use the Windows store with MimeKit. Just register the WindowsSecureMimeContext class that MimeKit comes with :) – jstedfast Nov 10 '17 at 11:58
  • @jstedfast Oh, really? Ok, I'll give it a go. – Alan S Nov 10 '17 at 12:22

0 Answers0