Home arrow Delphi-Kylix arrow Page 4 - Creating an SMTP Server
DELPHI-KYLIX

Creating an SMTP Server


A POP3 server only does half the job when it comes to email. In this article you will learn how to build an SMTP server.

Author Info:
By: Leidago
Rating: 5 stars5 stars5 stars5 stars5 stars / 17
May 08, 2006
TABLE OF CONTENTS:
  1. · Creating an SMTP Server
  2. · Setting the database connections
  3. · Optional
  4. · The Code
  5. · Conclusion

print this article
SEARCH DEVARTICLES

TOOLS YOU CAN USE

advertisement
Creating an SMTP Server - The Code
(Page 4 of 5 )

Take a look at the communication between an SMTP Server and a client. This is an intercept:

127.0.0.1:3976 Stat Connected.

127.0.0.1:3976 Sent 18/02/2006 18:03:57: 220 Welcome to SMTP Server<EOL>

127.0.0.1:3976 Recv 18/02/2006 18:03:57: EHLO LEIDAGO<EOL>

127.0.0.1:3976 Sent 18/02/2006 18:03:57: 250-Hello LEIDAGO
<EOL>250-AUTH LOGIN<EOL>250-ENHANCEDSTATUSCODES<EOL>250
PIPELINING<EOL>

127.0.0.1:3976 Recv 18/02/2006 18:03:57: AUTH LOGIN<EOL>

127.0.0.1:3976 Sent 18/02/2006 18:03:57: 334 VXNlcm5hbWU6<EOL>

127.0.0.1:3976 Recv 18/02/2006 18:03:57: amFjcXVlcw==<EOL>

127.0.0.1:3976 Sent 18/02/2006 18:03:57: 334 UGFzc3dvcmQ6<EOL>

127.0.0.1:3976 Recv 18/02/2006 18:03:57: bm9haA==<EOL>

127.0.0.1:3976 Sent 18/02/2006 18:03:57: 235 2.7.0  welcome
Leidago<EOL>

127.0.0.1:3976 Recv 18/02/2006 18:03:57: RSET<EOL>

127.0.0.1:3976 Sent 18/02/2006 18:03:57: 250 Ok<EOL>

127.0.0.1:3976 Recv 18/02/2006 18:03:57: MAIL FROM:
<admin@localhost><EOL>

127.0.0.1:3976 Sent 18/02/2006 18:03:57: 250 2.1.0
admin@localhost Address Okay<EOL>

127.0.0.1:3976 Recv 18/02/2006 18:03:57: RCPT
TO:<admin@localhost.com><EOL>

127.0.0.1:3976 Sent 18/02/2006 18:03:57: 250 2.1.5
admin@localhost.com Address Okay<EOL>

127.0.0.1:3976 Recv 18/02/2006 18:03:58: RSET<EOL>

127.0.0.1:3976 Sent 18/02/2006 18:03:58: 250 Ok<EOL>

127.0.0.1:3976 Recv 18/02/2006 18:03:58: RSET<EOL>

127.0.0.1:3976 Sent 18/02/2006 18:03:58: 250 Ok<EOL>

127.0.0.1:3976 Recv 18/02/2006 18:04:01: MAIL FROM:
<admin@localhost><EOL>

127.0.0.1:3976 Sent 18/02/2006 18:04:01: 250 2.1.0
admin@localhost Address Okay<EOL>

127.0.0.1:3976 Recv 18/02/2006 18:04:01: RCPT
TO:<admin@localhost.com><EOL>

127.0.0.1:3976 Sent 18/02/2006 18:04:01: 250 2.1.5
admin@localhost.com Address Okay<EOL>

127.0.0.1:3976 Recv 18/02/2006 18:04:01: DATA<EOL>

127.0.0.1:3976 Sent 18/02/2006 18:04:01: 354 Start mail input;
end with <CRLF>.<CRLF><EOL>

127.0.0.1:3976 Recv 18/02/2006 18:04:01: From: admin@localhost
<admin@localhost><EOL>Subject: hello<EOL>To:
admin@localhost.com<EOL>Date: Sat, 18 Feb 2006 18:03:57
+0000<EOL><EOL><EOL>

127.0.0.1:3976 Recv 18/02/2006 18:04:01: <EOL>.<EOL>

127.0.0.1:3976 Sent 18/02/2006 18:04:01: 250 Ok<EOL>

127.0.0.1:3976 Recv 18/02/2006 18:04:01: QUIT<EOL>

127.0.0.1:3976 Sent 18/02/2006 18:04:01: 221 Signing Off<EOL>

127.0.0.1:3976 Stat Disconnected.

0.0.0.0:0 Stat Disconnected.

************************** End intercept************************

I will heavily comment the code where it is not easy to work out what is happening.

This procedure is triggered when the server receives a message:

procedure TForm1.IdSMTPServer1MsgReceive(ASender:
TIdSMTPServerContext;
  AMsg: TStream; var LAction: TIdDataReply);
 var
 lmsg : TIdMessage;
 LStream : TFileStream;
 toad,from,sub,body:string;
 abuff:tstrings;
 six:int64;
  begin
 CoInitialize(nil);
//get message size..
  six:=amsg.Size;
  LStream := TFileStream.Create(ExtractFilePath
(Application.exename) + 'test.eml', fmCreate);
Try
//put message contents in LStream...
 LStream.CopyFrom(AMsg, 0);
Finally
 FreeAndNil(LStream);
End;
  mess.NoDecode:=true;
//Load the message into idMessage component
 mess.LoadFromFile('test.eml',false);
 label4.Caption:=datetostr(mess.Date);
  label1.Caption:=mess.Recipients.EMailAddresses;
  label2.Caption:=mess.From.Address;
  label3.Caption:=mess.Subject;
  memo1.Lines.Text:=mess.Body.Text;
//if mess.From.Address <> '' then begin
ado1.TableName:='email';
ado1.Active:=true;
ado1.Insert;
ado1.FieldByName('to').Text:=mess.Recipients.EMailAddresses;
ado1.FieldByName('from').Text:= mess.From.Address;
ado1.FieldByName('subject').Text:=mess.Subject;
ado1.FieldByName('mbody').AsString:=mess.Body.Text;
//Date: Wed, 1 Feb 2006 17:34:43 +0000
ado1.FieldByName('mdate').AsDateTime:=mess.Date;
ado1.FieldByName('msize').value:=six;
ado1.FieldByName('ismarked').value:=0;
ado1.Post;
CoUnInitialize;
//end;
end;

The message is received in a stream and is therefore stored physically on disk by the TFilestream method. It is loaded again to be stored in the database.

Next is  the rcptTo command, here you just validate the entered emailAddress. The Address is stored in the "AAddress: String;" bit of the procedure header.  All that I did here is to check that the entered email address contains a '@' character, since all email addresses have to contain one. If the email address contains a '@' character then Vaction is set to AddressOK, otherwise it's set to InValid or any of the responses outlined in the code below:

procedure TForm1.IdSMTPServer1RcptTo(ASender: TIdSMTPServerContext;
  const AAddress: String; var VAction: TIdRCPToReply;
  var VForward: String);
begin

  // The following actions can be returned to the server:
 {
    rAddressOk, //address is okay
    rRelayDenied, //we do not relay for third-parties
    rInvalid, //invalid address
    rWillForward, //not local - we will forward
    rNoForward, //not local - will not forward - please use
    rTooManyAddresses, //too many addresses
    rDisabledPerm, //disabled permanently - not accepting E-Mail
    rDisabledTemp //disabled temporarily - not accepting E-Mail
 }
  if Pos('@', AAddress) > 0 then  begin

 VAction := rAddressOk;
end
 else begin
  VAction :=rInvalid;
 end;
end;

procedure TForm1.IdSMTPServer1Received(ASender:
TIdSMTPServerContext;
  var AReceived: String);
begin
  // This is a new event in the rewrite of IdSMTPServer for Indy
10.
 // It lets you control the Received: header that is added to the
e-mail.
 // If you do not want a Received here to be added, set
AReceived := '';
 // Formatting 'keys' are available in the received header --
please check
 // the IdSMTPServer source for more detail.
 AReceived := '';
end;

procedure TForm1.IdSMTPServer1UserLogin(ASender:
TIdSMTPServerContext;
  const AUsername, APassword: String; var VAuthenticated:
Boolean);
begin
 // This event is fired if a user attempts to login to the server
 // Normally used to grant relay access to specific users etc.
//Search for the username and password in "users" table..
q2.SQL.Text := 'SELECT * from users WHERE uname=:user AND
upass=:pwd';
        q2.Parameters.ParamByName('user').Value :=AUsername;
        q2.Parameters.ParamByName('pwd').Value := APassword;
        q2.open;
//if the user is not found, set authentication to false
if q2.RecordCount = 0 then begin

VAuthenticated := False;
 end else begin
 VAuthenticated := True;
 end;
end;

Same as RcptTo, check if the email address contains a '@'
character and reply accordingly...

procedure TForm1.IdSMTPServer1MailFrom(ASender:
TIdSMTPServerContext;
  const AAddress: String; var VAction: TIdMailFromReply);
begin
 // Here we are testing the MAIL FROM line sent to the server.
 // MAIL FROM address comes in via AAddress. VAction sets the
return action to the //server.
// The following actions can be returned to the server:
 { mAccept, mReject }

   if Pos('@', AAddress) > 0 then  begin
 VAction:= mAccept;

 end
 else begin
  VAction := mReject;
 end;   
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
idsmtpserver1.Greeting.SetReply(220,'Welcome to SMTP Server');
end;

procedure TForm1.IdSMTPServer1Execute(AContext: TIdContext);
begin
logfile.DoLogWriteString(acontext.Connection.IOHandler.ReadLn);
end;

procedure TForm1.IdSMTPServer1Exception(AContext: TIdContext;
  AException: Exception);
begin
acontext.Connection.IOHandler.Write(aexception.Message);
end;


blog comments powered by Disqus
DELPHI-KYLIX ARTICLES

- Loading an XML Document into the DOM
- Delphi Wrapper Classes and XML
- Delphi and the DOM
- Delphi and XML
- Internet Access: Client Service
- Finishing the Client for an Internet Access ...
- The Client for an Internet Access Control Ap...
- User Management for an Internet Access Contr...
- Important Procedures for an Internet Access ...
- Server Code for an Internet Access Control A...
- Constructing the Interface for an Internet A...
- Building a Server Application for an Interne...
- Building an Internet Access Control Applicat...
- Client Dataset: Working with Data Packets an...
- Using the Client Dataset in an N-Tiered Appl...

Dev Articles Forums 
 RSS  Articles
 RSS  Forums
 RSS  All Feeds
Weekly Newsletter
 
Developer Updates  
Free Website Content 
Contact Us 
Site Map 
Privacy Policy 
Support 



© 2003-2012 by Developer Shed. All rights reserved. DS Cluster 2 - Follow our Sitemap
Popular Web Development Topics
All Web Development Tutorials