none
Envoi de mail qui ne passe pas RRS feed

  • Discussion générale

  • Bonjour tout le monde,

    J'essaie d'envoyer un mail en C#. J'ai récupéré les chaînes de caractères de ma configuration Thunderbird, où les envois de mails se font, même si je ne reçois la copie qu'au bout de dix minutes.

    Pour tenir compte du temps de réaction je fais l'envoi en asynchrone.

    Les deux boîtes de messages, avant et après l'envoi, se succèdent immédiatement (en synchrone j'ai un timeout même avec une minute).

    J'attends un quart d'heure, je ne vois rien venir dans la boîte destinataire. Me serais-je trompé quelque part ?

    Le mot de passe que j'ai mis est bien celui du compte utilisé habituellement en SMTP. J'y ai accédé en webmail pour vérifier qu'il est toujours valable.

    Dans la configuration sous Thunderbird, il y a

    Sécurité de la connexion : SSL/TLS 
       (les autres valeurs possibles étant STARTTLS et aucune)
    Méthode d''authentification : mot de passe normal
       (les autres valeurs possibles étant pas d''authentification,
         mot de passe chiffré, Kerberos / GSSAPI, NTLM, OAuth2)

    Voici le code :

    SmtpClient client = new SmtpClient(strHost, intPort);
    client.UseDefaultCredentials = true;
    client.Credentials = new NetworkCredential(strEnvoyeur, strPass);
    MailMessage msg = new MailMessage(strEnvoyeur, strDest, strSubject, strBody);
    MessageBox.Show("On va l'envoyer");
    try
    {
    	client.Timeout = 30000;
    	client.EnableSsl = true;
    	client.DeliveryMethod = SmtpDeliveryMethod.Network;
    	client.SendAsync(msg, null);
    	
    	MessageBox.Show("On l'a envoyé");
    }
    catch(Exception ex)
    {
    	MessageBox.Show(ex.Message);
    }

    lundi 21 mai 2018 18:08

Toutes les réponses

  • Bonjour Gloops,

    Quel port ciblez-vous? 465 n’est pas pris en charge par la classe SmtpClient, comme indiqué ci-dessous. Essayez d’envoyer un message après le message pertinant. Cela pourrait vider les tampons, d’après la deuxième réponse dans ce thread:
    Won't send mail message - C#

    Si vous utilisez les types de serveur SMTP indiqués dans ces threads, ils pourraient aussi vous être utiles pour choisir le port respectif:
    Email Send Form C# Application
    How to use System.Net.Mail.SmtpClient via SSL and Authentication?
    Using SmtpClient to send an email from Gmail

    Cordialement,
    Dimitar

    mardi 22 mai 2018 18:02
    Modérateur
  • Bonjour, désolé pour le délai. Et merci pour la réponse.

    En effet, c'est bien le port 465, qui correspond à la doc fournie par le serveur. Comme c'est un service gratuit j'essaie de ne pas trop les solliciter pour du support ...

    Si je mets le port 25 comme dans le premier exemple de code, j'ai erreur d'authentification (avec pourtant nom d'utilisateur et mot de passe qui sont acceptés par le webmail ; pour le mot de passe j'ai fait un copier/coller).

    Si je mets le port 465 la CallBack n'est pas appelée ; mais c'est vrai que si le MailClient ne le supporte pas ...

    Ah, si, lors du timeout : il paraît que j'ai une erreur de syntaxe.

    Voilà ce que je réussis à en tirer (un peu taquin, la fin du message, je trouve) :

    ? e.Error.Message
    "Erreur de syntaxe, commande non reconnue. La réponse du serveur était : "
    ? e.Error.Data
    {System.Collections.ListDictionaryInternal}
        Count: 0
        IsFixedSize: false
        IsReadOnly: false
        IsSynchronized: false
        Keys: {System.Collections.ListDictionaryInternal.NodeKeyValueCollection}
        SyncRoot: {object}
        Values: {System.Collections.ListDictionaryInternal.NodeKeyValueCollection}
        Affichage des résultats: Le développement de l'affichage des résultats permet d'énumérer IEnumerable
    ? e.UserState
    null
    ? e.Cancelled
    false
    ? e.Error.InnerException
    null
    ? e.Error.StackTrace
    "   à System.Net.Mail.SmtpConnection.ConnectAndHandshakeAsyncResult.End(IAsyncResult result)\r\n   
        à System.Net.Mail.SmtpTransport.EndGetConnection(IAsyncResult result)\r\n   
        à System.Net.Mail.SmtpClient.ConnectCallback(IAsyncResult result)"

    Ce qu'il y a de changé par rapport au premier message c'est

    client.SendCompleted += new SendCompletedEventHandler(SendCompletedCallback);

    et la callback est recopiée du premier exemple de code au-dessus. D'ailleurs, j'ai défini un MailMessage à l'intérieur de la callback pour pouvoir faire tourner, car il ne paraissait pas simple à partir d'une fonction static d'appeler une propriété de la classe appelante.



    • Modifié Gloops dimanche 27 mai 2018 16:37
    dimanche 27 mai 2018 16:32
  • Si je mets le port 25 comme dans le premier exemple de code, j'ai erreur d'authentification (avec pourtant nom d'utilisateur et mot de passe qui sont acceptés par le webmail ; pour le mot de passe j'ai fait un copier/coller).

    Avec le port 587 aussi ?


    dimanche 27 mai 2018 18:12
  • Avec le 587, "échec de l'authentification".

    Ah, avec le 465 on n'a pas échec de l'authentification (ce qui est cohérent avec le fait que c'est celui que le serveur dit d'utiliser), mais on a une erreur de syntaxe coton à situer.

    dimanche 27 mai 2018 18:33
  • Je crois que j'ai une piste.

    Je me suis simplifié la vie avec

    client.SendAsync(Msg, null);
    

    mais ... ce n'est peut-être pas comme ça que ça se passe :)

    Alors d'après la doc, le deuxième argument s'appelle userToken.

    Bon c'est bien gentil, mais comment est-ce qu'on l'initialise ?

    lundi 28 mai 2018 07:29
  • Des fois que ça mette quelqu'un sur la voie, j'ai une erreur ‭FFFFFFFF80131500‬, et sur un autre projet quelqu'un a trouvé que ça correspondait à "invalid column name".

    Bon, alors colonne de mail ou colonne de token ...

    Pourtant, l'intitulé de l'erreur est "Erreur de syntaxe, commande non reconnue. La réponse du serveur était : "

    avec toujours un double point en fin d'intitulé, mais après tout on a bien déjà vu des trucs du style "l'intitulé propriété", ou "la taille propriété".

    Bon mais alors si la commande non reconnue n'est pas dans mon code mais dans l'implémentation de SmtpClient, ça promet de ne pas spécialement être du gâteau ...

    Et éplucher en pas à pas un traitement asynchrone, il faut en vouloir.

    lundi 28 mai 2018 14:10
  • Je crois que j'ai une piste.

    Je me suis simplifié la vie avec

    client.SendAsync(Msg, null);

    mais ... ce n'est peut-être pas comme ça que ça se passe :)

    Alors d'après la doc, le deuxième argument s'appelle userToken.

    Bon c'est bien gentil, mais comment est-ce qu'on l'initialise ?

    Je me suis dit que ça pouvait "être bien" de mettre quelque chose, alors la commande est devenue :

    client.SendAsync(Msg, client.Credentials);

    alors certes ça revient à se raccrocher aux branches, et l'ennui avec cette méthode est qu'on n'est pas assuré de se raccrocher à la bonne branche.

    userToken étant de type Object, en l'absence de précision dans la doc de SmtpClient je me suis dit qu'on pouvait mettre ce qu'on voulait dedans.

    C'est bien quand on peut faire ce qu'on veut :) Mais quand même, surtout quand ça marche.

    lundi 28 mai 2018 14:17
  • Alors récapitulons.

    J'ai essayé les ports 465, 25 et 587.

    La doc du serveur dit d'utiliser le port 465 pour SMTP, or les deux autres donnent une erreur d'authentification.

    Sur le port 465, au bout du timeout la callback reçoit dans ses paramètres une erreur avec l'intitulé "Erreur de syntaxe, commande non reconnue. La réponse du serveur était : ".

    J'ai pris conscience que la commande SendAsync attend un deuxième argument de type objet, nommé userToken. Comme je n'ai trouvé aucune précision j'y ai mis une copie de client.Credentials, en me doutant que ce n'est pas forcément très orthodoxe. De fait, il y a peut-être quelque chose de changé mais je n'ai pas su où.

    Dans les propriétés reçues en retour par la callback, il y a un UserState. Voici ce qu'il contient. Domain : chaîne vide. Password : le mot de passe. SecurePassword : System.Security.SecureString. UserName : l'adresse mail de l'utilisateur du serveur SMTP.

    SecurePassword est de longueur 13. Il peut être intéressant de rappeler que dans le paramétrage de Thunderbird nous avons SSL/TLS, "mot de passe normal".

    Accessoirement, pour la callback ça pouvait être intéressant de lui passer une copie du message mail pour pouvoir informer l'utilisateur de ce qu'on a cherché à envoyer et du résultat obtenu, je tourne un peu en rond là-dessus, une méthode static ne pouvant appeler de champ de la classe appelante. Le sender reçu en premier argument est le SmtpClient.



    • Modifié Gloops lundi 28 mai 2018 14:56
    lundi 28 mai 2018 14:34