Creating an Email Client with Borland Delphi: conclusion - Code
(Page 3 of 4 )
Now that we got the GUI out of the way, let's start coding! First, to retrieve the messages from our email server, we have to connect to the server using a hostname, username and password. The idpop3 component (refered to here as pop) has a username, host and password properties that can be filled in by using the object inspector, but I prefer to do this programmatically. So, double click on the check messages button and type the following:
Before continuing add the following in the public section of the form:
FAttachPath: string;
li:tlistitem;
MsgCount, FMailBoxSize: integer;
Also, add: IdAttachmentFile, IdText, idglobal and idsync to the uses clause of the form.
procedure TForm1.Button1Click(Sender: TObject);
var
inindex:integer;
begin
//Setup connection
pop.Host:=yourhostname;
pop.Username:=yourusername;
pop.Password:=yourpassword;
//connect to the server
try
if not pop.Connected then
pop.Connect;
except
showmessage('Could not connect to pop server, please check your
connection details');
exit;
end;
//retrieve msgs
fmailboxsize:=pop.RetrieveMailBoxSize div 1024;
msgcount:=pop.CheckMessages;
statusbar1.Panels[0].Text:='Total Messages: '+inttostr(pop.CheckMessages);
if msgcount > 0 then
begin
pop.RetrieveHeader(msgcount,mess);
//announce that you have mail! THIS IS OPTIONAL!! YOU CAN JUST
DISPLAY A MESSAGEIF YOU WANT.
playsound('ar.wav',0,SND_ASYNC)
end
else
showmessage('No new messages on server');
{*******************Load messages and display in
listview**************}
list.Items.Clear;
for intindex:= 1 to msgcount do
begin
statusbar1.Panels[0].Text:=(format('Downloading Messages... %d of
%d', [intIndex, msgcount]));
Application.ProcessMessages;
Mess.Clear;
pop.RetrieveHeader(intIndex, Mess);
li:=list.Items.Add;
li.ImageIndex := 4;
li.Caption:= mess.From.text;
li.SubItems.Add(mess.Subject);
li.SubItems.add(formatdatetime('dd/mm/yyy hh:mm:ss',mess.Date));
li.SubItems.Add(IntToStr(POP.RetrieveMsgSize(intIndex))+'Kb');
statusbar1.Panels[0].Text:='Total Messages '+inttostr
(pop.CheckMessages);
end;
Double click on the "compose message" button and type the following:
procedure TForm1.Button3Click(Sender: TObject);
begin
form2.show;
end;
Let's step through the code: First, we connect to the server by supplying our connection credentials. Then we try to connect and if it fails, we show a message saying "check your connection details," otherwise we continue downloading the messages. We then go on to check how many email messages are currently on the server and display the number in the status bar. This is done by this line of code:
msgcount:=pop.CheckMessages;
statusbar1.Panels[0].Text:='Total Messages: '+inttostr
(pop.CheckMessages);
The next block of code checks whether the number of messages is more that 0, if so, it downloads the messages and shows the download progress on the statusbar as in:
statusbar1.Panels[1].Text:=(format('Downloading Messages... %d of
%d', [intIndex, msgcount]));
The remaining code just populates the listview and updates the statusbar accordingly.
Here's a sample run of the above event, with one message:

At the moment only a selected number of headers are shown (as above). What we are going to do next is get the full message. As you can see, the middle section of the application has label1 to 4 with appropriate names to the left. We are going to fill these labels and memo with the full message parameters, and also check to see whether the message has an attachment. Click on the listview component(lv1) and go to the object inspector. Click on the events tab, then double click on the onclick event and add the following code:
procedure TForm1.lv1Click(Sender: TObject);
var
s: string;
intIndex: Integer;
li: TListItem;
begin
//Prevent crash when there are no messages and user click's on
lv1
if lv1.Items.Count = 0 then begin
showmessage('No Messages');
exit;
end;
//clear all components
lvAttachments.Items.clear;
s:='';
memo1.clear;
//check if there are messages and if any is selected
if lv1.Items.Count > 0 then begin
lv1.Selected.SubItems.Strings[0];
//if msg is selected, retrieve it's headers
POP.Retrieve(lv1.Selected.Index+1 , Mess);
label2.Caption:=mess.from.Text;
label1.caption:=mess.Recipients.EMailAddresses;
label3.Caption:=mess.Subject;
label4.Caption:=FormatDateTime('dd mmm yyyy hh:mm:ss',
Mess.Date);
//add msg body to memo
memo1.lines.Add(mess.body.Text);
//Check for attachments
for intIndex := 0 to Pred(Mess.MessageParts.Count) do
begin
//if attachment found, add filename to lvattachment
if (Mess.MessageParts.Items[intIndex] is
TIdAttachmentFile) then
begin
li := lvAttachments.Items.Add;
li.ImageIndex := 0;
li.Caption := TIdAttachmentFile(Mess.MessageParts.Items[intIndex]).Filename;
li.SubItems.Add(TIdAttachmentFile
(Mess.MessageParts.Items[intIndex]).ContentType);
end
else
begin
//if no attachments, then add the text to memo
if Mess.MessageParts.Items[intIndex] is TIdText
then
Format(' > Mime format for text part%d is <%s>',
[intIndex,mess.MessageParts.Items[intIndex].ContentType]);
if Pos('text/plain',mess.MessageParts.Items
[intIndex].ContentType) <> 0 then begin
s:=s+TidText(mess.MessageParts.Items
[intIndex]).Body.Text ;
memo1.Lines.Add(s);
end
end
end;
end
end;
The meat of this code is to loop through the selected message and search for attachments. If one is found, it is retrieved and added to the lvattachment box; otherwise, just the text of the message is added to the memo. I think a bit more explanation is in order here.
The idmessage component that basically represents an email message usually contains several message parts. First, there is the text part. This part contains the actual text of a message. The second part normally contains attachments, but can also contain pictures, sound files, and so on. Different programming languages employ different methods of checking what these parts are and parse them accordingly. Take a careful look at how I've done the searching for these parts in the above code.
Here's a sample run of the application so far:

Next: Deleting a message >>
More Delphi-Kylix Articles
More By Jacques Noah