I'm trying to send an email with a certificate PFX, I can read the certificate with a password and add it to the mail client.
I'm also using an Alternate View to insert the image to the message Base64
The problem is the email is not signed, and I'm missing something.
I researched a lot but the outcome was not expected.
public static void SendEmailSmtpRelay(string subject, string text, MailAddress from, MailAddress to, List<MailAddress> cc, List<MailAddress> bcc = null, string pass = null)
private static Stream Base64ToImageStream(string base64String)
private static AlternateView ContentToAlternateView(string content, out string contentReplaced)
public static void SendEmailSmtpRelay(string subject, string text, MailAddress from, MailAddress to, List<MailAddress> cc, List<MailAddress> bcc = null, string pass = null)
{
String mailPassword = @"xc8ByK0GRODq4 /GQfXjdbmAP2x5+3PZidnsgXu2RdeBEMJGV8uGS3uXP92WJsG6OVc/2K/vX0m2IGQ8lmZP0wl40TtmdsNwZxjD6Ah/FwiU1QAmD03LylGXrJfdC7Kmb";
var fileName = AssemblyDirectory + @"\" + "cert.pfx";
var cipher = StringCipher.Decrypt(mailPassword, pass);
SecureString secureMailpassword = new SecureString();
foreach (char c in cipher)
{
secureMailpassword.AppendChar(c);
}
var mailClient = new SmtpClient();
mailClient.Host = "mail.mycorp.com";
mailClient.Port = 25;
mailClient.EnableSsl = true;
mailClient.DeliveryMethod = SmtpDeliveryMethod.Network;
mailClient.UseDefaultCredentials = false;
mailClient.Credentials = new NetworkCredential("USER", cipher);
var msgMail = new MailMessage
{
From = from
};
msgMail.To.Add(to);
foreach (var addr in cc)
{
msgMail.CC.Add(addr);
}
if (bcc != null)
{
foreach (var addr in bcc)
{
msgMail.Bcc.Add(addr);
}
}
X509Certificate2 cert = new X509Certificate2(fileName, "pass");
byte[] data = Encoding.ASCII.GetBytes(text);
ContentInfo content = new ContentInfo(data);
SignedCms signedCms = new SignedCms(content, false);
CmsSigner signer = new CmsSigner(SubjectIdentifierType.IssuerAndSerialNumber, cert);
signedCms.ComputeSignature(signer);
byte[] signedbytes = signedCms.Encode();
msgMail.Subject = subject;
msgMail.Body = text;
msgMail.IsBodyHtml = true;
//msgMail.AlternateViews.Add(av);
string _replaced = String.Empty;
AlternateView alterView = ContentToAlternateView(text, out _replaced);
msgMail.Body = _replaced;
msgMail.AlternateViews.Add(alterView);
mailClient.Send(msgMail);
msgMail.Dispose();
}
/* *
https://stackoverflow.com/questions/39407474/add-attachment-base64-image-in-mailmessage-and-read-it-in-html-body
* */
private static Stream Base64ToImageStream(string base64String)
{
byte[] imageBytes = Convert.FromBase64String(base64String);
MemoryStream ms = new MemoryStream(imageBytes, 0, imageBytes.Length);
return ms;
}
private static AlternateView ContentToAlternateView(string content, out string contentReplaced)
{
int imgCount = 0;
List<LinkedResource> resourceCollection = new List<LinkedResource>();
Regex regex = new Regex(@"<img[^>]+src=['""]([^ "">]+)['""]");
MatchCollection matchCollection = regex.Matches(content);
//
foreach (Match m in matchCollection)
{
imgCount++;
string imgContent = m.Groups[1].Value;
string type = Regex.Match(imgContent, "data:(?<type>.*?);base64,").Groups["type"].Value;
Regex b64contentRegex = new Regex(@"base64,(.*)");
MatchCollection base64ContentMatchCollection = b64contentRegex.Matches(imgContent);
string base64Content = String.Empty;
if (base64ContentMatchCollection.Count > 0 && base64ContentMatchCollection[0].Groups.Count > 1)
{
base64Content = base64ContentMatchCollection[0].Groups[1].Value;
}
if (String.IsNullOrEmpty(type) || String.IsNullOrEmpty(base64Content))
{
//ignore replacement when match normal <img> tag
continue;
}
string replacement = "cid:" + imgCount;
content = content.Replace(imgContent, replacement);
LinkedResource tempResource = new LinkedResource(Base64ToImageStream(base64Content), new ContentType(type))
{
ContentId = imgCount.ToString(),
};
resourceCollection.Add(tempResource);
}
AlternateView alternateView = AlternateView.CreateAlternateViewFromString(content, null, MediaTypeNames.Text.Html);
foreach (var item in resourceCollection)
{
alternateView.LinkedResources.Add(item);
}
contentReplaced = content;
return alternateView;
}