.NET SmtpClient: есть ли способ убедиться, что все электронные письма разрешаются до отправки MailMessage?

Я использую SmtpClient для отправки электронной почты нескольким получателям. Когда сотрудники покидают компанию, их адреса электронной почты становятся недействительными. Поскольку их адреса электронной почты остаются в нашей базе данных до тех пор, пока не будут удалены вручную, попытка отправить им электронное письмо приводит к тому, что наше приложение генерирует исключение во время SmtpClient.Send(MailMessage). Однако, несмотря на возникновение исключения, он все равно отправляет электронное письмо. Это проблема, потому что мы хотим обработать эту ошибку, заблокировав попытку пользователя сохранить запись, и отобразить понятное сообщение с советом удалить все недопустимые партнеры из базы данных.

Если бы существовал способ перебрать все рецепты, чтобы убедиться, что все они действительны, мы могли бы запретить отправку всех писем до тех пор, пока пользователь не выполнит набор условий.


person oscilatingcretin    schedule 07.11.2012    source источник
comment
Зависит от того, насколько тщательными вы должны быть - вам может потребоваться сторонний компонент, например EmailVerify. NET.   -  person Bridge    schedule 07.11.2012
comment
Вы упомянули, что это сотрудники. Вы используете сервер Exchange для своей электронной почты или Active Directory для идентификации? Проверять ли все электронные письма сотрудников? Один из вариантов - перебрать объявления перед отправкой и проверкой статуса учетной записи в AD или пройти проверку через EWS.   -  person randcd    schedule 08.08.2013


Ответы (2)


Это очень старый вопрос, я не знаю, разрешили ли вы его.

Согласно MSDN: http://msdn.microsoft.com/en-us/library/swas0fwc(v=vs.100).aspx.

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

Это пример перехвата этого исключения, взятого из MSDN:

try {
    client.Send(message);
}
catch (SmtpFailedRecipientsException ex) {
    for (int i = 0; i < ex.InnerExceptions.Length; i++) {
        SmtpStatusCode status = ex.InnerExceptions[i].StatusCode;
        if (status == SmtpStatusCode.MailboxBusy || status == SmtpStatusCode.MailboxUnavailable) {
            Console.WriteLine("Delivery failed - retrying in 5 seconds.");
            System.Threading.Thread.Sleep(5000);
            client.Send(message);
        } 
        else {
            Console.WriteLine("Failed to deliver message to {0}", ex.InnerExceptions[i].FailedRecipient);
        }
    }
}

Полный пример здесь: http://msdn.microsoft.com/en-us/library/system.net.mail.smtpfailedrecipientsexception.aspx?cs-save-lang=1&cs-lang=csharp#code-snippet-2

Внутренне Send использует statuscode, возвращенный командой RCPT TO, чтобы вызвать соответствующее исключение.

Проверьте реализацию PrepareCommand в RecipientCommand.Send методе smtpTransport.SendMail (этот метод вызывается внутри SmtpClient.Send). Он использует RCPT TO для получения StatusCode, который затем анализируется в методе CheckResponse и, соответственно, поднимается SmtpFailedRecipientsException. Однако и VRFY, и RCPT не очень надежны, потому что почтовые серверы имеют тенденцию задерживать (ограничивать NDR) или поглощать ответ в качестве меры защиты от спама.

person Abhitalks    schedule 01.08.2013
comment
Я здесь в тупике. Внезапно исключение больше не генерируется. Когда я изначально писал этот вопрос, возникали исключения, но теперь Exchange Server просто отправляет электронное письмо, в котором говорится, что он не может доставить конкретным получателям. Вы знаете, что могло измениться? - person oscilatingcretin; 09.08.2013
comment
@oscilatingcretin Я только что протестировал его на своем сервере, и он отлично работает. Умею поймать SmtpFailedRecipientsException. Проверьте свою среду Exchange, не были ли изменены параметры фильтрации получателей. Есть две настройки, которые нужно искать: (1) SMTP Tarpitting: Tarpitting задерживает ответ 5.1.1 User Unkown. Возможно, что запоминание вызывает тайм-аут send в вашем коде. (2) Recipient Filtering: если RecipientValidationEnabled установлено в false, то сервер ответит 2.1.5 Получатель ОК, но все равно будет генерировать отчет о недоставке. Исключение не возникло. - person Abhitalks; 09.08.2013
comment
Если все, что вам нужно, это проверить наличие получателя, чтобы немедленно заблокировать пользователя, вы можете сначала проверить по AD. Если пользователь доступен в AD, продолжайте только с вашим почтовым кодом. UserPrincipal.FindByIdentity будет здесь твоим другом. - person Abhitalks; 09.08.2013

Взгляните на следующее: Как чтобы проверить, существует ли адрес электронной почты, не отправляя электронное письмо?

Что вы хотите сделать, так это проверить, существуют ли электронные письма, прежде чем продолжить отправку.

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

Цитата:

Вы можете подключиться к серверу и дать команду VRFY. Очень немногие серверы поддерживают эту команду, но она предназначена именно для этого. Если сервер отвечает DSN 2.0.0, пользователь существует.

Пользователь VRFY

Вы можете отправить RCPT и посмотреть, отклонено ли письмо.

ПОЧТА ОТ: ‹>

RCPT TO:

person Menelaos    schedule 05.08.2013
comment
+1 Никогда не пробовала, но выглядит очень интересно! - person pedrommuller; 08.08.2013
comment
Это именно то, что SmtpClient.Send делает внутренне. Проверьте реализацию PrepareCommand в RecipientCommand.Send методе smtpTransport.SendMail (этот метод вызывается внутри SmtpClient.Send). Он использует RCPT TO для получения StatusCode, который затем анализируется в методе CheckResponse и, соответственно, поднимается SmtpFailedRecipientsException. Однако и VRFY, и RCPT не очень надежны, потому что почтовые серверы имеют тенденцию задерживать (ограничивать NDR) или поглощать ответ в качестве меры защиты от спама. - person Abhitalks; 08.08.2013
comment
спасибо @abhitalks, что может быть надежным решением? или хотя бы обходной путь? Любые идеи? - person pedrommuller; 08.08.2013
comment
К сожалению, нет. Ближайший перехватывает исключение в Send. Мы не можем заставить какой-либо почтовый сервер немедленно ответить (или даже ответить). Меры по борьбе со спамом - необходимое неудобство :) - person Abhitalks; 08.08.2013
comment
@abhitalks, если SmtpClient уже делает это, то почему отправка на недопустимый адрес не вызывает исключения? stackoverflow.com/questions/5052282/capture-smtp-errors -в сети - person Arturo Torres Sánchez; 19.12.2014
comment
@ ArturoTorresSánchez: Принятый ответ на вопрос, на который вы ссылаетесь, и мой ответ и комментарии ниже уже отвечают на этот ваш вопрос! Магазин и вперед - одна из причин. Что еще более важно, в наше время почти все почтовые серверы используют задержку отчета о недоставке и всегда немедленно отвечают ok. - person Abhitalks; 19.12.2014
comment
@abhitalks, извини, я все еще не слежу. Открою новый вопрос. - person Arturo Torres Sánchez; 19.12.2014