用C++BUILDER制作群发邮件程序
BCB是一种功能强大的WINDOWS环境编程工具,有着DELPHI的外表和C++的内涵。它提供了SMTP组件用于发送电子邮件,将繁琐的操作封装在组件内部,使程序员通过友好的界面就可以实现编程。我们来开发一个群发邮件的程序,通过实例学习BCB编程。
第一节:系统的功能特点和使用的组件
我们假设阅读者能够使用标准C编写小的应用程序,使用过诸如TURBO C之类的DOS时代的C编译系统;并且接触过C++BUILDER,初步了解常用组件的使用,能够做一个类似于传统C的“HELLO,WORLD”档次的小小程序。我们在实例中将学习MEMO、LISTBOX等文本编辑类控件、OPENDIALOG、SAVEDIALOG等对话框类控件和TIMER时间控件、TNMSMTP邮件发送控件的使用方法与技巧,不必担心,所讲的内容是很浅显易懂的,充分考虑到了BCB初学者的需要,对于一些控件的技术细节和编程中的技巧给出了详细的讲解,并且所用实例是一个完整的群发邮件程序的BCB源码,读者可以前后对照,学习编写一个完整的应用程序。
所用实例是东川花园系列软件的“飞花”群发邮件FAA1.0版本的源码,这是一个单SMTP发送的群发程序,提供了检测用EMAIL地址、“第一行问候语”等特色功能及良好的发送邮件管理文件的列表管理功能。完整的程序源码和可执行文件FAA10.EXE见“东川花园”(镜像站点:http://wlcjz.yeah.net、http://zycjz.163.net、http://zycjz.533.net)的“C++BUILDER小学”。
FAA1.0程序的设计思路是这样的:用SMTP控件可以很简单的实现一封邮件的发送,关键在于如何实现“群发”,也就是说,如何实现从BCC文件中读取EMAIL地址,连续不断的发送。程序采用了点击BUTTON1按钮发送一封邮件,然后在发送成功后的NMSMTP1Success()事件中,读取BCC文件中的规定数目的EMAIL地址作为BCC项目的内容并再次调用BUTTON1按钮的点击操作,实现新邮件的发送;新邮件发送成功后,再次触发NMSMTP1Success()事件,再次读取BCC文件并再次调用BUTTON1点击操作。如此循环,直至BCC文件中的邮件地址全部发完或用户终止操作。也许细心的读者会问,这样是不是一个递归操作?每次调用都会将上一次的调用数据压入堆栈,如果BCC文件足够大是不是会导致系统资源被耗尽而导致系统崩溃呢?事实确实如此,这也就是我们使用TIMER控件的原因,具体的解决方法会在后述章节中有详细说明。
一般用于群发的BCC文件都是非常大的,用户可能分多次发送,这就需要程序提供用户终止本次发送后“保护现场”的“发送邮件管理文件”,以备用户下次发送时,能够“恢复现场”,继续本次发送。FAA1.0程序中提供了列表管理模块实现这种功能。
我们共分五节来分析源码:(1)系统的功能特点和使用的组件;(2)发送按钮操作;(3)成功事件处理;(4)BCC文件的操作;(5)文件列表的操作。下面首先给出程序中主要用到的控件、函数、变量的列表。
/*------------主要用到的控件列表-------------*/
//<EDIT类>
TEdit *Edit1;//发件人姓名
TEdit *Edit2;//发件人邮件地址
TEdit *Edit5;//收件人姓名
TEdit *Edit6;//发件人邮件地址
TEdit *Edit7;//邮件主题
TEdit *Edit8;//发信检测用EMAIL
TEdit *Edit_one;//第一行问候语
TEdit *Edit3;//SMTP主机地址
TEdit *Edit4;//用户ID
TEdit *Edit9;//每次发送邮件的BCC单位数,介于1~100之间,默认为10
TEdit *Edit10;//BCC文件名
TEdit *Edit_bcc_begin;//读取BCC文件的开始字节
TEdit *Edit_bcc_end;//读取BCC文件的结束字节
TEdit *Edit_bcc_q;//读取BCC文件的当前字节
//<MEMO类>
TMemo *Memo1;//邮件正文
TMemo *Memo2;//当前发送邮件的BCC内容
TMemo *Memo3;//程序帮助内容
TMemo *Memo4;//当前选择的发送邮件管理文件的内容
TMemo *Memo5;//发送邮件情况的信息窗口
//<BUTTON类>
TButton *Button1;//开始发送按钮
TButton *Button2;//强制断开按钮
TButton *Button3;//退出系统按钮
TButton *Button4;//打开历史列表文件按钮
TButton *Button5;//保存当前设置到列表文件按钮
//<LISTBOX类>
TListBox *ListBox1;//邮件的附件(可多个)
TListBox *ListBox2;//发送邮件管理文件的列表
//<其他类>
TNMSMTP *NMSMTP1;//SMTP发送邮件控件,我们就依靠它工作啊!
TTimer *Timer1;//时间部件
TPanel *Panel3;//与服务器连接情况显示板
TOpenDialog *OpenDialog1;//打开文件对话框
TSaveDialog *SaveDialog1;//保存文件对话框
另外还有用于美化屏幕、显示状态的控件。
/*------------主要用到的函数列表-------------*/
void __fastcall Button1Click();//发送按钮的操作处理
void __fastcall NMSMTP1Success();//每次发送成功后的处理,涉及循环压栈的处理
void __fastcall Timer1Timer();//时间控件,为了处理循环压栈问题
void __fastcall Edit10KeyDown();//BCC文件被选择时的处理
void __fastcall ListBox1KeyDown();//邮件附件选择框
void __fastcall FormCreate();//窗体创建时加载发送邮件管理文件的列表
void __fastcall Button4Click();//打开历史列表文件,加载至内存,恢复当时的发送现场
void __fastcall Button5Click();//保存当前的发送现场到管理文件,并将管理文件加入列表
void __fastcall ListBox2KeyDown();//增删列表中的管理文件
void __fastcall ListBox2Click();//选定列表中的管理文件
void __fastcall Button3Click();//退出系统按钮,保存管理文件列表
另外用到的还有一些状态和数据的设置、显示用的函数:NMSMTP1ConnectionFailed()、Button2Click()、NMSMTP1Connect()、NMSMTP1Disconnect()、Edit9Change()、Edit_bcc_beginChange()、Edit_bcc_endChange()、FormClose()等。
/*------------主要用到的内存变量列表-------------*/
/*
zflag1 : 标志BCC文件是否已经打开
zflag2 :标志BCC发送单位数
zflag3 :发送成功的次数
zflag4 :总共发送成功的邮件数
zflag_limit:每发送200次进行一次特殊处理
zflag_limit_js:多少次特殊处理
zflag_file_b:BCC文件开始字节处
zflag_file_e:BCC文件结束字节处
fp: BCC文件句柄
fp1: 临时用文件句柄
*/
//begin for 全局变量
int zflag1=0,zflag2=10,zflag3=0,zflag4=0,zflag_limit=0,zflag_limit_js=0;
long int zflag_file_b=0,zflag_file_e=0,zflag_list=0;
FILE * fp,* fp1;
//end of 全局变量
//begin for 临时变量(因为程序中涉及循环压栈的问题,所以将这些不具有全局意义的临时变量也放在全局变量处定义,以减少运行时的内存占用)
char ch;
char ss[290],ss1[290],ss2[290],ss3[290],ss4[290],ach[180],filename[10],test[90];
int i=0,si=0,a1=0,a2=0,i1=0,i2=0,aa=10,j;
long i3;
//end of 临时变量
介绍完要用的控件和变量,将全局变量在ufaa1.cpp中定义如下。注意在文件首的include头文件中,STDLIB.H头文件包含exit()的定义;STDIO.H包含FILE结构的定义,这是传统C文件操作不可缺少的。如果不添加这两个头文件,那么exit()函数和传统C的I/O系统就无法使用。
我们要用到的文件除了ufaa1.cpp外,还有与之对应的ufaa1.h头文件,在那里面有我们所用的控件和函数的定义(声明),也就是“主要用到的控件列表”、“主要用到的函数列表”中出现的内容。另外与ufaa1.cpp单元文件对应的窗体文件是ufaa1.dfm文件。
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include <stdlib.h>
#include <stdio.h>
#include "ufaa1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
//全局变量定义开始
int zflag1=0,zflag2=10,zflag3=0,zflag4=0,zflag_limit=0,zflag_limit_js=0;
long int zflag_file_b=0,zflag_file_e=0,zflag_list=0;
FILE * fp,* fp1;
char ch;
char ss[290],ss1[290],ss2[290],ss3[290],ss4[290],ach[180],filename[10],test[90];
int i=0,si=0,a1=0,a2=0,i1=0,i2=0,aa=10,j;
long i3;
//全局变量定义结束
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
OK!从这里我们就要开始具体编写代码了,放轻松,这是一个快乐的过程,我们会很快就能编写一个实际的INTERNET应用程序,来吧,LET’S GO!
——————1/5 TO BE CONTINUE....
_____________________________________________________________________
题目:《用C++BUILDER制作群发邮件程序(1)》
作者:陈嘉洲
www.wlcjz.com