source: trunk/Packages/synapse/source/lib/smtpsend.pas

Last change on this file was 2, checked in by chronos, 12 years ago
  • Přidáno: Základní kostra projektu.
  • Přidáno: Knihovna synapse.
File size: 24.6 KB
Line 
1{==============================================================================|
2| Project : Ararat Synapse | 003.005.001 |
3|==============================================================================|
4| Content: SMTP client |
5|==============================================================================|
6| Copyright (c)1999-2010, Lukas Gebauer |
7| All rights reserved. |
8| |
9| Redistribution and use in source and binary forms, with or without |
10| modification, are permitted provided that the following conditions are met: |
11| |
12| Redistributions of source code must retain the above copyright notice, this |
13| list of conditions and the following disclaimer. |
14| |
15| Redistributions in binary form must reproduce the above copyright notice, |
16| this list of conditions and the following disclaimer in the documentation |
17| and/or other materials provided with the distribution. |
18| |
19| Neither the name of Lukas Gebauer nor the names of its contributors may |
20| be used to endorse or promote products derived from this software without |
21| specific prior written permission. |
22| |
23| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
24| AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
25| IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
26| ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR |
27| ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
28| DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
29| SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
30| CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
31| LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
32| OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
33| DAMAGE. |
34|==============================================================================|
35| The Initial Developer of the Original Code is Lukas Gebauer (Czech Republic).|
36| Portions created by Lukas Gebauer are Copyright (c) 1999-2010. |
37| All Rights Reserved. |
38|==============================================================================|
39| Contributor(s): |
40|==============================================================================|
41| History: see HISTORY.HTM from distribution package |
42| (Found at URL: http://www.ararat.cz/synapse/) |
43|==============================================================================}
44
45{:@abstract(SMTP client)
46
47Used RFC: RFC-1869, RFC-1870, RFC-1893, RFC-2034, RFC-2104, RFC-2195, RFC-2487,
48 RFC-2554, RFC-2821
49}
50
51{$IFDEF FPC}
52 {$MODE DELPHI}
53{$ENDIF}
54{$H+}
55
56{$IFDEF UNICODE}
57 {$WARN IMPLICIT_STRING_CAST OFF}
58 {$WARN IMPLICIT_STRING_CAST_LOSS OFF}
59{$ENDIF}
60
61unit smtpsend;
62
63interface
64
65uses
66 SysUtils, Classes,
67 blcksock, synautil, synacode;
68
69const
70 cSmtpProtocol = '25';
71
72type
73 {:@abstract(Implementation of SMTP and ESMTP procotol),
74 include some ESMTP extensions, include SSL/TLS too.
75
76 Note: Are you missing properties for setting Username and Password for ESMTP?
77 Look to parent @link(TSynaClient) object!
78
79 Are you missing properties for specify server address and port? Look to
80 parent @link(TSynaClient) too!}
81 TSMTPSend = class(TSynaClient)
82 private
83 FSock: TTCPBlockSocket;
84 FResultCode: Integer;
85 FResultString: string;
86 FFullResult: TStringList;
87 FESMTPcap: TStringList;
88 FESMTP: Boolean;
89 FAuthDone: Boolean;
90 FESMTPSize: Boolean;
91 FMaxSize: Integer;
92 FEnhCode1: Integer;
93 FEnhCode2: Integer;
94 FEnhCode3: Integer;
95 FSystemName: string;
96 FAutoTLS: Boolean;
97 FFullSSL: Boolean;
98 procedure EnhancedCode(const Value: string);
99 function ReadResult: Integer;
100 function AuthLogin: Boolean;
101 function AuthCram: Boolean;
102 function AuthPlain: Boolean;
103 function Helo: Boolean;
104 function Ehlo: Boolean;
105 function Connect: Boolean;
106 public
107 constructor Create;
108 destructor Destroy; override;
109
110 {:Connects to SMTP server (defined in @link(TSynaClient.TargetHost)) and
111 begin SMTP session. (First try ESMTP EHLO, next old HELO handshake). Parses
112 ESMTP capabilites and if you specified Username and password and remote
113 server can handle AUTH command, try login by AUTH command. Preffered login
114 method is CRAM-MD5 (if safer!). If all OK, result is @true, else result is
115 @false.}
116 function Login: Boolean;
117
118 {:Close SMTP session (QUIT command) and disconnect from SMTP server.}
119 function Logout: Boolean;
120
121 {:Send RSET SMTP command for reset SMTP session. If all OK, result is @true,
122 else result is @false.}
123 function Reset: Boolean;
124
125 {:Send NOOP SMTP command for keep SMTP session. If all OK, result is @true,
126 else result is @false.}
127 function NoOp: Boolean;
128
129 {:Send MAIL FROM SMTP command for set sender e-mail address. If sender's
130 e-mail address is empty string, transmited message is error message.
131
132 If size not 0 and remote server can handle SIZE parameter, append SIZE
133 parameter to request. If all OK, result is @true, else result is @false.}
134 function MailFrom(const Value: string; Size: Integer): Boolean;
135
136 {:Send RCPT TO SMTP command for set receiver e-mail address. It cannot be an
137 empty string. If all OK, result is @true, else result is @false.}
138 function MailTo(const Value: string): Boolean;
139
140 {:Send DATA SMTP command and transmit message data. If all OK, result is
141 @true, else result is @false.}
142 function MailData(const Value: Tstrings): Boolean;
143
144 {:Send ETRN SMTP command for start sending of remote queue for domain in
145 Value. If all OK, result is @true, else result is @false.}
146 function Etrn(const Value: string): Boolean;
147
148 {:Send VRFY SMTP command for check receiver e-mail address. It cannot be
149 an empty string. If all OK, result is @true, else result is @false.}
150 function Verify(const Value: string): Boolean;
151
152 {:Call STARTTLS command for upgrade connection to SSL/TLS mode.}
153 function StartTLS: Boolean;
154
155 {:Return string descriptive text for enhanced result codes stored in
156 @link(EnhCode1), @link(EnhCode2) and @link(EnhCode3).}
157 function EnhCodeString: string;
158
159 {:Try to find specified capability in ESMTP response.}
160 function FindCap(const Value: string): string;
161 published
162 {:result code of last SMTP command.}
163 property ResultCode: Integer read FResultCode;
164
165 {:result string of last SMTP command (begin with string representation of
166 result code).}
167 property ResultString: string read FResultString;
168
169 {:All result strings of last SMTP command (result is maybe multiline!).}
170 property FullResult: TStringList read FFullResult;
171
172 {:List of ESMTP capabilites of remote ESMTP server. (If you connect to ESMTP
173 server only!).}
174 property ESMTPcap: TStringList read FESMTPcap;
175
176 {:@TRUE if you successfuly logged to ESMTP server.}
177 property ESMTP: Boolean read FESMTP;
178
179 {:@TRUE if you successfuly pass authorisation to remote server.}
180 property AuthDone: Boolean read FAuthDone;
181
182 {:@TRUE if remote server can handle SIZE parameter.}
183 property ESMTPSize: Boolean read FESMTPSize;
184
185 {:When @link(ESMTPsize) is @TRUE, contains max length of message that remote
186 server can handle.}
187 property MaxSize: Integer read FMaxSize;
188
189 {:First digit of Enhanced result code. If last operation does not have
190 enhanced result code, values is 0.}
191 property EnhCode1: Integer read FEnhCode1;
192
193 {:Second digit of Enhanced result code. If last operation does not have
194 enhanced result code, values is 0.}
195 property EnhCode2: Integer read FEnhCode2;
196
197 {:Third digit of Enhanced result code. If last operation does not have
198 enhanced result code, values is 0.}
199 property EnhCode3: Integer read FEnhCode3;
200
201 {:name of our system used in HELO and EHLO command. Implicit value is
202 internet address of your machine.}
203 property SystemName: string read FSystemName Write FSystemName;
204
205 {:If is set to true, then upgrade to SSL/TLS mode if remote server support it.}
206 property AutoTLS: Boolean read FAutoTLS Write FAutoTLS;
207
208 {:SSL/TLS mode is used from first contact to server. Servers with full
209 SSL/TLS mode usualy using non-standard TCP port!}
210 property FullSSL: Boolean read FFullSSL Write FFullSSL;
211
212 {:Socket object used for TCP/IP operation. Good for seting OnStatus hook, etc.}
213 property Sock: TTCPBlockSocket read FSock;
214 end;
215
216{:A very useful function and example of its use would be found in the TSMTPsend
217 object. Send maildata (text of e-mail with all SMTP headers! For example when
218 text of message is created by @link(TMimemess) object) from "MailFrom" e-mail
219 address to "MailTo" e-mail address (If you need more then one receiver, then
220 separate their addresses by comma).
221
222 Function sends e-mail to a SMTP server defined in "SMTPhost" parameter.
223 Username and password are used for authorization to the "SMTPhost". If you
224 don't want authorization, set "Username" and "Password" to empty strings. If
225 e-mail message is successfully sent, the result returns @true.
226
227 If you need use different port number then standard, then add this port number
228 to SMTPhost after colon. (i.e. '127.0.0.1:1025')}
229function SendToRaw(const MailFrom, MailTo, SMTPHost: string;
230 const MailData: TStrings; const Username, Password: string): Boolean;
231
232{:A very useful function and example of its use would be found in the TSMTPsend
233 object. Send "Maildata" (text of e-mail without any SMTP headers!) from
234 "MailFrom" e-mail address to "MailTo" e-mail address with "Subject". (If you
235 need more then one receiver, then separate their addresses by comma).
236
237 This function constructs all needed SMTP headers (with DATE header) and sends
238 the e-mail to the SMTP server defined in the "SMTPhost" parameter. If the
239 e-mail message is successfully sent, the result will be @TRUE.
240
241 If you need use different port number then standard, then add this port number
242 to SMTPhost after colon. (i.e. '127.0.0.1:1025')}
243function SendTo(const MailFrom, MailTo, Subject, SMTPHost: string;
244 const MailData: TStrings): Boolean;
245
246{:A very useful function and example of its use would be found in the TSMTPsend
247 object. Sends "MailData" (text of e-mail without any SMTP headers!) from
248 "MailFrom" e-mail address to "MailTo" e-mail address (If you need more then one
249 receiver, then separate their addresses by comma).
250
251 This function sends the e-mail to the SMTP server defined in the "SMTPhost"
252 parameter. Username and password are used for authorization to the "SMTPhost".
253 If you dont want authorization, set "Username" and "Password" to empty Strings.
254 If the e-mail message is successfully sent, the result will be @TRUE.
255
256 If you need use different port number then standard, then add this port number
257 to SMTPhost after colon. (i.e. '127.0.0.1:1025')}
258function SendToEx(const MailFrom, MailTo, Subject, SMTPHost: string;
259 const MailData: TStrings; const Username, Password: string): Boolean;
260
261implementation
262
263constructor TSMTPSend.Create;
264begin
265 inherited Create;
266 FFullResult := TStringList.Create;
267 FESMTPcap := TStringList.Create;
268 FSock := TTCPBlockSocket.Create;
269 FSock.Owner := self;
270 FSock.ConvertLineEnd := true;
271 FTimeout := 60000;
272 FTargetPort := cSmtpProtocol;
273 FSystemName := FSock.LocalName;
274 FAutoTLS := False;
275 FFullSSL := False;
276end;
277
278destructor TSMTPSend.Destroy;
279begin
280 FSock.Free;
281 FESMTPcap.Free;
282 FFullResult.Free;
283 inherited Destroy;
284end;
285
286procedure TSMTPSend.EnhancedCode(const Value: string);
287var
288 s, t: string;
289 e1, e2, e3: Integer;
290begin
291 FEnhCode1 := 0;
292 FEnhCode2 := 0;
293 FEnhCode3 := 0;
294 s := Copy(Value, 5, Length(Value) - 4);
295 t := Trim(SeparateLeft(s, '.'));
296 s := Trim(SeparateRight(s, '.'));
297 if t = '' then
298 Exit;
299 if Length(t) > 1 then
300 Exit;
301 e1 := StrToIntDef(t, 0);
302 if e1 = 0 then
303 Exit;
304 t := Trim(SeparateLeft(s, '.'));
305 s := Trim(SeparateRight(s, '.'));
306 if t = '' then
307 Exit;
308 if Length(t) > 3 then
309 Exit;
310 e2 := StrToIntDef(t, 0);
311 t := Trim(SeparateLeft(s, ' '));
312 if t = '' then
313 Exit;
314 if Length(t) > 3 then
315 Exit;
316 e3 := StrToIntDef(t, 0);
317 FEnhCode1 := e1;
318 FEnhCode2 := e2;
319 FEnhCode3 := e3;
320end;
321
322function TSMTPSend.ReadResult: Integer;
323var
324 s: String;
325begin
326 Result := 0;
327 FFullResult.Clear;
328 repeat
329 s := FSock.RecvString(FTimeout);
330 FResultString := s;
331 FFullResult.Add(s);
332 if FSock.LastError <> 0 then
333 Break;
334 until Pos('-', s) <> 4;
335 s := FFullResult[0];
336 if Length(s) >= 3 then
337 Result := StrToIntDef(Copy(s, 1, 3), 0);
338 FResultCode := Result;
339 EnhancedCode(s);
340end;
341
342function TSMTPSend.AuthLogin: Boolean;
343begin
344 Result := False;
345 FSock.SendString('AUTH LOGIN' + CRLF);
346 if ReadResult <> 334 then
347 Exit;
348 FSock.SendString(EncodeBase64(FUsername) + CRLF);
349 if ReadResult <> 334 then
350 Exit;
351 FSock.SendString(EncodeBase64(FPassword) + CRLF);
352 Result := ReadResult = 235;
353end;
354
355function TSMTPSend.AuthCram: Boolean;
356var
357 s: ansistring;
358begin
359 Result := False;
360 FSock.SendString('AUTH CRAM-MD5' + CRLF);
361 if ReadResult <> 334 then
362 Exit;
363 s := Copy(FResultString, 5, Length(FResultString) - 4);
364 s := DecodeBase64(s);
365 s := HMAC_MD5(s, FPassword);
366 s := FUsername + ' ' + StrToHex(s);
367 FSock.SendString(EncodeBase64(s) + CRLF);
368 Result := ReadResult = 235;
369end;
370
371function TSMTPSend.AuthPlain: Boolean;
372var
373 s: ansistring;
374begin
375 s := ansichar(0) + FUsername + ansichar(0) + FPassword;
376 FSock.SendString('AUTH PLAIN ' + EncodeBase64(s) + CRLF);
377 Result := ReadResult = 235;
378end;
379
380function TSMTPSend.Connect: Boolean;
381begin
382 FSock.CloseSocket;
383 FSock.Bind(FIPInterface, cAnyPort);
384 if FSock.LastError = 0 then
385 FSock.Connect(FTargetHost, FTargetPort);
386 if FSock.LastError = 0 then
387 if FFullSSL then
388 FSock.SSLDoConnect;
389 Result := FSock.LastError = 0;
390end;
391
392function TSMTPSend.Helo: Boolean;
393var
394 x: Integer;
395begin
396 FSock.SendString('HELO ' + FSystemName + CRLF);
397 x := ReadResult;
398 Result := (x >= 250) and (x <= 259);
399end;
400
401function TSMTPSend.Ehlo: Boolean;
402var
403 x: Integer;
404begin
405 FSock.SendString('EHLO ' + FSystemName + CRLF);
406 x := ReadResult;
407 Result := (x >= 250) and (x <= 259);
408end;
409
410function TSMTPSend.Login: Boolean;
411var
412 n: Integer;
413 auths: string;
414 s: string;
415begin
416 Result := False;
417 FESMTP := True;
418 FAuthDone := False;
419 FESMTPcap.clear;
420 FESMTPSize := False;
421 FMaxSize := 0;
422 if not Connect then
423 Exit;
424 if ReadResult <> 220 then
425 Exit;
426 if not Ehlo then
427 begin
428 FESMTP := False;
429 if not Helo then
430 Exit;
431 end;
432 Result := True;
433 if FESMTP then
434 begin
435 for n := 1 to FFullResult.Count - 1 do
436 FESMTPcap.Add(Copy(FFullResult[n], 5, Length(FFullResult[n]) - 4));
437 if (not FullSSL) and FAutoTLS and (FindCap('STARTTLS') <> '') then
438 if StartTLS then
439 begin
440 Ehlo;
441 FESMTPcap.Clear;
442 for n := 1 to FFullResult.Count - 1 do
443 FESMTPcap.Add(Copy(FFullResult[n], 5, Length(FFullResult[n]) - 4));
444 end
445 else
446 begin
447 Result := False;
448 Exit;
449 end;
450 if not ((FUsername = '') and (FPassword = '')) then
451 begin
452 s := FindCap('AUTH ');
453 if s = '' then
454 s := FindCap('AUTH=');
455 auths := UpperCase(s);
456 if s <> '' then
457 begin
458 if Pos('CRAM-MD5', auths) > 0 then
459 FAuthDone := AuthCram;
460 if (not FauthDone) and (Pos('PLAIN', auths) > 0) then
461 FAuthDone := AuthPlain;
462 if (not FauthDone) and (Pos('LOGIN', auths) > 0) then
463 FAuthDone := AuthLogin;
464 end;
465 end;
466 s := FindCap('SIZE');
467 if s <> '' then
468 begin
469 FESMTPsize := True;
470 FMaxSize := StrToIntDef(Copy(s, 6, Length(s) - 5), 0);
471 end;
472 end;
473end;
474
475function TSMTPSend.Logout: Boolean;
476begin
477 FSock.SendString('QUIT' + CRLF);
478 Result := ReadResult = 221;
479 FSock.CloseSocket;
480end;
481
482function TSMTPSend.Reset: Boolean;
483begin
484 FSock.SendString('RSET' + CRLF);
485 Result := ReadResult div 100 = 2;
486end;
487
488function TSMTPSend.NoOp: Boolean;
489begin
490 FSock.SendString('NOOP' + CRLF);
491 Result := ReadResult div 100 = 2;
492end;
493
494function TSMTPSend.MailFrom(const Value: string; Size: Integer): Boolean;
495var
496 s: string;
497begin
498 s := 'MAIL FROM:<' + Value + '>';
499 if FESMTPsize and (Size > 0) then
500 s := s + ' SIZE=' + IntToStr(Size);
501 FSock.SendString(s + CRLF);
502 Result := ReadResult div 100 = 2;
503end;
504
505function TSMTPSend.MailTo(const Value: string): Boolean;
506begin
507 FSock.SendString('RCPT TO:<' + Value + '>' + CRLF);
508 Result := ReadResult div 100 = 2;
509end;
510
511function TSMTPSend.MailData(const Value: TStrings): Boolean;
512var
513 n: Integer;
514 s: string;
515 t: string;
516 x: integer;
517begin
518 Result := False;
519 FSock.SendString('DATA' + CRLF);
520 if ReadResult <> 354 then
521 Exit;
522 t := '';
523 x := 1500;
524 for n := 0 to Value.Count - 1 do
525 begin
526 s := Value[n];
527 if Length(s) >= 1 then
528 if s[1] = '.' then
529 s := '.' + s;
530 if Length(t) + Length(s) >= x then
531 begin
532 FSock.SendString(t);
533 t := '';
534 end;
535 t := t + s + CRLF;
536 end;
537 if t <> '' then
538 FSock.SendString(t);
539 FSock.SendString('.' + CRLF);
540 Result := ReadResult div 100 = 2;
541end;
542
543function TSMTPSend.Etrn(const Value: string): Boolean;
544var
545 x: Integer;
546begin
547 FSock.SendString('ETRN ' + Value + CRLF);
548 x := ReadResult;
549 Result := (x >= 250) and (x <= 259);
550end;
551
552function TSMTPSend.Verify(const Value: string): Boolean;
553var
554 x: Integer;
555begin
556 FSock.SendString('VRFY ' + Value + CRLF);
557 x := ReadResult;
558 Result := (x >= 250) and (x <= 259);
559end;
560
561function TSMTPSend.StartTLS: Boolean;
562begin
563 Result := False;
564 if FindCap('STARTTLS') <> '' then
565 begin
566 FSock.SendString('STARTTLS' + CRLF);
567 if (ReadResult = 220) and (FSock.LastError = 0) then
568 begin
569 Fsock.SSLDoConnect;
570 Result := FSock.LastError = 0;
571 end;
572 end;
573end;
574
575function TSMTPSend.EnhCodeString: string;
576var
577 s, t: string;
578begin
579 s := IntToStr(FEnhCode2) + '.' + IntToStr(FEnhCode3);
580 t := '';
581 if s = '0.0' then t := 'Other undefined Status';
582 if s = '1.0' then t := 'Other address status';
583 if s = '1.1' then t := 'Bad destination mailbox address';
584 if s = '1.2' then t := 'Bad destination system address';
585 if s = '1.3' then t := 'Bad destination mailbox address syntax';
586 if s = '1.4' then t := 'Destination mailbox address ambiguous';
587 if s = '1.5' then t := 'Destination mailbox address valid';
588 if s = '1.6' then t := 'Mailbox has moved';
589 if s = '1.7' then t := 'Bad sender''s mailbox address syntax';
590 if s = '1.8' then t := 'Bad sender''s system address';
591 if s = '2.0' then t := 'Other or undefined mailbox status';
592 if s = '2.1' then t := 'Mailbox disabled, not accepting messages';
593 if s = '2.2' then t := 'Mailbox full';
594 if s = '2.3' then t := 'Message Length exceeds administrative limit';
595 if s = '2.4' then t := 'Mailing list expansion problem';
596 if s = '3.0' then t := 'Other or undefined mail system status';
597 if s = '3.1' then t := 'Mail system full';
598 if s = '3.2' then t := 'System not accepting network messages';
599 if s = '3.3' then t := 'System not capable of selected features';
600 if s = '3.4' then t := 'Message too big for system';
601 if s = '3.5' then t := 'System incorrectly configured';
602 if s = '4.0' then t := 'Other or undefined network or routing status';
603 if s = '4.1' then t := 'No answer from host';
604 if s = '4.2' then t := 'Bad connection';
605 if s = '4.3' then t := 'Routing server failure';
606 if s = '4.4' then t := 'Unable to route';
607 if s = '4.5' then t := 'Network congestion';
608 if s = '4.6' then t := 'Routing loop detected';
609 if s = '4.7' then t := 'Delivery time expired';
610 if s = '5.0' then t := 'Other or undefined protocol status';
611 if s = '5.1' then t := 'Invalid command';
612 if s = '5.2' then t := 'Syntax error';
613 if s = '5.3' then t := 'Too many recipients';
614 if s = '5.4' then t := 'Invalid command arguments';
615 if s = '5.5' then t := 'Wrong protocol version';
616 if s = '6.0' then t := 'Other or undefined media error';
617 if s = '6.1' then t := 'Media not supported';
618 if s = '6.2' then t := 'Conversion required and prohibited';
619 if s = '6.3' then t := 'Conversion required but not supported';
620 if s = '6.4' then t := 'Conversion with loss performed';
621 if s = '6.5' then t := 'Conversion failed';
622 if s = '7.0' then t := 'Other or undefined security status';
623 if s = '7.1' then t := 'Delivery not authorized, message refused';
624 if s = '7.2' then t := 'Mailing list expansion prohibited';
625 if s = '7.3' then t := 'Security conversion required but not possible';
626 if s = '7.4' then t := 'Security features not supported';
627 if s = '7.5' then t := 'Cryptographic failure';
628 if s = '7.6' then t := 'Cryptographic algorithm not supported';
629 if s = '7.7' then t := 'Message integrity failure';
630 s := '???-';
631 if FEnhCode1 = 2 then s := 'Success-';
632 if FEnhCode1 = 4 then s := 'Persistent Transient Failure-';
633 if FEnhCode1 = 5 then s := 'Permanent Failure-';
634 Result := s + t;
635end;
636
637function TSMTPSend.FindCap(const Value: string): string;
638var
639 n: Integer;
640 s: string;
641begin
642 s := UpperCase(Value);
643 Result := '';
644 for n := 0 to FESMTPcap.Count - 1 do
645 if Pos(s, UpperCase(FESMTPcap[n])) = 1 then
646 begin
647 Result := FESMTPcap[n];
648 Break;
649 end;
650end;
651
652{==============================================================================}
653
654function SendToRaw(const MailFrom, MailTo, SMTPHost: string;
655 const MailData: TStrings; const Username, Password: string): Boolean;
656var
657 SMTP: TSMTPSend;
658 s, t: string;
659begin
660 Result := False;
661 SMTP := TSMTPSend.Create;
662 try
663// if you need SOCKS5 support, uncomment next lines:
664 // SMTP.Sock.SocksIP := '127.0.0.1';
665 // SMTP.Sock.SocksPort := '1080';
666// if you need support for upgrade session to TSL/SSL, uncomment next lines:
667 // SMTP.AutoTLS := True;
668// if you need support for TSL/SSL tunnel, uncomment next lines:
669 // SMTP.FullSSL := True;
670 SMTP.TargetHost := Trim(SeparateLeft(SMTPHost, ':'));
671 s := Trim(SeparateRight(SMTPHost, ':'));
672 if (s <> '') and (s <> SMTPHost) then
673 SMTP.TargetPort := s;
674 SMTP.Username := Username;
675 SMTP.Password := Password;
676 if SMTP.Login then
677 begin
678 if SMTP.MailFrom(GetEmailAddr(MailFrom), Length(MailData.Text)) then
679 begin
680 s := MailTo;
681 repeat
682 t := GetEmailAddr(Trim(FetchEx(s, ',', '"')));
683 if t <> '' then
684 Result := SMTP.MailTo(t);
685 if not Result then
686 Break;
687 until s = '';
688 if Result then
689 Result := SMTP.MailData(MailData);
690 end;
691 SMTP.Logout;
692 end;
693 finally
694 SMTP.Free;
695 end;
696end;
697
698function SendToEx(const MailFrom, MailTo, Subject, SMTPHost: string;
699 const MailData: TStrings; const Username, Password: string): Boolean;
700var
701 t: TStrings;
702begin
703 t := TStringList.Create;
704 try
705 t.Assign(MailData);
706 t.Insert(0, '');
707 t.Insert(0, 'X-mailer: Synapse - Delphi & Kylix TCP/IP library by Lukas Gebauer');
708 t.Insert(0, 'Subject: ' + Subject);
709 t.Insert(0, 'Date: ' + Rfc822DateTime(now));
710 t.Insert(0, 'To: ' + MailTo);
711 t.Insert(0, 'From: ' + MailFrom);
712 Result := SendToRaw(MailFrom, MailTo, SMTPHost, t, Username, Password);
713 finally
714 t.Free;
715 end;
716end;
717
718function SendTo(const MailFrom, MailTo, Subject, SMTPHost: string;
719 const MailData: TStrings): Boolean;
720begin
721 Result := SendToEx(MailFrom, MailTo, Subject, SMTPHost, MailData, '', '');
722end;
723
724end.
Note: See TracBrowser for help on using the repository browser.