How can I send emails through SSL SMTP with the .NET Framework?
Asked Answered
S

12

49

Is there a way with the .NET Framework to send emails through an SSL SMTP server on port 465?

The usual way:

System.Net.Mail.SmtpClient _SmtpServer = new System.Net.Mail.SmtpClient("tempurl.org");
_SmtpServer.Port = 465;
_SmtpServer.EnableSsl = true;
_SmtpServer.Credentials = new System.Net.NetworkCredential("username", "password");
_SmtpServer.Timeout = 5000;
_SmtpServer.UseDefaultCredentials = false;

MailMessage mail = new MailMessage();
mail.From = new MailAddress(from);
mail.To.Add(to);
mail.CC.Add(cc);
mail.Subject = subject;
mail.Body = content;
mail.IsBodyHtml = useHtml;
_SmtpServer.Send(mail);

times out:

System.Net Verbose: 0 : [1024] SmtpClient::.ctor(host=ssl0.ovh.net, port=465)
System.Net Information: 0 : [1024] Associating SmtpClient#64923656 with SmtpTransport#44624228
System.Net Verbose: 0 : [1024] Exiting SmtpClient::.ctor()  -> SmtpClient#64923656
System.Net Information: 0 : [1024] Associating MailMessage#17654054 with Message#52727599
System.Net Verbose: 0 : [1024] SmtpClient#64923656::Send(MailMessage#17654054)
System.Net Information: 0 : [1024] SmtpClient#64923656::Send(DeliveryMethod=Network)
System.Net Information: 0 : [1024] Associating SmtpClient#64923656 with MailMessage#17654054
System.Net Information: 0 : [1024] Associating SmtpTransport#44624228 with SmtpConnection#14347911
System.Net Information: 0 : [1024] Associating SmtpConnection#14347911 with ServicePoint#51393439
System.Net.Sockets Verbose: 0 : [1024] Socket#26756241::Socket(InterNetwork#2)
System.Net.Sockets Verbose: 0 : [1024] Exiting Socket#26756241::Socket() 
System.Net.Sockets Verbose: 0 : [1024] Socket#23264094::Socket(InterNetworkV6#23)
System.Net.Sockets Verbose: 0 : [1024] Exiting Socket#23264094::Socket() 
System.Net.Sockets Verbose: 0 : [1024] Socket#26756241::Connect(20:465#337754884)
System.Net.Sockets Verbose: 0 : [1024] Exiting Socket#26756241::Connect() 
System.Net.Sockets Verbose: 0 : [1024] Socket#23264094::Close()
System.Net.Sockets Verbose: 0 : [1024] Socket#23264094::Dispose()
System.Net.Sockets Verbose: 0 : [1024] Exiting Socket#23264094::Close() 
System.Net Information: 0 : [1024] Associating SmtpConnection#14347911 with SmtpPooledStream#14303791
System.Net.Sockets Verbose: 0 : [1024] Socket#26756241::Receive()
System.Net.Sockets Verbose: 0 : [2404] Socket#26756241::Dispose()
System.Net.Sockets Error: 0 : [1024] Exception in the Socket#26756241::Receive - A blocking operation was interrupted by a call to WSACancelBlockingCall
System.Net.Sockets Verbose: 0 : [1024] Exiting Socket#26756241::Receive()   -> 0#0
System.Net Error: 0 : [1024] Exception in the SmtpClient#64923656::Send - Unable to read data from the transport connection: A blocking operation was interrupted by a call to WSACancelBlockingCall.
System.Net Error: 0 : [1024]    at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
   at System.Net.DelegatedStream.Read(Byte[] buffer, Int32 offset, Int32 count)
   at System.Net.BufferedReadStream.Read(Byte[] buffer, Int32 offset, Int32 count)
   at System.Net.Mail.SmtpReplyReaderFactory.ReadLines(SmtpReplyReader caller, Boolean oneLine)
   at System.Net.Mail.SmtpReplyReaderFactory.ReadLine(SmtpReplyReader caller)
   at System.Net.Mail.SmtpConnection.GetConnection(String host, Int32 port)
   at System.Net.Mail.SmtpTransport.GetConnection(String host, Int32 port)
   at System.Net.Mail.SmtpClient.GetConnection()
   at System.Net.Mail.SmtpClient.Send(MailMessage message)
System.Net Verbose: 0 : [1024] Exiting SmtpClient#64923656::Send() 
System.Net Information: 0 : [1024] Associating MailMessage#49584532 with Message#19699911

I googled around and found that System.Net.Mail supports connections on port 587 (default port for Explicit SSL that starts unencrypted then issues a STARTTLS then switches to an Encrypted connection: RFC 2228), but doesn't support Implicit SSL (entire connection is wrapped in an SSL layer) ...

Scandalize answered 18/6, 2009 at 7:24 Comment(1)
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." FWIWApiculate
S
39

Here is an example of how to send email through GMail which also uses SSL/465. Minor tweaking of the code below should work!

using System.Web.Mail;
using System;
public class MailSender
{
    public static bool SendEmail(
        string pGmailEmail, 
        string pGmailPassword, 
        string pTo, 
        string pSubject,
        string pBody, 
        System.Web.Mail.MailFormat pFormat,
        string pAttachmentPath)
    {
    try
    {
        System.Web.Mail.MailMessage myMail = new System.Web.Mail.MailMessage();
        myMail.Fields.Add
            ("http://schemas.microsoft.com/cdo/configuration/smtpserver",
                          "smtp.gmail.com");
        myMail.Fields.Add
            ("http://schemas.microsoft.com/cdo/configuration/smtpserverport",
                          "465");
        myMail.Fields.Add
            ("http://schemas.microsoft.com/cdo/configuration/sendusing",
                          "2");
        //sendusing: cdoSendUsingPort, value 2, for sending the message using 
        //the network.

        //smtpauthenticate: Specifies the mechanism used when authenticating 
        //to an SMTP 
        //service over the network. Possible values are:
        //- cdoAnonymous, value 0. Do not authenticate.
        //- cdoBasic, value 1. Use basic clear-text authentication. 
        //When using this option you have to provide the user name and password 
        //through the sendusername and sendpassword fields.
        //- cdoNTLM, value 2. The current process security context is used to 
        // authenticate with the service.
        myMail.Fields.Add
        ("http://schemas.microsoft.com/cdo/configuration/smtpauthenticate","1");
        //Use 0 for anonymous
        myMail.Fields.Add
        ("http://schemas.microsoft.com/cdo/configuration/sendusername",
            pGmailEmail);
        myMail.Fields.Add
        ("http://schemas.microsoft.com/cdo/configuration/sendpassword",
             pGmailPassword);
        myMail.Fields.Add
        ("http://schemas.microsoft.com/cdo/configuration/smtpusessl",
             "true");
        myMail.From = pGmailEmail;
        myMail.To = pTo;
        myMail.Subject = pSubject;
        myMail.BodyFormat = pFormat;
        myMail.Body = pBody;
        if (pAttachmentPath.Trim() != "")
        {
            MailAttachment MyAttachment = 
                    new MailAttachment(pAttachmentPath);
            myMail.Attachments.Add(MyAttachment);
            myMail.Priority = System.Web.Mail.MailPriority.High;
        }

        System.Web.Mail.SmtpMail.SmtpServer = "smtp.gmail.com:465";
        System.Web.Mail.SmtpMail.Send(myMail);
        return true;
    }
    catch (Exception ex)
    {
        throw;
    }
}
}
Streamline answered 18/6, 2009 at 20:1 Comment(6)
System.Web.Mail is deprecated.Farly
Old code from my library! Hence the statement "Minor tweaking of the code below should work!"Streamline
Is this intended for versions of .Net previous to 4.0?Distribute
based on link you are right, This is not considered a bug, it’s by design. There are two types of SSL authentication for SMTP, and we only support one with System.Net.Mail (by design) – Explicit SSL. And only Web.Mail can send ssl mailsDripps
It seems like this is a requirement now with Gmail? This solution fixed my problem in 2017!Rafflesia
To any serious programmer: please use the solution provided by Bob Mc here underneath ;-)Tiphane
A
23

I'm late to this party but I'll offer my approach for any passersby that might be interested in an alternative.

As noted in previous answers, the System.Net.Mail SmtpClient class does not support Implicit SSL. It does support Explicit SSL, which requires an insecure connection to the SMTP server over port 25 in order to negotiate the transport level security (TLS). I blogged about my travails with this subtlety here.

In short, SMTP over Implict SSL port 465 requires TLS to be negotiated before connecting to the SMTP server. Rather than write a .Net SMTPS implementation I turned to a utility named Stunnel. It's a small service that will let you redirect traffic on a local port to a remote port via SSL.

DISCLAIMER: Stunnel uses portions of the OpenSSL library, which recently had a high-profile exploit published in all major tech news media. I believe the latest version uses the patched OpenSSL but please use at your own risk.

Once the utility is installed a small addition to the configuration file:

; Example SSL client mode services
[my-smtps]
client = yes
accept = 127.0.0.1:465
connect = mymailserver.com:465

...instructs the Stunnel service to reroute local requests to port 465 to my mail server on port 465. This happens over TLS, which satisfies the SMTP server on the other end.

Using this utility, the following code will successfully transmit over port 465:

using System;
using System.Net;
using System.Net.Mail;

namespace RSS.SmtpTest
{
    class Program
    {
        static void Main( string[] args )
        {
            try {
                using( SmtpClient smtpClient = new SmtpClient( "localhost", 465 ) ) { // <-- note the use of localhost
                    NetworkCredential creds = new NetworkCredential( "username", "password" );
                    smtpClient.Credentials = creds;
                    MailMessage msg = new MailMessage( "[email protected]", "[email protected]", "Test", "This is a test" );
                    smtpClient.Send( msg );
                }
            }
            catch( Exception ex ) {
                Console.WriteLine( ex.Message );
            }
        }
    }
}

So the advantage here is that you can use Implict SSL and port 465 as the security protocol while still using the send mail methods built into the framework. The disadvantage is that it requires the use of a third party service that may not be useful for anything but this specific function.

Abert answered 10/4, 2015 at 0:48 Comment(2)
Thank you Bob. It's just incredible that in 2019, this remains the most elegant solution. Using the deprecated System.Web.Mail.MailMessage is simply not acceptable, even less when knowing that you have to insure that the default input language is en-US, else you get an "COMException: The requested body part was not found in this message" error (which by the way should trigger automatically a WTF? reaction ;-)Tiphane
@StephaneEhret I agree. As I noted in my blog post, I intended on writing an implicit SSL .Net SMTP library but just never was able to find the time. There are a few libraries available that support implicit SSL, but most of them didn't feel like a good fit for me. Maybe I'll revisit this project.Abert
S
12

It works with System.Web.Mail (which is marked as obsolete):

private const string SMTP_SERVER        = "http://schemas.microsoft.com/cdo/configuration/smtpserver";
private const string SMTP_SERVER_PORT   = "http://schemas.microsoft.com/cdo/configuration/smtpserverport";
private const string SEND_USING         = "http://schemas.microsoft.com/cdo/configuration/sendusing";
private const string SMTP_USE_SSL       = "http://schemas.microsoft.com/cdo/configuration/smtpusessl";
private const string SMTP_AUTHENTICATE  = "http://schemas.microsoft.com/cdo/configuration/smtpauthenticate";
private const string SEND_USERNAME      = "http://schemas.microsoft.com/cdo/configuration/sendusername";
private const string SEND_PASSWORD      = "http://schemas.microsoft.com/cdo/configuration/sendpassword";

System.Web.Mail.MailMessage mail = new System.Web.Mail.MailMessage();

mail.Fields[SMTP_SERVER] = "tempurl.org";
mail.Fields[SMTP_SERVER_PORT] = 465;
mail.Fields[SEND_USING] = 2;
mail.Fields[SMTP_USE_SSL] = true;
mail.Fields[SMTP_AUTHENTICATE] = 1;
mail.Fields[SEND_USERNAME] = "username";
mail.Fields[SEND_PASSWORD] = "password";

System.Web.Mail.SmtpMail.Send(mail);

What is your point of view regarding obsolete namespace usage?

Scandalize answered 18/6, 2009 at 7:45 Comment(1)
this answer could be improved. There's no to, from, subject, or body here. That is, your missing the entire email part. Sure, not hard, but why not just put it all in one spot?Subphylum
S
10

In VB.NET while trying to connect to Rackspace's SSL port on 465 I encountered the same issue (requires implicit SSL). I made use of https://www.nuget.org/packages/MailKit/ in order to successfully connect.

The following is an example of an HTML email message.

Imports MailKit.Net.Smtp
Imports MailKit
Imports MimeKit

Sub somesub()
    Dim builder As New BodyBuilder()
    Dim mail As MimeMessage
    mail = New MimeMessage()
    mail.From.Add(New MailboxAddress("", c_MailUser))
    mail.To.Add(New MailboxAddress("", c_ToUser))
    mail.Subject = "Mail Subject"
    builder.HtmlBody = "<html><body>Body Text"
    builder.HtmlBody += "</body></html>"
      mail.Body = builder.ToMessageBody()

      Using client As New SmtpClient
        client.Connect(c_MailServer, 465, True)
        client.AuthenticationMechanisms.Remove("XOAUTH2") ' Do not use OAUTH2
        client.Authenticate(c_MailUser, c_MailPassword) ' Use a username / password to authenticate.
        client.Send(mail)
        client.Disconnect(True)
    End Using 

End Sub
Schizophrenia answered 9/9, 2016 at 15:11 Comment(1)
This really helped me. It is a very good alternative to SmtpClient which cannot handle implicit SSL. Also, it is much more mature than AIM (suggested in another answer) and works fine with UTF-8 (and other encodings).Thanks.Obligor
E
9

Try to check this free an open source alternative https://www.nuget.org/packages/AIM It is free to use and open source and uses the exact same way that System.Net.Mail is using To send email to implicit ssl ports you can use following code

public static void SendMail()
{    
    var mailMessage = new MimeMailMessage();
    mailMessage.Subject = "test mail";
    mailMessage.Body = "hi dude!";
    mailMessage.Sender = new MimeMailAddress("[email protected]", "your name");
    mailMessage.To.Add(new MimeMailAddress("[email protected]", "your friendd's name")); 
// You can add CC and BCC list using the same way
    mailMessage.Attachments.Add(new MimeAttachment("your file address"));

//Mail Sender (Smtp Client)

    var emailer = new SmtpSocketClient();
    emailer.Host = "your mail server address";
    emailer.Port = 465;
    emailer.SslType = SslMode.Ssl;
    emailer.User = "mail sever user name";
    emailer.Password = "mail sever password" ;
    emailer.AuthenticationMode = AuthenticationType.Base64;
    // The authentication types depends on your server, it can be plain, base 64 or none. 
//if you do not need user name and password means you are using default credentials 
// In this case, your authentication type is none            
    emailer.MailMessage = mailMessage;
    emailer.OnMailSent += new SendCompletedEventHandler(OnMailSent);
    emailer.SendMessageAsync();
}

// A simple call back function:
private void OnMailSent(object sender, AsyncCompletedEventArgs asynccompletedeventargs)
{
if (e.UserState!=null)
    Console.Out.WriteLine(e.UserState.ToString());
if (e.Error != null)
{
    MessageBox.Show(e.Error.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
else if (!e.Cancelled)
{
    MessageBox.Show("Send successfull!", "Information", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
} 
Enchantress answered 19/1, 2015 at 2:49 Comment(2)
can you provide the documentation of this AIM? ? ? no documentation or website is found on the sourceforge ???Illdefined
The best way is to download sample application and codeEnchantress
U
9

I know I'm joining late to the discussion, but I think this can be useful to others.

I wanted to avoid deprecated stuff and after a lot of fiddling I found a simple way to send to servers requiring Implicit SSL: use NuGet and add the MailKit package to the project. (I used VS2017 targetting .NET 4.6.2 but it should work on lower .NET versions...)

Then you'll only need to do something like this:

using MailKit.Net.Smtp;
using MimeKit;

var client = new SmtpClient();
client.Connect("server.name", 465, true);

// Note: since we don't have an OAuth2 token, disable the XOAUTH2 authentication mechanism.
client.AuthenticationMechanisms.Remove ("XOAUTH2");

if (needsUserAndPwd)
{
    // Note: only needed if the SMTP server requires authentication
    client.Authenticate (user, pwd);
}

var msg = new MimeMessage();
msg.From.Add(new MailboxAddress("[email protected]"));
msg.To  .Add(new MailboxAddress("[email protected]"));
msg.Subject = "This is a test subject";

msg.Body = new TextPart("plain") {
    Text = "This is a sample message body"
};

client.Send(msg);
client.Disconnect(true);

Of course you can also tweak it to use Explicit SSL or no transport security at all.

Urban answered 13/9, 2017 at 17:2 Comment(2)
i am using a code based on your above code to send emails via mailkit, but iget the error, can you see here, i will be very glad of you. #46421823Illdefined
I replied to your post and then added more options.. but your problem seems a little too broad to get a simple answer, unless you try excluding some of the possible causes..Urban
I
5

If it's Implicit SSL, it looks like it can't be done with System.Net.Mail and isn't supported as of yet.

http://blogs.msdn.com/webdav_101/archive/2008/06/02/system-net-mail-with-ssl-to-authenticate-against-port-465.aspx

To check if it's Implicit SSL try this.

Ish answered 18/6, 2009 at 20:28 Comment(0)
T
4

You can also connect via port 465, but due to some limitations of the System.Net.Mail namespace you may have to alter your code. This is because the namespace does not offer the ability to make implicit SSL connections. This is discussed at http://blogs.msdn.com/b/webdav_101/archive/2008/06/02/system-net-mail-with-ssl-to-authenticate-against-port-465.aspx.

It is possible to make implicit connections without having to use the now obsolete System.Web.Mail namespace, but you have to access the Microsoft CDO (Collaborative Data Object). I have supplied an example of how to use the CDO in another discussion (GMail SMTP via C# .Net errors on all ports).

Hope this helps!

Torose answered 3/10, 2010 at 14:2 Comment(0)
M
2

As stated in a comment at

http://blogs.msdn.com/webdav_101/archive/2008/06/02/system-net-mail-with-ssl-to-authenticate-against-port-465.aspx

with System.Net.Mail, use port 25 instead of 465:

You must set SSL=true and Port=25. Server responds to your request from unprotected 25 and then throws connection to protected 465.

Mislay answered 18/1, 2018 at 13:38 Comment(2)
I need to -1 this. The cited blog page has a single comment-reference to this with no confirmation. That comment refers to another blog in Russian that also doesn't have a single note of confirmation. Until there is some confirmation that this is a factual solution, so far it's one guy followed by one guy followed by one guy ... and that's not good enough for a SO answer.Boyette
Addendum: This answer describes connecting on port x, then being thrown to port y. This is the definition of STARTTLS, which the OP said he doesn't want. "The System.Net.Mail namespace only supports explicit SSL. Explicit SSL starts as unencrypted on port 25, then issues a STARTTLS signal, and then switches to an encrypted connection." - Ref: support.microsoft.com/en-us/help/950260/… I verified System.Net.Mail.SmtpClient does support port 587 connections for STARTTLS. I was unable to connect on 25.Boyette
M
0

If any doubt in this code, please ask your questions(Here for gmail Port number is 587)

// code to Send Mail 
// Add following Lines in your web.config file 
//               <system.net>
//                  <mailSettings>
//                    <smtp>
//                        <network host="smtp.gmail.com" port="587" userName="[email protected]" password="yyy"   defaultCredentials="false"/>
//                    </smtp>
//               </mailSettings>
//               </system.net>
// Add below lines in your config file inside appsetting tag <appsetting></appsetting>
//          <add key="emailFromAddress" value="[email protected]"/>
//       <add key="emailToAddress" value="[email protected]"/>
//        <add key="EmailSsl" value="true"/>

// Namespace Used

using System.Net.Mail;
     public static bool SendingMail(string subject, string content)
    {
       // getting the values from config file through c#
        string fromEmail = ConfigurationSettings.AppSettings["emailFromAddress"];
        string mailid = ConfigurationSettings.AppSettings["emailToAddress"];
        bool useSSL;
        if (ConfigurationSettings.AppSettings["EmailSsl"] == "true")
        {
            useSSL = true;
        }
        else
        {
            useSSL = false;
        }



        SmtpClient emailClient;
        MailMessage message;
        message = new MailMessage();
        message.From = new MailAddress(fromEmail);
        message.ReplyTo = new MailAddress(fromEmail);
        if (SetMailAddressCollection(message.To, mailid))
        {
            message.Subject = subject;
            message.Body = content;
            message.IsBodyHtml = true;
            emailClient = new SmtpClient();
            emailClient.EnableSsl = useSSL;
            emailClient.Send(message);
        }
        return true;
    }
    // if you are sending mail in group

    private static bool SetMailAddressCollection(MailAddressCollection toAddresses, string    mailId)
    {
        bool successfulAddressCreation = true;
        toAddresses.Add(new MailAddress(mailId));
        return successfulAddressCreation;
    }
Mauro answered 15/5, 2014 at 13:47 Comment(1)
The question was about using port 465, but your example is for port 587. There is a significant difference.Cyanocobalamin
T
0

For gmail these settings worked for me, the ServicePointManager.SecurityProtocol line was necessary. Because I has setup 2 step verification I needed get a App Password from google app password generator.

SmtpClient mailer = new SmtpClient();
mailer.Host = "smtp.gmail.com";
mailer.Port = 587;
mailer.EnableSsl = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;
Tarweed answered 10/6, 2016 at 14:2 Comment(1)
Caveat: SecurityProtocolType.Tls means TLS 1.0 only. If you want to allow other protocols (as of Oct 2021 Microsoft has discontinued use of TLS 1.0), you need to include them, too. If you have targeted .Net 4.8 or later, you can use SecurityProtocolType.SystemDefault so the operating system picks the latest protocol (or one set as the system default).Lobachevsky
O
0

to expand on Idriss's answer, here's my static method that works like a champ:

using System.Web.Mail;

public static void SendEmail(String Subject, String sMessage, String EmailAddress, String STMPServer, int SMTPPort, String UserName = "", String Password = null, Boolean IsSecure = true, Boolean IsHTML = true, String FromAddress = "[email protected]") {
    string SMTP_SERVER = "http://schemas.microsoft.com/cdo/configuration/smtpserver";
    string SMTP_SERVER_PORT = "http://schemas.microsoft.com/cdo/configuration/smtpserverport";
    string SEND_USING = "http://schemas.microsoft.com/cdo/configuration/sendusing";
    string SMTP_USE_SSL = "http://schemas.microsoft.com/cdo/configuration/smtpusessl";
    string SMTP_AUTHENTICATE = "http://schemas.microsoft.com/cdo/configuration/smtpauthenticate";
    string SEND_USERNAME = "http://schemas.microsoft.com/cdo/configuration/sendusername";
    string SEND_PASSWORD = "http://schemas.microsoft.com/cdo/configuration/sendpassword";

    MailMessage mail = new MailMessage();

    mail.Fields[SMTP_SERVER] = STMPServer;
    mail.Fields[SMTP_SERVER_PORT] = SMTPPort;
    mail.Fields[SEND_USING] = 2;
    mail.Fields[SMTP_USE_SSL] = IsSecure;
    if(!String.IsNullOrEmpty(UserName) && !String.IsNullOrEmpty(Password))
    {
        mail.Fields[SMTP_AUTHENTICATE] = 1;
        mail.Fields[SEND_USERNAME] = UserName;
        mail.Fields[SEND_PASSWORD] = Password;
    }
    else
    {
        mail.Fields[SMTP_AUTHENTICATE] = 0;
    }
    mail.From = FromAddress;
    mail.To = EmailAddress;
    mail.Subject = Subject;

    if (IsHTML)
    {
        mail.BodyFormat = MailFormat.Html;
    }
    else
    {
        mail.BodyFormat = MailFormat.Text;
    }
    mail.Body = sMessage;

    SmtpMail.Send(mail);
}
Overton answered 25/8, 2020 at 15:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.