Лучший способ проверить код отправки электронной почты с большим объемом SMTP? - PullRequest
6 голосов
/ 26 июля 2010

Я написал компонент в службе Windows (C #), который отвечает за отправку иногда больших объемов электронных писем.Эти электронные письма будут отправляться получателям на многих доменах - на самом деле, на любой домен. (Да, получатели хотят получить электронное письмо. Нет, я не рассылаю спам. Да, я жалуюсь на CAN-SPAM. Да, я в курсе отправка электронной почты с кодом отстой .) Многие электронные письма являются транзакционными (генерируются в ответ на действия пользователя);некоторые из них массовые (слияние почты в основном).

Я не хочу полагаться на внешний SMTP-сервер.(Среди прочих соображений мысль о необходимости проверять почтовый ящик на предмет ненадежных сообщений и пытаться разобрать их вызывает у меня плохие чувства.)

Мой дизайн довольно прост.Как транзакционные, так и массовые сообщения генерируются и вставляются в таблицу БД.Эта таблица содержит почтовый конверт и содержимое, а также количество попыток и дату повторной попытки.

Служба запускает несколько рабочих потоков, которые одновременно получают по 20 строк и перебирают каждый из них.Используя библиотеку Simple DNS Plus , я беру MX-записи домена получателя и затем использую System.Net.Mail.SmtpClient для синхронной отправки электронной почты.Если вызов на Send() завершится успешно, я могу удалить электронную почту из очереди.Если это временно не удается, я могу увеличить счетчик попыток и установить соответствующую дату повторной попытки.Если это не удастся, я могу удалить из очереди и обработать ошибку.

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

Даже мои небольшие трудности с тестированием усугубляются моим недавним открытиеммой провайдер блокирует соединения с портом 25 на любом сервере, кроме SMTP-сервера моего провайдера.(В производственном процессе эта вещь, конечно, будет на правильном сервере, где порт 25 не заблокирован. Это не помогает мне тестировать с моей машины разработки.)

Итак, две вещи, которые мне наиболее интересныabout:

  1. Как мне протестировать мой код?
  2. Какими различными способами может не работать SmtpClient.Send()?Шесть исключений перечислены;SmtpException и SmtpFailedRecipientsException кажутся наиболее актуальными.

Обновление: Ответ Марка Б указывает, что я в основномсоздать свой собственный SMTP-сервер.Он делает правильное замечание, что я заново изобретаю колесо, поэтому вот мое обоснование того, что вместо этого вместо «фактического» (Postfix и т. Д.) Следует использовать следующее:

  1. Письма имеют разные приоритеты отправки (хотя это не связано с конвертом X-Priority).Массовая электронная почта имеет низкий приоритет;Транзакционный высокий.(И любая электронная почта или группа электронных писем могут быть дополнительно настроены на произвольный приоритет.) Мне нужно иметь возможность приостановить отправку писем с более низким приоритетом, чтобы письма с более высоким приоритетом могли доставляться первыми.(Для этого рабочие потоки просто выбирают элементы с наивысшим приоритетом из очереди каждый раз, когда получают еще 20).

    Если я уже отправил несколько тысяч массовых элементов на внешний SMTP-сервер, у меня естьнет никакой возможности отложить их, пока отправляемые мной элементы отправляются.Беглый поиск Google показывает, что Postfix не поддерживает приоритеты; Sendmail расставляет приоритеты для информации в конверте, которая не соответствует моим потребностям.

  2. Мне нужно иметь возможность отображать ход процесса отправки взрыва (группа массовых писем) для моих пользователей.Если я просто передал все свои электронные письма на внешний сервер, я понятия не имею, как далеко продвигается фактическая доставка.

  3. Я не решаюсь анализировать отказов сообщения, потому что отказов каждого MTA разные.Sendmail отличается от Exchange отличается от [...].Кроме того, на какой частоте я проверяю свой почтовый ящик отказов?Что делать, если само сообщение о пересылке не доставлено?

  4. Меня не слишком беспокоит то, что на полпути провал взрыва.

    Если мы говоримкатастрофический сбой (необработанное исключение, завершающее работу приложения, сбой питания и т. д.): поскольку рабочие потоки удаляют каждое сообщение из базы данных при успешной доставке, я могу знать, кто получил взрыв, а кто нет.Кроме того, когда служба сбрасывается после сбоя, она просто определяет, где она остановилась в очереди.

    Если мы говорим о локальном сбое (SmtpException, сбое DNS и т. Д.): Iпросто зарегистрируйте ошибку, увеличьте счетчик попыток электронной почты и повторите попытку позже.(Это в основном то, что требует спецификация SMTP.) После n попыток я могу окончательно пропустить сообщение (удалить его из очереди) и зарегистрировать сбой для проверки позже.Таким образом, я могу найти странные крайние случаи, которые мой код не обрабатывает - даже если мой код не на 100% совершенен в первый раз.(И давайте будем честными, этого не произойдет.)

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

Ответы [ 2 ]

2 голосов
/ 26 июля 2010

Предположим, у вас есть два доступных сервера.Один будет отправителем, другой будет получателем.Вы можете настроить DNS (или даже просто файлы хостов) на обоих с длинной серией поддельных доменов.Что касается двух серверов, то эти домены являются абсолютно допустимыми, поскольку локальные DNS-серверы являются для них полномочными, но совершенно недействительными в отношении остальной части сети.Просто убедитесь, что распознаватель проверяет файл hosts перед DNS.

После того, как это будет сделано, вы можете заставить отправляющий сервер рассылать спам на принимающем сервере, как вам хочется, а также, чтобы получатель делал разные вещи для проверки реакции вашего кода.Серые списки, задержки TCP, жесткие отскоки, недоступность ICMP, превышение количества переходов по протоколу ICMP и т. Д. *

Конечно, если вам необходимо протестировать все эти условия, вы в основном создаете собственный SMTP-сервер, так почему бы и нетиспользовать реальный для начала?Я предполагаю, что усилия, необходимые для некоторого базового анализа отказов, будут намного меньше, чем необходимость придумывать куски кода для обработки всех режимов сбоя, которые postfix / sendmail / exim / etc ... уже отлично справляются со своимисобственные.

И это особенно верно, если учесть, что ваш код отправки должен быть идеальным с самого начала.Если электронная почта не удалась на полпути, и только половина списка получателей получит сообщение, вы окажетесь в гораздо большей дыре, чем если бы отскочили несколько сотен или несколько тысяч сообщений.Или, что еще хуже, дает сбой несколькими различными способами (некоторые серверы недоступны, некоторые вывели вас из-за чрезмерного трафика и т. Д.).Принимая во внимание, что отскоки будут счастливо находиться во входящей очереди, пока вы не обработаете их вручную или не исправите свой анализатор отказов для их обработки.

0 голосов
/ 02 августа 2010

После поиска около я в итоге запустил Papercut на нескольких дополнительных машинах, которые я лежал вокруг. Затем я заполнил свою базу данных тестовыми адресами *@[test-machine-*.local].

Хотя это работало достаточно хорошо, я протестировал с 25 потоками отправки, и, похоже, я перегружал четыре компьютера, на которых работал Papercut. Несколько сотен попыток отправки вызвали сбои соединения TCP; эти сообщения были должным образом поставлены в очередь для отправки позже (и в конечном итоге все же пришли). Однако из 25 000 тестовых электронных писем около 500 просто исчезли - ndash; добавление файлов * .eml в папку Papercut на каждом тестовом компьютере дало всего ~ 24 500.

Теперь мне остается только задаться вопросом, являются ли пропущенные электронные письма причиной проблемы в моем коде, или Papercut отбросил сообщения, которые он сообщил в SMTP как 250 OK.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...