Building a Mailing List with Borland Delphi - How the program works
(Page 4 of 5 )
Now, this is basically how the program will work. After you have filled in the "from," "subject: and message fields, you will need to choose whether you want the message sent to everybody on the mailing list or to a specific group. When you select the "send to group" option, a listview component with a list of group names in it will appear, and when you click on a particular group name, another listview component will appear, listing all the email addresses in that group. There is also a option for you to add an attachment to a message; you just click on the "browse" button and it will open up a window with a list of files on the local disk.
When you click on the "Options" menu, you get two options to choose from:
Add a new contact - Brings up a new form that will take input.
View all email addresses- Lists all email addresses in the database.
When the program starts, we want a list of group names to be ready when the user selects the send to group option. So we make sure that the information is listed in the lvgroups listview component. Now, this component, together with the lvgroups and lvgrpemail listview components, is invisible at startup, and will only become visible when the user selects the "send to group" option as explained before. We set the visibility options in the forms' on show event:
Double click on the forms' Onshow event and add the following code:
procedure TForm1.FormShow(Sender: TObject);
var
li:tlistitem;
begin
lvgrpemails.Visible:=false;
lvgroups.Visible:=false;
query1.Close;
query1.SQL.Text:='SELECT * FROM groups';
query1.Open;
while not query1.Eof do begin
li:=lvgroups.Items.Add;
li.Caption:=query1.fieldbyname('groupname').AsString;
query1.Next;
end;
end;
The code above just makes some components invisible, and then runs a query to retrieve all the group names from the groups table. These names are made available in the lvgroups listview box.
When one of the radio buttons is selected, we need to make sure that the options that are available on the other one are unavailable to the user. This is because you can only choose one of the two options, not both. For example, when the "send to all" radio button is selected, we do not want the list boxes with the group names to be visible, because it will just be confusing and you don't really need it since you are going to send the message to everybody. So, on radio button one's Onclick event, add the following code:
procedure TForm1.rb1Click(Sender: TObject);
begin
if rb1.Checked then begin
lvgroups.Visible:=true;
end;
end;
And on radio button two's onclick event, add the following code:
procedure TForm1.rb2Click(Sender: TObject);
begin
lvgroups.Visible:=false;
if lvgrpemails.Visible=true then lvgrpemails.Visible:=false;
end;
Double click on the 'send mail' button and add the following code:
procedure TForm1.btnSentMailClick(Sender: TObject);
var
gname:string;
aID,left:integer;
begin
//setup idSMTP connection parameters
idSMTP.Host :='yourmail host'; //usually starting something
like mail.xxxxxx.com';
idSMTP.Port := 25; //smtp service usually runs on this port
idSMTP.Password:='yourpassword';
idSMTP.Username:='yourusername';
//setup idmessage
idmessage.From.address:=edFrom.Text;
idmessage.Subject :=edSubject.Text;
idmessage.Body.Text := memo1.Lines.Text;
//send mail
if not idsmtp.Connected then idsmtp.Connect;
//check which radio button is selected:
if rb1.Checked then begin
gname:=lvgroups.Selected.Caption;
query1.Close;
query1.sql.Text:='SELECT groupID FROM groups WHERE
groupname=:Aname';
query1.Parameters.ParamByName('Aname').Value:=gname;
query1.Open;
if query1.RecordCount > 0 then begin
aID:= query1.FieldByName('groupID').AsInteger;
query1.Close;
query1.sql.Text:='SELECT * FROM contacts WHERE gid=:AID';
query1.Parameters.ParamByName('AID').Value:=aID;
query1.Open;
re.Perform(EM_SETSEL, -1, -1);
re.SelAttributes.Color:= clGreen;
re.SelAttributes.Style:=[fsBold];
re.SelText:='Sending ' +inttostr(query1.RecordCount)+
' email messages to email addresses in group: ' + gname
+':'+ #13#10;
while not query1.Eof do begin
left:=query1.RecordCount -1;
re.Perform(EM_SETSEL, -1, -1);
re.SelAttributes.Color:= clGreen;
re.SelAttributes.Style:=[fsBold];
re.SelText:='Sending message#:'+inttostr(query1.RecNo)+' of ';
re.Perform(EM_SETSEL, -1, -1);
re.SelAttributes.Color:= clBlack;
re.SelText:=inttostr(query1.RecordCount)+#13#10;
idmessage.Recipients.EMailAddresses:=
query1.fieldbyname('email').Text;
try
idSMTP.send(idmessage);
except
on E: EIdSMTPReplyError do
begin
ShowMessage(E.Message);
end;
end;
query1.Next;
end;
re.Perform(EM_SETSEL, -1, -1);
re.SelAttributes.Color:= clRed;
re.SelAttributes.Style:=[fsBold];
re.SelText:='All messages have been successfully sent.';
end;
end;
if rb2.Checked then begin
query1.Close;
query1.sql.Text:='SELECT * FROM contacts ';
query1.Open;
while not query1.Eof do begin
re.Perform(EM_SETSEL, -1, -1);
re.SelAttributes.Color:= clGreen;
re.SelAttributes.Style:=[fsBold];
re.SelText:='Sending message#: ' +inttostr(query1.RecNo)+
' of ' ;
re.Perform(EM_SETSEL, -1, -1);
re.SelAttributes.Color:= clBlack;
re.SelText:=inttostr(query1.RecordCount)+#13#10;
idmessage.Recipients.EMailAddresses:=
query1.fieldbyname('email').Text;
try
idSMTP.send(idmessage);
except
on E: EIdSMTPReplyError do
begin
ShowMessage(E.Message);
end;
end;
query1.Next;
end;
re.Perform(EM_SETSEL, -1, -1);
re.SelAttributes.Color:= clRed;
re.SelAttributes.Style:=[fsBold];
re.SelText:='All messages have been successfully sent.';
if idsmtp.Connected then idsmtp.Disconnect;
end;
end;
This code is at the heart of the program. It actually does the donkey work of checking what choice you made when deciding who to send the message to. The first thing that it does is set the parameters needed to actually sent a email message. These parameters include a hostname, username and password. I've commented the code so you can see where exactly these parameters are used and how they are applied to the idsmtp component.
The next section of the code then checks which of the two methods of sending the email has been chosen. The first option is to send the message to a group. When this option is selected, the program caches the name of the group:
gname:=lvgroups.Selected.Caption;
and then runs a query to get the groupID of the groupname. This is important because you need the groupID from the groups table to retrieve all the email addresses in the "contacts" table that has the same groupid, as you will see in a moment :
query1.Close;
query1.sql.Text:='SELECT groupID FROM groups WHERE groupname=:Aname';
query1.Parameters.ParamByName('Aname').Value:=gname;
query1.Open;
if query1.RecordCount > 0 then begin
aID:= query1.FieldByName('groupID').AsInteger;
Now that you have the group ID stored in the "aID" variable, the next thing to do is to find all the email addresses in the contacts table that have the same groupID. In the contacts table the groupID is called "gid."
query1.Close;
query1.sql.Text:='SELECT * FROM contacts WHERE gid=:AID';
query1.Parameters.ParamByName('AID').Value:=aID;
query1.Open;
Now that we have all the email addresses in that group, we run a "while loop" to get them out of storage and then send the message to them one by one, while at the same time updating both the rich edit component and the memo2:
while not query1.Eof do begin
left:=query1.RecordCount -1;
re.Perform(EM_SETSEL, -1, -1);
re.SelAttributes.Color:= clGreen;
re.SelAttributes.Style:=[fsBold];
re.SelText:='Sending message#:'+inttostr(query1.RecNo)+' of ';
re.Perform(EM_SETSEL, -1, -1);
re.SelAttributes.Color:= clBlack;
re.SelText:=inttostr(query1.RecordCount)+#13#10;
idmessage.Recipients.EMailAddresses:=
query1.fieldbyname('email').Text;
Here's where you actually send the messages:
try
idSMTP.send(idmessage);
except
on E: EIdSMTPReplyError do
begin
ShowMessage(E.Message);
end;
end;
query1.Next;
end;
re.Perform(EM_SETSEL, -1, -1);
re.SelAttributes.Color:= clRed;
re.SelAttributes.Style:=[fsBold];
re.SelText:='All messages have been successfully sent.';
end;
end;
You might wonder what all this is about:
re.Perform(EM_SETSEL, -1, -1);
re.SelAttributes.Color:= clRed;
re.SelAttributes.Style:=[fsBold];
re.SelText:='All messages have been successfully sent.';
Well, this is basically how we get the richedit to show the different text in different colors. Here I'm telling the richedit component to display the text in bold red format. I use different colors to display different messages, as you will see in the screen shot below.
Here's a screen shot of a test run of the application:

Next: Status reports >>
More Delphi-Kylix Articles
More By Leidago