4
votes

La méthode SmtpClient.SendMailAsync se bloque lors de l'envoi d'une grande quantité de mails

J'essaie d'envoyer de nombreux e-mails à l'aide de la méthode SmtpClient.SendMailAsync . Voici ma méthode de test que j'appelle depuis l'application console simple.

    static void Main(string[] args)
    {

        SendMailsOnebyOneAsync().GetAwaiter().GetResult();

    }


    public static async Task SendMailsOnebyOneAsync()
    {
        for (int i = 0; i < 1000; i++)
        {
            try
            {
                using (SmtpClient sMail = new SmtpClient("XXX"))
                {
                    sMail.DeliveryMethod = SmtpDeliveryMethod.Network;
                    sMail.UseDefaultCredentials = false;
                    sMail.Credentials = null;

                    var fromMailAddress = new MailAddress("XXX");
                    var toMailAddress = new MailAddress("XXX");

                    MailMessage message = new MailMessage(fromMailAddress, toMailAddress)
                    {
                        Subject = "test"
                    };

                    await sMail.SendMailAsync(message);

                    Console.WriteLine("Sent {0}", i);
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
        }
    }

Parfois, la méthode se bloque - elle attend SendMailAsync qui semble bloquée et ne revient pas .

Je vois une question connexe SmtpClient SendMailAsync ne revient parfois jamais . Mais il n'y a pas de solution suggérée qui fonctionne pour moi.

Quand j'ai essayé d'utiliser la méthode synchrone SmtpClient.Send tout est OK et l'application ne se bloque jamais.

Quelqu'un a-t-il une idée de ce qui ne va pas?


7 commentaires

Avez-vous accès au serveur SMTP? L'examen des journaux peut révéler le problème.


Sachez que vous ne pouvez pas envoyer 2 milliards d'e-mails asynchrones. J'exagère mais vous êtes limité physiquement à un certain montant. Dans votre cas, l'e-mail est très petit, mais s'il ne s'agit que d'un exemple de code et du vrai, vous avez une pièce jointe, un e-mail de 1 à 2 Mo et cela tue complètement votre carte réseau en envoyant 1000 e-mails dans la même seconde, surtout lorsque vous êtes au mieux peut envoyer 60-70 par seconde sur un réseau gigabit.


Vérifiez l'identité avec le service smtp que vous utilisez sur les limites de taux dont ils disposent - les services les plus populaires les auront. Pour le surmonter, vous pouvez utiliser une file d'attente (beaucoup d'implémentations de différences pour les files d'attente - base de données, rabbitMQ, EASendMail, MSMQ, etc.) dans ce genre de situation où vous avez beaucoup, beaucoup d'e-mails qui sortent. S'il s'agit de votre propre serveur smtp, comme l'a dit @virusstorm, jetez un œil aux journaux


J'essaierai de regarder dans les journaux si j'aurai accès.


Question - en cas de "Killing Network Card" que Frank a mentionné, dois-je obtenir une exception ou est-ce simplement suspendu?


De plus, je ne comprends pas pourquoi cela fonctionne bien avec la méthode non asynchrone si le problème dans "Killing Network Card"


@Inako Typiquement non, vous n'obtiendrez jamais d'erreurs asynchrones car le serveur SMTP est probablement celui qui ralentit tout. Vous pouvez vérifier les journaux de l'observateur d'événements pour voir les échecs de smtp si vous les suivez ou s'ils échouent sur le serveur smtp, vous pouvez parfois lire les journaux qui vous indiquent si un e-mail a échoué. Comme GregH l'a suggéré, la mise en file d'attente est la meilleure option. Personnellement, j'ai essayé MSMQ pour ce genre de travail et cela fonctionne très bien. Non async est automatiquement limité par votre système d'exploitation et ne peut plus envoyer s'il est saturé, il doit donc attendre. Attention à être marqué comme emailer zombie par le FAI.


3 Réponses :


1
votes

Utilisez un client pour envoyer les e-mails répétés. Créer et éliminer continuellement que de nombreux clients peuvent avoir des problèmes de port.

public static async Task SendMailsOnebyOneAsync() {
    using (var sMail = new SmtpClient("XXX")) {
        sMail.DeliveryMethod = SmtpDeliveryMethod.Network;
        sMail.UseDefaultCredentials = false;
        sMail.Credentials = null;

        for (int i = 0; i < 1000; i++) {
            try {
                var fromMailAddress = new MailAddress("XXX");
                var toMailAddress = new MailAddress("XXX");

                var message = new MailMessage(fromMailAddress, toMailAddress) {
                    Subject = "test"
                };

                await sMail.SendMailAsync(message);

                Console.WriteLine("Sent {0}", i);
            } catch (Exception e) {
                Console.WriteLine(e.Message);
            }
        }
    }
}

Deuxièmement, même s'il s'agit probablement d'un exemple, il n'est pas raisonnable d'essayer d'envoyer autant d'e-mails en une seule fois. p>


1 commentaires

J'ai essayé ceci et cela n'a pas résolu le problème. Merci.



1
votes

L'un de mes collègues m'a fait remarquer que SmtpClient est en fait obsolète et que Microsoft recommande de ne pas l'utiliser.

Voir ce qui suit lien .

   **********************************


0 commentaires

0
votes
  • Pour envoyer un grand nombre d'e-mails avec SmtpClient, je me souviens qu'il était recommandé de réutiliser la même connexion.
  • Je changerais la façon dont vous gérez l'asynchrone pour cela. Essayez le ThreadPool .

En remarque, SmtpClient ne prend pas en charge les protocoles modernes. Il est toujours possible de l'utiliser pour le courrier électronique occasionnel à des fins d'utilisation interne et de tests.
Vous pouvez essayer MailKit


0 commentaires