Masowa wysyłka maili przy użyciu SmtpClient

13.04.2013

“Masowa” i “SmtpClient” w jednym zdaniu? Nie, to nie jest żart. Każdy, kto choć raz musiał wysyłać serię maili z poziomu kodu C# pomyśli, że zwariowałem. Blokowanie wątku, cała gama wyjątków, które może rzucić metoda Send(), czy obsługa stanu aplikacji po takim błędzie. To ważniejsze atrakcje, jakie możemy napotkać korzystając z tej klasy. Jest na to jedna prosta metoda. Wróć. Właściwość… DeliveryMethod.

Dzięki tej właściwości możemy zmienić tryb wysyłki z bezpośredniego (standardowo wybrany), łączącego się z serwerem poczty i blokującego wątek, na zapis wiadomości email do pliku .eml. Wystarczy ustawić odpowiednio właściwości:

var smtpClient = new SmtpClient
{
    DeliveryMethod = SmtpDeliveryMethod.SpecifiedPickupDirectory,
    PickupDirectoryLocation = "tutaj ścieżka do katalogu pickup"
};

No świetnie. Miało być o masowej wysyłce maili, a tymczasem gość prawi o zapisie na dysk. To nie koniec. Tak zapisana wiadomość będzie zawierała wszystkie potrzebne do wysyłki dane (w tym załączniki, cc, bcc itp.) i co najważniejsze będzie rozumiana przez oprogramowanie serwerów email, np. MailEnable czy wbudowany w Windows/IIS serwer poczty email. Właśnie ten ostatni posłużył mi do wysyłki.

Konfiguracja IIS’a opisana jest tutaj. Teraz wystarczy zapisać w określonym katalogu (pickup) paczkę maili do wysyłki i już. Serwer email zadba o ich dostarczenie do adresata. Jeżeli z jakiegoś powodu dostarczenie się nie uda (a będzie próbował kilka razy w różnych odstępach czasu), to taka wiadomość wyląduje w katalogu badmail.

Ważna uwaga na koniec. SmtpClient zapisuje pliki pod nazwą guid.eml. Serwer po przetworzeniu wiadomości i dajmy, wrzuceniu jej do katalogu badmail zapiszę tą samą wiadomość wraz z dodatkowymi informacjami pod inną nazwą, nie rzadko w kilku plikach z różnymi rozszerzeniami! Żeby poradzić sobie z identyfikacją wiadomości, które przechodzą przez serwer mail, warto dodać do każdej z nich własny nagłówek np. z identyfikatorem obiektu (zadania, użytkownika, kampanii itp.), którego dotyczy dany email.

mail.Headers.Add("kid", kampaniaId.ToString());

Teraz identyfikacja będzie juz prosta.