I was writing a program to have my Raspbery Pi send me a message a few times a day letting me know that it was up and running and connected to the network (e.g. I wouldn't get the message if it wasn't). The idea being that the headless appliance without a keyboard, mouse or monitor could let me know that everything was running fine. My program was sending mail find when I would run it manually from the terminal but would fail when I ran it from a cronjob with this exception:
Message could not be sent
After some research I found that the failures had to do with certificates and there were a few things I had to do (two terminal commands and then one change to my mono/.net code). First, here are the two commands to deal with certificate issues (you may need to sudo these):
mozroots --import --ask-remove
certmgr -ssl smtps://smtp.gmail.com:465
In my .Net/mono code I had to add before my SMTP clients sending of the message. I will include both the VB.Net and the C# calls:
VB.Net (Mono)
ServicePointManager.ServerCertificateValidationCallback = Function(s As Object, certificate As X509Certificate, chain As X509Chain, sslPolicyErrors As SslPolicyErrors) True
C# (Mono)
ServicePointManager.ServerCertificateValidationCallback = delegate(object s, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
return true;
};
To be complete, I'll include a VB.Net and C# example of a Using block that should be all you need to send a message:
VB.Net (Mono)
Using smtp As New SmtpClient("smtp.gmail.com", 587)
smtp.EnableSsl = True
smtp.DeliveryMethod = SmtpDeliveryMethod.Network
smtp.UseDefaultCredentials = False
smtp.Credentials = New NetworkCredential("youraddress@gmail.com", "yourpassword")
Using msg As New MailMessage("youraddress@gmail.com", "somebody@somewhere.com", "Your Subject", "Your Message Body")
' If the body is HTML
msg.IsBodyHtml = True
' this is required to fix the "Message could not be sent" exception when running in croin
ServicePointManager.ServerCertificateValidationCallback = Function(s As Object, certificate As X509Certificate, chain As X509Chain, sslPolicyErrors As SslPolicyErrors) True
smtp.Send(msg)
End Using
End Using
C# (Mono)
using (var smtp = new SmtpClient("smtp.gmail.com", 587))
{
smtp.EnableSsl = true;
smtp.DeliveryMethod = SmtpDeliveryMethod.Network;
smtp.UseDefaultCredentials = false;
smtp.Credentials = new NetworkCredential("youraddress@gmail.com", "yourpassword");
using (var msg = new MailMessage("youraddress@gmail.com", "somebody@somewhere.com", "Your Subject", "Your Message Body"))
{
// If the body is HTML
msg.IsBodyHtml = true;
// this is required to fix the "Message could not be sent" exception when running in croin
ServicePointManager.ServerCertificateValidationCallback =
delegate(object s, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{ return true; };
smtp.Send(msg);
}
}
Both of these require if not fully referenced imports to System.Security.Cryptography.X509Certificates.