Sign in Join
Wiki copytemporary

lNet examples: what changed

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

OldNewLine
11> **Tip:** You can use the non-visual code in Lazarus applications. This is necessary for macOS because lNet visual components do not support the Cocoa or Carbon widget sets. To successfully compile the lNet library and non-visual code examples with FPC 3.2.2 or FPC 3.3.1 requires the lNet version available from <https://github.com/trevoz/lnet> which has many changes made to it so that it will compile with a modern FPC and to support TLSv1.3.
22
33## lNet provided console (non-visual) code examples
44
55In the **[[lNet]]** `examples/console/` directory you will find example programs for:
66
77- FTP
88- HTTP
99- SMTP
1010- TCP
1111- Telnet
1212- UDP
1313
1414## lNet provided visual code examples
1515
1616In the lNet `examples/visual/` directory you will find example programs for:
1717
1818- FTP
1919- HTTP
2020- SMTP
2121- TCP and UDP (combined)
2222- Telnet
2323
2424These examples will not compile on macOS because the lNet visual components have no interface bindings for the Cocoa or Carbon widget sets.
2525
2626## Lazarus SMTP client example
2727
2828This is a simple Lazarus SMTP client.
2929
3030- Memo1 contains the body of the email message.
3131- For debugging purposes, Memo2 is used to record the log of the email transaction.
3232- Compiles with FPC 3.2.2 and FPC 3.3.1 on FreeBSD (tested on 12-RELEASE), macOS 10.12+, Linux (Ubuntu 21.10) and Windows 32 bit and 64 bit (tested on Windows 10).
3333- STARTTLS is enabled (with FSMTP.StartTLS;). The encrypted TLS (Transport Layer Security) connection is used when communicating between the mail server and the client to provide better security. FreeBSD 12, macOS 10.12+ and Windows 10 pick TLS v1.3, Linux (Ubuntu 21.10) picks TLS v1.2 (except Linux has problems - see below).
3434- Note: TLS does not work in Linux due to an inscrutable epoll error (Error on epoll \[4\]: Interrupted system call) from the Linux-specific `lib/sys/lepolleventer.inc` file. Fixes welcome :-)
3535- TLS v1.3 has been added.
3636- All insecure SSL and TLS methods have been removed (ie SSL2, SSL3, TLSv1, TLSv1.1) leaving TLS v1.2 and v1.3.
3737- The lNet library from <https://github.com/trevoz/lnet> is required.
3838- Add the path to the lNet library units to the Project Options \> Paths - "Other unit files".
3939
4040``` pascal
4141unit Unit1;
4242
4343{$mode objfpc}{$H+}
4444
4545interface
4646
4747uses
4848 Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls,
4949 lnet, lsmtp, lnetssl;
5050
5151type
5252
5353 { TForm1 }
5454
5555 TForm1 = class(TForm)
5656 Button1: TButton; // Send email button
5757 BodyLabel: TLabel;
5858 EmailLogLabel: TLabel;
5959 Memo1: TMemo; // Mail content
6060 Memo2: TMemo; // Mail log
6161 SubjectEdit: TEdit; // Mail subject
6262 SubjectLabel: TLabel;
6363 MailToEdit: TEdit; // MailTo
6464 MailToLabel: TLabel;
6565 MailFromEdit: TEdit; // MailFrom
6666 MailFromLabel: TLabel;
6767 procedure Button1Click(Sender: TObject);
6868 private
6969
7070 public
7171
7272 end;
7373
7474 type
7575
7676 { TLSMTPClientTest }
7777
7878 TLSMTPClientTest = class(TComponent)
7979 private
8080 FSMTP: TLSMTPClient; // this is THE smtp connection
8181 FSSL: TLSSLSession;
8282 FQuit: Boolean; // helper for main loop
8383 { these events are used to see what happens on the SMTP connection. They are used via "CallAction".
8484 OnReceive will get fired whenever new data is received from the SMTP server.
8585 OnConnect will get fired when connecting to the SMTP server ends with success.
8686 OnDisconnect will get fired when the other side closes the connection gracefully.
8787 OnError will get called when any kind of error occurs on the connection. }
8888 procedure OnReceive(aSocket: TLSocket);
8989 procedure OnConnect(aSocket: TLSocket);
9090 procedure OnDisconnect(aSocket: TLSocket);
9191 procedure OnError(const msg: string; aSocket: TLSocket);
9292 { This event is used to monitor TLS session handshake. If SSL or TLS is used
9393 we will know if the handshake went ok if this event is fired on the session }
9494 procedure OnSSLConnect(aSocket: TLSocket);
9595 public
9696 constructor Create(aOwner: TComponent); override;
9797 procedure Run; // main SMTP processing loop
9898 end;
9999
100100var
101101 Form1: TForm1;
102102 SMTP: TLSMTPClientTest;
103103
104104implementation
105105
106106{$R *.lfm}
107107
108108{ TForm1 }
109109
110110procedure TLSMTPClientTest.OnReceive(aSocket: TLSocket);
111111var
112112 s: string;
113113begin
114114 if FSMTP.GetMessage(s) > 0 then // if we actually received something from SMTP server
115115 begin
116116 Form1.Memo2.Append(s); // inform user
117117
118118 // Check server response to see if we should quit because mail delivered
119119 If pos('250 2.0.0',s) <> 0 then
120120 FQuit := True
121121 end;
122122end;
123123
124124procedure TLSMTPClientTest.OnConnect(aSocket: TLSocket);
125125begin
126126 Form1.Memo2.Append('Connected' + LineEnding); // inform user of successful connect
127127end;
128128
129129procedure TLSMTPClientTest.OnDisconnect(aSocket: TLSocket);
130130begin
131131 Form1.Memo2.Append('Lost connection'); // inform user about lost connection
132132 FQuit := True; // since SMTP shouldn't do this unless we issued a QUIT,
133133 // consider it to be end of session and quit it.
134134end;
135135
136136procedure TLSMTPClientTest.OnError(const msg: string; aSocket: TLSocket);
137137begin
138138 Form1.Memo2.Append(msg); // inform user of error
139139 FQuit := True; // and quit session.
140140end;
141141
142142procedure TLSMTPClientTest.OnSSLConnect(aSocket: TLSocket);
143143begin
144144 Form1.Memo2.Append('SSL session handshake was successful');
145145end;
146146
147147constructor TLSMTPClientTest.Create(aOwner: TComponent);
148148begin
149149 inherited;
150150 FQuit := False;
151151
152152 FSSL := TLSSLSession.Create(Self);
153153 FSSL.SSLActive := False; // make it "off" by default
154154 FSSL.OnSSLConnect := @OnSSLConnect; // let's watch if TLS/SSL handshake is ok
155155
156156 FSMTP := TLSMTPClient.Create(Self);
157157 FSMTP.Session := FSSL; // set the SSL session, so if it's a SSL/TLS SMTP we can use it
158158 FSMTP.Timeout := 100; // responsive enough, but won't hog CPU
159159 FSMTP.OnReceive := @OnReceive; // assign all events
160160 FSMTP.OnConnect := @OnConnect;
161161 FSMTP.OnDisconnect := @OnDisconnect;
162162 FSMTP.OnError := @OnError;
163163end;
164164
165165// Main SMTP processing loop
166166procedure TLSMTPClientTest.Run;
167167var
168168 Addr, Subject, Sender, Recipients, Message: string;
169169 Port: Integer;
170170begin
171171 Addr := '192.168.1.4'; // hard code my mailserver
172172 Port := 25; // hard code my SMTP port number
173173
174174 Sender := Form1.MailFromEdit.Text; // get info about email from Form1 edit fields
175175 Recipients := Form1.MailToEdit.Text;
176176 Subject := Form1.SubjectEdit.Text;
177177 Message := Form1.Memo1.Text;
178178
179179 Form1.Memo2.Append('Connecting to ' + Addr + ':' + IntToStr(Port) + '... ');
180180
181181 if FSMTP.Connect(Addr, Port) then
182182 repeat // try to connect
183183 FSMTP.CallAction; // if initial connect went ok, wait for acknowledgment/otherwise
184184 until FSMTP.Connected or FQuit; // if quit (eg error), or we connected, then continue
185185
186186 If(FQuit) then // if we need to quit because of a connection error
187187 exit; // exit now
188188
189189 while not FQuit do // do main loop
190190 begin
191191 FSMTP.Ehlo; // "Polite people say HELO first" (yeah, but nearly everyone is enhanced now)
192192 FSMTP.CallAction; // main event mechanism, must call periodicly and ASAP, or specify high timeout
193193 FSMTP.StartTLS; // ask for TLS
194194 FSMTP.SendMail(Sender, Recipients, Subject, Message); // send the email
195195 end;
196196 end;
197197
198198procedure TForm1.Button1Click(Sender: TObject);
199199begin
200200 Button1.Enabled := False; // disable button until session finished
201201 Memo2.Clear; // clear email log
202202 SMTP := TLSMTPClientTest.Create(nil);
203203
204204 Try
205205 SMTP.Run; // try to deliver the mail
206206 Finally
207207 SMTP.Free;
208208 Button1.Enabled := True; // enable button now session finished
209209 Memo1.Clear; // clear email content
210210 End;
211211end;
212212
213213end.
214214```
215215
216216![](/wiki-images/2/21/Lazarus_lnet_smtp_client_tls.png)
217217
218218Here's a copy of the transaction on the mail server for the above message:
219219
220-`Mar 18 16:22:33 shadow sm-mta[66179]: 221820LG031423: Milter (milter-relay): init success to negotiate`\
221-`Mar 18 16:22:33 shadow sm-mta[66179]: 221820LG031423: Milter (milter-regex): init success to negotiate`\
222-`Mar 18 16:22:33 shadow sm-mta[66179]: 221820LG031423: Milter (greylist): init success to negotiate`\
223-`Mar 18 16:22:33 shadow sm-mta[66179]: 221820LG031423: Milter: connect to filters`\
224-`Mar 18 16:22:33 shadow sm-mta[66179]: 221820LG031423: STARTTLS=server, relay=macmini8.example.org [192.168.1.21], version=TLSv1.3, verify=NO, cipher=TLS_AES_256_GCM_SHA384, bits=256/256`\
225-`Mar 18 16:22:34 shadow milter-greylist[25940]: 221820LG031423: addr = macmini8.example.org[192.168.1.21], from = <trev@nowhereonearth.com>, rcpt = <trev@example.org>`\
226-`Mar 18 16:22:34 shadow milter-greylist[25940]: whitelisted by {greylist}`\
227-`Mar 18 16:22:34 shadow sm-mta[66179]: 221820LG031423: Subject:Test.email`\
228-`Mar 18 16:22:34 shadow sm-mta[66179]: 221820LG031423: from=<trev@nowhereonearth.com>, size=73, class=0, nrcpts=1, msgid=<202203180522.22I5MXc3066179@shadow.example.org>, proto=ESMTP, daemon=IPv4, relay=macmini8.example.org [192.168.1.21]`\
229-`Mar 18 16:22:34 shadow sm-mta[66179]: 221820LG031423: Milter (greylist) add: header: X-Greylist: Message whitelisted by Sendmail access database, not delayed by milter-greylist-4.6.4 (shadow.example.org [192.168.1.4]); Fri, 18 Mar 2022 16:22:34 +1100 (AEDT)`\
230-`Mar 18 16:22:34 shadow sm-mta[66179]: 221820LG031423: Milter accept: message`\
231-`Mar 18 16:22:34 shadow sm-mta[66180]: 221820LG031423: to=<trev@example.org>, delay=00:00:00, xdelay=00:00:00, mailer=local, pri=30597, relay=local, dsn=2.0.0, stat=Sent`
220+```text
221+Mar 18 16:22:33 shadow sm-mta[66179]: 221820LG031423: Milter (milter-relay): init success to negotiate
222+Mar 18 16:22:33 shadow sm-mta[66179]: 221820LG031423: Milter (milter-regex): init success to negotiate
223+Mar 18 16:22:33 shadow sm-mta[66179]: 221820LG031423: Milter (greylist): init success to negotiate
224+Mar 18 16:22:33 shadow sm-mta[66179]: 221820LG031423: Milter: connect to filters
225+Mar 18 16:22:33 shadow sm-mta[66179]: 221820LG031423: STARTTLS=server, relay=macmini8.example.org [192.168.1.21], version=TLSv1.3, verify=NO, cipher=TLS_AES_256_GCM_SHA384, bits=256/256
226+Mar 18 16:22:34 shadow milter-greylist[25940]: 221820LG031423: addr = macmini8.example.org[192.168.1.21], from = <trev@nowhereonearth.com>, rcpt = <trev@example.org>
227+Mar 18 16:22:34 shadow milter-greylist[25940]: whitelisted by {greylist}
228+Mar 18 16:22:34 shadow sm-mta[66179]: 221820LG031423: Subject:Test.email
229+Mar 18 16:22:34 shadow sm-mta[66179]: 221820LG031423: from=<trev@nowhereonearth.com>, size=73, class=0, nrcpts=1, msgid=<202203180522.22I5MXc3066179@shadow.example.org>, proto=ESMTP, daemon=IPv4, relay=macmini8.example.org [192.168.1.21]
230+Mar 18 16:22:34 shadow sm-mta[66179]: 221820LG031423: Milter (greylist) add: header: X-Greylist: Message whitelisted by Sendmail access database, not delayed by milter-greylist-4.6.4 (shadow.example.org [192.168.1.4]); Fri, 18 Mar 2022 16:22:34 +1100 (AEDT)
231+Mar 18 16:22:34 shadow sm-mta[66179]: 221820LG031423: Milter accept: message
232+Mar 18 16:22:34 shadow sm-mta[66180]: 221820LG031423: to=<trev@example.org>, delay=00:00:00, xdelay=00:00:00, mailer=local, pri=30597, relay=local, dsn=2.0.0, stat=Sent
233+```
232234
233235The full project source code is available for download from [SourceForge](https://sourceforge.net/p/lazarus-wiki-projects/code/ci/767b0a105a3ec6f4c8f54aab861984f7f90be81f/tree/laz_lnet_smtp/).
234236
235237## See also
236238
237239- [[lNet]]
238240- [[Synapse - Email Examples]]
239241- [RFC2821](https://www.ietf.org/rfc/rfc2821.txt) Simple Mail Transfer Protocol (SMTP)
240242- [RFC3207](https://www.ietf.org/rfc/rfc3207.txt) SMTP Service Extension for Secure SMTP over Transport Layer Security (TLS)
241243- [RFC5246](https://www.ietf.org/rfc/rfc5246.txt) The Transport Layer Security (TLS) Protocol Version 1.2
242244- [RFC8446](https://www.ietf.org/rfc/rfc8446.txt) The Transport Layer Security (TLS) Protocol Version 1.3
243245
244246---
245247*From the Free Pascal wiki, page "lNet examples", as it stood on 2022-05-18 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).*
246248Category: Components
247249Category: Example programs
248250Category: Networking

Back to history