Getting SmtpClient to work with a self signed SSL certificate - c#

I'm attempting to use the System.Net.Mail.SmtpClient class to relay an email through my company's email server. All SMTP connections to the mail server have to be SSL and it uses a self signed certificate. That's fine for Outlook where you can just click ok on the warning dialogue but does anyone know a way to get SmtpClient to accept a self signed certificate?
I'm planning on using this app on the Windows Azure Platform so I won't be able to install the self signed certificate as a trusted root.

You may take a look at the ServerCertificateValidationCallback property:
ServicePointManager.ServerCertificateValidationCallback =
(sender, certificate, chain, sslPolicyErrors) => true;
It represents a callback which is called by the runtime when it tries to validate an SSL certificate. By returning true you basically say that you don't care if the certificate is valid or not -> you always accept it. Of course having self signed certificates in production environment is not a good idea.

My issue ended up being that the .Net SmtpClient class apparently doesn't support the use of port 465 for SMTP SSL connections. Using port 25 with a self signed SSL certificate worked correctly.
MSDN System.Net forum question Can SmtpClient be configured to work with a self signed certificate?.

If you want to be more secure, you might want to look at doing the following:
theClient.EnableSsl = true;
ServicePointManager.ServerCertificateValidationCallback =
(sender, certificate, chain, sslPolicyErrors) => {
if (sender == theClient) {
return true;
} else {
// you should apply the code from this SO answer
// https://stackoverflow.com/a/25895486/795690
// if you find that anything in your app uses this path
throw new ApplicationException("Certificate validation is currently disabled, extra code neeeded here!");
}
};
In this code we are auto-approving certificates only for the specific SMTP client in question; we have a stub code path which you should upgrade to explicitly reinstate default certificate validation if you find that anything else in your app is using it.
Another different, useful approach to approving certificates only in contexts where you actually want to is in this SO answer.

Related

WSE + self-signed certificat

There is an old code on the WSE (Web Services Enhancements). Now in "sandbox" of service with which it works for HTTPS began to use self-signed certificat.
And now in the sandbox i am getting error -- Could not create SSL / TLS secure channel.
Something like this does not help.
System.Net.ServicePointManager.ServerCertificateValidationCallback =
(sender, certificate, chain, sslPolicyErrors) => true;
How i can to ignore a certificate?
Should be able to do something like this to ignore cert validation.
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
you could also see this question and answers for additional details that might better apply to your situation.
How to ignore the certificate check when ssl

"The remote certificate is invalid according to the validation procedure" wcf

There's a problem. I have a site, that expanded locally on IIS, that needs to be connected to the remote WCF service. I've added all required certificates to the TrustedRoot store of LocalComputer. I've granted all permissions to my domain account for using certificates. But there's still a problem:
"The remote certificate is invalid according to the validation
procedure"
when I'm trying to run method of WCF-service (but it's connected to this WCF service fine).
I have some thinks about that:
1) Maybe I need to select SSL on IIS setting of this site?
2) Maybe I need to put certificates not only to LocalMachine, but to the CurrentUser too?
Advice me some tips for how to establish SSL connection and pass this exception. Thank you :)
This is because, the certificate you use on your local IIS, is a virtual one. Probably, you will not get it in real time. There are several hacks available to make it work locally.
NOTE: Never ever do this on production...
Add following code segment(an event handler), before calling any method of service.
ServicePointManager.ServerCertificateValidationCallback +=
EasyCertCheck;
bool EasyCertCheck(object sender, X509Certificate cert,
X509Chain chain, System.Net.Security.SslPolicyErrors error)
{
return true;
}

How to Connect to a Web-service that has a faulty security certificate [duplicate]

We are setting up a new SharePoint for which we don't have a valid SSL certificate yet. I would like to call the Lists web service on it to retrieve some meta data about the setup. However, when I try to do this, I get the exception:
The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel.
The nested exception contains the error message:
The remote certificate is invalid according to the validation procedure.
This is correct since we are using a temporary certificate.
My question is: how can I tell the .Net web service client (SoapHttpClientProtocol) to ignore these errors?
Alternatively you can register a call back delegate which ignores the certification error:
...
ServicePointManager.ServerCertificateValidationCallback = MyCertHandler;
...
static bool MyCertHandler(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors error)
{
// Ignore errors
return true;
}
Like Jason S's answer:
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
I put this in my Main and look to my app.config and test if (ConfigurationManager.AppSettings["IgnoreSSLCertificates"] == "True") before calling that line of code.
I solved it this way:
Call the following just before calling your ssl webservice that cause that error:
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
/// <summary>
/// solution for exception
/// System.Net.WebException:
/// The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel. ---> System.Security.Authentication.AuthenticationException: The remote certificate is invalid according to the validation procedure.
/// </summary>
public static void BypassCertificateError()
{
ServicePointManager.ServerCertificateValidationCallback +=
delegate(
Object sender1,
X509Certificate certificate,
X509Chain chain,
SslPolicyErrors sslPolicyErrors)
{
return true;
};
}
The approach I used when faced with this problem was to add the signer of the temporary certificate to the trusted authorities list on the computer in question.
I normally do testing with certificates created with CACERT, and adding them to my trusted authorities list worked swimmingly.
Doing it this way means you don't have to add any custom code to your application and it properly simulates what will happen when your application is deployed. As such, I think this is a superior solution to turning off the check programmatically.
I was having same error using DownloadString; and was able to make it works as below with suggestions on this page
System.Net.WebClient client = new System.Net.WebClient();
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
string sHttpResonse = client.DownloadString(sUrl);
ServicePointManager.ServerCertificateValidationCallback +=
(mender, certificate, chain, sslPolicyErrors) => true;
will bypass invaild ssl . Write it to your web service constructor.
For newbies,
you can extend your partial service class in a separate cs file and add the code the code provided by "imanabidi" to get it integrated
To further expand on Simon Johnsons post - Ideally you want a solution that will simulate the conditions you will see in production and modifying your code won't do that and could be dangerous if you forget to take the code out before you deploy it.
You will need a self-signed certificate of some sort. If you're using IIS Express you will have one of these already, you'll just have to find it. Open Firefox or whatever browser you like and go to your dev website. You should be able to view the certificate information from the URL bar and depending on your browser you should be able to export the certificate to a file.
Next, open MMC.exe, and add the Certificate snap-in. Import your certificate file into the Trusted Root Certificate Authorities store and that's all you should need. It's important to make sure it goes into that store and not some other store like 'Personal'. If you're unfamiliar with MMC or certificates, there are numerous websites with information how to do this.
Now, your computer as a whole will implicitly trust any certificates that it has generated itself and you won't need to add code to handle this specially. When you move to production it will continue to work provided you have a proper valid certificate installed there. Don't do this on a production server - that would be bad and it won't work for any other clients other than those on the server itself.

https using BasicHttpBinding and ignoring certificate errors

I am using BasicHttpBinding to connect a web service hosted on a secured (https) port. To get it working, I have changed the Security.Mode to TransportWithMessageCredential and Security.Message to BasicHttpMessageCredentialType.Cerificate. I am also calling
client.ClientCredentials.ClientCertificate.SetCertificate()
with localhost as the subject name.
The issue here is that for unit testing, I have an unsigned certificate from the web server and am supposed to ignore any certificate error thrown during the proxy creation; but I am unable to do so, because I keep getting an error telling me to "specify a certificate". Right now, I am clueless; I appreciate any help here.
You can use the following code to skip certificate validation. This creates a RemoteCertificateValidationCallback that always return true for any certificate.
System.Net.ServicePointManager.ServerCertificateValidationCallback =
(sender, certificate, chain, errors) => true;
For server ssl, the SecurityMode should be set to Transport.

Problem sending E-mail using C#

When I try to send E-mail using C# with gmail's smtp server,I get this error..
"The remote certificate is invalid according to the validation procedure".
SSL is enabled
Port used is 587
server name used is "Smtp.gmail.com".
username and password is correct
outlook express works fine on the same pc with the same settings
The c# program also works fine in other places...we get this error only in the clients place.
Would appreciate any help..
Thanks
Edit: #Andomar,Where do I find the root certificates in the client? How do I fix this?
#Alnitak,How do I issue starttls using System.Net.Mail library though?
#David,What do I pass as parameter for "(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)"
Thanks David. I've added those lines. But,I'm still confused about whats going on since this code doesn't have any direct connection with System.Net.Mail as far as my understanding.Hope the problem goes away.
Also check that the root certificates are in the Client's Trusted Root Authority store. If this is from a service then adding the root certificates to the Local Machine store may also help. To get a better grasp of the reason then I have found the following policy helpful...
public bool ValidateServerCertificate( object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
// No errors so continue…
if (sslPolicyErrors == SslPolicyErrors.None)
return true;
// I’m just logging it to a label on the page,
// this should be stored or logged to the event log at this time.
lblStuff.Text += string.Format("Certificate error: {0} <BR/>", sslPolicyErrors);
// If the error is a Certificate Chain error then the problem is
// with the certificate chain so we need to investigate the chain
// status for further info. Further debug capturing could be done if
// required using the other attributes of the chain.
if (sslPolicyErrors == SslPolicyErrors.RemoteCertificateChainErrors)
{
foreach (X509ChainStatus status in chain.ChainStatus)
{
lblStuff.Text += string.Format("Chain error: {0}: {1} <BR/>", status.Status, status.StatusInformation);
}
}
// Do not allow this client to communicate
//with unauthenticated servers.
return false;
}
To add the policy in, use the following, this only needs to be done once for the Application domain.
using System.Net;
...
ServicePointManager.ServerCertificateValidationCallback =
new Security.RemoteCertificateValidationCallback(ValidateServerCertificate);
You can also use the policy to remove the error altogether but it would be better to fix the problem than do that.
Check if the proper root certificates are in the client's store. And the client's system date is correct.
Are you using STARTTLS or assuming that the connection on port 587 is SSL encrypted from the outset?
Google's servers on smtp.gmail.com require STARTTLS.
Did you set
client.EnableSsl = true;
because gmail needs it

Categories

Resources