I want to send an encrypted and signed mail without using any third-party library.
I'm able to send an email signed or encrypted. But both is not working.
I've tried to send a mail with Thunderbird and looked at the source, but theres nothing that tells the mail is encrypted and signed.
When I use following code
byte[] bodyBytes = Encoding.UTF8.GetBytes("TestBody");
SignedCms cms = new SignedCms(new ContentInfo(bodyBytes), false);
CmsSigner signer = new CmsSigner(SubjectIdentifierType.IssuerAndSerialNumber, signerCert); //X509Certificate2 with private key of sender
cms.ComputeSignature(signer);
byte[] signedBytes = cms.Encode();
EnvelopedCms ecms = new EnvelopedCms(new ContentInfo(signedBytes));
CmsRecipient cmsr = new CmsRecipient(SubjectIdentifierType.IssuerAndSerialNumber, encryptCert); //X509Certificate2 with public key of recipient
ecms.Encrypt(cmsr);
byte[] encryptedBytes = ecms.Encode();
MailMessage msg = new MailMessage();
msg.To.Add(new MailAddress(to));
msg.From = new MailAddress(from);
msg.Subject = subject;
MemoryStream ms = new MemoryStream(encryptedBytes);
AlternateView av = new AlternateView(ms, "application/pkcs7-mime; smime-type=enveloped-data;name=smime.p7m");
msg.AlternateViews.Add(av);
SmtpClient smtp = new SmtpClient("[smtpServer]", 25);
smtp.Send(msg);
the MailClient just decrypts or checks the signature of the message.. the action which i perform last. How can I tell the Client to do both, decryption and signature check?
Related
Im trying to send an email with the office 365 smtp, but im getting the following error:
The SMTP server requires a secure connection or the client was not authenticated. The server response was: 5.7.57
Client not authenticated to send mail. Error: 535 5.7.139
Authentication unsuccessful, the user credentials were incorrect.
[XXXX.XXXX.prod.outlook.com]
I noticed that some things got changed "recently" with the office 365 smtp and the most recent code, that I found, that works for most people was this:
SmtpClient mySmtpClient = new SmtpClient();
mySmtpClient.Host = "smtp.office365.com";
mySmtpClient.Port = 587;
mySmtpClient.UseDefaultCredentials = false;
mySmtpClient.DeliveryMethod = SmtpDeliveryMethod.Network;
mySmtpClient.Credentials = new NetworkCredential(email, password);
mySmtpClient.TargetName = "STARTTLS/smtp.office365.com";
mySmtpClient.EnableSsl = true;
// add from,to mailaddresses
MailAddress from = new MailAddress(email);
MailAddress to = new MailAddress(email);
MailMessage myMail = new System.Net.Mail.MailMessage(from, to);
// set subject and encoding
myMail.Subject = "Test message";
myMail.SubjectEncoding = System.Text.Encoding.UTF8;
// set body-message and encoding
myMail.Body = "<b>Test Mail</b><br>using <b>HTML</b>.";
myMail.BodyEncoding = System.Text.Encoding.UTF8;
// text or html
myMail.IsBodyHtml = true;
mySmtpClient.Send(myMail);
But Im still getting the same error as before (MustIssueStartTlsFirst).
Anyone know the problem?
I have a C# application that uses SmtpClient to send emails. Emails all appear to be being delivered fine however when sending emails with attachments, periodically the attachment will be 0 bytes.
I'm using MemoryStream to write the attachment and the stream cursor is explicitly set to the start of the stream.
I'm using gmails smtp server to send the mail. The troubling part is sometimes attachments send fine and other times they have 0 bytes. I haven't been able to find any consistent pattern when testing either. I'll manually send 5 emails in secession all to the same email address all with the same attachment. Randomly only 1 or 2 of the email contain the attachment well the others are all 0 bytes.
Any guess? Here's the snippet of my code where I create and send the mail.
private void DispatchSmtpAsync(MessagePayload payload, IUnitOfWork unitOfWork)
{
MailMessage message = new MailMessage();
SmtpClient client = new SmtpClient();
foreach (EmailAddress recipient in payload.To)
message.To.Add(new MailAddress(recipient.Email, recipient.Name));
foreach (EmailAddress recipient in payload.Cc)
message.CC.Add(new MailAddress(recipient.Email, recipient.Name));
foreach (EmailAddress recipient in payload.Bcc)
message.Bcc.Add(new MailAddress(recipient.Email, recipient.Name));
foreach (MyApp.Services.Email.Common.Models.Attachment attachment in payload.Content.Attachments)
{
byte[] content = Convert.FromBase64String(attachment.Content);
MemoryStream stream = new MemoryStream();
stream.Seek(0, SeekOrigin.Begin);
stream.Write(content, 0, content.Length);
message.Attachments.Add(new System.Net.Mail.Attachment(stream, attachment.Name, MimeMapping.GetMimeMapping(attachment.Name)));
}
message.From = new MailAddress(payload.From.Email, payload.From.Name);
message.Body = payload.Content.Html;
message.Subject = payload.Content.Subject;
message.IsBodyHtml = true;
client.Host = unitOfWork.SystemSettingRepository.GetValue<string>(SystemSettingName.SmtpHost);
client.Port = unitOfWork.SystemSettingRepository.GetValue<int>(SystemSettingName.SmtpPort);
client.EnableSsl = unitOfWork.SystemSettingRepository.GetValue<bool>(SystemSettingName.SmtpSsl);
client.Credentials = new NetworkCredential(unitOfWork.SystemSettingRepository.GetValue<string>(SystemSettingName.SmtpUsername),
unitOfWork.SystemSettingRepository.GetValue<string>(SystemSettingName.SmtpPassword));
client.SendAsync(message, Guid.NewGuid().ToString());
}
I how can I have email encrypted and signed ?
Seem that I can either encrypt or signed but not both.
Below is my code
public void SendEncryptedEmail04(
//string SigningCertPath, string EncryptingCertPath,
String sender, String To,
string Subject, string Body,
// string SmtpServer, int SmtpPort, bool HTML)
bool HTML)
{
X509Certificate2 SignCert = new X509Certificate2("D:\\certwithprivatekey.pfx", "password"));
X509Certificate2 EncryptCert = new X509Certificate2("abc#gmail.crt", "");
StringBuilder Message = new StringBuilder();
Message.AppendLine("Content-Type: text/" + ((HTML) ? "html" : "plain") +
"; charset=\"iso-8859-1\"");
Message.AppendLine("Content-Transfer-Encoding: 7bit");
Message.AppendLine();
Message.AppendLine(Body);
byte[] BodyBytes = Encoding.ASCII.GetBytes(Message.ToString());
EnvelopedCms ECms = new EnvelopedCms(new ContentInfo(BodyBytes));
CmsRecipient Recipient = new CmsRecipient(
SubjectIdentifierType.IssuerAndSerialNumber, EncryptCert);
ECms.Encrypt(Recipient);
byte[] EncryptedBytes = ECms.Encode();
SignedCms Cms = new SignedCms(new ContentInfo(EncryptedBytes));
CmsSigner Signer = new CmsSigner
(SubjectIdentifierType.IssuerAndSerialNumber, SignCert);
Cms.ComputeSignature(Signer);
byte[] SignedBytes = Cms.Encode();
MailMessage Msg = new MailMessage();
Msg.To.Add(new MailAddress(To));
Msg.From = new MailAddress(sender);
Msg.Subject = Subject;
//MemoryStream ms = new MemoryStream(EncryptedBytes);
MemoryStream ms = new MemoryStream(SignedBytes);
AlternateView av = new AlternateView(ms,
"application/pkcs7-mime; smime-type=signed-data;name=smime.p7m");
//"application/pkcs7-mime; smime-type=enveloped-data;name=smime.p7m");
Msg.AlternateViews.Add(av);
SmtpClient smtp = new SmtpClient(emailServer, 25);
smtp.UseDefaultCredentials = false;
smtp.Credentials = new System.Net.NetworkCredential(sender,"xxxx"));
smtp.Send(Msg);
}
The email received by ThunderBird has the following
However, I changed to
MemoryStream ms = new MemoryStream(EncryptedBytes);
I have
How can I have encrypted and signed ?
Thanks
I have method, which sign my email by certificate. This work fine if the line with adding an attachment is commented out.
private static void mailer()
{
MailAddress from = new MailAddress("test#email.cz");
MailAddress to = new MailAddress("test#email.cz");
MailMessage message = new MailMessage(from, to);
message.Subject = "Test subject email";
message.IsBodyHtml = true;
string body = "Content-Type: text/html; charset=utf-8 \r\n Content-Transfer-Encoding: 7bit \r\n\r\n";
body += " Email body signed by certificate ";
byte[] messageData = Encoding.ASCII.GetBytes(body);
SignedCms Cms = new SignedCms(new ContentInfo(messageData));
RSACryptoServiceProvider csp = null;
X509Certificate2 cert = new X509Certificate2(#"C:\TFS\cert_test.p12", "password");
if (cert != null)
{
csp = (RSACryptoServiceProvider)cert.PrivateKey;
}
else
{
throw new Exception("Valid certificate was not found");
}
CmsSigner Signer = new CmsSigner(SubjectIdentifierType.IssuerAndSerialNumber, cert);
Cms.ComputeSignature(Signer);
byte[] SignedBytes = Cms.Encode();
MemoryStream signedStream = new MemoryStream(SignedBytes);
AlternateView signedView = new AlternateView(signedStream, "application/pkcs7-mime; smime-type=signed-data; name=sig.p7m");
message.AlternateViews.Add(signedView);
ContentType contentType = new ContentType();
contentType.MediaType = MediaTypeNames.Application.Octet;
contentType.Name = "test.xml";
MemoryStream ms = new MemoryStream(fileData);
ms.Position = 0;
Attachment attachment = new Attachment(ms, contentType);
//message.Attachments.Add(attachment);
SmtpClient client = new SmtpClient("smtp.server.net");
client.UseDefaultCredentials = false;
client.Credentials = new System.Net.NetworkCredential("smtp.server.net", "password", "user");
try
{
client.Send(message);
}
catch (Exception ex)
{
throw ex;
}
}
But I must add attachments (3 or more) to email. When I add an attachment (just one attachment yet), the email no longer shows as signed and the body of email doesn't show up. I find some samples of my problem, but it useless for me.
I don't encrypt the body of email and an attachment. I need only sign an email by certificate.
Thanks for help.
EDIT: Sorry, I had commented out the line with adding signed AlternateView. Right commented out the line is with adding attachment to the email.
I am using C# .NET 4.0 to send a signed SMTP mail message like so:
private void SendMailMessage(object data)
{
MailMessage message = new MailMessage();
message.From = new MailAddress(fromAddress);
message.To.Add(new MailAddress(emailTo));
message.Subject = "Subject";
message.IsBodyHtml = true;
message.Body += "Blah blah blah.";
byte[] messageBytes = Encoding.ASCII.GetBytes(message.Body);
SignedCms Cms = new SignedCms(new ContentInfo(messageBytes));
CmsSigner Signer = new CmsSigner(SubjectIdentifierType.IssuerAndSerialNumber, certificate);
Cms.ComputeSignature(Signer);
byte[] SignedBytes = Cms.Encode();
MemoryStream signedStream = new MemoryStream(SignedBytes);
AlternateView signedView = new AlternateView(signedStream, "application/pkcs7-mime; smime-type=signed-data;name=sig.p7m");
message.AlternateViews.Add(signedView);
SmtpClient client = new SmtpClient(smtpServer, int.Parse(smtpServerPort));
client.DeliveryMethod = SmtpDeliveryMethod.Network;
client.Send(message);
message.Dispose();
client = null;
}
From what I can tell, this "works" in that if view the raw data of the message, I see the alternate view with a big PKCS signature in it. But Outlook doesn't recognize it. The Outlook client normally recognizes signed messages and attempts to validate them and puts a little certificate on the message and all that...
I want that... what am I missing?
Edit: I have made some progress on this on my own, but still having some trouble. Here is what the code looks like now:
private void SendMailMessage(string emailTo)
{
MailMessage message = new MailMessage();
message.From = new MailAddress(fromAddress);
message.To.Add(new MailAddress(emailTo));
message.Subject = "Special Delivery";
message.IsBodyHtml = false;
string body = "Content-Type: text/plain;charset=\"iso-8859-1\"\nContent-Transfer-Encoding: quoted-printable\n\nHere is some body text!";
byte[] messageBytes = Encoding.ASCII.GetBytes(body);
ContentInfo content = new ContentInfo(messageBytes);
SignedCms signedCms = new SignedCms(content, false);
CmsSigner Signer = new CmsSigner(SubjectIdentifierType.IssuerAndSerialNumber, certificate);
signedCms.ComputeSignature(Signer);
byte[] signedBytes = signedCms.Encode();
MemoryStream ms = new MemoryStream(signedBytes);
AlternateView av = new AlternateView(ms, "application/pkcs7-mime; smime-type=signed-data;name=smime.p7m");
message.AlternateViews.Add(av);
SmtpClient client = new SmtpClient(smtpServer, int.Parse(smtpServerPort));
client.DeliveryMethod = SmtpDeliveryMethod.Network;
client.Send(message);
message.Dispose();
client = null;
}
Of note is that I left message.Body blank this time, only sending the AlternateView. Now, when I send this to an Outlook inbox, I get the padlock icon over my email, the S/MIME doodad kicks in and tries to verify the signer, but fails. The certificate used to sign the email is issued by a publically trusted CA. Edit: That's my fault, the certificate didn't have the "secure email" usage attribute. I'll get a new certificate.
When I send the same email to a Gmail address, I get a blank message with a *.p7m attachment on it that contains a bunch of garbage.
The code that gets this working in Outlook looks like this:
private void SendMailMessage(string emailTo)
{
MailMessage message = new MailMessage();
message.From = new MailAddress(fromAddress);
message.To.Add(new MailAddress(emailTo));
message.Subject = "Regarding your lottery winnings";
message.IsBodyHtml = false;
string body = "Content-Type: text/plain;charset=\"iso-8859-1\"\nContent-Transfer-Encoding: quoted-printable\n\nBlah blah blah blah blah blah.";
byte[] messageBytes = Encoding.ASCII.GetBytes(body);
ContentInfo content = new ContentInfo(messageBytes);
SignedCms signedCms = new SignedCms(content, false);
CmsSigner Signer = new CmsSigner(SubjectIdentifierType.IssuerAndSerialNumber, emailCert);
signedCms.ComputeSignature(Signer);
byte[] signedBytes = signedCms.Encode();
MemoryStream ms = new MemoryStream(signedBytes);
AlternateView av = new AlternateView(ms, "application/pkcs7-mime; smime-type=signed-data;name=smime.p7m");
message.AlternateViews.Add(av);
SmtpClient client = new SmtpClient(smtpServer, int.Parse(smtpServerPort));
client.DeliveryMethod = SmtpDeliveryMethod.Network;
client.Send(message);
message.Dispose();
client = null;
}
Using a valid certificate, of course. Now when I send this email and view it in Outlook, I get the certificate icon on the email, and the S/MIME control successfully validates the signature, and the text shows up just like I want it to without displaying the headers to the user.
Notice that I have to leave message.Body empty. Putting anything in message.Body will break it.