Sign in Join
Wiki copytemporary

Synapse - Email Examples: what changed

Revision 1 to 2. Removed lines have a minus sign; added lines have a plus sign.

OldNewLine
11## Example 1 - sending to Gmail
22
33(forum user **ludob**). This works for me with Gmail using [[Synapse]].
44
55``` pascal
66uses
77 ..., smtpsend, ssl_openssl;
88
99function SendMail(const User, Password, MailFrom, MailTo, SMTPHost, SMTPPort, MailData: string): Boolean;
1010var
1111 SMTP: TSMTPSend;
1212 sl:TStringList;
1313begin
1414 Result:=False;
1515 SMTP:=TSMTPSend.Create;
1616 sl:=TStringList.Create;
1717 try
1818 sl.text:=Maildata;
1919 SMTP.UserName:=User;
2020 SMTP.Password:=Password;
2121 SMTP.TargetHost:=SMTPHost;
2222 SMTP.TargetPort:=SMTPPort;
2323 SMTP.AutoTLS:=true;
2424 if SMTPPort<> '25' then
2525 SMTP.FullSSL:=true;
2626 if SMTP.Login then
2727 begin
2828 Result:=SMTP.MailFrom(MailFrom, Length(MailData)) and
2929 SMTP.MailTo(MailTo) and
3030 SMTP.MailData(sl);
3131 SMTP.Logout;
3232 end;
3333 finally
3434 SMTP.Free;
3535 sl.Free;
3636 end;
3737end;
3838```
3939
4040## Example 2 - sending attachments
4141
4242(forum user **y.ivanov**). Here is my small helper unit for [[Synapse]]. The password is the sender password (for SMTP).
4343
4444``` pascal
4545unit mailsendu;
4646
4747{$mode objfpc}{$H+}
4848
4949interface
5050
5151uses
5252 Classes, SysUtils, smtpsend;
5353
5454type
5555
5656 { TMySMTPSend }
5757
5858 TMySMTPSend = class(TSMTPSend)
5959 private
6060 FSendSize: Integer;
6161 protected
6262 function SendToRaw(const AFrom, ATo: String; const AMailData: TStrings)
6363 : Boolean;
6464 public
6565 function SendMessage(AFrom, ATo, ASubject: String; AContent,
6666 AAttachments: TStrings): Boolean;
6767
6868 property SendSize: Integer read FSendSize write FSendSize;
6969
7070 end;
7171
7272implementation
7373
7474uses
7575 ssl_openssl, mimemess, mimepart, synautil, synachar;
7676
7777{ TMySMTPSend }
7878
7979function TMySMTPSend.SendToRaw(const AFrom, ATo: String; const AMailData
8080 : TStrings): Boolean;
8181var
8282 S, T: String;
8383begin
8484 Result := False;
8585 if Self.Login then
8686 begin
8787 FSendSize := Length(AMailData.Text);
8888 if Self.MailFrom(GetEmailAddr(AFrom), FSendSize) then
8989 begin
9090 S := ATo;
9191 repeat
9292 T := GetEmailAddr(Trim(FetchEx(S, ',', '"')));
9393 if T <> '' then
9494 Result := Self.MailTo(T);
9595 if not Result then
9696 Break;
9797 until S = '';
9898 if Result then
9999 Result := Self.MailData(AMailData);
100100 end;
101101 Self.Logout;
102102 end;
103103end;
104104
105105function TMySMTPSend.SendMessage(AFrom, ATo, ASubject: String; AContent,
106106 AAttachments: TStrings): Boolean;
107107var
108108 Mime: TMimeMess;
109109 P: TMimePart;
110110 I: Integer;
111111begin
112112 Mime := TMimeMess.Create;
113113 try
114114 // Set some headers
115115 Mime.Header.CharsetCode := UTF_8;
116116 Mime.Header.ToList.Text := ATo;
117117 Mime.Header.Subject := ASubject;
118118 Mime.Header.From := AFrom;
119119
120120 // Create a MultiPart part
121121 P := Mime.AddPartMultipart('mixed', Nil);
122122
123123 // Add as first part the mail text
124124 Mime.AddPartTextEx(AContent, P, UTF_8, True, ME_8BIT);
125125
126126 // Add all attachments:
127127 if Assigned(AAttachments) then
128128 for I := 0 to Pred(AAttachments.Count) do
129129 Mime.AddPartBinaryFromFile(AAttachments[I], P);
130130
131131 // Compose message
132132 Mime.EncodeMessage;
133133
134134 // Send using SendToRaw
135135 Result := Self.SendToRaw(AFrom, ATo, Mime.Lines);
136136
137137 finally
138138 Mime.Free;
139139 end;
140140end;
141141
142142end.
143143```
144144
145145This is how to use that unit:
146146
147147``` pascal
148148program mailsend_test;
149149
150150uses
151151 Classes, SysUtils, mailsendu, blcksock;
152152
153153type
154154
155155 { TSink }
156156
157157 TSink = class(TObject)
158158 procedure Progress(Sender: TObject; Reason: THookSocketReason;const Value: String);
159159 end;
160160
161161var
162162 Content, Attach: TStringList;
163163 SMTP: TMySMTPSend;
164164 Sink: TSink;
165165 Written: Integer;
166166
167167{ TSink }
168168
169169procedure TSink.Progress(Sender: TObject; Reason: THookSocketReason;
170170 const Value: String);
171171begin
172172 case Reason of
173173 {:Socket connected to IP and Port. Connected IP and Port is in parameter in
174174 format like: 'localhost.somewhere.com:25'.}
175175 HR_Connect: Written := 0;
176176 {:report count of bytes writed to socket. Number is in parameter string. If
177177 you need is in integer, you must use StrToInt function!}
178178 HR_WriteCount:
179179 begin
180180 Written := Written + StrToInt(Value);
181181 WriteLn('Written ', Written, ' of ', SMTP.SendSize, ' bytes');
182182 end;
183183 {:report situation where communication error occured. When raiseexcept is
184184 @true, then exception is called after this Hook reason.}
185185 HR_Error: WriteLn('Error: ', Value);
186186 end;
187187end;
188188
189189begin
190190 Sink := TSink.Create;
191191 Content := TStringList.Create;
192192 Content.Add('Hello!');
193193 Content.Add('This is a SMTP send test.');
194194 Content.Add('Hello from the other side!');
195195 Content.Add('Regards,');
196196 Attach := TStringList.Create;
197197 Attach.Add('mismisc.pas');
198198 Attach.Add('notused.pas');
199199
200200 SMTP := TMySMTPSend.Create;
201201 try
202202 SMTP.TargetHost := 'smtp.googlemail.com';
203203 SMTP.TargetPort := '465';
204204 SMTP.Username := 'user@gmail.com';
205205 SMTP.Password := 'password here';
206206 SMTP.FullSSL := True;
207207 SMTP.Sock.OnStatus := @Sink.Progress;
208208 SMTP.Sock.RaiseExcept := True;
209209 try
210210 if SMTP.SendMessage(
211211 'user@gmail.com', // AFrom
212212 'recipient@domain.com', // ATo
213213 'Test subject FullSSL 2', // ASubject
214214 Content,
215215 Attach)
216216 then
217217 WriteLn('Success.')
218218 else
219219 begin
220220 WriteLn('Failure!');
221221 end;
222222 except
223223 on E: Exception do
224224 WriteLn('EXCEPTION: ', E.Message);
225225 end;
226226
227227 with SMTP do
228228 begin
229229 WriteLn;
230230 WriteLn(' ResultCode: ', ResultCode);
231231 WriteLn('ResultString: ', ResultString);
232232 WriteLn(' FullResult: ', FullResult.Text);
233233 WriteLn(' AuthDone: ', AuthDone) ;
234234 end;
235235 finally
236236 SMTP.Free;
237237 end;
238238
239239end.
240240```
241241
242242## Example 3 - using the XMailer wrapper
243243
244244(forum user **Silvio Clécio**). I use [XMailer plugin](https://github.com/MFernstrom/xmailer) (it uses Synapse framework). Works fine with Gmail, Hotmail, Yahoo etc.
245245
246246It is also available in the [[Online Package Manager]].
247247
248248## Example 4 - with error checking for debugging
249249
250250This version is "advanced" in so far as it does a lot of error checking and shows you the responses from the remote mail server. It is very useful for debugging especially when you do not have access to the remote mail server's logs.
251251
252252``` pascal
253253unit Unit1;
254254
255255{$mode objfpc}{$H+}
256256
257257interface
258258
259259uses
260260 Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls;
261261
262262type
263263
264264 { TForm1 }
265265
266266 TForm1 = class(TForm)
267267 Button1: TButton;
268268 Memo1: TMemo;
269269 procedure Button1Click(Sender: TObject);
270270 private
271271 public
272272 end;
273273
274274var
275275 Form1: TForm1;
276276
277277implementation
278278
279279{$R *.lfm}
280280uses
281281 // "ssl_openssl" unit is required to use SSL / TLS
282282 ssl_openssl, SMTPsend;
283283
284284// MailData is the text of the mail.
285285procedure SendMail(User, Password, MailFrom, MailTo, SMTPHost, SMTPPort: string; MailData: string);
286286var
287287 SMTP: TSMTPSend;
288288 email_lines: TStringList;
289289begin
290290 SMTP := TSMTPSend.Create;
291291 email_lines := TStringList.Create;
292292
293293 try
294294 email_lines.text := Maildata;
295295 SMTP.UserName := User;
296296 SMTP.Password := Password;
297297 SMTP.TargetHost := SMTPHost;
298298 SMTP.TargetPort := SMTPPort;
299299 //SMTP.AutoTLS := True; // upgrade to SSL/TLS if remote server supports it
300300
301301 if Trim(SMTPPort) <> '25' then
302302 SMTP.FullSSL := true; // if sending to port 25, don't use encryption
303303
304304 Form1.Memo1.Clear; // clear memo text
305305
306306 if not SMTP.Login() then
307307 begin
308308 Form1.Memo1.Append('SMTP ERROR: Login:' + SMTP.EnhCodeString);
309309 Form1.Memo1.Append('SMTP Login: Failed - does server exist? does it accept mail?');
310310 Exit
311311 end
312312 else
313313 begin
314314 Form1.Memo1.Append('SMTP Login: OK');
315315 Form1.Memo1.append('-- Remote response: ' + SMTP.FullResult[0]);
316316 end;
317317
318318 if(SMTP.ESMTP) then
319319 Form1.Memo1.Append('SMTP: ' + SMTPHost + ' supports ESMTP')
320320 else
321321 Form1.Memo1.Append('SMTP: ' + SMTPHost + ' supports plain SMTP');
322322
323323 // Insist on SSL/TLS connection to remote server
324324 // - if the server might not support it, omit and then
325325 // uncomment SMTP.AutoTLS above
326326 if not SMTP.StartTLS() then
327327 Form1.Memo1.Append('SMTP ERROR: StartTLS:' + SMTP.EnhCodeString)
328328 else
329329 begin
330330 Form1.Memo1.Append('SMTP StartTLS: OK');
331331 Form1.Memo1.append('-- Remote response: ' + SMTP.FullResult[0]);
332332 end;
333333
334334 if not SMTP.MailFrom(MailFrom, Length(MailFrom)) then
335335 Form1.Memo1.Append('SMTP ERROR: MailFrom:' + SMTP.EnhCodeString)
336336 else
337337 begin
338338 Form1.Memo1.Append('SMTP MailFrom: OK');
339339 Form1.Memo1.append('-- Remote response: ' + SMTP.FullResult[0]);
340340 end;
341341
342342 if not SMTP.MailTo(MailTo) then
343343 Form1.Memo1.Append('SMTP ERROR: MailTo:' + SMTP.EnhCodeString)
344344 else
345345 begin
346346 Form1.Memo1.Append('SMTP MailTo: OK');
347347 Form1.Memo1.append('-- Remote response: ' + SMTP.FullResult[0]);
348348 end;
349349
350350 if not SMTP.MailData(email_lines) then
351351 Form1.Memo1.Append('SMTP ERROR: MailData:' + SMTP.EnhCodeString)
352352 else
353353 begin
354354 Form1.Memo1.Append('SMTP MailData: OK');
355355 Form1.Memo1.append('-- Remote response: ' + SMTP.FullResult[0]);
356356 end;
357357
358358 if not SMTP.Logout() then
359359 Form1.Memo1.Append('SMTP ERROR: Logout:' + SMTP.EnhCodeString)
360360 else
361361 begin
362362 Form1.Memo1.Append('SMTP Logout: OK');
363363 Form1.Memo1.append('-- Remote response: ' + SMTP.FullResult[0]);
364364 end;
365365
366366 finally
367367 SMTP.Free;
368368 email_lines.Free;
369369 end;
370370end;
371371
372372procedure TForm1.Button1Click(Sender: TObject);
373373begin
374374 SendMail(
375375 '', // Name if authentication required
376376 '', // Password if authentication required
377377 'trev@example.com', // MailFrom
378378 'trev@example.org', // MailTo
379379 'shadow.example.org', // Mail server to send to
380380 '25', // Mail server port
381381 'To: trev@example.org' // Otherwise To: is blank on receipt
382382 + LineEnding + 'Subject: Test' // Otherwise Subject: is blank on receipt
383383 + LineEnding +'Gday!' // Email body
384384 + LineEnding);
385385end;
386386
387387end.
388388```
389389
390390**Example Memo1 output on success**
391391
392-`SMTP Login: OK`\
393-`-- Remote response: 250-shadow.example.org Hello macmini8.example.org [192.168.1.21], pleased to meet you`\
394-`SMTP: shadow.example.org supports ESMTP`\
395-`SMTP StartTLS: OK`\
396-`-- Remote response: 220 2.0.0 Ready to start TLS`\
397-`SMTP MailFrom: OK`\
398-`-- Remote response: 250 2.1.0 <trev@example.com>... Sender ok`\
399-`SMTP MailTo: OK`\
400-`-- Remote response: 250 2.1.5 <trev@example.org>... Recipient ok`\
401-`SMTP MailData: OK`\
402-`-- Remote response: 250 2.0.0 22G97AqL046395 Message accepted for delivery`\
403-`SMTP Logout: OK`\
404-`-- Remote response: 221 2.0.0 shadow.example.org closing connection`
392+```text
393+SMTP Login: OK
394+-- Remote response: 250-shadow.example.org Hello macmini8.example.org [192.168.1.21], pleased to meet you
395+SMTP: shadow.example.org supports ESMTP
396+SMTP StartTLS: OK
397+-- Remote response: 220 2.0.0 Ready to start TLS
398+SMTP MailFrom: OK
399+-- Remote response: 250 2.1.0 <trev@example.com>... Sender ok
400+SMTP MailTo: OK
401+-- Remote response: 250 2.1.5 <trev@example.org>... Recipient ok
402+SMTP MailData: OK
403+-- Remote response: 250 2.0.0 22G97AqL046395 Message accepted for delivery
404+SMTP Logout: OK
405+-- Remote response: 221 2.0.0 shadow.example.org closing connection
406+```
405407
406408**Example Memo1 output on failure**
407409
408-`SMTP Login: OK`\
409-`-- Remote response: 250-shadow.example.org Hello 103-216-191-138.dyn.launtel.net.au [103.216.191.138], pleased to meet you`\
410-`SMTP: shadow.example.org supports ESMTP`\
411-`SMTP StartTLS: OK`\
412-`-- Remote response: 220 2.0.0 Ready to start TLS`\
413-`SMTP MailFrom: OK`\
414-`-- Remote response: 250 2.1.0 <trev@example.com>... Sender ok`\
415-`SMTP ERROR: `[`MailTo:Persistent`](MailTo:Persistent)` Transient Failure-Delivery not authorized, message refused`\
416-`-- Remote response: 451 4.7.1 Spam alert: 103-116-191-138.dyn.launtel.net.au [103.116.191.138] mail delivery delayed`\
417-`SMTP ERROR: MailData:Permanent Failure-Other undefined Status`\
418-`-- Remote response: 503 5.0.0 Need RCPT (recipient)`\
419-`SMTP Logout: OK`\
420-`-- Remote response: 221 2.0.0 shadow.example.org closing connection`
410+```text
411+SMTP Login: OK
412+-- Remote response: 250-shadow.example.org Hello 103-216-191-138.dyn.launtel.net.au [103.216.191.138], pleased to meet you
413+SMTP: shadow.example.org supports ESMTP
414+SMTP StartTLS: OK
415+-- Remote response: 220 2.0.0 Ready to start TLS
416+SMTP MailFrom: OK
417+-- Remote response: 250 2.1.0 <trev@example.com>... Sender ok
418+SMTP ERROR: MailTo:Persistent Transient Failure-Delivery not authorized, message refused
419+-- Remote response: 451 4.7.1 Spam alert: 103-116-191-138.dyn.launtel.net.au [103.116.191.138] mail delivery delayed
420+SMTP ERROR: MailData:Permanent Failure-Other undefined Status
421+-- Remote response: 503 5.0.0 Need RCPT (recipient)
422+SMTP Logout: OK
423+-- Remote response: 221 2.0.0 shadow.example.org closing connection
424+```
421425
422426## See also
423427
424428- [RFC2821](https://www.ietf.org/rfc/rfc2821.txt) - Simple Mail Transfer Protocol (SMTP).
425429
426430- [RFC3207](https://www.ietf.org/rfc/rfc3207.txt) - SMTP Service Extension for Secure SMTP over Transport Layer Security (TLS).
427431
428432- [RFC5246](https://www.ietf.org/rfc/rfc5246.txt) - The Transport Layer Security (TLS) Protocol Version 1.2.
429433
430434- [RFC8446](https://www.ietf.org/rfc/rfc8446.txt) - The Transport Layer Security (TLS) Protocol Version 1.3.
431435
432436- [[Synapse]]
433437
434438- [Synapse documentation](https://synapse.ararat.cz/doku.php/public:howto:tmimepart) on sending attachments.
435439
436440- [Article (PDF)](https://www.freepascal.org/~michael/articles/lazmail/lazmail-en.pdf) that covers sending email, including attachments, using Synapse.
437441
438442- [[lNet examples]] - email example using [[lNet]] library.
439443
440444---
441445*From the Free Pascal wiki, page "Synapse - Email Examples", as it stood on 2022-05-19 after a change by Trev, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*
442446Category: Example programs
443447Category: Networking

Back to history