How do I programmatically send encrypted emails in Outlook Express using Python? - c#

I'm a new programmer and I've reached the point where my lack of knowledge (of the C# and VBA language) and experience is preventing me from continuing with my program. I only know Python and all the documentation that I've tried digging into is in C# and VB.
My story: I'm working on a GUI that automates and manages specialized email operations for my company using Outlook Express 2016. I've figured out that win32com is the package to use, and I've figured out how to create and send basic emails, but I'm struggling to figure out how to send emails encrypted. My company uses the McAfee SaaS Email Encryption add-in found at: http://www.mcafee.com/us/downloads/saas/encrypted-from-microsoft-outlook-addin.aspx.
Note: the site doesn't specify that this add-in is supported in the 2016 version but it indeed works. Also, the built-in Outlook option to encrypt all emails is not viable because I need some emails to not be encrypted.
What I've garnered from another similar post is that I need to use the PropertyAccessor method:
mailItem.PropertyAccessor.SetProperty(
"http://schemas.microsoft.com/mapi/proptag/0xHHHHHHHH", x);
where HHHHHHHH is some hexadecimal code and x represents a state such as 0 = off. I tried digging into some property tag documentation but I'm having trouble understanding them.
Am I on the right track? There may be a completely different + easier way of doing this. I do realize a lot of my difficulty may be due to not knowing C#/VBA, but it would be highly appreciated if someone out there can point me in the right direction.

First, you need a Secure Email certificate issued to the email address you want to use.
Let's say this is mymail.somecompany.com. Your cert should have this in the subject name and should be enabled for secure email.
Next, you need to programmatically get the certificate or load from a pfx file like
X509Store store = new X509Store(StoreLocation.CurrentUser);
store.Open(OpenFlags.OpenExistingOnly | OpenFlags.ReadOnly);
X509Certificate2Collection certs = store.Certificates;
X509Certificate2 certificate = null;
foreach (X509Certificate2 cert in certs)
{
if (cert.Subject.IndexOf("mymail#somecompany.com") >= 0)
{
certificate = cert;
break;
}
}
Next, you need to have an entity that you want to sign and send.
string strbody = #"Content-Type: text/plain;charset=""iso-8859-1""
Content-Transfer-Encoding: quoted-printable
This is a test s/mime message";
This is where it gets a little not very intuitive since there is no programatic way of creating the email entity you want to send
Note the headers and a series of two \r\n before the entity body "this is a test s/mime" message begins
Next, you need to generate a signed envelope for this content
byte[] data = Encoding.ASCII.GetBytes(strbody);
ContentInfo content = new ContentInfo(data);
SignedCms signedCms = new SignedCms(content, false);
CmsSigner signer = new CmsSigner(SubjectIdentifierType.IssuerAndSerialNumber, certificate);
signedCms.ComputeSignature(signer);
byte[] signedbytes = signedCms.Encode();
Now that you have the content you want to send is signed with the certificate of your choice you need to
create a mail message object and create an alternate view and add this to your alternate view collection
MailMessage msg = new MailMessage();
msg.From = new MailAddress("");
msg.To.Add(new MailAddress(""));
msg.Subject = "test s/mime";
MemoryStream ms = new MemoryStream(signedbytes);
AlternateView av = new AlternateView(ms, "application/pkcs7-mime; smime-type=signed-data;name=smime.p7m");
msg.AlternateViews.Add(av);
Now that you have the message prepared you can just send it
SmtpClient client = new SmtpClient("smtphost", 25);
client.UseDefaultCredentials = true;
client.Send(msg);
This is a kind of hack at this time and requires some manual preparation of the entity body
you want to sign. I need to do some more research on this and find out if there is a better way of doing this.

Related

Office 365 Exchange SMTP intermittent authentication failure in .NET application

We have a number of C# (.net 4) apps that send email via our Office 365 Exchange account. This works absolutely fine 90% of the time. But sporadically we get the following error:
The SMTP server requires a secure connection or the client was not authenticated. The server response was: 5.7.57 SMTP; Client was not authenticated to send anonymous mail during MAIL FROM.
Here is the code:
private void SendEmail(string strTo, string strFrom, string strMessage, string strSubject, bool htmlFormat = true)
{
System.Net.Mail.MailMessage mail = new System.Net.Mail.MailMessage();
System.Net.Mail.MailAddress mto = new System.Net.Mail.MailAddress(strTo);
System.Net.Mail.MailAddress mfrom = new System.Net.Mail.MailAddress(strFrom);
mail.Subject = strSubject;
mail.From = mfrom;
mail.To.Add(mto);
mail.Body = strMessage;
mail.IsBodyHtml = htmlFormat;
System.Net.Mail.SmtpClient mailClient = new System.Net.Mail.SmtpClient("smtp.office365.com", 587);
mailClient.Timeout = 1000000;
mailClient.EnableSsl = true;
mailClient.UseDefaultCredentials = false;
mailClient.Credentials = new System.Net.NetworkCredential("my#emailaddress.com", "mypassword");
mailClient.Send(mail);
}
I've seen questions asked about this error message on here before, but I have not yet found any explanations as to why it might be happening only intermittently. The error message is confusing since I am not trying to send anonymously, and I am already using EnableSsl. (Note: if I remove the Credentials line or the EnableSSL line, then I get this error every time)
EDIT: As a test, I made a simple app that emails me 1 time per minute. I typically get between 12 and 25 successful emails before one blows up. Then it will go right back to normal for another 12-25, before blowing up again.
EDIT: Since the issue is so sporadic, and involves an error message returned from the 365 SMTP server, I don't really think its a problem with the code itself. Given that, I'm not sure if I've tagged the question properly, or if SO is even the best community for it. If any of you Stack Exchange veterans think this would be better placed in a different community, I am all ears. I'm a bit new here myself.
Any thoughts are appreciated!
I opened a case with Microsoft 365 support on this, and they told me I was not the only one experiencing the issue. They had me try capturing SMTP logs when the issue occurs, but we never found much of anything very helpful. The MS tech also stated that he was going to try upgrading something on our mail server on the back end (not sure what exactly). After he did that the problem was still occurring but seemed less frequent.
Eventually it became less and less frequent and now I have not seen it occur in about 5 days. So, I don't know that this is from anything specific that my MS tech did, or just a larger problem eventually getting solved. But for now, the problem seems to have gone away, and not by changing anything on our end.
public static void SendEmail(string sTo, string subject, string body)
{
var Port = int.Parse(ConfigurationManager.AppSettings["SmtpPort"]);
using (var client = new SmtpClient(Your EmailHost, Port))
using (var message = new MailMessage()
{
From = new MailAddress(FromEmail),
Subject = subject,
Body = body
})
{
message.To.Add(sTo);
client.DeliveryMethod = SmtpDeliveryMethod.Network;
client.Credentials = new NetworkCredential(ConfigurationManager.AppSettings["EmailCredential"],
ConfigurationManager.AppSettings["EmailPassword"]);
client.EnableSsl = true;
client.Send(message);
};
}
After adding SMTP details properly in your email application
You need to go to on the > Microsoft 365 admin center (https://admin.microsoft.com) > Active users
Select a user you wish to authenticate with the SMTP server
Select the Mail Tab (See Image 1)
Under Email apps, Select> Manage email apps
Make sure that "Authenticated SMTP" checkbox is selected (See Image 2)
And save
Your email should work after that.
IMAGES EXAMPLES HERE
Image 1
Image 2

Generate Oulook Email From Server

I have an ASP.NET site that needs to be able to dynamically generate an email that will get sent back to the users local machine to then be sent via Outlook. The code below does just that but it uses the Outlook Interop to create the message and I was a bit hesitent to use Interop on a Web App. I looked into OpenXML but couldnt seem to find much on Outlook.
// Creates a new Outlook Application Instance
Microsoft.Office.Interop.Outlook.Application objOutlook = new Microsoft.Office.Interop.Outlook.Application();
// Creating a new Outlook Message from the Outlook Application Instance
Microsoft.Office.Interop.Outlook.MailItem mic = (Microsoft.Office.Interop.Outlook.MailItem)(objOutlook.CreateItem(Microsoft.Office.Interop.Outlook.OlItemType.olMailItem));
mic.To = "to#email.com";
mic.CC = "cc#email.com";
mic.Subject = "Test Subject";
mic.HTMLBody = "Test Message Body";
string strNewEmailPath = strEmailPath + "\\EmailMessages\\" + strUser + "_Message_PEI.msg";
mic.SaveAs(strNewEmailPath, Microsoft.Office.Interop.Outlook.OlSaveAsType.olMSG);
HttpContext.Current.Response.ContentType = "application/vnd.ms-outlook";
HttpContext.Current.Response.AppendHeader("Content-Disposition", "attachment; filename=Message.msg");
HttpContext.Current.Response.TransmitFile(strNewEmailPath);
HttpContext.Current.Response.End();
Can anyone help with perhaps a better suggestion for automating an Outlook message using ASP.NET?
Update:
I did find the Javascript code which seems do have similar functionality.
var theApp //Reference to Outlook.Application
var theMailItem //Outlook.mailItem
//Attach Files to the email, Construct the Email including
//To(address),subject,body
var subject = sub
var msg = body
//Create a object of Outlook.Application
try
{
var theApp = new ActiveXObject("Outlook.Application")
var theMailItem = theApp.CreateItem(0) // value 0 = MailItem
//Bind the variables with the email
theMailItem.to = to
theMailItem.Subject = (subject);
theMailItem.Body = (msg);
//Show the mail before sending for review purpose
//You can directly use the theMailItem.send() function
//if you do not want to show the message.
theMailItem.display()
}
catch(err)
{
alert("Error");
}
I have had a similar need before. I shelved the idea because of the complexity of generating .msg files (though I think there's some commercial libraries that can do it). One alternative you may consider is installing an Outlook add-in on the user's machine. Poll the web server (or this would be a great case for SignalR so the server could push data) and have the web server send the details of the email to the user's machine. Then the add-in could generate the email based on the details it received from the server. This would avoid running Interop on the server (which is a bad idea). However, you'll now have the complexity of deploying an Outlook Add-In, but if this is a corporate environment it shouldn't be too difficult.
If you didn't want to do it as an add-in, you could still do it by just writing a service application that runs on the user's machine and uses Interop, but that still has all the complexities of the add-in technique.
Alternatively, if your email is really simple, you could just use a mailto URI. But I find them very limiting, since it's difficult or impossible to send an HTML message that way.
And lastly, you could have the server just send the email on the user's behalf, not involving code running on the user's machine at all.
I did find the Javascript code which seems do have similar functionality. I was hoping someone might have an OpenXML solution but this JS solution can work and is better than Outlook Interop
var theApp //Reference to Outlook.Application
var theMailItem //Outlook.mailItem
//Attach Files to the email, Construct the Email including
//To(address),subject,body
var subject = sub
var msg = body
//Create a object of Outlook.Application
try
{
var theApp = new ActiveXObject("Outlook.Application")
var theMailItem = theApp.CreateItem(0) // value 0 = MailItem
//Bind the variables with the email
theMailItem.to = to
theMailItem.Subject = (subject);
theMailItem.Body = (msg);
//Show the mail before sending for review purpose
//You can directly use the theMailItem.send() function
//if you do not want to show the message.
theMailItem.display()
}
catch(err)
{
alert("Error");
}

How to put contact us page in windows application c# [duplicate]

I'm thinking of implementing "Report a bug/Suggestions" option to my game, however I am not quite sure how I could get that working. I do not have my own server or anything, so I can't just send the text that user has written to there.
The only way I came up with is that the client would write a message and I would send it to an email account where I could read them. However, I do not want that users would need to send the reports through their personal accounts. I am not quite sure how I could implement this and googling didn't bring up any good suggestions.
I haven't done a lot of network stuff, so I'd really appreciate it if you could explain ( possibly even in code ) the process step-by-step.
I am using C# and the game is being programmed for Windows Phone 7.
Yes, it is absolutely possible to do that. From a relatively low-level perspective, you need to:
Resolve the MX (mail-exchanger) server for the e-mail account you want to send to.
Open a socket to the MX server.
Send the appropriate SMTP commands to cause the e-mail message to be delivered to your recipient account. You essentially have the freedom to set the "from" address to be any arbitrary thing you want.
SMTP is a very simple/human-friendly protocol, so it's not a massive effort to do all of that by hand. At the same time, there are prebuilt libraries that will handle all of that for you (except possibly the resolution of the recipient's MX server).
Note that emails sent this way are more likely to be filtered out as spam (generally because the sender's IP/hostname is not going to match whatever domain you put on the outgoing e-mail address you decide to use).
Also note that since you can set the "from" address to anything, you have the option of asking the user if they want to provide their actual contact address, and if they do you can make that the "from" address so that you can actually get back in touch with them if necessary.
You don't need to use email at all. Consider using an error reporting service like sentry or airbrake.
These services have clients that you embed in your program; which automatically log your errors, including any debugging information/stacktrace; and notify you by email when your application reports a problem.
Usually you integrate the app's API into your own error handling mechanism. At the point of an error, the client will capture your debugging information, you can popup a modal asking user for information like "what were you doing when this error happened?", save that as part of your error response that is sent back to the service.
Since the app works over HTTP, you don't need any special ports to be open. It is easier and more helpful than having users send you emails with "it doesn't work!!", and you don't have to deal with email sending headaches.
I recently wrote an article on this: Sending email with C#
You basically have two choices, either you send it using an SMTP-client, this means that you have to have a SMTP-server and be able to connect to port 25 (if you're not using an external SMTP, then you have to manage that by yourself). Or you can use an external email provider, such as:
AlphaMail
SendGrid
Mandrill
If you're using AlphaMail you can send emails in the following way:
IEmailService emailService = new AlphaMailEmailService()
.SetServiceUrl("http://api.amail.io/v1/")
.SetApiToken("YOUR-ACCOUNT-API-TOKEN-HERE");
var person = new Person()
{
Id = 1234,
UserName = "jdoe78",
FirstName = "John",
LastName = "Doe",
DateOfBirth = 1978
};
var response = emailService.Queue(new EmailMessagePayload()
.SetProjectId(12345) // ID of AlphaMail project (determines options, template, etc)
.SetSender(new EmailContact("support#company.com", "from#example.com"))
.SetReceiver(new EmailContact("Joe E. Receiver", "to#example.org"))
.SetBodyObject(person) // Any serializable object
);
Another thing that differs from just building HTML and sending it with an SMTP-client is that with AlphaMail you have the ability to edit your emails outside your code directly in a GUI. You can also easily create highly dynamic templates using AlphaMail's templating language Comlang.
<html>
<body>
<b>Name:</b> <# payload.FirstName " " payload.LastName #><br>
<b>Date of Birth:</b> <# payload.DateOfBirth #><br>
<# if (payload.Id != null) { #>
Sign Up Free!
<# } else { #>
Sign In
<# } #>
</body>
</html>
So this is my thought, why don't you have the email sent to you...as you?
using System.Net;
using System.Net.Mail;
var fromAddress = new MailAddress("from#gmail.com", "From Name"); //Both the email addresses would be yours
var toAddress = new MailAddress("to#example.com", "To Name"); //Both the email addresses would be yours
const string fromPassword = "fromPassword";
const string subject = "There name or whatever";
const string body = "Errors ect....";
var smtp = new SmtpClient
{
Host = "smtp.gmail.com",
Port = 587,
EnableSsl = true,
DeliveryMethod = SmtpDeliveryMethod.Network,
UseDefaultCredentials = false,
Credentials = new NetworkCredential(fromAddress.Address, fromPassword)
};
using (var message = new MailMessage(fromAddress, toAddress)
{
Subject = subject,
Body = body
})
{
smtp.Send(message);
}
code from here
All they would see would be the submit button so they wouldn't have all your personal username/password, also you should prolly set up a dummy account to have them sent to even if it just then forwards them to your real email account.
Another way to achieve this would be to host a WCF Service which takes in your Message and stores in db or /sends email. One downside of this is you'll need a web server to do this.
Try following code this might help you :
Dim objCDOMail
Set objCDOMail = Server.CreateObject("CDONTS.NewMail")
objCDOMail.From = "sender#domain.com"
objCDOMail.To = "receiver#domain.com"
objCDOMail.Subject = "Test Mail Script"
objCDOMail.BodyFormat = 0
objCDOMail.MailFormat = 0
objCDOMail.Body = "Testing Mail from Test Script"
objCDOMail.Importance = 1
objCDOMail.Send
Set objCDOMail = Nothing

How to Domainkeys/DKIM email signing using the C# SMTP client?

I have written an program in C# which sends out emails. Now I have a requirement to sign outbound emails using Dominkeys/DKIM, but I'm not sure how to do it.
I have set up all keys, but I don't know how to get those and how to include them in the email header.
There is a fundamental problem with trying to do DKIM signatures with System.Net.Mail.MailMessage and System.Net.Mail.SmtpClient which is that in order to sign the message, you need to poke the internals of SmtpClient in order to hash the message body as one of the steps in generating the DKIM-Signature header. The problem comes in when you have alternative views or attachments because SmtpClient will generate new multipart boundaries each time it writes out the message which breaks the body hash and thus the DKIM-Signature validity.
To work around this, you can use the MimeKit and MailKit open source libraries for .NET as an alternative framework to using System.Net.Mail.
To add a DKIM signature to a message in MimeKit, you would do something like this:
MimeMessage message = MimeMessage.CreateFromMailMessage(mailMessage);
HeaderId[] headersToSign = new HeaderId[] { HeaderId.From, HeaderId.Subject, HeaderId.Date };
string domain = "example.net";
string selector = "brisbane";
DkimSigner signer = new DkimSigner ("C:\my-dkim-key.pem", domain, selector)
{
SignatureAlgorithm = DkimSignatureAlgorithm.RsaSha1,
AgentOrUserIdentifier = "#eng.example.com",
QueryMethod = "dns/txt",
};
// Prepare the message body to be sent over a 7bit transport (such as
// older versions of SMTP). This is VERY important because the message
// cannot be modified once we DKIM-sign our message!
//
// Note: If the SMTP server you will be sending the message over
// supports the 8BITMIME extension, then you can use
// `EncodingConstraint.EightBit` instead.
message.Prepare (EncodingConstraint.SevenBit);
message.Sign (signer, headersToSign,
DkimCanonicalizationAlgorithm.Relaxed,
DkimCanonicalizationAlgorithm.Simple);
To send the message using MailKit, you would do something like this:
using (var client = new MailKit.Net.Smtp.SmtpClient ()) {
client.Connect ("smtp.gmail.com", 465, true);
client.Authenticate ("username", "password");
client.Send (message);
client.Disconnect (true);
}
Hope that helps.
see https://github.com/dmcgiv/DKIM.Net it's a DomainKeys Identified Mail (DKIM) implementation for .Net written in C# - it enables you to sign MailMessage objects.
Use
http://www.mimekit.org
Not only does it allow to use DKIM for signing, also you can include S/MIME certificates, PGP certificates and more.
Also, its a very mature lib - the only one i've found that handles foreign languages (apart from english) correctly, since its completely and thoroughly coded with unicode in mind.
Its free and opensource.
This solved it for me when using Mailenable as SMTP relay server.
http://www.mailenable.com/kb/content/article.asp?ID=ME020700
When creating the DKIM TXT record on the domain name don't forget to use the active selector as prefix => yourselector._domainkey.yourdomainname.be
If you are looking to DKIM-sign the body of the MailMessage then DKIM.NET is great. If you are looking to have alternative views in your message then I wasnt able to find a solution and wrote my own (open-source with the usual disclaimers) that can be found at https://github.com/yannispsarras/DKIM-AlternativeViews
I understand this is a pretty old thread but I thought it may help someone.
i didnt find much help on this issue, but my problem got solve by configuring smtp server.
i cant post those steps as i am using 3rd party smtp server and every server has their own configuration. after proper configuration my smtp automatically adds DM/DKIM signature.

Troubleshooting "The server committed a protocol violation" when sending mail with SmtpClient

I want to send a mail message with the SmtpClient class.
Here's the code I use:
SmtpClient smtpClient = new SmtpClient("Host",25);
NetworkCredential basicCredential =
new NetworkCredential("UserName", "Password");
MailMessage message = new MailMessage();
MailAddress fromAddress = new MailAddress("me#domain.com");
smtpClient.UseDefaultCredentials = false;
smtpClient.Credentials = basicCredential;
message.From = fromAddress;
message.Subject = "test send";
message.IsBodyHtml = true;
message.Body = "<h1>hello</h1>";
message.To.Add("mail#domain.com");
smtpClient.Send(message);
But it always throws an exception:
The server committed a protocol violation The server response was: UGFzc3dvcmQ6
I can't find the reason for that. Please, if anyone has faced something like this, tell me what to do.
I had the same problem, for my case it was for setting user#domain instead of user, I mean
Old code
new NetworkCredential("UserName#domain.com", "Password");
New code
new NetworkCredential("UserName", "Password");
This looks to me like SmtpClient authentication is somehow getting out of step.
Some authentication mechanisms are "Client: request auth with username and password, Server: success/fail" others are "Client: request auth with username, Server: request password, Client: reply with password, Server: success/fail".
It looks like SmtpClient is expecting the former, while your server is expecting the latter.
As dave wenta suggested, a log of a session would tell you what auth mechanism SmtpClient is trying to use, but it will also say what auth mechanisms the server supports.
What normally happens is that the server offers a number of authetication options, and the client choses which one it is going to use. The behaviour from there should be determined by the protocol chosen. I would hope that the SmtpClient class took care of that for you though, but I'm afraid I've never used that particular class.
Also remember - If you are going to post a log here, change to a throwaway password before you log the session, as a base64 encoded plain text password can be trivially changed back to human readable plain text password.
UGFzc3dvcmQ6 is "Password:" base 64 encoded (without quotes), meaning the password is probably wrong or not send encoded. Try base 64 encoding the password:
string password = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes("Password));
Enable logging for System.Net.Mail. Then view the log file. This will show you exactly what is happening during the SMTP layer.
Here is a link with more info:
http://systemnetmail.com/faq/4.10.aspx
thousand of hit on google for UGFzc3dvcmQ6
it seem the server expect encrypted(with base64) username/password
Had the same problem. Solved it in the following steps:
1) find out, what the server offers for SMTP Authentication by connecting to the SMTP Server using Telnet or putty or any other terminal:
telnet xxx.yyy.zzz.aaa 587
(xxx.yyy.zzz.aaa = IP address of the SMTP Server, 587 = port number)
< Server answers with "220 protocol + version + time"
ehlo testing
< Server displays list of capabilities e.g.
250-AUTH NTLM CRAM-MD5 LOGIN
The SMTP client tries to take the most secure protocol first. In my case:
1. System.Net.Mail.SmtpNegotiateAuthenticationModule
2. System.Net.Mail.SmtpNtlmAuthenticationModule
3. System.Net.Mail.SmtpDigestAuthenticationModule
4. System.Net.Mail.SmtpLoginAuthenticationModule
It looks as if the SMTP client tries NTLM while the server tries to run LOGIN.
With a hack (cf. https://blogs.msdn.microsoft.com/knom/2008/04/16/hacking-system-net-mail-smtpclient/), all protocols can be turned of except for the one the server assumes (LOGIN in this case):
FieldInfo transport = smtpClient.GetType().GetField("transport", BindingFlags.NonPublic | BindingFlags.Instance);
FieldInfo authModules = transport.GetValue(smtpClient).GetType().GetField("authenticationModules",BindingFlags.NonPublic | BindingFlags.Instance);
Array modulesArray = authModules.GetValue(transport.GetValue(smtpClient)) as Array;
foreach (var module in modulesArray)
{
Console.WriteLine(module.ToString());
}
// System.Net.Mail.SmtpNegotiateAuthenticationModule
// System.Net.Mail.SmtpNtlmAuthenticationModule
// System.Net.Mail.SmtpDigestAuthenticationModule
// System.Net.Mail.SmtpLoginAuthenticationModule
// overwrite the protocols that you don't want
modulesArray.SetValue(modulesArray.GetValue(3), 0);
modulesArray.SetValue(modulesArray.GetValue(3), 1);
modulesArray.SetValue(modulesArray.GetValue(3), 2);
This can also happen when you simply don't provide the password. In my case I was using credentials from a web.config smtp block and on my deployment server (using octopus deploy) had forgotten to populate the password attribute.
For anyone else coming across this on google.. I fixed this by supplying my username in the "username" format instead of "DOMAIN\username"
$Credential = Get-Credential
Send-MailMessage -SmtpServer exchange.contoso.com -Credential $Credential -From 'user#contoso.com' -To 'recipient#domain.com' -Subject 'Test email' -Port 587 -UseSsl

Categories