lsmtp.pp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754
  1. { lNet SMTP unit
  2. CopyRight (C) 2005-2007 Ales Katona
  3. This library is Free software; you can rediStribute it and/or modify it
  4. under the terms of the GNU Library General Public License as published by
  5. the Free Software Foundation; either version 2 of the License, or (at your
  6. option) any later version.
  7. This program is diStributed in the hope that it will be useful, but WITHOUT
  8. ANY WARRANTY; withOut even the implied warranty of MERCHANTABILITY or
  9. FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License
  10. for more details.
  11. You should have received a Copy of the GNU Library General Public License
  12. along with This library; if not, Write to the Free Software Foundation,
  13. Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  14. This license has been modified. See File LICENSE.ADDON for more inFormation.
  15. Should you find these sources without a LICENSE File, please contact
  16. me at [email protected]
  17. }
  18. unit lsmtp;
  19. {$mode objfpc}{$H+}
  20. {$inline on}
  21. interface
  22. uses
  23. Classes, SysUtils, Contnrs, lNet, lEvents, lCommon, lMimeWrapper, lMimeStreams;
  24. type
  25. TLSMTP = class;
  26. TLSMTPClient = class;
  27. TLSMTPStatus = (ssNone, ssCon, ssHelo, ssEhlo, ssMail,
  28. ssRcpt, ssData, ssRset, ssQuit);
  29. TLSMTPStatusSet = set of TLSMTPStatus;
  30. TLSMTPStatusRec = record
  31. Status: TLSMTPStatus;
  32. Args: array[1..2] of string;
  33. end;
  34. { TLSMTPStatusFront }
  35. {$DEFINE __front_type__ := TLSMTPStatusRec}
  36. {$i lcontainersh.inc}
  37. TLSMTPStatusFront = TLFront;
  38. TLSMTPClientStatusEvent = procedure (aSocket: TLSocket;
  39. const aStatus: TLSMTPStatus) of object;
  40. { TMail }
  41. TMail = class
  42. protected
  43. FMailText: string;
  44. FMailStream: TMimeStream;
  45. FRecipients: string;
  46. FSender: string;
  47. FSubject: string;
  48. function GetCount: Integer;
  49. function GetSection(i: Integer): TMimeSection;
  50. procedure SetSection(i: Integer; const AValue: TMimeSection);
  51. public
  52. constructor Create;
  53. destructor Destroy; override;
  54. procedure AddTextSection(const aText: string; const aCharSet: string = 'UTF-8');
  55. procedure AddFileSection(const aFileName: string);
  56. procedure AddStreamSection(aStream: TStream; const FreeStream: Boolean = False);
  57. procedure DeleteSection(const i: Integer);
  58. procedure RemoveSection(aSection: TMimeSection);
  59. public
  60. property MailText: string read FMailText write FMailText; deprecated; // use sections!
  61. property Sender: string read FSender write FSender;
  62. property Recipients: string read FRecipients write FRecipients;
  63. property Subject: string read FSubject write FSubject;
  64. property Sections[i: Integer]: TMimeSection read GetSection write SetSection; default;
  65. property SectionCount: Integer read GetCount;
  66. end;
  67. TLSMTP = class(TLComponent)
  68. protected
  69. FConnection: TLTcp;
  70. protected
  71. function GetTimeout: Integer;
  72. procedure SetTimeout(const AValue: Integer);
  73. function GetConnected: Boolean;
  74. function GetSocketClass: TLSocketClass;
  75. procedure SetSocketClass(const AValue: TLSocketClass);
  76. function GetEventer: TLEventer;
  77. procedure SetEventer(Value: TLEventer);
  78. public
  79. constructor Create(aOwner: TComponent); override;
  80. destructor Destroy; override;
  81. public
  82. property Connected: Boolean read GetConnected;
  83. property Connection: TLTcp read FConnection;
  84. property SocketClass: TLSocketClass read GetSocketClass write SetSocketClass;
  85. property Eventer: TLEventer read GetEventer write SetEventer;
  86. property Timeout: Integer read GetTimeout write SetTimeout;
  87. end;
  88. { TLSMTPClient }
  89. TLSMTPClient = class(TLSMTP, ILClient)
  90. protected
  91. FStatus: TLSMTPStatusFront;
  92. FCommandFront: TLSMTPStatusFront;
  93. FPipeLine: Boolean;
  94. FOnConnect: TLSocketEvent;
  95. FOnReceive: TLSocketEvent;
  96. FOnDisconnect: TLSocketEvent;
  97. FOnSuccess: TLSMTPClientStatusEvent;
  98. FOnFailure: TLSMTPClientStatusEvent;
  99. FOnError: TLSocketErrorEvent;
  100. FOnSent: TLSocketProgressEvent;
  101. FSL: TStringList;
  102. FStatusSet: TLSMTPStatusSet;
  103. FBuffer: string;
  104. FDataBuffer: string; // intermediate wait buffer on DATA command
  105. FCharCount: Integer; // count of chars from last CRLF
  106. FStream: TStream;
  107. protected
  108. procedure OnEr(const msg: string; aSocket: TLSocket);
  109. procedure OnRe(aSocket: TLSocket);
  110. procedure OnCo(aSocket: TLSocket);
  111. procedure OnDs(aSocket: TLSocket);
  112. procedure OnCs(aSocket: TLSocket);
  113. protected
  114. function CanContinue(const aStatus: TLSMTPStatus; const Arg1, Arg2: string): Boolean;
  115. function CleanInput(var s: string): Integer;
  116. procedure EvaluateAnswer(const Ans: string);
  117. procedure ExecuteFrontCommand;
  118. procedure ClearCR_LF;
  119. procedure SendData(const FromStream: Boolean = False);
  120. public
  121. constructor Create(aOwner: TComponent); override;
  122. destructor Destroy; override;
  123. function Connect(const aHost: string; const aPort: Word = 25): Boolean; virtual; overload;
  124. function Connect: Boolean; virtual; overload;
  125. function Get(var aData; const aSize: Integer; aSocket: TLSocket = nil): Integer; virtual;
  126. function GetMessage(out msg: string; aSocket: TLSocket = nil): Integer; virtual;
  127. procedure SendMail(From, Recipients, Subject, Msg: string);
  128. procedure SendMail(From, Recipients, Subject: string; aStream: TStream);
  129. procedure SendMail(aMail: TMail);
  130. procedure Helo(aHost: string = '');
  131. procedure Ehlo(aHost: string = '');
  132. procedure Mail(const From: string);
  133. procedure Rcpt(const RcptTo: string);
  134. procedure Data(const Msg: string);
  135. procedure Rset;
  136. procedure Quit;
  137. procedure Disconnect; override;
  138. procedure CallAction; override;
  139. public
  140. property PipeLine: Boolean read FPipeLine write FPipeLine;
  141. property StatusSet: TLSMTPStatusSet read FStatusSet write FStatusSet;
  142. property OnConnect: TLSocketEvent read FOnConnect write FOnConnect;
  143. property OnReceive: TLSocketEvent read FOnReceive write FOnReceive;
  144. property OnDisconnect: TLSocketEvent read FOnDisconnect write FOnDisconnect;
  145. property OnSuccess: TLSMTPClientStatusEvent read FOnSuccess write FOnSuccess;
  146. property OnFailure: TLSMTPClientStatusEvent read FOnFailure write FOnFailure;
  147. property OnError: TLSocketErrorEvent read FOnError write FOnError;
  148. property OnSent: TLSocketProgressEvent read FOnSent write FOnSent;
  149. end;
  150. implementation
  151. const
  152. EMPTY_REC: TLSMTPStatusRec = (Status: ssNone; Args: ('', ''));
  153. {$i lcontainers.inc}
  154. function StatusToStr(const aStatus: TLSMTPStatus): string;
  155. const
  156. STATAR: array[ssNone..ssQuit] of string = ('ssNone', 'ssCon', 'ssHelo', 'ssEhlo', 'ssMail',
  157. 'ssRcpt', 'ssData', 'ssRset', 'ssQuit');
  158. begin
  159. Result := STATAR[aStatus];
  160. end;
  161. function MakeStatusRec(const aStatus: TLSMTPStatus; const Arg1, Arg2: string): TLSMTPStatusRec;
  162. begin
  163. Result.Status := aStatus;
  164. Result.Args[1] := Arg1;
  165. Result.Args[2] := Arg2;
  166. end;
  167. { TLSMTP }
  168. function TLSMTP.GetTimeout: Integer;
  169. begin
  170. Result := FConnection.Timeout;
  171. end;
  172. procedure TLSMTP.SetTimeout(const AValue: Integer);
  173. begin
  174. FConnection.Timeout := aValue;
  175. end;
  176. function TLSMTP.GetConnected: Boolean;
  177. begin
  178. Result := FConnection.Connected;
  179. end;
  180. function TLSMTP.GetSocketClass: TLSocketClass;
  181. begin
  182. Result := FConnection.SocketClass;
  183. end;
  184. procedure TLSMTP.SetSocketClass(const AValue: TLSocketClass);
  185. begin
  186. FConnection.SocketClass := AValue;
  187. end;
  188. function TLSMTP.GetEventer: TLEventer;
  189. begin
  190. Result := FConnection.Eventer;
  191. end;
  192. procedure TLSMTP.SetEventer(Value: TLEventer);
  193. begin
  194. FConnection.Eventer := Value;
  195. end;
  196. constructor TLSMTP.Create(aOwner: TComponent);
  197. begin
  198. inherited Create(aOwner);
  199. FConnection := TLTcp.Create(nil);
  200. end;
  201. destructor TLSMTP.Destroy;
  202. begin
  203. FConnection.Free;
  204. inherited Destroy;
  205. end;
  206. { TLSMTPClient }
  207. constructor TLSMTPClient.Create(aOwner: TComponent);
  208. begin
  209. inherited Create(aOwner);
  210. FPort := 25;
  211. FStatusSet := []; // empty set for "ok/not-ok" Event
  212. FSL := TStringList.Create;
  213. // {$warning TODO: fix pipelining support when server does it}
  214. FPipeLine := False;
  215. FConnection.OnError := @OnEr;
  216. FConnection.OnCanSend := @OnCs;
  217. FConnection.OnReceive := @OnRe;
  218. FConnection.OnConnect := @OnCo;
  219. FConnection.OnDisconnect := @OnDs;
  220. FStatus := TLSMTPStatusFront.Create(EMPTY_REC);
  221. FCommandFront := TLSMTPStatusFront.Create(EMPTY_REC);
  222. end;
  223. destructor TLSMTPClient.Destroy;
  224. begin
  225. Quit;
  226. FSL.Free;
  227. FStatus.Free;
  228. FCommandFront.Free;
  229. inherited Destroy;
  230. end;
  231. procedure TLSMTPClient.OnEr(const msg: string; aSocket: TLSocket);
  232. begin
  233. if Assigned(FOnError) then
  234. FOnError(msg, aSocket);
  235. end;
  236. procedure TLSMTPClient.OnRe(aSocket: TLSocket);
  237. begin
  238. if Assigned(FOnReceive) then
  239. FOnReceive(aSocket);
  240. end;
  241. procedure TLSMTPClient.OnCo(aSocket: TLSocket);
  242. begin
  243. if Assigned(FOnConnect) then
  244. FOnConnect(aSocket);
  245. end;
  246. procedure TLSMTPClient.OnDs(aSocket: TLSocket);
  247. begin
  248. if Assigned(FOnDisconnect) then
  249. FOnDisconnect(aSocket);
  250. end;
  251. procedure TLSMTPClient.OnCs(aSocket: TLSocket);
  252. begin
  253. SendData(FStatus.First.Status = ssData);
  254. end;
  255. function TLSMTPClient.CanContinue(const aStatus: TLSMTPStatus; const Arg1, Arg2: string): Boolean;
  256. begin
  257. Result := FPipeLine or FStatus.Empty;
  258. if not Result then
  259. FCommandFront.Insert(MakeStatusRec(aStatus, Arg1, Arg2));
  260. end;
  261. function TLSMTPClient.CleanInput(var s: string): Integer;
  262. var
  263. i: Integer;
  264. begin
  265. FSL.Text := s;
  266. if FSL.Count > 0 then
  267. for i := 0 to FSL.Count-1 do
  268. if Length(FSL[i]) > 0 then EvaluateAnswer(FSL[i]);
  269. s := StringReplace(s, CRLF, LineEnding, [rfReplaceAll]);
  270. i := Pos('PASS', s);
  271. if i > 0 then
  272. s := Copy(s, 1, i-1) + 'PASS';
  273. Result := Length(s);
  274. end;
  275. procedure TLSMTPClient.EvaluateAnswer(const Ans: string);
  276. function GetNum: Integer;
  277. begin
  278. try
  279. Result := StrToInt(Copy(Ans, 1, 3));
  280. except
  281. Result := -1;
  282. end;
  283. end;
  284. function ValidResponse(const Answer: string): Boolean; inline;
  285. begin
  286. Result := (Length(Ans) >= 3) and
  287. (Ans[1] in ['1'..'5']) and
  288. (Ans[2] in ['0'..'9']) and
  289. (Ans[3] in ['0'..'9']);
  290. if Result then
  291. Result := (Length(Ans) = 3) or ((Length(Ans) > 3) and (Ans[4] = ' '));
  292. end;
  293. procedure Eventize(const aStatus: TLSMTPStatus; const Res: Boolean);
  294. begin
  295. if Res then begin
  296. if Assigned(FOnSuccess) and (aStatus in FStatusSet) then
  297. FOnSuccess(FConnection.Iterator, aStatus);
  298. end else begin
  299. if Assigned(FOnFailure) and (aStatus in FStatusSet) then
  300. FOnFailure(FConnection.Iterator, aStatus);
  301. end;
  302. end;
  303. var
  304. x: Integer;
  305. begin
  306. x := GetNum;
  307. if ValidResponse(Ans) and not FStatus.Empty then
  308. case FStatus.First.Status of
  309. ssCon,
  310. ssHelo,
  311. ssEhlo: case x of
  312. 200..299: begin
  313. Eventize(FStatus.First.Status, True);
  314. FStatus.Remove;
  315. end;
  316. else begin
  317. Eventize(FStatus.First.Status, False);
  318. Disconnect;
  319. end;
  320. end;
  321. ssMail,
  322. ssRcpt: begin
  323. Eventize(FStatus.First.Status, (x >= 200) and (x < 299));
  324. FStatus.Remove;
  325. end;
  326. ssData: case x of
  327. 200..299: begin
  328. Eventize(FStatus.First.Status, True);
  329. FStatus.Remove;
  330. end;
  331. 300..399: begin
  332. FBuffer := FDataBuffer;
  333. FDataBuffer := '';
  334. SendData(True);
  335. end;
  336. else begin
  337. FDataBuffer := '';
  338. Eventize(FStatus.First.Status, False);
  339. FStatus.Remove;
  340. end;
  341. end;
  342. ssRset: begin
  343. Eventize(FStatus.First.Status, (x >= 200) and (x < 299));
  344. FStatus.Remove;
  345. end;
  346. ssQuit: begin
  347. Eventize(FStatus.First.Status, (x >= 200) and (x < 299));
  348. FStatus.Remove;
  349. if Assigned(FOnDisconnect) then
  350. FOnDisconnect(FConnection.Iterator);
  351. Disconnect;
  352. end;
  353. end;
  354. if FStatus.Empty and not FCommandFront.Empty then
  355. ExecuteFrontCommand;
  356. end;
  357. procedure TLSMTPClient.ExecuteFrontCommand;
  358. begin
  359. with FCommandFront.First do
  360. case Status of
  361. ssHelo: Helo(Args[1]);
  362. ssEhlo: Ehlo(Args[1]);
  363. ssMail: Mail(Args[1]);
  364. ssRcpt: Rcpt(Args[1]);
  365. ssData: Data(Args[1]);
  366. ssRset: Rset;
  367. ssQuit: Quit;
  368. end;
  369. FCommandFront.Remove;
  370. end;
  371. procedure TLSMTPClient.ClearCR_LF;
  372. var
  373. i: Integer;
  374. Skip: Boolean = False;
  375. begin
  376. for i := 1 to Length(FBuffer) do begin
  377. if Skip then begin
  378. Skip := False;
  379. Continue;
  380. end;
  381. if (FBuffer[i] = #13) or (FBuffer[i] = #10) then begin
  382. if FBuffer[i] = #13 then
  383. if (i < Length(FBuffer)) and (FBuffer[i + 1] = #10) then begin
  384. FCharCount := 0;
  385. Skip := True; // skip the crlf
  386. end else begin // insert LF to a standalone CR
  387. System.Insert(#10, FBuffer, i + 1);
  388. FCharCount := 0;
  389. Skip := True; // skip the new crlf
  390. end;
  391. if FBuffer[i] = #10 then begin
  392. System.Insert(#13, FBuffer, i);
  393. FCharCount := 0;
  394. Skip := True; // skip the new crlf
  395. end;
  396. end else if FCharCount >= 1000 then begin // line too long
  397. System.Insert(CRLF, FBuffer, i);
  398. FCharCount := 0;
  399. Skip := True;
  400. end else
  401. Inc(FCharCount);
  402. end;
  403. end;
  404. procedure TLSMTPClient.SendData(const FromStream: Boolean = False);
  405. const
  406. SBUF_SIZE = 65535;
  407. procedure FillBuffer;
  408. var
  409. s: string;
  410. begin
  411. SetLength(s, SBUF_SIZE - Length(FBuffer));
  412. SetLength(s, FStream.Read(s[1], Length(s)));
  413. FBuffer := FBuffer + s;
  414. if FStream.Position = FStream.Size then begin // we finished the stream
  415. FBuffer := FBuffer + CRLF + '.' + CRLF;
  416. FStream := nil;
  417. end;
  418. end;
  419. var
  420. n: Integer;
  421. Sent: Integer;
  422. begin
  423. if FromStream and Assigned(FStream) then
  424. FillBuffer;
  425. n := 1;
  426. Sent := 0;
  427. while (Length(FBuffer) > 0) and (n > 0) do begin
  428. ClearCR_LF;
  429. n := FConnection.SendMessage(FBuffer);
  430. Sent := Sent + n;
  431. if n > 0 then
  432. Delete(FBuffer, 1, n);
  433. if FromStream and Assigned(FStream) and (Length(FBuffer) < SBUF_SIZE) then
  434. FillBuffer;
  435. end;
  436. if Assigned(FOnSent) and (FStatus.First.Status = ssData) then
  437. FOnSent(FConnection.Iterator, Sent);
  438. end;
  439. function TLSMTPClient.Connect(const aHost: string; const aPort: Word = 25): Boolean;
  440. begin
  441. Result := False;
  442. Disconnect;
  443. if FConnection.Connect(aHost, aPort) then begin
  444. FHost := aHost;
  445. FPort := aPort;
  446. FStatus.Insert(MakeStatusRec(ssCon, '', ''));
  447. Result := True;
  448. end;
  449. end;
  450. function TLSMTPClient.Connect: Boolean;
  451. begin
  452. Result := Connect(FHost, FPort);
  453. end;
  454. function TLSMTPClient.Get(var aData; const aSize: Integer; aSocket: TLSocket): Integer;
  455. var
  456. s: string;
  457. begin
  458. Result := FConnection.Get(aData, aSize, aSocket);
  459. if Result > 0 then begin
  460. SetLength(s, Result);
  461. Move(aData, PChar(s)^, Result);
  462. CleanInput(s);
  463. end;
  464. end;
  465. function TLSMTPClient.GetMessage(out msg: string; aSocket: TLSocket): Integer;
  466. begin
  467. Result := FConnection.GetMessage(msg, aSocket);
  468. if Result > 0 then
  469. Result := CleanInput(msg);
  470. end;
  471. procedure TLSMTPClient.SendMail(From, Recipients, Subject, Msg: string);
  472. var
  473. i: Integer;
  474. begin
  475. FStream := nil;
  476. From := EncodeMimeHeaderText(From);
  477. Recipients := EncodeMimeHeaderText(Recipients);
  478. Subject := EncodeMimeHeaderText(Subject);
  479. if (Length(Recipients) > 0) and (Length(From) > 0) then begin
  480. Mail(From);
  481. FSL.CommaText := StringReplace(Recipients, ' ', ',', [rfReplaceAll]);
  482. for i := 0 to FSL.Count-1 do
  483. Rcpt(FSL[i]);
  484. Data('From: ' + From + CRLF + 'Subject: ' + Subject + CRLF + 'To: ' + FSL.CommaText + CRLF + Msg);
  485. Rset;
  486. end;
  487. end;
  488. procedure TLSMTPClient.SendMail(From, Recipients, Subject: string; aStream: TStream);
  489. var
  490. i: Integer;
  491. begin
  492. From := EncodeMimeHeaderText(From);
  493. Recipients := EncodeMimeHeaderText(Recipients);
  494. Subject := EncodeMimeHeaderText(Subject);
  495. FStream := aStream;
  496. if (Length(Recipients) > 0) and (Length(From) > 0) then begin
  497. Mail(From);
  498. FSL.CommaText := StringReplace(Recipients, ' ', ',', [rfReplaceAll]);
  499. for i := 0 to FSL.Count-1 do
  500. Rcpt(FSL[i]);
  501. Data('From: ' + From + CRLF + 'Subject: ' + Subject + CRLF + 'To: ' + FSL.CommaText + CRLF);
  502. Rset;
  503. end;
  504. end;
  505. procedure TLSMTPClient.SendMail(aMail: TMail);
  506. begin
  507. if Length(aMail.FMailText) > 0 then
  508. SendMail(aMail.Sender, aMail.Recipients, aMail.Subject, aMail.FMailText)
  509. else if Assigned(aMail.FMailStream) then
  510. SendMail(aMail.Sender, aMail.Recipients, aMail.Subject, aMail.FMailStream);
  511. end;
  512. procedure TLSMTPClient.Helo(aHost: string = '');
  513. begin
  514. if Length(Host) = 0 then
  515. aHost := FHost;
  516. if CanContinue(ssHelo, aHost, '') then begin
  517. FBuffer := FBuffer + 'HELO ' + aHost + CRLF;
  518. FStatus.Insert(MakeStatusRec(ssHelo, '', ''));
  519. SendData;
  520. end;
  521. end;
  522. procedure TLSMTPClient.Ehlo(aHost: string = '');
  523. begin
  524. if Length(aHost) = 0 then
  525. aHost := FHost;
  526. if CanContinue(ssEhlo, aHost, '') then begin
  527. FBuffer := FBuffer + 'EHLO ' + aHost + CRLF;
  528. FStatus.Insert(MakeStatusRec(ssEhlo, '', ''));
  529. SendData;
  530. end;
  531. end;
  532. procedure TLSMTPClient.Mail(const From: string);
  533. begin
  534. if CanContinue(ssMail, From, '') then begin
  535. FBuffer := FBuffer + 'MAIL FROM:' + '<' + From + '>' + CRLF;
  536. FStatus.Insert(MakeStatusRec(ssMail, '', ''));
  537. SendData;
  538. end;
  539. end;
  540. procedure TLSMTPClient.Rcpt(const RcptTo: string);
  541. begin
  542. if CanContinue(ssRcpt, RcptTo, '') then begin
  543. FBuffer := FBuffer + 'RCPT TO:' + '<' + RcptTo + '>' + CRLF;
  544. FStatus.Insert(MakeStatusRec(ssRcpt, '', ''));
  545. SendData;
  546. end;
  547. end;
  548. procedure TLSMTPClient.Data(const Msg: string);
  549. begin
  550. if CanContinue(ssData, Msg, '') then begin
  551. FBuffer := 'DATA ' + CRLF;
  552. FDataBuffer := '';
  553. if Assigned(FStream) then begin
  554. if Length(Msg) > 0 then
  555. FDataBuffer := Msg;
  556. end else
  557. FDataBuffer := Msg + CRLF + '.' + CRLF;
  558. FStatus.Insert(MakeStatusRec(ssData, '', ''));
  559. SendData(False);
  560. end;
  561. end;
  562. procedure TLSMTPClient.Rset;
  563. begin
  564. if CanContinue(ssRset, '', '') then begin
  565. FBuffer := FBuffer + 'RSET' + CRLF;
  566. FStatus.Insert(MakeStatusRec(ssRset, '', ''));
  567. SendData;
  568. end;
  569. end;
  570. procedure TLSMTPClient.Quit;
  571. begin
  572. if CanContinue(ssQuit, '', '') then begin
  573. FBuffer := FBuffer + 'QUIT' + CRLF;
  574. FStatus.Insert(MakeStatusRec(ssQuit, '', ''));
  575. SendData;
  576. end;
  577. end;
  578. procedure TLSMTPClient.Disconnect;
  579. begin
  580. FConnection.Disconnect;
  581. FStatus.Clear;
  582. FCommandFront.Clear;
  583. end;
  584. procedure TLSMTPClient.CallAction;
  585. begin
  586. FConnection.CallAction;
  587. end;
  588. { TMail }
  589. function TMail.GetCount: Integer;
  590. begin
  591. Result := FMailStream.Count;
  592. end;
  593. function TMail.GetSection(i: Integer): TMimeSection;
  594. begin
  595. Result := FMailStream.Sections[i];
  596. end;
  597. procedure TMail.SetSection(i: Integer; const AValue: TMimeSection);
  598. begin
  599. FMailStream.Sections[i] := aValue;
  600. end;
  601. constructor TMail.Create;
  602. begin
  603. FMailStream := TMimeStream.Create;
  604. end;
  605. destructor TMail.Destroy;
  606. begin
  607. FMailStream.Free;
  608. end;
  609. procedure TMail.AddTextSection(const aText: string; const aCharSet: string);
  610. begin
  611. FMailStream.AddTextSection(aText, aCharSet);
  612. end;
  613. procedure TMail.AddFileSection(const aFileName: string);
  614. begin
  615. FMailStream.AddFileSection(aFileName);
  616. end;
  617. procedure TMail.AddStreamSection(aStream: TStream; const FreeStream: Boolean);
  618. begin
  619. FMailStream.AddStreamSection(aStream, FreeStream);
  620. end;
  621. procedure TMail.DeleteSection(const i: Integer);
  622. begin
  623. FMailStream.Delete(i);
  624. end;
  625. procedure TMail.RemoveSection(aSection: TMimeSection);
  626. begin
  627. FMailStream.Remove(aSection);
  628. end;
  629. end.