c# - SmtpClient con Gmail
mono monodevelop (6)
Comencé a recibir esto con GMail en mayo de 2013 después de trabajar para 6 meses. El documento de Uso de las Raíces Confiables del Proyecto Mono Respetuosamente proporcionó orientación sobre cómo trabajar. Elegí la opción # 1:
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
Es demasiado perturbador que el correo electrónico de mi servicio deje de funcionar sin previo aviso.
Actualización del 26 de agosto de 2016: el usuario Chico sugirió la siguiente implementación completa de la devolución de llamada ServerCertificateValidationCallback. No he probado.
ServicePointManager.ServerCertificateValidationCallback = MyRemoteCertificateValidationCallback;
bool MyRemoteCertificateValidationCallback(System.Object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) {
bool isOk = true;
// If there are errors in the certificate chain, look at each error to determine the cause.
if (sslPolicyErrors != SslPolicyErrors.None) {
for (int i=0; i<chain.ChainStatus.Length; i++) {
if (chain.ChainStatus [i].Status != X509ChainStatusFlags.RevocationStatusUnknown) {
chain.ChainPolicy.RevocationFlag = X509RevocationFlag.EntireChain;
chain.ChainPolicy.RevocationMode = X509RevocationMode.Online;
chain.ChainPolicy.UrlRetrievalTimeout = new TimeSpan (0, 1, 0);
chain.ChainPolicy.VerificationFlags = X509VerificationFlags.AllFlags;
bool chainIsValid = chain.Build ((X509Certificate2)certificate);
if (!chainIsValid) {
isOk = false;
}
}
}
}
return isOk;
}
Estoy desarrollando un cliente de correo para un proyecto escolar. He logrado enviar correos electrónicos usando el SmtpClient
en C #. Esto funciona perfectamente con cualquier servidor, pero no funciona con Gmail. Creo que es debido a Google utilizando TLS. He intentado establecer EnableSsl
en true
en el SmtpClient
pero esto no hace una diferencia.
Este es el código que estoy usando para crear el SmtpClient
y enviar un correo electrónico.
this.client = new SmtpClient("smtp.gmail.com", 587);
this.client.EnableSsl = true;
this.client.UseDefaultCredentials = false;
this.client.Credentials = new NetworkCredential("username", "password");
try
{
// Create instance of message
MailMessage message = new MailMessage();
// Add receiver
message.To.Add("[email protected]");
// Set sender
// In this case the same as the username
message.From = new MailAddress("[email protected]");
// Set subject
message.Subject = "Test";
// Set body of message
message.Body = "En test besked";
// Send the message
this.client.Send(message);
// Clean up
message = null;
}
catch (Exception e)
{
Console.WriteLine("Could not send e-mail. Exception caught: " + e);
}
Este es el error que recibo cuando intento enviar un correo electrónico.
Could not send e-mail. Exception caught: System.Net.Mail.SmtpException: Message could not be sent. ---> System.IO.IOException: The authentication or decryption has failed. ---> System.InvalidOperationException: SSL authentication error: RemoteCertificateNotAvailable, RemoteCertificateChainErrors
at System.Net.Mail.SmtpClient.<callback>m__4 (System.Object sender, System.Security.Cryptography.X509Certificates.X509Certificate certificate, System.Security.Cryptography.X509Certificates.X509Chain chain, SslPolicyErrors sslPolicyErrors) [0x00000] in <filename unknown>:0
at System.Net.Security.SslStream+<BeginAuthenticateAsClient>c__AnonStorey7.<>m__A (System.Security.Cryptography.X509Certificates.X509Certificate cert, System.Int32[] certErrors) [0x00000] in <filename unknown>:0
at Mono.Security.Protocol.Tls.SslClientStream.OnRemoteCertificateValidation (System.Security.Cryptography.X509Certificates.X509Certificate certificate, System.Int32[] errors) [0x00000] in <filename unknown>:0
at Mono.Security.Protocol.Tls.SslStreamBase.RaiseRemoteCertificateValidation (System.Security.Cryptography.X509Certificates.X509Certificate certificate, System.Int32[] errors) [0x00000] in <filename unknown>:0
at Mono.Security.Protocol.Tls.SslClientStream.RaiseServerCertificateValidation (System.Security.Cryptography.X509Certificates.X509Certificate certificate, System.Int32[] certificateErrors) [0x00000] in <filename unknown>:0
at Mono.Security.Protocol.Tls.Handshake.Client.TlsServerCertificate.validateCertificates (Mono.Security.X509.X509CertificateCollection certificates) [0x00000] in <filename unknown>:0
at Mono.Security.Protocol.Tls.Handshake.Client.TlsServerCertificate.ProcessAsTls1 () [0x00000] in <filename unknown>:0
at Mono.Security.Protocol.Tls.Handshake.HandshakeMessage.Process () [0x00000] in <filename unknown>:0
at (wrapper remoting-invoke-with-check) Mono.Security.Protocol.Tls.Handshake.HandshakeMessage:Process ()
at Mono.Security.Protocol.Tls.ClientRecordProtocol.ProcessHandshakeMessage (Mono.Security.Protocol.Tls.TlsStream handMsg) [0x00000] in <filename unknown>:0
at Mono.Security.Protocol.Tls.RecordProtocol.InternalReceiveRecordCallback (IAsyncResult asyncResult) [0x00000] in <filename unknown>:0
--- End of inner exception stack trace ---
at Mono.Security.Protocol.Tls.SslStreamBase.AsyncHandshakeCallback (IAsyncResult asyncResult) [0x00000] in <filename unknown>:0
--- End of inner exception stack trace ---
at System.Net.Mail.SmtpClient.Send (System.Net.Mail.MailMessage message) [0x00000] in <filename unknown>:0
at P2Mailclient.SMTPClient.send (P2Mailclient.Email email) [0x00089] in /path/to/my/project/SMTPClient.cs:57
¿Alguien tiene una idea de por qué podría estar recibiendo este error?
Creo que es necesario validar el certificado del servidor que se utiliza para establecer las conexiones SSL ...
Utilice el siguiente código para enviar correo con el certificado del servidor de validación ...
this.client = new SmtpClient(_account.SmtpHost, _account.SmtpPort);
this.client.EnableSsl = _account.SmtpUseSSL;
this.client.Credentials = new NetworkCredential(_account.Username, _account.Password);
try
{
// Create instance of message
MailMessage message = new MailMessage();
// Add receivers
for (int i = 0; i < email.Receivers.Count; i++)
message.To.Add(email.Receivers[i]);
// Set sender
message.From = new MailAddress(email.Sender);
// Set subject
message.Subject = email.Subject;
// Send e-mail in HTML
message.IsBodyHtml = email.IsBodyHtml;
// Set body of message
message.Body = email.Message;
//validate the certificate
ServicePointManager.ServerCertificateValidationCallback =
delegate(object s, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{ return true; };
// Send the message
this.client.Send(message);
// Clean up
message = null;
}
catch (Exception e)
{
Console.WriteLine("Could not send e-mail. Exception caught: " + e);
}
Importe el espacio de nombres de System.Security.Cryptography.X509Certificates
para usar ServicePointManager
Debe habilitar la verificación de 2 pasos en su cuenta de gmail y crear una contraseña de aplicación ( https://support.google.com/accounts/answer/185833?hl=en ). Una vez que reemplace su contraseña con la nueva contraseña de la aplicación, debería funcionar.
Credentials = new System.Net.NetworkCredential("your email address", "your app password");
El servidor SMTP de Gmail requiere que autentique su solicitud con una combinación válida de correo electrónico / contraseña de Gmail. Usted necesita SSL habilitado también. Sin ser capaz de ver cómo se transfieren todas sus variables en la mejor conjetura que puedo hacer es que sus credenciales no son válidas, asegúrese de estar usando una combinación válida de correo electrónico y contraseña de GMAIL .
Es posible que desee leer here para un ejemplo de trabajo.
EDIT: Bueno, aquí hay algo que escribí y probé en ese momento y funcionó bien para mí:
public static bool SendGmail(string subject, string content, string[] recipients, string from) {
if (recipients == null || recipients.Length == 0)
throw new ArgumentException("recipients");
var gmailClient = new System.Net.Mail.SmtpClient {
Host = "smtp.gmail.com",
Port = 587,
EnableSsl = true,
UseDefaultCredentials = false,
Credentials = new System.Net.NetworkCredential("******", "*****")
};
using (var msg = new System.Net.Mail.MailMessage(from, recipients[0], subject, content)) {
for (int i = 1; i < recipients.Length; i++)
msg.To.Add(recipients[i]);
try {
gmailClient.Send(msg);
return true;
}
catch (Exception) {
// TODO: Handle the exception
return false;
}
}
}
Si necesitas más información, hay un artículo SO similar here
Este código funciona bien para mí, intente pegarlo en LinqPad, edite las direcciones de correo y la contraseña y díganos lo que ve:
var client = new System.Net.Mail.SmtpClient("smtp.gmail.com", 587);
client.EnableSsl = true;
client.UseDefaultCredentials = false;
client.Credentials = new System.Net.NetworkCredential("[email protected]", "xxxxxxx");
try
{
// Create instance of message
System.Net.Mail.MailMessage message = new System.Net.Mail.MailMessage();
// Add receiver
message.To.Add("[email protected]");
// Set sender
// In this case the same as the username
message.From = new System.Net.Mail.MailAddress("[email protected]");
// Set subject
message.Subject = "Test";
// Set body of message
message.Body = "En test besked";
// Send the message
client.Send(message);
// Clean up
message = null;
}
catch (Exception e)
{
Console.WriteLine("Could not send e-mail. Exception caught: " + e);
}
Intenta ejecutar esto:
mozroots --import --ask-remove
en su sistema (solo en bash o desde la solicitud de comando Mono si está en Windows). Y luego ejecute el código de nuevo.
EDITAR:
Olvidé que tú también deberías correr
certmgr -ssl smtps://smtp.gmail.com:465
(y responda sí a las preguntas). Esto me funciona en Mono 2.10.8, Linux (con su ejemplo).