web-dev-qa-db-fra.com

Comment puis-je envoyer des emails via SSL SMTP avec le .NET Framework?

Existe-t-il un moyen avec .NET Framework d’envoyer des courriers électroniques via un serveur SMTP SSL sur le port 465?

La manière habituelle:

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);

le temps est écoulé:

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

J'ai cherché sur Google et constaté que System.Net.Mail prend en charge les connexions sur le port 587 (le port par défaut pour SSL explicite qui commence non crypté, puis émet un STARTDLS, puis passe à une connexion cryptée: RFC 2228), mais ne prend pas en charge le SSL implicite est enveloppé dans une couche SSL) ...

33
Idriss

Voici un exemple d’envoi de courrier électronique via GMail qui utilise également SSL/465. Des modifications mineures du code ci-dessous devraient fonctionner!

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;
    }
}
}
32
Andrew Siemer

Je suis en retard pour cette soirée mais je proposerai mon approche à tous les passants qui pourraient être intéressés par une alternative.

Comme indiqué dans les réponses précédentes, la classe System.Net.MailSmtpClient ne prend pas en charge SSL implicite. Il prend en charge Explicit SSL, qui nécessite une connexion non sécurisée au serveur SMTP sur le port 25 afin de négocier la sécurité du niveau de transport (TLS). J'ai blogué à propos de mes travails avec cette subtilité ici .

En résumé, le port 465 de SMTP sur Implict SSL requiert la négociation de TLS avant connexion au serveur SMTP. Plutôt que d’écrire une implémentation .Net SMTPS, je me suis tourné vers un utilitaire nommé Stunnel . C'est un petit service qui vous permettra de rediriger le trafic sur un port local vers un port distant via SSL.

CLAUSE DE NON-RESPONSABILITÉ: Stunnel utilise des parties de la bibliothèque OpenSSL, qui a récemment publié un exploit très médiatisé dans tous les principaux médias d’information technologique. Je pense que la dernière version utilise le patch OpenSSL mais veuillez l’utiliser à vos risques et périls.

Une fois l’utilitaire installé, un petit ajout au fichier de configuration:

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

... demande au service Stunnel de rediriger les demandes locales vers le port 465 vers mon serveur de messagerie sur le port 465. Cela se produit via TLS, qui satisfait le serveur SMTP de l'autre côté.

En utilisant cet utilitaire, le code suivant transmettra avec succès sur le 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 );
            }
        }
    }
}

L’avantage ici est donc que vous pouvez utiliser Implict SSL et le port 465 comme protocole de sécurité tout en utilisant les méthodes d’envoi de courrier intégrées au framework. L'inconvénient est qu'il nécessite l'utilisation d'un service tiers qui peut ne pas être utile pour autre chose que cette fonction spécifique.

13
Bob Mc

Cela fonctionne avec System.Web.Mail (qui est marqué comme obsolète):

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);

Quel est votre point de vue concernant l'utilisation obsolète des espaces de noms?

10
Idriss

Essayez de vérifier gratuitement cette alternative open source https://www.nuget.org/packages/AIM Il est gratuit d’utilisation et open source et utilise exactement la même méthode que System.Net. .Mail utilisePour envoyer un courrier électronique à des ports SSL implicites, vous pouvez utiliser le code suivant 

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);
}
} 
8
Nil Null

En VB.NET, alors que j'essayais de me connecter au port SSL de Rackspace sur 465, je rencontrais le même problème (nécessite SSL implicite). J'ai utilisé https://www.nuget.org/packages/MailKit/ afin de vous connecter avec succès. 

Voici un exemple de message électronique HTML.

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
5
Cody G.

Vous pouvez également vous connecter via le port 465, mais en raison de certaines limitations de l'espace de noms System.Net.Mail, vous devrez peut-être modifier votre code. Cela est dû au fait que l'espace de noms n'offre pas la possibilité d'établir des connexions SSL implicites. Ceci est discuté à http://blogs.msdn.com/b/webdav_101/archive/2008/06/02/system-net-mail-with-ssl-to-authenticate-against-port-465.aspx .

Il est possible d'établir des connexions implicites sans avoir à utiliser l'espace de noms System.Web.Mail, devenu obsolète, mais vous devez accéder à Microsoft CDO (Collaborative Data Object). J'ai fourni un exemple d'utilisation du CDO dans une autre discussion ( GMail SMTP via des erreurs C # .Net sur tous les ports ).

J'espère que cela t'aides!

4
Bryan Allred

S'il s'agit de SSL implicite, il semble que cela ne puisse pas être fait avec System.Net.Mail et qu'il ne soit pas encore pris en charge.

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

Pour vérifier si c'est SSL implicite, essayez this.

4
Kinze

Je sais que je participe tard à la discussion, mais je pense que cela peut être utile aux autres.

Je voulais éviter les trucs déconseillés et après beaucoup de manipulations j'ai trouvé un moyen simple d'envoyer aux serveurs nécessitant un SSL implicite: utilisez NuGet et ajoutez le paquet MailKit au projet. (J'ai utilisé VS2017 pour cibler .NET 4.6.2 mais cela devrait fonctionner avec des versions inférieures .NET ...)

Ensuite, il vous suffira de faire quelque chose comme ceci:

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);

Bien sûr, vous pouvez également le modifier pour utiliser Explicit SSL ou aucune sécurité de transport.

1
Luke

Comme indiqué dans un commentaire à 

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

avec System.Net.Mail, utilisez le port 25 au lieu de 465:

Vous devez définir SSL = true et Port = 25. Le serveur répond à votre demande de 25 non protégés, puis établit la connexion avec le protocole 465.

1
net_prog

Pour Gmail, ces paramètres fonctionnaient pour moi, la ligne ServicePointManager.SecurityProtocol était nécessaire. Parce que j'ai la configuration en 2 étapes, j'avais besoin d'un mot de passe d'application de Générateur de mot de passe d'application Google . SmtpClient mailer = new SmtpClient(); mailer.Host = "smtp.gmail.com"; mailer.Port = 587; mailer.EnableSsl = true; ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;

0
user2584621