Не все электронные письма, отправляемые с помощью SmtpClient в ASP.NET MVC, доставляются. Почему? Как решить?

Вот настройка:

  1. У меня есть контроллер уведомлений, который вызывается из планировщика задач 1 раз в день.
  2. Метод действия извлекает до 300 адресов, перебирает их и использует класс SmtpClient для отправки отдельного электронного письма каждому получателю.

Насколько я могу судить, процесс работает нормально, без исключений... за исключением того, что не все электронные письма доставляются. У кого-нибудь есть идеи о том, что происходит и как решить?

Вот код:

foreach (var emp in division.Users)
{
    var fromAddress = "myfromaddress";
    var mailServer = "mymailserver";

    var toEmail = emp.EmailAddress;

    var message = new MailMessage(fromAddress, toEmail)
                    {
                        Subject = subject,
                        Body = "<body style='font:normal 13px tahoma,arial,helvetica;'>" + body + "</body>",
                        IsBodyHtml = true
                    };

    var client = new SmtpClient(mailServer);
    client.Send(message);
}

ОБНОВЛЕНИЕ:

Добавление паузы между отправкой сообщений электронной почты решает проблему. Но почему это работает? И есть ли лучший способ (например, использование Async()), который в равной степени решит проблему лучше???

Обновлен код...

foreach (var emp in division.Users)
{
    var fromAddress = "myfromaddress";
    var mailServer = "mymailserver";

    var toEmail = emp.EmailAddress;

    var message = new MailMessage(fromAddress, toEmail)
                    {
                        Subject = subject,
                        Body = "<body style='font:normal 13px tahoma,arial,helvetica;'>" + body + "</body>",
                        IsBodyHtml = true
                    };

    var client = new SmtpClient(mailServer);
    client.Send(message);

    Thread.Sleep(3000); // Wait 3s until sending next message
}

person wgpubs    schedule 16.02.2010    source источник
comment
Вы уверены в работоспособности вашего SMTP-сервера? Возможно, попробуйте ваш код с Gmail, это поможет вам найти проблему. Также попробуйте войти в систему с помощью какого-нибудь инструмента для ведения журнала, надеюсь, это поможет.   -  person Parsa    schedule 16.02.2010
comment
К сожалению, я подозреваю, что в вашем коде ничего нельзя изменить, чтобы исправить это; скорее всего, это проблема с конфигурацией сервера. Существует много препятствий, которые необходимо преодолеть при настройке сервера smtp для массовых рассылок, иначе ваши сообщения будут помечены как спам многими поставщиками услуг электронной почты. Вероятно, вам следует попробовать версию этого вопроса при сбое сервера.   -  person Joel Coehoorn    schedule 16.02.2010
comment
Да, я проверил, что это работает с меньшими списками электронных писем (например, я только что протестировал отправку 20 электронных писем в цикле... нет проблем)   -  person wgpubs    schedule 16.02.2010


Ответы (3)


есть тайм-аут по умолчанию с smtp-клиентом, и значение по умолчанию составляет 100 секунд.

подробнее здесь

person Fredou    schedule 16.02.2010
comment
Я не думаю, что это тайм-аут, поскольку для отправки отдельного электронного письма не требуется и близко 100 секунд. - person wgpubs; 16.02.2010

Если у вас нет исключений, я бы проверил папки СПАМ и адреса электронной почты. Я также попытался бы отправить электронное письмо вручную из вашего внешнего вида на один из адресов, которые не получили сообщение.

Кстати, если вы не используете разные почтовые серверы, я думаю, вы можете изменить этот код на

var client = new SmtpClient(mailServer); 
var mailServer = "mymailserver";

foreach (var emp in division.Users) 
{ 
    var fromAddress = "myfromaddress"; 


    var toEmail = emp.EmailAddress; 

    var message = new MailMessage(fromAddress, toEmail) 
                    { 
                        Subject = subject, 
                        Body = "<body style='font:normal 13px tahoma,arial,helvetica;'>" + body + "</body>", 
                        IsBodyHtml = true 
                    }; 


    client.Send(message); 
} 

Вы также можете попробовать метод SendAsync класса SmtpClient, например:

// setup the callback method when the send finishes
client.SendCompleted += SendComplete; //new SendCompletedEventHandler(smtpSender_SendCompleted);

// send the email
client.SendAsync(message, null);



private void SendComplete(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
{
    // do stuff on complete
}
person Nate    schedule 16.02.2010
comment
Нет... мусор, в папках со спамом тоже нет сообщения - person wgpubs; 16.02.2010
comment
У меня есть похожее приложение, использующее метод SendAsync, и оно отправляет сотни писем без проблем... - person Nate; 16.02.2010
comment
Нет, это служба Windows ... но это не должно иметь значения, поскольку код в основном тот же. Попробуйте использовать метод Async, а затем исследуйте объект AsyncCompletedEventArgs, чтобы узнать, возникают ли какие-либо ошибки. - person Nate; 16.02.2010

Я настоятельно рекомендую использовать SmtpClient.SendAsync(), так как Send() блокирует.

Я бы проверил журналы SMTP-сервера, на который вы отправляете. Примечание. Отправка собственных электронных писем с большей вероятностью закончится нежелательной почтой, чем отправка доверенного поставщика.

Изменить: добавлен образец кода SendAsync.

smtpClient.SendCompleted += smtpClient_SendCompleted;

static void smtpClient_SendCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
{
    if (e.Error != null)
    {
        Log.ErrorFormat("Async Mail exception {0} :: {1}", 
            e.Error.GetType().Name, e.Error.Message);
    }
}
person mythz    schedule 16.02.2010
comment
Как это работает в среде MVC? Другими словами, как определить успех, неудачу и т. д.? - person wgpubs; 16.02.2010
comment
@Фреду Как так? Все, что нужно изменить, это вызвать SendAsync и предоставить обработчик событий для события SendCompleted... - person Nate; 16.02.2010
comment
@Fredou отредактировал ответ, включив пример проверки ошибок в асинхронном вызове. - person mythz; 16.02.2010
comment
Я до сих пор не уверен, как это работает в среде ASP.NET MVC, где у меня есть контроллер (NotificationsController) с методом действия (SendNotifications), который выполняет эту работу. Насколько мне известно, после завершения метода SendNotifications экземпляр NotificaitonsController удаляется сборщиком мусора, что делает его недоступным для получения сообщений от Async, не так ли? - person wgpubs; 16.02.2010
comment
Я считаю, что, поскольку SmtpClient.SendCompleted по-прежнему будет содержать ссылку на обработчик событий (определенный в NotificationsController), он должен оставаться до тех пор, пока все не завершится, с ошибкой или без нее. - person Nate; 16.02.2010
comment
Я должен буду проверить. Я заметил, что если я делаю паузу между отправкой почты (Thread.Sleep(3000)... 3s)... ВСЕ электронные письма отправляются. Так что мне интересно, имеет ли это какое-то отношение к тому, что почтовый сервер один за другим забивается???? - person wgpubs; 16.02.2010