Sign in Join
Wiki copytemporary

lNet examples: what changed

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

Title: lNet examples

OldNewLine
1+> **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.
2+
3+## lNet provided console (non-visual) code examples
4+
5+In the **[[lNet]]** `examples/console/` directory you will find example programs for:
6+
7+- FTP
8+- HTTP
9+- SMTP
10+- TCP
11+- Telnet
12+- UDP
13+
14+## lNet provided visual code examples
15+
16+In the lNet `examples/visual/` directory you will find example programs for:
17+
18+- FTP
19+- HTTP
20+- SMTP
21+- TCP and UDP (combined)
22+- Telnet
23+
24+These examples will not compile on macOS because the lNet visual components have no interface bindings for the Cocoa or Carbon widget sets.
25+
26+## Lazarus SMTP client example
27+
28+This is a simple Lazarus SMTP client.
29+
30+- Memo1 contains the body of the email message.
31+- For debugging purposes, Memo2 is used to record the log of the email transaction.
32+- 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).
33+- 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).
34+- 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 :-)
35+- TLS v1.3 has been added.
36+- All insecure SSL and TLS methods have been removed (ie SSL2, SSL3, TLSv1, TLSv1.1) leaving TLS v1.2 and v1.3.
37+- The lNet library from <https://github.com/trevoz/lnet> is required.
38+- Add the path to the lNet library units to the Project Options \> Paths - "Other unit files".
39+
40+``` pascal
41+unit Unit1;
42+
43+{$mode objfpc}{$H+}
44+
45+interface
46+
47+uses
48+ Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls,
49+ lnet, lsmtp, lnetssl;
50+
51+type
52+
53+ { TForm1 }
54+
55+ TForm1 = class(TForm)
56+ Button1: TButton; // Send email button
57+ BodyLabel: TLabel;
58+ EmailLogLabel: TLabel;
59+ Memo1: TMemo; // Mail content
60+ Memo2: TMemo; // Mail log
61+ SubjectEdit: TEdit; // Mail subject
62+ SubjectLabel: TLabel;
63+ MailToEdit: TEdit; // MailTo
64+ MailToLabel: TLabel;
65+ MailFromEdit: TEdit; // MailFrom
66+ MailFromLabel: TLabel;
67+ procedure Button1Click(Sender: TObject);
68+ private
69+
70+ public
71+
72+ end;
73+
74+ type
75+
76+ { TLSMTPClientTest }
77+
78+ TLSMTPClientTest = class(TComponent)
79+ private
80+ FSMTP: TLSMTPClient; // this is THE smtp connection
81+ FSSL: TLSSLSession;
82+ FQuit: Boolean; // helper for main loop
83+ { these events are used to see what happens on the SMTP connection. They are used via "CallAction".
84+ OnReceive will get fired whenever new data is received from the SMTP server.
85+ OnConnect will get fired when connecting to the SMTP server ends with success.
86+ OnDisconnect will get fired when the other side closes the connection gracefully.
87+ OnError will get called when any kind of error occurs on the connection. }
88+ procedure OnReceive(aSocket: TLSocket);
89+ procedure OnConnect(aSocket: TLSocket);
90+ procedure OnDisconnect(aSocket: TLSocket);
91+ procedure OnError(const msg: string; aSocket: TLSocket);
92+ { This event is used to monitor TLS session handshake. If SSL or TLS is used
93+ we will know if the handshake went ok if this event is fired on the session }
94+ procedure OnSSLConnect(aSocket: TLSocket);
95+ public
96+ constructor Create(aOwner: TComponent); override;
97+ procedure Run; // main SMTP processing loop
98+ end;
99+
100+var
101+ Form1: TForm1;
102+ SMTP: TLSMTPClientTest;
103+
104+implementation
105+
106+{$R *.lfm}
107+
108+{ TForm1 }
109+
110+procedure TLSMTPClientTest.OnReceive(aSocket: TLSocket);
111+var
112+ s: string;
113+begin
114+ if FSMTP.GetMessage(s) > 0 then // if we actually received something from SMTP server
115+ begin
116+ Form1.Memo2.Append(s); // inform user
117+
118+ // Check server response to see if we should quit because mail delivered
119+ If pos('250 2.0.0',s) <> 0 then
120+ FQuit := True
121+ end;
122+end;
123+
124+procedure TLSMTPClientTest.OnConnect(aSocket: TLSocket);
125+begin
126+ Form1.Memo2.Append('Connected' + LineEnding); // inform user of successful connect
127+end;
128+
129+procedure TLSMTPClientTest.OnDisconnect(aSocket: TLSocket);
130+begin
131+ Form1.Memo2.Append('Lost connection'); // inform user about lost connection
132+ FQuit := True; // since SMTP shouldn't do this unless we issued a QUIT,
133+ // consider it to be end of session and quit it.
134+end;
135+
136+procedure TLSMTPClientTest.OnError(const msg: string; aSocket: TLSocket);
137+begin
138+ Form1.Memo2.Append(msg); // inform user of error
139+ FQuit := True; // and quit session.
140+end;
141+
142+procedure TLSMTPClientTest.OnSSLConnect(aSocket: TLSocket);
143+begin
144+ Form1.Memo2.Append('SSL session handshake was successful');
145+end;
146+
147+constructor TLSMTPClientTest.Create(aOwner: TComponent);
148+begin
149+ inherited;
150+ FQuit := False;
151+
152+ FSSL := TLSSLSession.Create(Self);
153+ FSSL.SSLActive := False; // make it "off" by default
154+ FSSL.OnSSLConnect := @OnSSLConnect; // let's watch if TLS/SSL handshake is ok
155+
156+ FSMTP := TLSMTPClient.Create(Self);
157+ FSMTP.Session := FSSL; // set the SSL session, so if it's a SSL/TLS SMTP we can use it
158+ FSMTP.Timeout := 100; // responsive enough, but won't hog CPU
159+ FSMTP.OnReceive := @OnReceive; // assign all events
160+ FSMTP.OnConnect := @OnConnect;
161+ FSMTP.OnDisconnect := @OnDisconnect;
162+ FSMTP.OnError := @OnError;
163+end;
164+
165+// Main SMTP processing loop
166+procedure TLSMTPClientTest.Run;
167+var
168+ Addr, Subject, Sender, Recipients, Message: string;
169+ Port: Integer;
170+begin
171+ Addr := '192.168.1.4'; // hard code my mailserver
172+ Port := 25; // hard code my SMTP port number
173+
174+ Sender := Form1.MailFromEdit.Text; // get info about email from Form1 edit fields
175+ Recipients := Form1.MailToEdit.Text;
176+ Subject := Form1.SubjectEdit.Text;
177+ Message := Form1.Memo1.Text;
178+
179+ Form1.Memo2.Append('Connecting to ' + Addr + ':' + IntToStr(Port) + '... ');
180+
181+ if FSMTP.Connect(Addr, Port) then
182+ repeat // try to connect
183+ FSMTP.CallAction; // if initial connect went ok, wait for acknowledgment/otherwise
184+ until FSMTP.Connected or FQuit; // if quit (eg error), or we connected, then continue
185+
186+ If(FQuit) then // if we need to quit because of a connection error
187+ exit; // exit now
188+
189+ while not FQuit do // do main loop
190+ begin
191+ FSMTP.Ehlo; // "Polite people say HELO first" (yeah, but nearly everyone is enhanced now)
192+ FSMTP.CallAction; // main event mechanism, must call periodicly and ASAP, or specify high timeout
193+ FSMTP.StartTLS; // ask for TLS
194+ FSMTP.SendMail(Sender, Recipients, Subject, Message); // send the email
195+ end;
196+ end;
197+
198+procedure TForm1.Button1Click(Sender: TObject);
199+begin
200+ Button1.Enabled := False; // disable button until session finished
201+ Memo2.Clear; // clear email log
202+ SMTP := TLSMTPClientTest.Create(nil);
203+
204+ Try
205+ SMTP.Run; // try to deliver the mail
206+ Finally
207+ SMTP.Free;
208+ Button1.Enabled := True; // enable button now session finished
209+ Memo1.Clear; // clear email content
210+ End;
211+end;
212+
213+end.
214+```
215+
216+![](/wiki-images/2/21/Lazarus_lnet_smtp_client_tls.png)
217+
218+Here's a copy of the transaction on the mail server for the above message:
219+
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`
232+
233+The full project source code is available for download from [SourceForge](https://sourceforge.net/p/lazarus-wiki-projects/code/ci/767b0a105a3ec6f4c8f54aab861984f7f90be81f/tree/laz_lnet_smtp/).
234+
235+## See also
236+
237+- [[lNet]]
238+- [[Synapse - Email Examples]]
239+- [RFC2821](https://www.ietf.org/rfc/rfc2821.txt) Simple Mail Transfer Protocol (SMTP)
240+- [RFC3207](https://www.ietf.org/rfc/rfc3207.txt) SMTP Service Extension for Secure SMTP over Transport Layer Security (TLS)
241+- [RFC5246](https://www.ietf.org/rfc/rfc5246.txt) The Transport Layer Security (TLS) Protocol Version 1.2
242+- [RFC8446](https://www.ietf.org/rfc/rfc8446.txt) The Transport Layer Security (TLS) Protocol Version 1.3
243+
244+---
245+*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).*
246+Category: Components
247+Category: Example programs
248+Category: Networking

Back to history