I have a basic email web service that runs on one of my boxes. This box sends email using Amazon SES. It has sent 250,000 emails per month for the last 5 months without issue.
Suddenly, today, around lunch, the event log started spewing thousands of errors:
The remote certificate is invalid according to the validation procedure.
The email send is pretty basic. It looks like this:
using (var client = new SmtpClient(host, port))
{
client.Credentials = new NetworkCredential(username, password);
client.EnableSsl = true;
client.Send(message);
}
Host is amazon ses server, port is 25, and username and password are the smtp credentials you are given from amazon. Just to double check I created new username and password credentials and recompiled the software, but I still have the same issue.
I am decent at software but I have never worked with certs, and I have no idea how they work. All I know is the box that the emails are being sent from has a valid Digi Cert certificate and it doesn't look like anything has changed on our end.
Can someone help me resolve this or at least ask the right question?
It appears that the SSL certificate that is being presented is invalid. That could be for any number of reasons. If the hostname ('Alternate DNS' address) in the cert doesn't match the address you're connecting to, you'll get this error. The cert might not be valid according to the expiration date of the cert. The certificate issuer might no longer be trusted. The certificate may have been revoked and is in a revoked list somewhere.
What address are you trying to connect to, and what does that certificate look like?
Related
Our company is switching the SMTP mail server to Office 365. The key issue is the new SMTP server "smtp.office365.com" only supports TLS encryption. Thus I cannot use CredentialCache.DefaultNetworkCredentials to encode my Windows log-in password automatically.
var smtpClient = new SmtpClient("smtp.oldserver.com")
{
Credentials = CredentialCache.DefaultNetworkCredentials
};
const string from = "myemail#xyz.com";
const string recipients = "myemail#xyz.com";
smtpClient.Send(from, recipients, "Test Subject", "Test Body");
Previously this works without any issue. But if I now change the above snippet to:
var smtpClient = new SmtpClient("smtp.office365.com");
smtpClient.EnableSsl = true;
smtpClient.Port = 587;
smtpClient.Credentials = CredentialCache.DefaultNetworkCredentials;
I'm now getting:
Unhandled Exception: System.Net.Mail.SmtpException: 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
But if I specify my Windows login username and password in the code it works fine:
smtpClient.Credentials = new NetworkCredential("myemail#xyz.com", "mypassword");
So:
Is it possible to encode the password using DefaultNetworkCredentials but make it workable under TLS encryption?
If 1. is not possible, is there a better way to encode my Windows password somewhere else without directly revealing it as plaintext in the code?
The two topics - credentials and encryption - are unrelated. DefaultNetworkCredentials only works when the mail server and your computer belong to the same "network" or to be more accurate, the same or connected Active Directory server. I'm guessing that the old SMTP server was on premise and was part of your office network. The O365 server is in the cloud and doesn't share the AD.
When you provide your credentials explicitly, it works because O365 is able to authenticate you.
There is a possibility to use Azure Active Directory and somehow connect it to your on premise Active Directory. I'm not familiar with the details but I know it can be done. I believe that if you set this up correctly, DefaultNetworkCredentials will start working again.
Details about O365 authentication: https://blogs.office.com/2014/05/13/choosing-a-sign-in-model-for-office-365/
If you need to store the password, you need to store it encrypted. See this answer: Best way to store encryption keys in .NET C#
In my situation I encrypt the section of the web.config that I store these credentials in. I have similarly stored an encrypted version of the credentials in my DB and had a routine to decrypt them in the application.
Im using a webservice in my program.
this is the web service : "https://X.Y.Z.W/ib/ws/openbill.asmx?wsdl"
It works as local. when I write this on Internet Explorer, I can see the proper page after selecting "Continue to this website (not recommended)" in this attachment :
but when I want to access to this, in my c# code, I get this exception :
The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel.
So how can I access this in my c# program?
I think you should first acquire a certificate file, and then use it in your code. For example, to set it for a SMTPClient object:
string certificate = "Certificate.cer";
X509Certificate cert = new X509Certificate2(certificate);
MailMessage message = new MailMessage(from, to);
SmtpClient client = new SmtpClient(server);
client.ClientCertificates.Add(cert);
client.Send(message);
The web service that you are trying to connect to is using SSL/TLS. When you open the web service via internet explorer, it is giving you a warning that it cannot validate the certificate of the web service.
This has many reasons, and I guess in your case it is that the certificate that the web service is using is not for X.Y.Z.W.
Another reason could be that your machine does not trust the root issuer of the web service certificate. But from the error message that you have, I don't think this is the case.
You can view the certificate in IE by click on "Continue on this web site..", and the clicking on "Certificate Error", and the "View certificates".
From there, you will view the certificate. Go to details, and look for DNS Name inside Subject Alternative Name.
The DNS name is the name of the machine that the web service certificate was given for.
I guess in your case it will not be X.Y.Z.W.
Is the web service yours? can you obtain a different certificate for it? If so, can make sure you create a certificate that has the correct DNS name.
As a last resort, you can skip certificate validation from your code (this is not recommended). Take a look at this question.
I'm trying to send email through C#. Although I beleive I've done everything right, it still throws this exception :
"The SMTP server requires a secure connection or the client was not authenticated. The server response was: 5.5.1 Authentication Required. Learn more at"
At first I thought, it could be a zone/ip/region problem... But when i logged into gmail, there wasn't any warning of that. And to be sure, i've uploaded a file to a website to check from there, still the error was thrown.
Than I've tried changing the port to 465. It didn't work either.
I've first tried with accounts that are managed by a Google Apps account. So I thought it could be it, but it wasn't either...
I'm truly out of ideas right now.
Any of you have an idea ?
Here is the example code :
SmtpClient sm = new SmtpClient("smtp.gmail.com",587);
sm.Credentials = new NetworkCredential("blabla#gmail.com","**");
sm.UseDefaultCredentials = false;
sm.EnableSsl = true;
sm.DeliveryMethod = SmtpDeliveryMethod.Network;
sm.Send("blabla#gmail.com","blabla2#tr3reklam.com","Test","Test");
** Note **
I've checked the account name and password, they both are right.
"Access for less secure apps" must be enabled for the Gmail account used by the NetworkCredential using Google's settings page.
It was caused by 2-Step Verification after all !
It is odd, but without turning on "Allow users to be able to turn on 2-Step verification on" option set to true, I couldn't send any mails.
2-Step verification is still off for the accounts but, probably allowing users to choose for themselves make some security settings in the background.
I couldn't find any documentation about this but I can send now...
Put the code sm.UseDefaultCredentials = false; before sm.Credentials = ...
This seems a common error but while I've found a work-around (see below) I can't pin down the reason I'm getting it in the first place.
I am writing SMTP functionality into our application and I'm attempting to add SSL functionality to the working SMTP we already have.
I am testing using our company's MS Exchange server and specifically the webmail option enabled on that. I can send emails internally through my code by not authenticating my connection and sending anonymously, however those emails won't relay to external email addresses due to our companies policy. Besides which I am programming this for our customers and they don't all allow open relay and/or anonymous connections.
I believe the Exchange server is using Explicit SSL/ TLS. I have tried telnet to the server's address on port 25 and got a text response, human readable response, which according to some of my searches previously means it's using Explicit SSL/ TLS.
I have the following test code
SmtpClient SMTPClient = new SmtpClient(webmailaddress);
SMTPClient.Port = 25;
SMTPClient.UseDefaultCredentials = true;
SMTPClient.EnableSsl = true;
System.Net.Mail.MailMessage Message = new `
System.Net.Mail.MailMessage(emailFrom,emailTo,subject,body);
SMTPClient.Send(Message);
During my searching for a solution I came across this "The remote certificate is invalid according to the validation procedure." using Gmail SMTP server
From which I got the following code...
ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(ValidateServerCertificate);
public static bool ValidateServerCertificate(object sender,X509Certificate certificate,X509Chain chain,SslPolicyErrors sslPolicyErrors)
{
if (sslPolicyErrors == SslPolicyErrors.None)
return true;
else
{
if (System.Windows.Forms.MessageBox.Show("The server certificate is not valid.\nAccept?", "Certificate Validation", System.Windows.Forms.MessageBoxButtons.YesNo, System.Windows.Forms.MessageBoxIcon.Question) == System.Windows.Forms.DialogResult.Yes)
return true;
else
return false;
}
}
This works in my test code. HOWEVER the actual process I'm writing (rather than my test code) is going to run in the background and can't really ask the user (instead it reports errors in the windows error log).
As I started, my question is really why I'm getting this error at all. If I go to https:webmail.ourdomain.co.uk in a browser it shows a valid certificate and there is no option to install the certificate (as I would have done if it were a self-signed one).
However when I run my code, with a debug break poing in the ValidateServerCertificate method, I look at the certificate values and see an issuer of our local server and 'don't use before', and 'don't use after' properties of today. This does not match the certificate I am getting.
I've also checked what the sslPolicyErrors flags are in the debug of ValidateServerCertificate, and they are showing "RemoteCertificateChainErrors" and "RemoteCertificateNameMismatch".
So what am I missing about this... why is it not using the correct certificate? If there are steps I need to take to install the certificate locally for it to use then I need to know them so I can tell my customers what to do if they get this.
I don't want to just by-pass the check by returning true from the ValidateServerCertificate method, and because it's a background process I can't ask the user, so I need to understand how to get my code to use the correct/trusted certificate.
Hope someone can advise.
The answer I have finally found is that the SMTP service on the server is not using the same certificate as https.
The diagnostic steps I had read here make the assumption they use the same certificate and every time I've tried this in the past they have done and the diagnostic steps are exactly what I've done to solve the problem several times.
In this case those steps didn't work because the certificates in use were different, and the possibility of this is something I had never come across.
The solution is either to export the actual certificate from the server and then install it as a trusted certificate on my machine, or to get a different valid/trusted certificate for the SMTP service on the server. That is currently with our IT department who administer the servers to decide which they want to do.
Old post but as you said "why is it not using the correct certificate" I would like to offer an way to find out which SSL certificate is used for SMTP (see here) which required openssl:
openssl s_client -connect exchange01.int.contoso.com:25 -starttls smtp
This will outline the used SSL certificate for the SMTP service. Based on what you see here you can replace the wrong certificate (like you already did) with a correct one (or trust the certificate manually).
Old post, but I thought I would share my solution because there aren't many solutions out there for this issue.
If you're running an old Windows Server 2003 machine, you likely need to install a hotfix (KB938397).
This problem occurs because the Cryptography API 2 (CAPI2) in Windows
Server 2003 does not support the SHA2 family of hashing algorithms.
CAPI2 is the part of the Cryptography API that handles certificates.
https://support.microsoft.com/en-us/kb/938397
For whatever reason, Microsoft wants to email you this hotfix instead of allowing you to download directly. Here's a direct link to the hotfix from the email:
http://hotfixv4.microsoft.com/Windows Server 2003/sp3/Fix200653/3790/free/315159_ENU_x64_zip.exe
I installed hmailserver 5.3.2 and configured it. It receives and sends
emails normally, but I wanted to use it to send emails from a .net/C#
application located in another server, and for that I wanted to use
SSL communication. Before, the application was configured to send
emails via gmail, on port 587 and it worked ok, but now we want to use
our own mail server. We first configured the application to connect on
smtp.domain.com on port 25 and that works, it sends the email.
Then we
created a self signed certificate to test the if we could send the
message through a secure channel.I created the certificate with
openSSL setting common name as: mail.domain.com, smtp.domain.com,
*.domain.com, domain.com. I opened port 587 on the firewall and
configured hmailserver to use a certificate for inbound connections on
that port.
None of the certificates I created worked (I tried one and then
created another one and so on), generating the following (generic) exception in the
application:
System.Exception: _COMPlusExceptionCode = -532459699
Of course I also tried to connect via telnet: telnet smtp.domain.com
587, and I just got a blank screen. It is not a firewall issue since
when I disable the ssl on port 587 I can connect normally.
Looking at the log doesn't even show an attempt to connect when using
587 with SSL.
I already checked these questions: Getting SmtpClient to work with a self signed SSL certificate and Using a self-signed certificate with .NET’s HttpWebRequest/Response, but it didn't solve my problem. The approach with ServerCertificateValidationCallback didn't have any influence.
I tried with ports 25 (which is also proposed in one of the questions above), 465, 587, and with all 3 it happens the same: The initial handshake (SYN / SYN-ACK / ACK) and after about 80s the connection is closed (FIN), nothing in between.
Do I have to install that certificate somewhere so the .net application sees it as trusted? I mean, I already installed it as a Trusted Root Certification Authority and could check by running mmc, so I have no idea where to go now...
Thanks for the help!
PS: Not sure if this belongs to ServerFault since it concerns a C# application but also a mail server...
EDIT: Code sample:
ServicePointManager.ServerCertificateValidationCallback =
(sender, certificate, chain, sslPolicyErrors) => true;
SmtpClient mailClient = new SmtpClient("smtp.domain.com");
mailClient.Credentials = new NetworkCredential("username#domain.com", "pwd");
mailClient.Port = 587;
mailClient.EnableSsl = true;
MailMessage mailMessage = new MailMessage("mailAddressFrom", "mailAddressTo", "subject", "body");
mailMessage.IsBodyHtml = true;
mailClient.Send(mailMessage);
EDIT 2: Log (Based on Ramunas' suggestion):
"TCPIP" 3588 "2010-06-23 10:02:49.685" "TCPConnection - Posting AcceptEx on 0.0.0.0:465"
"DEBUG" 3588 "2010-06-23 10:02:49.809" "Creating session 24039"
"TCPIP" 772 "2010-06-23 10:04:29.639" "TCPConnection - SSL handshake with client failed. Error code: 2, Message: End of file, Remote IP: X"
"DEBUG" 772 "2010-06-23 10:04:29.639" "Ending session 24039"
currently, you can not send mail using c# 4/.NET 4 to a hMailServer regardless whether the certificate used by hMailServer is purchased or self-signed.
the problem is two part AFAIK ... c# 4/.NET 4 will only send using TLS and port 587; hMailServer does not currently support STARTTLS. c# 4/.NET 4 does not support the alternative of 465/SSL.
see this thread "configuring SSL confusion ..." at hMailServer's forum.
"SmtpClient.EnableSsl Property ":
"An alternate connection method is where an SSL session is established up front before any protocol commands are sent. This connection method is sometimes called SMTP/SSL, SMTP over SSL, or SMTPS and by default uses port 465. This alternate connection method using SSL is not currently supported." -- MSDN
As gerryLowry said:
c# 4/.NET 4 will only send using TLS and port 587;
hMailServer does not currently support STARTTLS
You can update your hMailServer to hMailServer 5.5.1 (BETA) here
It now supports STARTTLS and with port 587 all is working correctly.
This is a sophisticated mechanism but in simple words client (computer you're making connection from) should know about WHO is certificate issuer (in your case your server is certificate issuer). If it does not find it in it's Trusted Root Certificate Authorities list then it considers this connection to be unsafe. (I bet you've seen browser warning you about unsafe request to some https://.... site).
Open Certificates snap-in in your Microsoft management console on a client computer and try to add the same self signed certificate to a Trusted Root Certificate Authorities list.
I installed hMailServer, created self signed certificate, added it to hMailServer and was not able to send mail via it, too. Though I was successful while sending emails without certificate.
I enabled logging on hMailServer (for everything) and tried again with no luck. But I saw an error in a log file stating
"Severity: 2 (High), Code: HM5113,
Source: TCPServer::Run(), Description:
Failed to load certificate file. Path:
<...>test.cer,
Address: 0.0.0.0, Port: 25, Error: An
invalid argument was supplied"
Maybe this is a case on your hMailServer also?
I have port 25 as normal SMTP open on my hMailServer as well as port 465 for SSL, so I had to change my code to point to the normal SMTP configuration. It should work after that. As for SSL, sorry, it won't work on hMailServer...
MailMessage message = new MailMessage();
message.From = new MailAddress("me#myself.home", "Me");
message.Body = "hello, World!";
message.To.Add(new MailAddress("you#myself.home", "You"));
SmtpClient client = new SmtpClient("secure.myself.home", 25);
client.EnableSsl = false;
client.UseDefaultCredentials = false;
client.Credentials = new NetworkCredential("me#myself.home", "pwd");
client.Send(message);