Pakliže chceme odesílat emaily prostřednictvím SMTP protokolu, musíme najít nějaký vhodný komunikačních mechanismus. SMTP (Simple Mail Transfer Protocol) je jeden z nejstarších a dobře definovaných protokolů pro zajištění výměny emailů. Komunikace probíhá formou výměny speciálních zpráv mezi klientem a serverem. Samotná specifika komunikace nás ale zajímat nemusejí, neboť se o to dobře stará třídy SmtpClient.


Vytvoření zprávy

Před samotným odesláním je potřeba vytvořit samotnou zprávu. Pro zprávu je také připravena speciální třída – MailMessage. Tato třída nese veškeré informace – odesílatel, příjemce, předmět, tělo zprávy, apod. Typická hlavička emailu obsahuje následující části a tyto části odpovídají vlastnostem třídy MailMessage:

Část hlavičky Vlastnost třídy
Přílohy Attachments
Skrytá kopie (BCC) Bcc
Kopie (CC) Ccc
Druh obsahu BodyEncoding
Kódování hlavičky HeadersEncoding
Tělo zprávy Body
Priorita Priority
Příjemce To
Reply-To ReplyToList
Odesílatel From
Předmět Subject

Všechny tyto vlastnosti také naleznete v kolekci MailMessage.Headers. Kolekce je ale pouze pro čtení a nelze ji nastavit nějakou jinou. Nicméně lze do této kolekce přidávat a odebírat a hlavičku emailu tak ovlivnit. Pakliže budete hlavičku emailu výrazně měnit, může to ovlivnit doručení.

// vytvoření zprávy
MailMessage message = new MailMessage();

// nastavení účastníků
message.From = new MailAddress("odesilatel@hotmail.com");
message.To.Add(new MailAddress("prijemce@hotmail.com"));
message.CC.Add(new MailAddress("kopie@hotmail.com"));

// předmět
message.Subject = "Prvni zprava";
message.SubjectEncoding = Encoding.UTF8;

// tělo
message.BodyEncoding = Encoding.UTF8;
message.Body = "Ahoj světe!";
message.IsBodyHtml = false;

// uvolnění zprávy
message.Dispose();

Všimněte si posledního řádku. Třída MailMessage vyžaduje po odeslání zprávy její uvolnění. Pakliže tak neuděláte, můžete se setkat s problémy. Zatím ale zprávu neodesílám, takže by tam to Dispose() ještě být nemuselo.

Krom odesílatele, jsou všechny ostatní vlastnosti “účastníků” reprezentovány jako kolekce. Lze tak nastavit například více příjemců či kopií. Odesílatel i příjemce jsou instancemi třídy MailAddress.

SMTP klient

Nyní je potřeba připravit SMTP klienta pro odeslání emailu. Podívejte se na následující kód:

// instance třídy SmtpClient - nastavení host a port
SmtpClient client = new SmtpClient("smtp.live.com", 25);

// autorizace
client.Credentials = new NetworkCredential("odesilatel@hotmail.com", "nejvicTajneHeslo");
// typ zpracování zprávy
client.DeliveryMethod = SmtpDeliveryMethod.Network;
// nastavení SSL šifrování
client.EnableSsl = true;
// True nastavuje pro servery, které vyžadují ověření dříve
client.UseDefaultCredentials = false;
// klasický timeout
client.Timeout = 100000;

Z kódu je patrné, že hned při vytváření instance můžeme nastavit číslo portu a adresu smtp serveru. Dále je nutné nastavit jméno a heslo pro úspěšné přihlášení. Další vlastnosti už nejsou povinné a slouží pouze k více specifickému nastavení komunikace.

Odeslání emailu

Pro odeslání emailové zprávy slouží metoda Send() nebo SendAsync() ve tříde SmtpClient. Obě metody přijímají objekt typu MailMessage a dojdou ke stejnému výsledku. Rozdíl spočívá pouze v tom, že metoda SendAsync() pošle zprávu asynchronně na pozadí a o úspěšném odeslání nás informuje speciální událost. V ukázce bude používat první způsob, tedy metodu Send().

Třída SmtpClient nemá Finalize  metody. Je nutné uvolnit všechny její použití zdroje, proto jsem u zprávy zmínil nutnost použití explicitního volání Dispose(). Abychom nemuseli stále myslet na volání této metody, raději zprávu odložíme do bloku using, který to udělá za nás.

SmtpClient client = new SmtpClient("smtp.live.com", 25);
client.Credentials = new NetworkCredential("odesilatel@hotmail.com", "nejvicTajneHeslo");
client.DeliveryMethod = SmtpDeliveryMethod.Network;
client.EnableSsl = true;
client.UseDefaultCredentials = false;
client.Timeout = 100000;

using (MailMessage message = new MailMessage())
{
    message.From = new MailAddress("odesilatel@hotmail.com");
    message.To.Add(new MailAddress("prijemce@hotmail.com"));
    message.CC.Add(new MailAddress("kopie@hotmail.com"));
    message.Subject = "Prvni zprava";
    message.SubjectEncoding = Encoding.UTF8;
    message.BodyEncoding = Encoding.UTF8;
    message.Body = "Ahoj světe!";
    message.IsBodyHtml = false;

    // odeslání zprávy
    client.Send(message);
}

Připojení přílohy

Co by to bylo za email, kdyby neobsahoval přílohu. Samozřejmě si třída SmtpClient hravě poradí i s přílohy. Příloha je reprezentována objektem typu Attachment, kterému předáváme adresu souboru nebo streamu.

Můžeme přílohu upřesnit pomocí několika specifických vlastností:

Attachment att = new Attachment("C://Soubor.txt");
att.ContentDisposition.Inline = false;
att.ContentDisposition.DispositionType = DispositionTypeNames.Attachment;
att.ContentType.MediaType = "application/text";
att.TransferEncoding = TransferEncoding.Base64;
message.Attachments.Add(att);

Nebo postačí pouze vytvořit objekt Attachment a ten rovnou předat do kolekce příloh.

message.Attachments.Add(new Attachment("C://Soubor.txt"));

Možné problémy

Mohou ale nastat i nějaké problémy s touto třídou. Například nelze (nebo aspoň mě se nepodařilo) použít smpt server českého Seznamu. Je to z toho důvodu, že SmtpClient má jinou sekvenci autorizačních zpráv, která nelze nijak ovlivnit. V případě Seznamu je potřeba, aby poslal jen AUTH LOGIN a jméno s heslem až na vyžádání serveru. SmtpClient to posílá ale hned a Seznam pak vrací chybu.

Kompletní kód aplikace

SmtpClient client = new SmtpClient("smtp.live.com", 25);
client.Credentials = new NetworkCredential("odesilatel@hotmail.com", "nejvicTajneHeslo");
client.DeliveryMethod = SmtpDeliveryMethod.Network;
client.EnableSsl = true;
client.UseDefaultCredentials = false;
client.Timeout = 100000;

using (MailMessage message = new MailMessage())
{
    message.From = new MailAddress("odesilatel@hotmail.com");
    message.To.Add(new MailAddress("prijemce@hotmail.com"));
    message.CC.Add(new MailAddress("kopie@hotmail.com"));
    message.Subject = "Prvni zprava";
    message.SubjectEncoding = Encoding.UTF8;
    message.BodyEncoding = Encoding.UTF8;
    message.Body = "Ahoj světe!";
    message.IsBodyHtml = false;
    message.Attachments.Add(new Attachment("C:\\Soubor.txt"));

    client.Send(message);
}