Delphi-Kylix
  Home arrow Delphi-Kylix arrow Page 3 - Creating a POP3 Server
Dev Articles Forums 
ADO.NET  
Apache  
ASP  
ASP.NET  
C#  
C++  
ColdFusion  
COM/COM+  
Delphi-Kylix  
Design Usability  
Development Cycles  
DHTML  
Embedded Tools  
Flash  
Graphic Design  
HTML  
IIS  
Interviews  
Java  
JavaScript  
MySQL  
Oracle  
Photoshop  
PHP  
Reviews  
Ruby-on-Rails  
SQL  
SQL Server  
Style Sheets  
VB.Net  
Visual Basic  
Web Authoring  
Web Services  
Web Standards  
XML  
Moblin 
JMSL Numerical Library 
IBM® developerWorks 
Sun Developer Network 
Weekly Newsletter
 
Developer Updates  
Free Website Content 
 RSS  Articles
 RSS  Forums
 RSS  All Feeds
Write For Us Get Paid 
Request Media Kit
Contact Us 
Site Map 
Privacy Policy 
Support 
 USERNAME
 
 PASSWORD
 
 
  >>> SIGN UP!  
  Lost Password? 
DELPHI-KYLIX

Creating a POP3 Server
By: Leidago
  • Search For More Articles!
  • Disclaimer
  • Author Terms
  • Rating: 5 stars5 stars5 stars5 stars5 stars / 13
    2006-04-26

    Table of Contents:
  • Creating a POP3 Server
  • Setting the database connections
  • Implementing the Commands
  • Implementing the Commands, continued
  • Conclusion

  • Rate this Article: Poor Best 
      ADD THIS ARTICLE TO:
      Del.ici.ous Digg
      Blink Simpy
      Google Spurl
      Y! MyWeb Furl
    Email Me Similar Content When Posted
    Add Developer Shed Article Feed To Your Site
    Email Article To Friend
    Print Version Of Article
    PDF Version Of Article
     
     
    ADVERTISEMENT


    Creating a POP3 Server - Implementing the Commands


    (Page 3 of 5 )

    Once you have all of the components in place and connected, click on pops and go to the object inspector. Click on the events tab, double click on "OnCheckUser" and add the following code:

    procedure TForm1.popsCheckUser(aContext: TIdContext;
      aServerContext: TIdPOP3ServerContext);
    begin
    coinitialize(nil);
     q2.Close;
    //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 :=
    aServerContext.Username;
            q2.Parameters.ParamByName('pwd').Value :=
    aServerContext.Password;
            q2.open;
    //if the user is not found, display an error...       
    if q2.RecordCount = 0 then raise Exception.Create('Authentication
    failed');
     couninitialize;
    end;

    The above procedure checks whether the username and password exist in the database.

    Next, we deal with the DELE(TE) command. The delete command is in the following format: DELE msgNo. Below is a example C(lient) request the S(erver) to delete msg numbers 1 and 2:

    C: DELE 1
                 S: +OK message 1 deleted
                    ...
    C: DELE 2
                 S: -ERR message 2 already deleted

     

    Double click on  OnDelete and add the following code:

    procedure TForm1.popsDelete(aCmd: TIdCommand; AMsgNo: Integer);
    var
    n1,n2:integer;
    Data:TStringList;
    begin
     Data := TStringList.Create;
            try
                ado1.Open;
    //Check if a valid message number has been requested...
                if (AMsgNo < 1) or (AMsgNo > ado1.RecordCount) then
                    raise Exception.Create('invalid message number');
                ado1.RecNo := AMsgNo;
                n2:=ado1.Fieldbyname('mid').AsInteger;
                n1:=1;
    //mark the message for deletion...
    q2.Close;
    q2.SQL.text:='UPDATE email SET ismarked=:num WHERE mid =:msgnum';
    q2.Parameters.ParamByName('num').Value:=n1;
    q2.Parameters.ParamByName('msgnum').Value:=n2;
    q2.ExecSQL;
    //Send a reply confirming that message has been deleted
                aCmd.Reply.SetReply(OK, 'message'+inttostr(amsgno)
    +'deleted');
                aCmd.SendReply; // <-- YOU MUST DO THIS BEFORE
    SENDING THE DATA
                //aCmd.Context.Connection.WriteRFCStrings(Data); //
    <-- INCLUDESTHE TERMINATING '.' LINE
            finally
               FreeAndNil(Data);
            end;

    Now, you do not actually delete the messages at this point. All that you do is mark them for deletion when the pop3client disconnects from the server. In the above code, to mark a message for deletion I insert "1" in the ismarked column of the table, so, when the pop3 client quits or disconnects, the server will automatically search for messages where the column ismarked is set to 1 for deletion. The way I checked the validity of the msgNo is by comparing the msgNo by the number of records (ado1.RecordCount) in the database. If the message number is  greater than the number of records, then an exception will be raised.

    Next is the RSET command. This resets (unmarks) any messages previously marked for deletion in this session so that the QUIT command will not delete them. Below is a short example:

    C: RSET
                 S: +OK maildrop has 2 messages (320 octets)

    That is the end of the example. Now for some real code:

    procedure TForm1.popsReset(aCmd: TIdCommand);
    var
    n1,n2,i:integer;
    begin
    n1:=1;//marked for deletion
    n2:=0;//not marked
    q2.Close;
    q2.SQL.text:='select * FROM email WHERE ismarked =:num';
    q2.Parameters.ParamByName('num').Value:=n1;
    q2.open;
    //there are messages marked for deletion
    if q2.RecordCount > 0 then begin
    for i:= 1 to q2.RecordCount do begin
    //reset unmark them
    q2.Close;
    q2.SQL.text:='UPDATE email SET ismarked=:num';
    q2.Parameters.ParamByName('num').Value:=n2;
    q2.ExecSQL;
    end;
    end;
     q2.Close;
    //get the count of message that is NOT marked
    q2.SQL.text:='select * FROM email WHERE ismarked =:num';
    q2.Parameters.ParamByName('num').Value:=n2;
    q2.open;
    //Sent off the count of messages that is not marked
     aCmd.Reply.SetReply(OK, inttostr(q2.RecordCount)+' messages
    available');
     aCmd.SendReply; // <-- YOU MUST DO THIS BEFORE SENDING THE DATA
    end;

    The LIST command lists all the messages with their message ID and the message size. Below is an example of the LIST command:       

                 C: LIST
                 S: +OK 2 messages (320 octets)
                 S: 1 120
                 S: 2 200
                 S: .
                   ...
                 C: LIST 2
                 S: +OK 2 200
                   ...
                 C: LIST 3
                 S: -ERR no such message, only 2 messages in maildrop

    That is the end of that example; now for some more code:

    procedure TForm1.popsList(aCmd: TIdCommand; AMsgNo: Integer);
    var
    msgnum,thesize:integer;
    begin
     CoInitialize(nil);
    q2.Close;
    q2.SQL.text:='SELECT SUM(msize) AS tsize from email';
    q2.open;
    //get the size of the total messages...
    thesize:=q2.fieldbyname('tsize').AsInteger;
     q2.Close;
    q2.SQL.text:='SELECT * from email';
    q2.open;
    //Get total number of messages
    msgnum:= q2.recordcount;
    //now, send a reply ...
    aCmd.Reply.SetReply(OK, inttostr(msgnum) + ' messages  '+'('+inttostr(thesize) + ' octets)');
         aCmd.SendReply;
     q2.Close;
    q2.SQL.text:='SELECT * from email';
    q2.open;
    q2.First;
    while not q2.EOF do
    begin
    with aCmd.Context.Connection.IOHandler do
    begin
    WriteLn(inttostr(q2.RecNo{.Fieldbyname('mid').Value}) +' '+
    inttostr(q2.Fieldbyname('msize').Value));
    q2.Next;
    end;//cmd
    end;//w
    aCmd.Context.Connection.IOHandler.writeln('.');
     CoUnInitialize;
    end;

    Sometimes pop3 clients include a msgNo with this command, in which case you will have to retrieve that specific message based on its msgNo. But generally this won't be the case.

    More Delphi-Kylix Articles
    More By Leidago


       · Is a good article. POP3 protocol is well explained. Why do not insert the entire...
       · The sample code included at the very beginning of the article contains all the code...
       · Can u help me on how can I creat a log on all message usinng POP3.
       · Not sure if you noticed but in the source code for this app there is a component...
       · Hi there,I can't send messages over the net. I mean, it works fine with internal...
     

    DELPHI-KYLIX ARTICLES

    - 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...
    - Using the Client Dataset in Two-Tiered Clien...
    - Using the Client Dataset in File-Based Archi...
    - Demystifying the Client Dataset
    - Working with INI Files in Delphi
    - Creating Data Link (UDL) Files in Delphi






    © 2003-2008 by Developer Shed. All rights reserved. DS Cluster 6 hosted by Hostway
    Stay green...Green IT