.NET-ből e-mailt küldeni nem nagy durranás, három évvel ez előtt már egyszer megírtam, hogy milyen egyszerűen megy ez a MailMessage és az SmtpClient osztályok segítségével. Akkor szó esett arról, hogyan kérhetünk kézbesítési nyugtát, hogyan küldhetünk egy levélen belül többféle formátumban vagy éppen aszinkron módon, és hogy hogyan trace-elhetjük a levélküldést. Egy gyakori feladat azonban kimaradt: hogyan küldhetünk úgy levelet, hogy az e-mail sablonja egy külső fájlból jöjjön, amit a kódunktól függetlenül tudunk karbantartani?
Itt jön a képbe a System.Web.UI.WebControls.MailDefinition osztály. Elsőre igen szokatlan, hogy ezt az osztályt használjuk, hiszen a többi levélküldős osztály a System.Net.Mail névtérben van, ez pedig a WebControlsban, de az a lényeg, hogy működik. A MailDefinition osztály BodyFileName tulajdonságában kell megadnunk a sablont:
MailDefinition mail = new MailDefinition(); mail.BodyFileName = @"~/EmailTemplate.txt";
Megadhatjuk továbbá a levél feladóját (From), hogy ki kap másolatot (CC), a levél prioritását (Priority), sőt tárgyát (Subject) is, a legfontosabb azonban az IsBodyHtml tulajdonság beállítása, amivel azt jelezzük, hogy a betöltött sablon plain text vagy HTML fájl.
Az én esetemben plain text e-mailt küldünk, ezért a sablon is sima TXT:
Tisztelt <%DisplayName%>! A <%Acronym%> konferenciára sikeresen regisztrálta dolgozatát. Köszönjük.
A sablonban természetesen helyőrzők vannak, ahova a behelyettesítendő értékek kerülnek. Fontos, hogy itt a <% %> szintaktikát használjuk, más megoldással voltak rossz tapasztalataink. Egy szótár típusú gyűjteményben (dictionary) kell megadnunk, hogy a helyőrzők helyére milyen konkrét értékek kerüljenek (nálam az emailData objektum tartalmazta a szükséges információkat):
ListDictionary replacements = new ListDictionary(); replacements.Add( "<%DisplayName%>", emailData.DisplayName ); replacements.Add( "<%Acronym%>", emailData.Acronym );
A definícióból a CreateMailMessage függvénnyel állíthatjuk elő az elküldhető MailMessage objektumot, paraméterként a címzettet, a csere szótárt és egy tulajdonos Control objektumot kell átadnunk. Természetesen az így létrejött MailMessage tulajdonságait utána módosíthatjuk és már mehet is a küldés:
using( MailMessage message = mail.CreateMailMessage( emailData.Email, replacements, this ) ) { message.Subject = "Sikeres regisztráció"; try { using( SmtpClient client = new SmtpClient() ) { client.Send( message ); } } catch( Exception ex ) { // Naplózás } }
A levelezőszerver és a feladó adatai természetesen a web.config-ból is jöhetnek:
<system.net> <mailSettings> <smtp from="no-reply@example.com"> <network host="mail.example.com" password="" userName=""/> </smtp> </mailSettings> </system.net>
Nagyon testidegennek tűnhet egy ilyen GUI független kódtól egy olyan osztály, ami a WebControls névtérben van, ráadásul a hívott metódusának egy Control példányt is át kell adni. Ez valószínűleg onnan ered, hogy ezt az osztályt a beépített felhasználókezelő vezérlőkhöz készítették, mi csak kihasználjuk, hogy azoktól függetlenül is működik. Természetesen ugyanezt a funkcionalitást néhány perces kódolással bárki elkészítheti és akkor nincs ilyen probléma, én mégis jobban szeretem a standard, nem egyedi megoldásokat. Ráadásul ez készen van, csak használni kell.