别人的贴
如何批量发送电子邮件
本文将实现如何编写简单的应用程序向邮件订阅者发送内容一样或者内容基本一样的电子邮件。
一、 软件准备
读者应该拥有一份C++ Builder3.0或者Delphi 4.0或以上版本的拷贝。另外,还要有一份支持ODBC接口的数据库拷贝,例如:Microsoft Access、Paradox、dBase、Microsoft SQL Server、IBM DB2、Oracle等等。该数据库可以是平面文件数据库,也可以是关系型数据库。在本文中使用的是Delphi 5.0和Microsoft Access。二、数据库设计该email数据库中共有三个表:User表,Subject表,link表,各个表的字段格式如下:
link表的UserID字段引自User表的ID字段,Subscribe表的SubjectID字段引自Subjectx表的ID字段。如果您使用的数据库支持Trigger,mjh yidd Insert、Update、Delete的Trigger使User表和Subject表的ID字段具有唯一的值。
三、 程序设计过程
本程序需要的组件有:TdataBaseTquery、NMSmtp、TListBox组件。其中,Tquery组件负责数据库的查询工作,TdataBase负责数据库的连接工作,TListBox组件用来显示查询结果,NMSmtp组件用来发送E-Mail信息。
本程序实现的功能有:
1. 根据用户订阅的邮件主题,从数据库中查询出要发送的用户名称,电子邮件地址;
2. 在已经查询出的用户中进行进一步的调节;
3. 载入邮件正文,保存邮件正文;
4. 发送邮件;
5. 进行邮件发送状态的记录并保存。
四、具体的设计细节
本程序的VCL组件的属性:
DataMOdule1,数据窗口。此外,还需要三个eidt文本框(分别输入发信人姓名、发信人邮件地址、邮件主题),及一个memo邮件正文输入域。
Form2窗口,用户配置界面。需要注意的是,其中的Groupbox1和Groupbox2的Visible设为false,在查询出用户信息后再显示这些组件。
1. 查询数据库
在配置用户信息的窗体的FormCreat事件中,需要将数据库中的所有的邮件主题查询出来,显示在一个ComboBox组件中。其主要代码如下:
procedure TForm2.FormCreate(Sender: TObject);
var
i:integer;
begin
Query1.Active:=false; //在对TQuery组件进行查询之前,必须要关闭TQuery组件,或者将其属性Active设为false;
Query1.Active:=true; //打开TQuery组件
for I:=0 to Query1.RecordCount-1 do
begin
ComboBox1.Items.Add(Query1.FieldValues[‘subject']); //将查询主题加入到TComboBox中
Query1.Next;
end;
Query1.First; //将TQuery的记录设为第一条
ComboBox1.Text:=ComboBox1.Items[0];
end;
然后再根据ComboBox1中的主题查询用户和用户邮件地址。
procedure TForm2.Button1Click(Sender: TObject);
var
i:integer;
begin
listbox1.Clear;
listbox2.Clear; //清除两个ListBox中的内容,进行新的一次查询
Query1.Active:=false;
Query1.SQL.Clear;//清除TQuery的SQL语句
if not checkbox1.checked then//如果选择发送给订阅相应主题的用户
begin
Query1.SQL.Add(‘SELECT user.username, user.address, subject.subject '+‘FROM (link INNER JOIN subject ON link.subjectid = subject.subjectid) INNER JOIN user ON link.userid = user.userid ' +‘WHERE (((subject.subject)=:subject))');
Query1.Params[0].AsString:=ComboBox1.Text;//设置SQL中的主题参数
end
else //如果选择发送给全部用户
Query1.SQL.Add(‘select user.username,user.address from user');
Query1.Prepare;
Query1.Open;
for i:=0 to Query1.RecordCount-1 do
beginListBox1.Items.Add(expend(vartostr(Query 1.fieldvalues[‘username']))+vartostr(Query1.FieldValues[‘address']));
//在订阅用户框中显示查询到的用户信息
Query1.Next;
end;
label4.caption:=‘共有'+inttostr(listbox1.Items.Count)+‘项';
label5.Caption:=‘共有'+inttostr(listbox2.Items.Count)+‘项';//显示查询到的用户数量
GroupBox3.Visible:=true;
GroupBox2.Visible:=true;
Form2.Height:=554;
end;
2. 调整用户信息
双击需要发送的用户框中的条目,将其去掉;同样,双击不需要发送的用户框中的条目,将其加入发送用户框中,这部分代码相当简单,在此略去。
3. 保存、载入邮件正文
本程序中邮件正文是显示在TMemo1中的,保存和载入邮件正文可以使用TMemo1.lines.loadfromfile(string filename)方法及TMemo1.lines.savetofile(filenname)方法。实现代码如下:
载入邮件正文:
procedure TForm1.Button2Click(Sender: TObject);
begin
if (datasmtp.DataModule1.OpenDialog1.Execute) then
begin
Memo1.Lines.LoadFromFile(datasmtp.DataModule 1 .OpenDialog1.FileName);
end;
end;
保存邮件正文:
procedure TForm1.Button3Click(Sender: TObject);
begin
if (datasmtp.DataModule1.SaveDialog1.Execute) then
begin
Memo1.Lines.SaveToFile(datasmtp.DataModule 1.SaveDialog1.FileName);
end;
end;
4. 发送邮件
发送邮件使用的是Delphi和C++Builder中的VCL组件TNMSMTP,在此组件中封装了发送邮件的各种属性、方法和事件,其中PostMessage包含将要发送的邮件的相关信息,PostMessage中包括Attackments(邮件附件信息)、body(邮件正文)、Date(邮件发送日期)、FromAddress(发信人邮件地址)、FromName(发信人姓名)、LocalProgram(发送邮件程序的名称)、ReplyTo(回信地址)、subject(邮件主题)、ToAddress(收信人地址)、ToBlindCarbonCopy(邮件暗送地址)、ToCarbonCopy(邮件抄送地址)。此外,TNMSMTP的重要属性和方法有:Connected(是否与邮件服务器连接上)、Host(指定邮件服务器地址)、Port(端口号,默认为25)、Connect(与Host指定的服务器连接)、sendmail(发送邮件)。发送邮件的代码如下:
procedure TForm3.Button3Click(Sender: TObject);
var
i:integer;
begin
with datasmtp.DataModule1.smtp.PostMessage do
begin
FromAddress:=form1.edit2.Text;
FromName:=form1.edit1.Text;
Subject:=form1.edit3.text;
Body.Text:=form1.memo1.Text;
end;
with datasmtp.DataModule1.smtp do
begin
for i:=0 to form2.ListBox1.Items.Count-1 do
begin
PostMessage.ToAddress.Clear;
PostMessage.ToAddress.Add(getaddress(form2.List Box1.items));
Host:=gethost(getaddress(form2.ListBox1.Items));
try
datasmtp.DataModule1.smtp.Connect;
except
end;
if datasmtp.datamodule1.smtp.connected then
datasmtp.DataModule1.smtp.SendMail;
end;
end;
end;
5. 记录邮件发送状态并保存日志
使用TNMSMTP的各种事件(如,OnConnect、OnConnectFailed、OnFailure、OnHostResolved等等)记录邮件发送状态。实现过程请参见下面的代码:
procedure TDataModule1.smtpConnect(Sender: TObject);
var
s:string;
begin
s:=timetostr(time)+‘正在连接'+smtp.Post Message.ToAddress.Strings[0]+‘的服务器,请稍候!';
form3.Label1.Caption:=s;
form3.Memo1.Lines.Add(s);
end;
procedure TDataModule1.smtpConnectionFailed(Sender: TObject);
var
s:string;
begin
s:=timetostr(time)+‘连接'+smtp.Post Message.ToAddress.strings[0]+‘的服务器失败!';
form3.Label1.Caption:=s;
form3.Memo1.lines.add(s);
end;
procedure TDataModule1.smtpSendStart(Sender: TObject);
var
s:string;
begin
s:=timetostr(time)+‘开始发送给'+smtp.postmessage.ToAddress.strings[0]+‘的邮件!';
form3.Label1.Caption:=s;
form3.memo1.lines.add(s);
end;
procedure TDataModule1.smtpSuccess(Sender: TObject);
var
s:string;
begin
s:=timetostr(time)+‘成功发送给'+smtp.postmessage.ToAddress.strings[0]+‘的邮件!';
form3.Label1.Caption:=s;
form3.memo1.Lines.add(s);
end;
procedure TDataModule1.smtpInvalidHost(var Handled: Boolean);
var
s:string;
begin
s:=timetostr(time)+‘:发送邮件给'+smtp.PostMessage.ToAddress.strings[0]+‘时,服务器'+smtp.Host+‘无效!';
form3.Label1.Caption:=s;
form3.memo1.lines.add(s);
end;
procedure TDataModule1.smtpFailure(Sender: TObject);
var
s:string;
begin
s:=timetostr(time)+‘:给'+smtp.PostMessage.ToAddress.strings[0]+‘的邮件发送失败!';
form3.Label1.Caption:=s;
form3.memo1.Lines.add(s);
end;
procedure TDataModule1.smtpHostResolved(Sender: TComponent);
var
s:string;
begin
s:=timetostr(time)+‘:已经解析出'+smtp.PostMessage.ToAddress.strings[0]+‘的邮件服务器地址!';
form3.Label1.Caption:=s;
form3.memo1.Lines.add(s);
end;
保存日志的代码如下:
procedure TForm3.Button1Click(Sender: TObject);
begin
datasmtp.DataModule1.SaveDialog1.FileName:=datetostr(date)+‘邮件日志.txt';
if datasmtp.DataModule1.SaveDialog1.Execute then
memo1.Lines.SaveToFile(datasmtp.DataModule1.SaveDialog1.FileName);
end;
使用TNMSMTP组件我们可以方便地实现批量发送电子邮件的功能,而如果将其组件使用在NSAPI中,加上高度的密码控制,我们就可以实现一个像在线邮局263一样的提供邮件服务的网站了。除了发送纯文本的邮件之外,TNMSMTP组件还可以通过TpostMessage中的Attachments属性粘贴附件,从而实现其他格式的文件发送。在本文的源代码中已经加上了发送附件的功能,请参考源程序 。另外,本文中的SMTP服务器是smtp.加上服务器主机名,如huangjiansword@263.net的服务器就是smtp.263.net,如果您的smtp服务器不是这种规则,请修改源程序。
本程序使用Delphi5.0,在Windows98中文版下调试通过。