Problem sending E-mail using C# - 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

Related

Server certificate/domain custom validation when connecting via TLS/SSL on production

The error below occurs when a web service request is sent to a remote web service:
Could not establish trust relationship for the SSL/TLS secure channel
The remote certificate is invalid according to the validation procedure.
My question:
1 Is the code below combined with TLS/SSL still safe to use on production given the server is in our control. Think of attack like man-in-the-middle, and others.
2 What about if the server is not in our control, can the validation prove secure?
System.Net.ServicePointManager.ServerCertificateValidationCallback += delegate (
object sender,
X509Certificate cert,
X509Chain chain,
SslPolicyErrors sslPolicyErrors)
{
if (sslPolicyErrors == SslPolicyErrors.None)
{
return true; //Is valid
}
//validate Server's certificate or Server's domain name or IP
if (IsValidServerCertificate(cert) ||
IsValidServerIP(cert))
{
return true;
}
return false;
};
public bool IsValidServerCertificate(X509Certificate cert){
return cert.GetCertHashString() == "server's public certificate thumbprint")
}
public bool IsValidServerIP(){
//compare server's ip address from the request with the address we are given"
}
The proper way is to login using server's public certificate from client side, but what validation this method provides that my custom validation need to add?
Update:
For whose who voted down the ticket: If you know the solution, why cannot you provide it. There is no solution in code on SO.
I believe this ticket can benefit someone else in the future, if a simple solution with code sample can be found.
... safe to use on production given the server is in our control. Think of attack like man-in-the-middle, and others.
Man in the middle attacks are not attacks at the client nor at the server but in the middle. Therefore it does not matter at all if the server is in your control. You could only be sure that no man in the middle attacks occur if everything between client and server would be in your control too. And to achieve this you have to make sure that the client is even using the path you control: things like DNS spoofing might return in a different destination IP address and thus in a different path than you expect.
In other words: the code is unsafe, no matter if you control the server or not. It should not be used in production. Instead of trying to work around broken setups you should fix the cause of the problem. These are usually broken certificates, incomplete chain or broken setup of trust anchors.

AuthenticationException when tryign to connect to mail server using MailKit

I am using MailKit to try and send email though an exchange server via SMTP but when I try to connect I get the following error:
An exception of type
'System.Security.Authentication.AuthenticationException' occurred in
MailKit.dll but was not handled in user code
Additional information: The remote certificate is invalid according to
the validation procedure.
Googleing this brings up a lot of stuff about Gmail or as part of other error messages (like FTP or web api requests and such). I have talked with the IT guys and it is not a self-signed cert and we don't require authentication (in fact the BugZilla instance I admin is setup with the same settings and works fine). What am I doing wrong or how can I get more details to further troubleshoot?
using (var Client = new SmtpClient())
{
Client.Connect("mail.address.com", 587, false);
Client.AuthenticationMechanisms.Remove("XOAUTH2");
Client.Send(Message);
Client.Disconnect(true);
}
Edit: I have verified with IT that it is the same cert used in IIS that hosts the mail.address.com domain as well as in exchange. I have also installed it as a trusted root but still get the same error.
Edit 2: If I update the code to Client.Connect("mail.address.com", 587, true); then I get the error:
An exception of type 'System.IO.IOException' occurred in >System.Private.Networking.dll but was not handled in user code
Additional information: The handshake failed due to an unexpected packet format.
Try using Client.Connect("mail.address.com", 587, SecureSocketOptions.None); to disable STARTTLS.
If you want to keep STARTTLS, you might try overriding Client.ServerCertificateValidationCallback.
The easiest way to get more information about the error is to override ServerCertificateValidationCallback with something like this:
bool ValidateRemoteCertificate (object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
Console.WriteLine ("SslPolicyErrors: {0}", sslPolicyErrors);
return sslPolicyErrors == SslPolicyErrors.None;
}
I had the exact same error while trying to use MailKit with Gmail and figured out that by default the Mail Shield from Avast antivirus had the "Scan SSL connection" activated. Make sure to turn that off.
From my knowledge, Avast will "open" the mail, scan it for any viruses and then sign it using it's own certificate so the mail won't be signed by the gmail's certificate anymore which produces that error:
An exception of type 'System.Security.Authentication.AuthenticationException' occurred in MailKit.dll but was not handled in user code.
Additional information: The remote certificate is invalid according to the validation procedure.
Solution 1:
Turn off the SSL scans from your antivirus (or the entire mail shield).
Solution 2 (Should be the best security speaking):
Get somehow the certificate used by the antivirus (Avast has an option to export it)
Import it in your imap/pop/smtp client before connecting to gmail server.

"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.

Getting SmtpClient to work with a self signed SSL certificate

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.

Categories

Resources