MailKit - метод SmtpClient Connect зависает - PullRequest
4 голосов
/ 20 мая 2019

Я разрабатываю приложение для Android Xamarin, где в какой-то момент (после успешной транзакции) приложение должно отправить клиенту информационное письмо. Весь процесс создания экземпляра MimeMessage, а также его фактическая отправка выполняются с помощью задачи. Сообщение (которое в большинстве случаев содержит связанные изображения) создается безупречно, но как только я вызываю метод для его фактической отправки, выполнение останавливается при этом вызове, и вся задача остается активной, но в этот момент замороженной.

Вот мой метод SendMail, который, кроме параметра MimeMessage, получает класс MailAccount с информацией о машине smtp, порте и учетной записи отправителя. Как только вызывается метод Connect экземпляра MailKit SmtpClient, у меня возникает «замороженное» поведение, которое я описал. Я пробовал все это много раз - даже после того, как код продолжался после этой строки.

private static int SendMail(MailAccount account, MimeMessage message)
{
    using (var client = new SmtpClient())
    {
        try
        {
            client.Connect(account.Server, account.Port, false);
        }
        catch (SmtpCommandException)
        {
            return -1;
        }
        catch (SmtpProtocolException)
        {
            return -2;
        }

        client.AuthenticationMechanisms.Remove("XOAUTH2");

        if (client.Capabilities.HasFlag(SmtpCapabilities.Authentication))
        {
            try
            {
                client.Authenticate(account.User, Decrypt(account.Pass));
            }
            catch (AuthenticationException)
            {
                return -3;
            }
            catch (SmtpCommandException)
            {
                return -1;
            }
            catch (SmtpProtocolException)
            {
                return -2;
            }
        }

        int status = 1; //assume success

        try
        {
            client.Send(message);
        }
        catch (SmtpCommandException ex)
        {
            switch (ex.ErrorCode)
            {
                case SmtpErrorCode.MessageNotAccepted:
                    status = -6;
                    break;

                case SmtpErrorCode.SenderNotAccepted:
                    status = -5;
                    break;

                case SmtpErrorCode.RecipientNotAccepted:
                    status = -4;
                    break;

                default:
                    status = -7;
                    break;
            }
        }

        client.Disconnect(true);
        return status;
    }
}

1 Ответ

0 голосов
/ 21 мая 2019

Как правило, зависание при вызове client.Connect указывает на то, что хост или порт, к которому вы пытаетесь подключиться, недоступны.Проверьте правильность хоста и порта.

Если они являются правильными , убедитесь, что вы используете последнюю версию MailKit, так как некоторые старые версии использовали Socket.BeginConnect (string, int ...), что на IPv6-с включенными операционными системами, иногда пытался использовать IPv4 поверх IPv6 и зависать в некоторых ситуациях (например, при использовании антивирусного сканера, такого как Avast).

Более новые версии MailKit (> = 2.1.4 и версии до 2.0)) выполнить поиск DNS удаленного хоста и вручную указать правильное семейство адресов, которое будет использоваться при создании экземпляра Socket (IPv4 против IPv6), чтобы избежать этой проблемы.

Также возможно, что зависание вызвано SSL/ TLS проверяет аннулирование сертификата с не отвечающим центром сертификации.Вы можете отключить проверки отзыва сертификатов, используя следующий фрагмент кода:

client.CheckCertificateRevocation = false;

Просто убедитесь, что это свойство установлено перед тем, как вызовет Connect.

Itвозможно, стоит проверить доступ к вашему SMTP-серверу, создав новое консольное приложение в Visual Studio и вставив следующий код и проверив его работоспособность:

using System;
using System.Threading;
using System.Threading.Tasks;

using MailKit;
using MailKit.Net.Smtp;

namespace ConsoleApp {
    public class Program
    {
        static void Main (string[] args)
        {
            using (var client = new SmtpClient (new ProtocolLogger ("smtp.log"))) {
                using (var cts = new CancellationTokenSource (60000)) {
                    try {
                        client.Connect ("your-host.com", 25, false, cts.Token);
                        client.Disconnect (true);
                    } catch (Exception ex) {
                        Console.WriteLine ("Error connecting: {0}", ex.Message);
                        Console.WriteLine (ex.StackTrace);
                    }
                }
            }
        }
    }
}

Также было бы интересно узнать, работает ли ваше приложение для Androidвозникают проблемы с подключением к smtp.gmail.com через порт 465 (useSsl = true).

...