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.
uses
smtpsend, mimepart, mimemess;
procedure TForm1.btn1Click(Sender: TObject);
var
oMessage : TMimeMess;
p, oMultiPartAlt: TMimePart;
begin
oMessage := TMimeMess.Create;
with oMessage do
try
Header.From := 'radek.cervinka@technodat.cz';
Header.ToList.Clear;
Header.ToList.Add('radekc@delphi.cz');
Header.CcList.Clear;
Header.Subject := 'Novy mail';
//%
p := AddPartMultipart('mixed', nil);
oMultiPartAlt := AddPartMultipart('alternative', p);
AddPartText(mem1.Lines, oMultiPartAlt);
AddPartBinaryFromFile('c:\test.pdf', p);
AddPartHTML(mem2.Lines, oMultiPartAlt);
//%
Header.XMailer := 'Muj program';
Header.Date := Now;
EncodeMessage;
if SendToRaw(Header.From, Header.ToList.CommaText, 'smtp.server.net', Lines, 'user', 'heslo') then
ShowMessage('Mail byl úspěšně odeslán!')
else
ShowMessage('Mail se nepodařilo odeslat.');
finally
Free;
end;
end;
v případě zprávy bez alternate bude část mezi % následující:
p := AddPartMultipart('mixed', nil);
AddPartText(mem1.Lines, p);
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:
AddPartText(mem1.Lines, nil); // text
//nebo
AddPartHTML(mem2.Lines, nil); // html
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í.
function mbTestSmtp(const sSMTPHost, sUser, sPwd:string; iPort:Integer; var sProblem:string):Boolean;
var
SMTP: TSMTPSend;
begin
Result := False;
sProblem := '';
SMTP := TSMTPSend.Create;
try
// if you need support for upgrade session to TSL/SSL, uncomment next lines:
SMTP.AutoTLS := True;
// if you need support for TSL/SSL tunnel, uncomment next lines:
// SMTP.FullSSL := True;
SMTP.TargetHost := sSMTPHost;
SMTP.TargetPort := IntToStr(iPort);
SMTP.Username := sUser;
SMTP.Password := sPwd;
if SMTP.Login then
begin
Result := True;
SMTP.Logout;
end
else
begin
sProblem := SMTP.EnhCodeString;
end;
finally
SMTP.Free;
end;
end;
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.