Minule jsem ukazoval, jak se dá poslat mail přes nainstalovaný program za pomocí MAPI (a Pepák v komentářích i přímo přes volání API MAPI), dnes ukáži vytvoření mailu za pomocí Synapse a jeho odeslání přes SMTP.
Synapse je knihovna nevizuálních komponent pro síťovou komunikaci na bázi blokujících soketů podporující kromě Delphi i Kylix a FreePascal. Kromě šikovného zapouzdření soketů obsahuje kvalitní podporu pro různé protokoly a další věci (včetně SSL). Její hlavní autor (Lukáš Gebauer) odvedl skvělou práci a osobně je jeho knihovna pro mne jedním z nejlepších open source kódů (spolu s FastMM4, VirtualTreeView atd.) a pravděpodobně i uzavřených.
Ale zpět k našemu úkolu. Celý úkol se skládá v podstatě ze dvou částí:
- vytvoření MIME zprávy obsahující data mailu
- odeslání vytvořené zprávy přes SMTP
Naštěstí Synapse má podporu pro obě části.
Vytvoření MIME zprávy
MIME je internetový standard, který umožňuje přenášet v mailu (a nejen v mailu) znaky s diakritikou nebo soubory (a další).
Podpora pro MIME je v Synapsi implementována (převážně) v jednotkách mimepart a mimemess.
Úplně na začátku je třeba se rozhodnou co bude mail obsahovat (zda jen čistý text, html nebo i soubory). Podle toho je třeba vytvářet strukturu MIME. MIME se skládá z částí, ale které části bude obsahovat záleží jen na nás.
Pokud mail bude obsahovat jen text nebo html, stačí jen jedna část. Pokud přidáme i soubor, musí MIME nejprve obsahovat část mixed, na kterou je navázán text mailu (čistý neboli plain nebo html) a vlastní soubor.
Relativně nejkomplikovanější je situace, kdy chceme přidat soubor, ale k základnímu textu přidat i alternativní text. Toto je celkem častá situace, kdy vytváříme HTML mail s přílohou, ale pro klienta, který neumí HTML chceme zobrazit alternativní zprávu (ať už jen informaci o tom, že je třeba HTML zobrazení, nebo zjednodušené zobrazení HTML zprávy). V takové případě musíme ještě přidat část alternate.
Ukázka kódu s alternate.
1uses
2 smtpsend, mimepart, mimemess;
3
4procedure TForm1.btn1Click(Sender: TObject);
5var
6 oMessage : TMimeMess;
7 p, oMultiPartAlt: TMimePart;
8begin
9 oMessage := TMimeMess.Create;
10 with oMessage do
11 try
12 Header.From := 'radek.cervinka@technodat.cz';
13 Header.ToList.Clear;
14 Header.ToList.Add('radekc@delphi.cz');
15 Header.CcList.Clear;
16 Header.Subject := 'Novy mail';
17
18 p := AddPartMultipart('mixed', nil);
19 oMultiPartAlt := AddPartMultipart('alternative', p);
20
21 AddPartText(mem1.Lines, oMultiPartAlt);
22 AddPartBinaryFromFile('c:\test.pdf', p);
23 AddPartHTML(mem2.Lines, oMultiPartAlt);
24
25 Header.XMailer := 'Muj program';
26
27 Header.Date := Now;
28 EncodeMessage;
29 if SendToRaw(Header.From, Header.ToList.CommaText, 'smtp.server.net', Lines, 'user', 'heslo') then
30 ShowMessage('Mail byl úspěšně odeslán!')
31 else
32 ShowMessage('Mail se nepodařilo odeslat.');
33 finally
34 Free;
35 end;
36end;
v případě zprávy bez alternate bude část mezi % následující:
1p := AddPartMultipart('mixed', nil);
2
3 AddPartText(mem1.Lines, p);
4 AddPartBinaryFromFile('c:\test.pdf', p);
Samozřejmě metod je tam spousta (včetně přidávání streamů atd). Navíc nic nebrání tomu si nějakou přidělat.
A pokud chceme poslat jen text nebo jen html tak jen pro úplnost:
1AddPartText(mem1.Lines, nil);
2
3 AddPartHTML(mem2.Lines, nil);
Vždy ten druhý parametr odkazuje na nadřazený MimePart, nil znamená kořen.
Odeslání MIME zprávy
Pokud nemáme zvláštní požadavky tak si vystačíme s procedurou SendToRaw jako v příkladu. Parametry jsou od koho, komu, SMTP server,
Mime, uživatel a heslo pro připojení k SMTP.
Pokud chceme větší kontrolu nad odesíláním (jako chybové kódy nebo podporu SSL) je třeba implementovat vlastní proceduru - ale v podstatě stačí minimálně upravit uvedenou (odstranění komentářů atd). Snad jen dvě věci:
Podpora SSL a chybový stav
Pro podporu SSL je třeba přidat jednotky implementující SSL, nejčastěji jsou to knihovny OpenSSL a jednotky ssl_openssl, ssl_openssl_lib. Následně pak knihovně Synapse naznačit, že je třeba je použít.
Pro získání chybového stavu je třeba volat metodu EnhCodeString třídy TSMTPSend
Následující procedura otestuje připojení k SMTP serveru, kdy pokud SMTP server podporuje povýšení komunikace na šifrovanou je toto použito (SMTP.AutoTLS := true) a vrátí případnou chybu. Jedná se o upravenou SendToRaw, ale bez odesílání.
1function mbTestSmtp(const sSMTPHost, sUser, sPwd:string; iPort:Integer; var sProblem:string):Boolean;
2var
3 SMTP: TSMTPSend;
4begin
5 Result := False;
6 sProblem := '';
7 SMTP := TSMTPSend.Create;
8 try
9
10 SMTP.AutoTLS := True;
11
12
13 SMTP.TargetHost := sSMTPHost;
14 SMTP.TargetPort := IntToStr(iPort);
15 SMTP.Username := sUser;
16 SMTP.Password := sPwd;
17 if SMTP.Login then
18 begin
19 Result := True;
20 SMTP.Logout;
21 end
22 else
23 begin
24 sProblem := SMTP.EnhCodeString;
25 end;
26 finally
27 SMTP.Free;
28 end;
29end;
Ohledně podporu SSL: nejsem žádný odborník, ale v podstatě AutoTLS značí, že se Synapse pokusí převést nešifrovanou komunikaci na šifrovanou na stejném portu, kdežto FullSSL předpokládá šifrovanou komunikaci od začátku a používá dva porty.
Poznámky
Aplikace pro použití SSL musí mít k dispozici knihovny OpenSSL, ke stažení třeba zde. Konkrétně stačí ssleay32.dll a libeay32.dll. Pokud je budete mít v adresáři aplikace, vyhnete se spoustě problémů.
Jelikož je Synapse hodně oblíbená, často je i zneužívána. Proto některé antispam řešení pravděpodobně kontrolují výskyt řetězce synapse, takže zvažte, zda ho něčím nenahradíte.