
华中大邮箱
-
2023年3月18日发(作者:晶粒度)电子邮件系统的设计与实现
第一章前言
1.1课题来源
当前流行的各大邮件客户端软件除了最主
要的收发信件之外,功能越来越复杂,但是人们
平常真正用到的功能很少,很多功能尤其对于那
些计算机知识相对缺乏的人来说,更加显得太过
于华丽而不太实用。有鉴于此,在了解RFC底
层协议的基础上,本人开发了这个各种功能相对
简单实用的邮件客户端程序,简化了很多不必要
的功能。
1.2电子邮件介绍
电子邮件(简称E-mail)又称电子信箱、电
子邮政,它是一种用电子手段提供信息交换的通
信方式。它是全球多种网络上使用最普遍的一项
服务。这种非交互式的通信,加速了信息的交流
及数据传送,它是一个简易、快速的方法。通过
连接全世界的Internet,实现各类信号的传送、
接收、存储等处理,将邮件送到世界的各个角落。
到目前为止,可以说电子邮件是Internet资源使
用最多的一种服务,E-mail不只局限于信件的传
递,还可用来传递文件、声音及图形、图像等不
同类型的信息。
电子邮件不是一种“终端到终端”的服务,是
系统的硬件是一个高性能、大容量的计算
机。硬盘作为信箱的存储介质,在硬盘上为用户
分一定的存储空间作为用户的“信箱”,每位用户
都有属于自己的一个电子信箱。并确定一个用户
和用户可以随意修改的口令。存储空间包含存放
所收信件、编辑信件以及信件存盘三部分空间,
用户使用口令开启自己的信箱,并进行发信、读
信、编辑、转发、存档等各种操作。系统功能主
要由软件实现。
1.4开发环境及运行环境
1.4.1开发环境
AMDAthlom(TM),512内存,80G硬盘
Microsoft(R)WindowsXPProfessional
MicosoftVisualStudio2003(CSharp)
MicosoftDeveloperNetworkforVisualSt
2003
1.4.2运行环境
Internetpentium2及以上处理器,32M以上
内存,4G以上硬盘
Micosoftwindows9X/NT操作系统
800*600或以上的屏幕分辨率
华中农业大学本科毕业论文(或设
计)
5
确保机器上安装有.NetFrameWork1.0或者
以上版本
第二章系统需求分析
2.1系统功能需求分析
电子邮件系统需求实现的功能包括新
建用户的帐号,接受简单邮件或带附件的邮件,
发送简单邮件或发送带附件的邮件,电子邮件编
号,电子邮件分类管理,通信薄管理。为了使用
通信薄,于是添加了对用户资料的增加,修改,
取消操作。
2.1.1软件的总体架构
图1软件构架图
2.1.2系统功能
发送接
主要功
主
用
华中农业大学本科毕业论文(或设
计)
6
图2系统功能图
2.1.3系统总体用例图
图3系统总体用例图
2.2数据库需求分析
在对系统进行系统需求分析的基础上,可以得
到系统在处理数据时会用到下面所示的数据项
和数据结构:
1)用户信息:帐号名称,用户名,密码,电子
邮箱地址,SMTP服务器,SMTP端口号,POP3
客户
电子电子附加各种
简
单
邮
件
带
有
附
件
简
单
邮
件
带
有
附
件
电
子
邮
件
电
子
邮
件
用
新建
发送
纯文
带附
接收
通
讯
薄
管
华中农业大学本科毕业论文(或设
计)
7
服务器,POP3端口号。
2)通信薄信息:姓名,邮箱地址,电话号码,
QQ号,手机号码,通信地址。
第三章系统设计
3.1系统的流程设计
邮件客户端最重要的两个功能就是接收邮
件和发送邮件,其中接收邮件的流程图如图4所
示。从流程图中可以看出,接收邮件时首先要创
建一个TCP连接到POP3服务器。如果连接不
成功就退出执行,连接成功后再发送USER和
PASS命令进行身份验证,身份验证通过后再通
过STAT命令获得要接收的邮件数,当邮件数大
于0时,通过RETR命令逐个接收邮件。接收
邮件完毕后,检查帐号中是否保留服务器上的邮
件设置,如果是就不作任何操作,否则从服务器
上删除已经接受的邮件。最后关闭连接。完成邮
件接收。
华中农业大学本科毕业论文(或设
计)
8
图4接收邮件流程图
发送邮件的流程图,先检查“发信箱”目录
中是否有待发邮件,如果有就逐个发送这些邮
件,流程图如图5所示。其发送过程,首先需要
创建一个TCP连接,连接到SMTP服务器,如
开始
连接服务器
连接成功?
登录服务器
登陆成功
获得邮件数目
邮件数>0
接受全部的邮件
保留服务器上
的邮件?
删除邮件
关闭
退
华中农业大学本科毕业论文(或设
计)
9
果连接不成功就退出程序。连接成功后发送
USER和PASS命令进行身份验证。身份验证通
过后发送邮件,如果发送成功就关闭连接,更新
数据库,完成邮件发送任务。
开
检查发信箱中的待
发邮件
待发邮件?
连接
连接成功
SMTP服务器需要身份
验证?
身份验证
身份验证
成功?
发送待发邮件
发送成功
关闭
更新
获得下一个邮件
退出
华中农业大学本科毕业论文(或设
计)
10
图5发送邮件流程
图
3.2SMTP协议的研究
由于要开发的是邮件客服端程序,就不得不用
到SMTP协议和POP协议。而我个人负责
的是邮件发送功能的实现,因此就必然会涉及到
SMTP(SimpleMailTransferProtocol)协议。
SMTP被用来在因特网上发送邮件,该协议规定
了一些基本的命令和方法使客服端与服务器进
行交互,以达到发送邮件的目的。
3.2.1SMTP介绍
简单邮件传输协议(SMTP)的目标是可
靠高效地传送邮件,它独立于传送子系统而且仅
要求一条可以保证传送数据单元顺序的通道。
SMTP的一个重要特点是它能够在传送中
接力传送邮件,传送服务器提供了进程间通信环
境(IPCE),此环境可以包括一个网络,几个网
络或一个网络的子网。理解到传输送系统(或
IPCE)不是一对一的是很重要的。进程可能直
接和其它进程通过已知的IPCE通信。邮件是一
个应用程序或进程间通信。邮件可以通过连接在
华中农业大学本科毕业论文(或设
计)
11
不同IPCE上的进程跨网络进行邮件传送。更特
别是,邮件可以通过不同网络上的主机接力式传
送。
3.2.2SMTP模型
SMTP设计基于以上通信模型:针对用户的邮
件请求,发送SMTP建立于接收SMTP
之间建立一个双向传送通道。接收SMTP可以
是最终接收者也可以是中间传送者。SMTP命令
由发送SMTP发出,由接收SMTP接收,而应
答则反方面传送。
一旦传送通道建立,SMTP发送者发送MAIL
命令指明邮件发送者。如果SMTP接收者可以
接收邮件则返回OK应答。SMTP发送者再发出
RCRT命令确认邮件是否接收到。如果SMTP
接收者接收,则返回OK应答;如果不能接收到,
则发出拒绝接收应答(但不中止整个邮件操作),
双方将如此重复多次。当接收者到全部邮件后会
接收到特别的序列,如果接收者成功处理了邮
件,则返回OK应答。
SMTP提供传送邮件的机制,如果接收方与发
送方连接在同一个传送服务下时,邮件可以直接
由发送方主机传送到接收方主机;或者,当两者
华中农业大学本科毕业论文(或设
计)
12
在不同一个传送服务下时,通过中继SMTP服
务器传送。为了能够对SMTP服务器提供中继
能力,它必须拥有最终目的主机地址和邮箱名
称。
MAIL命令参数是回复路径,它指定邮件从何
处来;而RCPT命令的参数是转发路径的,它
指定邮件向何处去。向前路径是源路径,而回复
路径是返回路径(它用于发生错误时返回邮件)。
当同一个消息要发往不同的接收者时,SMTP
遇到了向不同接收者发送同一份数据的复制品
的问题,邮件命令和应答有一个比较奇怪的语
法,应答也有一个数字代码。在下面,例子中可
以看到哪些使用实际的命令和应答。完整的命令
和应答在第四节。
命令与应答对大小写不敏感,也就是说,命令
和应答可以是大写,小写或两者的混合,但这一
点对用户邮件名称却不一定是对的,因为有的主
机对用户名大小写是敏感的。这样SMTP实现
中就将用户邮箱名称保留成初始时的样子,主机
名称对大小写不敏感。
命令与应答由ASCII字母表组成,当传送服
务提供8位子节传送通道,每7位字符正确传送,
华中农业大学本科毕业论文(或设
计)
13
而最高位被填充为0。当指定一般的命令或应答
格式后,参数会由一些类似于语言的字符串表示
出来,如“”或“”,这里
尖括号表示这是一种类似于语言的变量。
3.3SMTP协议的命令和应答
3.3.1SMTP协议的命令
SMTP命令定义了邮件传输或用户定义的系
统功能。它的命令是由结束的字符串。
而在带有参数的情况下,命令本身由和参
数分开,如果未带参数可以直接和连
接。邮箱的语法格式必须和接收站点的格式一
致。
3.3.2SMTP的应答码
对SMTP命令的响应是多样的,它确定了在
邮件传输过程中请求和处理的同步,也保证了发
送SMTP知道接收SMTP的状态。每个命令必
须有且只有一个响应。
SMTP响应由三位数字组成,其后跟一些文
本。数字帮助决定下一个应该进入的状态,而文
本对人是有意义的。三位的响应已经包括了足够
的信息,不用再阅读文本,文本可以直接抛弃或
者传递给用户。特别的是,文本是与接收和环境
华中农业大学本科毕业论文(或设
计)
14
相关的,所以每次接收到的文本可能不同。正规
的情况下,响应由下面序列构成:三位的数字,
,一行文本和一个,或者也可以是一
个多行响应。只有EXPN和HELP,命令可以导
致多行应答,然而,对所有命令,多行响应都是
允许的。
REPLYCODESBYFUNCTIONGROUPS500
格式错误,命令不可识别(此错误也包括命令行
过长)
第四章RFC822
说到发送和接收邮件,就不得不提RFC822
了。RFC822的全称是“ARPA因特网文信件格
式的标准”(StandardfortheFormatofARPA
InternetTextMessages)。该标准提供了邮件内
容的格式和相关语义。
4.1RFC822简单介绍
RFC822规定的电子邮件内容全部由ASCII
字符组成,就是通常所说的文本文件,因而标准
将它称为Internet文本信件(InternetText
Messages)。
从直观上看,信件非常简单,就是一系列由
华中农业大学本科毕业论文(或设
计)
15
ASCII字符组成的文本行,每一行以回车换形符
结束。
从组织上看,信件内容结构分为两大部分,
中间用一个空白行(只有CRLF符的行)来分
隔。第一部分称为信件的头部,包括有关发送方、
接收方、发送日期等信息。第二部分称为信件的
体部,包括信件内容的正文文体。信头是必需的,
信体是可选的,即信体可有可无。如果不存在信
体,用作分隔的空白行也就不需要。在信体中,
也可以有用作分隔的空白行。这样设计的信件便
于进行语法分析,提取信件的基本信息。
在RFC822中规定,信件体就是一系列的向
收信人表达信息的文本行,比较简单,可以包括
任意文本。并没有附加的结构。信件头则具有比
较复杂的结构,在下一小节中详述。
4.2信件的头部
4.2.1信头一般格式
信头的结构比较复杂,信头由若干信头字段
(headerfield)组成,这些字段为用户和程序提
供了关于信件的信息。要了解信头的结构就要弄
清楚各种信头字段。
所有的信头字段都具有相同的语法结构,从逻
华中农业大学本科毕业论文(或设
计)
16
辑上说,包括四部分,字段名(fieldname)紧
跟冒号“:”(colon),后跟字段体(fieldbody),
最后以回车换形符(CRLF)终止。即
信头字段=字段名:字段体CRLF
字段名必须由除了冒号和空格以外的可打印
US—ASCII字符(其值在33和126之间)组成,
大多数字段的字段名称由一系列字母,数字组
成,中间经常插入横线符。字段名告诉电子邮件
软件如何翻译该行中剩下的内容。
字段体可以包括除了CR和LF之外的任何
ASCII字符。但是其中的格式的空格,加括号的
注释,引号和多行都比较复杂,另外,字段体的
语法和语义依赖于字段名,每个类型的字段有特
定的格式。
4.2.2结构化字段和非结构化字段
每个字段包含的信息不同,字段大体可以分为
结构化字段和非结构化字段。结构化字段有特定
的格式,由语法分析程序检测。Sender字段就
是一个很好的例子,它的字段内容是信箱,有一
个离散的结构。
非结构化的字段含有任意的数据,没有固定格
式。例如,Subject字段可以含有任意的文字,
华中农业大学本科毕业论文(或设
计)
17
并且没有固定格式。非结构化的字段数量较少,
只有Subject、Comments、扩展字段、非标准字
段、IN—Reply和References等。所有其它字段
都是结构化的。
4.2.3信头字段的元素
尽管Email信件的总体结构非常简单,但一些
信头字段的结构是很复杂的。下面介绍一些大多
数字段共有的元素。
(1)空白符
像其它文本文件一样,空白符包括空格符
(ASCII码32)和制表符TAB(ASCII码19)
此外,行末的回车换形符CRLF也应算是空白
符。使用空白符可以对字段进行格式化,增加
它的可续性。例如,每个字段间用CRLF来分
离,在字段内用空格来分隔字段名和字段内容。
在Subject后面的冒号和内容之间插入空格字
符,会使字段结构更加清晰。在Email中。空
白符的使用并没有固定的规则,但应当正确地
使用,仅在需要时才使用空白符,以便接收软
件进行语法分析。
(2)注解
注解是由括号括起来的一系列字符,例如,
华中农业大学本科毕业论文(或设
计)
18
(这份礼物)。注解一般用在非结构化的信头字
段中,没有语法语义,仅为人提供了一些附加
的信息。如果在加引号的字符串中包括在括号
中的字符,那是字符串的一部分,不是注解。
在解释信件的时候,会将注解忽略,可以用一
个空格字符代替它们,这样就什么也不会破坏。
(3)字段折叠
每个信头字段从逻辑上说应当是一个由字
段名、冒号、字段体和CRLF组成的单一的行,
但为了书写与显示的方便,增加可续行,也为
了符号1000/80的行字符数的限制,可以将超
过80个字符的信头字段分为多行,即对于比较
长的字段,可以分割成几行,形成折叠。在结
果化和非结构化字段中都允许折叠,第一行后
面的行称为信头字段的续行。续行都以一个空
白符开始,这种方法称为折叠(folding),例如
标题字段Subject:Thisisatest可以表示为:
Subject:Thisisatest
反之,将一个被折叠成多行的信头字段恢复到
它的单行表示的过程叫做去折叠,只要简单地移
除后面跟着空格的CRLF,将折叠空白符CRLF
转换成空格字符,就可以完成折叠。在分析被折
华中农业大学本科毕业论文(或设
计)
19
叠的字段的语法时,要把一个多行的折叠字段展
开为一行,根据它的非折叠的形式来分析它的语
法与语义。
(4)字段大小写
字段名称是不区分大小写的,所以Subject、
subject或SUBJECT都一样。不过字段名称大
小写有习惯的常用形式,如主题字段的大小写形
式通常为Subject。字段体的大小写稍微复杂点,
要视情况而定。比如Subject后面的字段体,其
中的大写可能就是缩写的专用名词,不能改动。
(5)扩展字段
如果想在信头中加入RFC822中没有规定的
字段,就需要创建非标准字段。方法非常简单,
只要在自定义的信头字段名的前面使用X-前缀。
RFC822将这种方法称为扩展字段。事实上已经
有许多扩展字段被广泛应用,但没有标准定义。
例如:
X—LOOP字段
X—LOOP字段用来防止邮件的循环传送。过
滤或邮件列表处理程序,可以给它处理的每个信
件增加一个X—LOOP字段,以后就可以根据这
个字段中含有的特别值,判断一个信件是否被循
华中农业大学本科毕业论文(或设
计)
20
环传送。如果确认邮件发生了循环,过滤或邮件
列表处理程序就可以用不同的方式处理该信件。
◆X—Mailer字段
X—Mailer字段用于指示什么样的程序产生
了这个信件,它是使用最广泛的扩展字段。产生
邮件的软件可以为所有发送的信件增加合适的
X—Mailer字段,该字段不仅含有软件的名称,
还包含软件的版本号。例如软件名为Littlefox
Mailer,版本为V1.0,可以将“X—Mailer:
LittlefoxMailerV1.0”加到邮件信头中去。
图6列出了一些在因特网电子邮件可以找到
的普通关键字,以及使用它们的目的。
关键字含义
From发送方地址
TO接收方地址
Cc复制副本地址
Date信息创建日期
Subject信息主题
Reply—To回复地址
X—Charset使用的字符集(通常为
ASCII)
X—Mailer发送信息所使用的软
华中农业大学本科毕业论文(或设
计)
21
件
X—Sender发送方地址的副本
X—Face经编码的发送方面孔
的图像
整个系统的核心是收发信件的操作,因此为了
方便维护,以后的升级,故将这两个最主要的操
作写成类库(.dll)的形式,以组件的形式加载
到主程序中,而且其它的功能如果需要的话,也
可以通过这样的组件的形式增加到主程序中。这
也体现了CSharp这一新的微软主推语言的方
便和高效。而且这样做也方便了我们小组的程序
的顺利结合。
第五章系统实现
5.1发送邮件类
SmtpMail是发送邮件的核心,类名为
SmtpMail,隶属于命名空间MailSend。封装了
发送邮件的具体实现方法,也是具体的RFC用
代码实现的过程。而用户通过具体的操作接口,
接收与SmtpMail类通过交互操作来实现用户发
送信件的操作。
5.1.1主要成员变量说明
1)网络连接类及实例TcpClienttc
华中农业大学本科毕业论文(或设
计)
22
为TCP网络服务提供客户端连接类TcpClient
实例对象tc。TcpClient类提供了一些简单的方
法,用于在同步阻塞模式下通过网络来连接、发
送和接收流数据。而实例化的过程也是连接
SMTP服务器的过程。它的重载方法之一的两个
参数一个为服务器名称字符串,另一个为服务器
的埠。
2)提供用于网络访问的基础数据流及其实例
NetworkStreamns
此类提供访问网络的基础数据流的方法。其中
最基本也是最重要的两个方法就是Write()和
Read()方法,至于参数不再次描述。
3)一维字符串数组变量FilePath
此字符串数组主要用来存放用户选择的附件
的绝对路径名,并在发送带附件的邮件时用到。
4)发送邮件所需的基本参数
比如用于ESMTP登录检验用的用户名、密
码,发送邮件需要的收信人,发信人地址以及主
题等等在此不再陈述。
5.1.2主要成员函数说明
1)重载的构造函数SmtpMail()
此函数主要用于在初始化过程中,把用户
华中农业大学本科毕业论文(或设
计)
23
选择的附件的路径以参数的形式传给FilePath。
2)添加附件的函数AddAttachment
传给FilePath的路径,通过这样一个函数
就可以循环的动态的添加到LIST接口的一个对
象中了,方便以后在具体的实现过程中使用。
3)得到上传的附件的文件流GetStream
由于在网络中的操作都是以网络流的形式
来实现的,因此先将上传的附件转换成文件流,
然后再用Write的方法把这些附件的文件流写
入到网络中,来完成发送附件的操作。具体实现
代码如下所示:
///
///得到上传附件的文件流
///
///附件的绝对
路径
PrivatestringGetStream(stringFilePath)
{
Try
{
//新建文件流对象
reamFileStr
华中农业大学本科毕业论文(或设
计)
24
=ream(FilePath,
);
Byte[]by=new
byte[32()];
(by,0,
);
();
Return(64String(by));
}
Catch
{
(“可能你要
打开的文件的属性是只读的!”,“请检查权限”);
Returnnull;
}
}
4)将字符串编码为Base64字符串的函数
Base64Encode
由于ESMTP的LOGIN认证机制是采用
Base64编码,当用户发出AUTHLOGIN的命令
后,服务器返回334的应答码等待用户输入。如
华中农业大学本科毕业论文(或设
计)
25
果身份确认后服务器返回235的应答码,否则返
回失败信息。所以要将用户名和密码转换Base64
编码然后再发给服务器。此函数的作用就是把给
定的字符串转换成相应的Base64编码的字符
串。
5)发送SMTP命令的函数
SendCommand的函数作用是把SMTP命令
的字符串转换成对应的字节型值(C#中规定的
Write方法只能写入字节型的数据)然后写入网
络中,如果操作成功就返回一个标志为真的布尔
型变量,如果操作失败或者发生异常就返回标志
为假的布尔型变量。具体代码如下所示:
///
///发送SMTP命令
///
privateboolSendCommand(stringstr)
{
Byte[]WriteBuffer;
If(str==null||==)
{
returntrue;
}
华中农业大学本科毕业论文(或设
计)
26
WriteBuffer=es(str);
try
{
(WriteBuffer,0,
);
}
Catch
{
Errmsg=”网络链接错误”;
Returnfalse;
}
returntrue;
}
6)接受服务器应答的函数RecvResponse
它的作用就是从网络流中读取服务器返回
的字节型的信息,将其转换成字符串型的变量,
然后将其返回,可以通过其返回值来判断操作是
否成功。具体实现代码如下所示:
///
///接受SMTP服务器回应
///
华中农业大学本科毕业论文(或设
计)
27
privatestringRecvResponse()
{
intStreamSize;
stringReturnValue=;
byte[]ReadBuffer=newbyte[1024];
try
{
StreamSize=
(ReadBuffer,0,);
}
catch(Exceptionex)
{
(ng());
return“false”;
}
if(StreamSize==0)
{
returnReturnValue;
}
else
{
华中农业大学本科毕业论文(或设
计)
28
ReturnValue=
ing(ReadBuffer).Substr
ing(0,StreamSize);
returnReturnValue;
}
}
7)重载的函数Dialog
它们的作用是与服务器交互,发送命令并接收
回应。不同的是参数是字符串类型的那个函数,
每个发送一条命令,并接受服务器的响应,根据
响应的信息来判断交互的结果是否成功。而参数
是字符串数组的函数每次发送的是一组命令,用
于和服务器的交互,这个函数主要是用于
ESMTP服务器的验证的功能,因为验证的过程
是一个等待然后又输入的过程,因此将它们放在
一个数组中有利于理解和操作。而它们的实现主
要是通过调用上面的发送SMTP命令函数
SendCommand以及接受SMTP服务器响应的
函数RecvResponse来实现的。具体的代码如下
所示:
///
///与服务器交互,发送一条命令并接收
华中农业大学本科毕业论文(或设
计)
29
回应。
///
///一个要发送的命
令
///如果错误,要
反馈的信息
privateboolDialog(stringstr,string
errstr)
{
if(str==null||()
==””)
{
returntrue;
}
if(SendCommand(str))
{
stringRR=
RecvResponse();
if(RR==’’false”)
{
华中农业大学本科毕业论文(或设
计)
30
returnfalse;
}
try
{
stringRRCode=
ing(0,3);
if
(RightCodeHT[RRCode]!=null)
{
returntrue;
}
else
{
if
(ErrCodeHT[RRCode]!=null)
{
errmsg+=(RRCode+ErrCodeHT[RRCode].ToSt
ring());
errmsg+=enter;
}
华中农业大学本科毕业论文(或设
计)
31
else
{
errmsg+=RR;
}
errmsg+=errstr;
returnfalse;
}
}
catch
{
(“请检查附件的大小”);
ruturnfalse;
}
}
else
{
returnfalse;
}
}
发送一组命令主要用于服务器验证的重载函
数为:
华中农业大学本科毕业论文(或设
计)
32
///
///与服务器交互,发送一条命令并接收
回应。
///
privateboolDialog(string[]str,string
errstr)
{
for(intI=0;i<;i++)
{
//如果在身份验证阶段有一个不
成功,就返回错误标志位
if(!dialog(str[i],””))
{
errmsg+=enter;
errmsg+=enter;
returnfalse;
}
}
//身份验证全部正确的话,则返回正确
标志位
returntrue;
}
华中农业大学本科毕业论文(或设
计)
33
8)邮件发送程序SendMail
这是整个程序的核心部分。具体的实现
SMTP协议的程序正是通过它一步一步实现并
最终实现发送简单邮件甚至带附件的邮件的功
能,而它的实现是调用以上给出的各个函数的结
果。以下就是简单的通过几个SMTP命令的格
式来实现:
privateboolSendEmail()
{
//连接网络
try
{
//建立一个TCP连接
tc=new
TcpClient(mailserver,mailserverport);
}
catch
{
(“连接
失败”,”请确认”);
returnfalse;
}
华中农业大学本科毕业论文(或设
计)
34
//获取当前流的资料
ns=m();
SMTPCodeADD();
//验证网络连接是否正确
if
(RightCodeHT[RecvResponse().Substring(0,3)
]==null)
{
returnfalse;
}
string[]SendBuffer;
stringSendBuffer;
//进行SMTP验证
//具体的SMTP命令与代
码的结合
if(Esmtp)
{
SendBuffer=
newString[4];
SendBuffer[0]=”EHLO”+mailserver+enter
华中农业大学本科毕业论文(或设
计)
35
SendBuffer[1]=”AUTHLOGIN”+enter
SendBuffer[2]=Base64Encode(username)+enter
SendBuffer[3]=Base64Encode(password)+enter
if(!Dialog(SendBuffer,”SMTP服务器验证失
败,请核对用户和,密码。”))
returnfalse;
}
else
{
sendBufferstr=”HELO”+mailserver+enter;
if(!Dialog(SendBufferstr,””))
returnfalse;
}
SendBufferstr=””MAIL
FROM:”+enter;
if(!Dialog(SendBufferstr,”发件人地址错误,或不
能为空“))
华中农业大学本科毕业论文(或设
计)
36
returnfalse;
//把传过来的收件人的地
址分割然后提交给服务器
stringsplit=”,”;
string
[]address=(Recipient,split);
SendBuffer=new
string[];
for(int
i=0;i<;i++)
{
SendBuffer[i]=”RCPTTO:”+e
nter;
}
if(!Dialog(SendBuffer,”
收件人地址有误”))
returnfalse;
SendBufferstr=”DATA”+enter;
if(!Dialog(SendBuffer,””))
华中农业大学本科毕业论文(或设
计)
37
returnfalse;
SendBufferstr=”From:”+FromName+”<”+Fro
m+”>”+enter;
SendBufferstr+=enter+”,”+enter;
if(!Dialog(SendBuffer,”
错误信件信息”))
returnfalse;
SendBufferstr=”QUIT”+ENTER;
if(!Dialog(SendBuffer,”
断开连接时错误”))
returnfalse;
//关闭流对象
();
//关闭连接
();
FilePath=null;
returntrue;
}
以上即为发送不带附件的邮件SMTP命
令用代码实现的过程。
华中农业大学本科毕业论文(或设
计)
38
5.2接收邮件类
5.2.1主要成员变量说明
1)网络连接类的实例popClient,该实例
用于连接POP3服务器。
2)int变量count是用来记录接收邮件的
数目。
3)定义字符串stringPOPServer,port,
login,password分别代表服务器名,服务器端
口号,用户帐号,用户密码。
5.2.2主要成员函数说明
1)连接服务器函数connect
在接收邮件前,首先要调用connect()方
法连接POP3服务器,并调用GetMessageCount()
方法获得需要接收邮件的数目。返回值为要接收
的邮件数目,如果为0表示邮件没有接收。其实
现的代码如下所示:
publicintconnect()
{
//连接POP3服务器
=true;
nect();
华中农业大学本科毕业论文(或设
计)
39
t(POPServer,int,Parse(port));
popClient..Authenticate(login,password);
//得到邮件总数
count=popClient..
GetMessageCount();
();
returncount;
}
2)接收邮件函数receiveMail
当读取出邮件总数时,就进行接收邮件操
作,同时也进行接收附件。代码如下所示为:
publicvoidreceivMail(intbeginIndex,int
endIndex)
{
//收取邮件
for(int
i=beginIndex;i<=endIndex;i++)
{
receiveMail(i);
}
}
华中农业大学本科毕业论文(或设
计)
40
publicvoidreceivMail(intindex)
{
if(index>count)
index=count;
rser.
Messagem=popClient..
GetMessageCount(index,false);
try
{
(index,m);
}
catch(ArgumentException)
{
}
}
publicArraylistgetAttachmentName()
{
ArraylistAttachmentName=
newArraylist();
intcount=m.
华中农业大学本科毕业论文(或设
计)
41
AttachmentCount;
for(inti=0;i { if(achment(i).NotAttachment) continue; (achmentFileN ame(achment(i))); } returnAttachmentName; } publicvoidget Attachments(stringsavePath) { tachments(savePath); } 3)判断邮件内容格式函数showMessage() 该函数的功能是在阅读邮件内容时。提供 华中农业大学本科毕业论文(或设 计) 42 两种格式给用户选择,一种是HTML格式,另 一种是文本格式。用户可以根据要求来选择适当 格式阅读邮件。代码实现如下: privatevoidshowMessage(boolHTML) { if(!HTML) { (); TextBostxtBox=new TextBox(); ine=true; =txtmessage; ly=true; txtPanel. (txtBox); =; =”切 换至HTML格式”; } 华中农业大学本科毕业论文(或设 计) 43 else { (); WebBrowser txtBox=newWebBrowser(); ntText=txtmessage; txtPanel. (txtBox); =; =” 切换至文本格式”; } =+” ”; =[0]; } 华中农业大学本科毕业论文(或设 计) 44 5.3AddExtra类 这个附加的小类提供一些返回当前系统时间, 获取主机名,主机IP,及有关帮助的功能,在 此仅对帮助信息中的“关于”操作函数稍加说明。 因为它说明了在CSharp中调用windowAPI函 数所需如下几个步骤: 5.3.1调用window中API所需的命名空间 ——usingsystem..pservices; 而调用显示关于对话的函数ShellAbout还需 要用到两个命名空间如下所示 ——usingsystem..Reflection; ——usingsystem.。Diagnostics; 5.3.2在程序中声明所需的API函数 [D||Import(“”)] Staticexternintshellabout(intPtrh wnd,stringszApp,stringszOtherStuff,IntPtr hicon); 5.3.3在程序中具体的使用 Assenbly ass=cutingAssembly(); FileVersionInfomyVersion= sionInfo(on); 华中农业大学本科毕业论文(或设 计) 45 ShellAbout(,”邮件收发系统 #”,”版本”+jorPart+”.”+ jorPart+”.” anyName,); 至此就完成了在CSharp中调用window API函数的过程。 第六章系统运行界面 6.1系统的主界面 主界面显示用户名,主机名,相关的注册信 息以及使用时间。该界面的代码保存在 和文件 中。 创建界面时主要使用mainMenul, imageaccount,imagelistl,timerl控件。 6.2新用户注册页面 华中农业大学本科毕业论文(或设 计) 46 注册用户时。在相应的位置输入邮箱地址,用户 名,密码,帐号名称等信息数输入完毕后。进行 检测账户名。确认正确是执行下一步操作。当你 邮箱地址输入错误或者帐号名已经存在。系统会 检测到错误。并且给出相应的提示! 在实现检查帐号名是否存在代码中调用了 Accountoperate类的检查帐号是否占 用 的函数,并返回一个标志位。 6.3新用户设置界面 华中农业大学本科毕业论文(或设 计) 47 图8设 置界面 完成新用户注册后执行下一步操作是设置 POP3服务器和SMTP服务器设置。以及端口号 的设置。设置完这个步骤后。就能创建一个新用 户邮件收发操作。 首先调用Dispose()方法进行清空所有正在 使用的资源,然后用SmtpPop方法来调用有关 信息,完成设置后进行数据库插入操作。 6.4发送邮件界面 6.4.1发送不带附件的邮件 在新建帐号的过程中已经制定了邮件地址 和帐号名称,所有默认的以这些参数来发送邮 件。通过调用参数的不同程序会自动的调用相应 华中农业大学本科毕业论文(或设 计) 48 的代码来执行不同的操作。该界面主要使用了 mainMenul,openfiledialogl,imlsendmail, savefiledialogl,imlattachment,conattachment 等控件发送简单的邮件运行界面如下。 图9发送纯文本邮件 6.4.2发送带附件的邮件 和简单的邮件不同之处在于多了发送附件 的功能,软件模拟FoxMail里面发送邮件时,在 程序的下面自动显示增添的附件的名称,以及图 标等信息。并且邮件支持添加,删除,排列图标 等功能。运行界面如下所示: 华中农业大学本科毕业论文(或设 计) 49 图10 发送带有附件的邮件 6.5验证邮件发送是否成功 邮件发送出去之后,弹出对话框,提示信 件发送成功: 图11验证发送的邮件是否 成功 6.6邮件接收功能 选择用户,点击接收,可以接收邮箱中的 华中农业大学本科毕业论文(或设 计) 50 邮件。 第七章系统测试 7.1测试的目的 软件的目的就是为了更快,更早地将软件产 品或软件系统中所存在的各种问题找出来,并促 使程序员尽快地解决这些问题,最终及时地向客 户提供高质量地软件产品。要做到这一点,确保 找出系统中所有或绝大部分的软件缺陷,必须建 立在软件测试非常有用的基本方法之上。 软件测试的基本原则是站在用户角度,对产 品进行全面测试,尽早尽可能多地发现缺陷,就 是说软件测试的目的就是发现错误,发现的越多 测试的质量越高。发现错误后并且负责跟踪和分 析产品中的问题,对不足之处提出质疑和改进一 件零件缺陷是一种思想,足够好是测试的原则。 7.2同一SMTP服务器发送邮件的测试 这个方面测试的是,用户登录一个服务器来 发送一封邮件的测试。 7.3利用不同的SMTP服务器发送邮件的测试 这个方面的测试是指利用不同的邮箱来发送 邮件,至于测试的分类雷同于利用同一服务器发 送邮件的测试,所以不在陈述。 7.4同一POP3服务器接收邮件的测试 华中农业大学本科毕业论文(或设 计) 51 首先选择账户登录服务器来接收邮件。当接 收完邮件时系统会显示服务器名,用户名,接收 人,发送人,邮件数以及邮件的主题和内容。该 软件能接收到所有正确无误的邮件。经过这些验 证可以证明软件支持接收同一服务器的邮件。 7.5不同的POP服务器接收邮件的测试 通过发送邮件。软件一样能接收到邮件内容并 且正确无误。通过这次验证可以证明该软件支持 接收不同服务器的邮件。 总之,通过以上的各方面的测试,使我改正了 代码中的许多不合理以及错误之处,最终也证明 了,我们的软件系统是支持多种服务器,支持多 附件发送的群发软件。 第八章总结 这篇邮件客户端系统,我负责的是邮件发送 功能。在熟悉了专门用于发送邮件的SMTP协 议以及RFC规定的邮件的格式的基础上,运用 了微软推出的C#这一新型的面向对象语言的便 利性和灵活性,从SMTP协议规定的底层命令 做起,一步步的与服务器进行交互操作,最终实 现发送多附件多接收人的功能。其中,具体的和 华中农业大学本科毕业论文(或设 计) 52 服务器的交互操作,都封装了在 这个动态链接库里面了。而为了方便最终的调用 和整合,所有的有关后台操作发送邮件的类以及 其他的附加功能的类,全部都归属于MailSend 这个命名空间了。在力求达到FoxMail功能的同 时,又加了一点个人的思想并把它体现到了这一 软件上。最主要的体现就新建帐号的提前检测这 一特色上,这一功能类似于很多Web页面的“检 测新帐号”的功能,这样就免去了用户一直到确 定注册完成时,才因为账户已经被使用而注册失 败的麻烦。总之,通过这次的编程,使我对网络 编程有了一个很好的认识和锻炼,也使我对C Sharp 这一语言的掌握程度又上了一个新台阶,虽然编 出来的软件不能和功能强大的FoxMail相提并 论,但是相信它简单,易操作性,更多了几分实 用性。在以后的日子,随着我的技术提高和思想 的成熟,我一定会把它做的更好,更趋近于完美。 华中农业大学本科毕业论文(或设 计) 53 参考文献 [1]SimonRobinson,llen等.C#高级编 程[M].清华大学出版社,2002 [2]TomArcher.C#技术内幕[M].清华大学出版 社,2002 [3]沉舟.编程语言C#[M].希望 电子出版社,2001 [4]罗军舟,杨明等。TCP/IP协议及网络编程技 术[M].清华大学出版社,2004 [5]/IP协议及网络编程技术 [M].机械工业出版社,2000 [6]周存杰.VisualC#.NET网络核心编程[M]. 清华大学出版社,2002 [7]电脑编程技巧与维护杂志社.C#编程技巧典 型案例解析[J].中国电力出版社,2005 [8]马金虎,朱力勇。编写基于SMTP网络应用 程序[J].电脑爱好者,2003 [9]代继红.SMTP认证机制模块化设计及实现 [N].中南民族大学学报,2005 华中农业大学本科毕业论文(或设 计) 54 致谢 本次毕业设计是在罗老师的精心指导下完成 的。我借此机会向他表示衷心的感谢! 同时,也对计算机科学与技术系的全体老师的 帮助和指导表示感谢!另外,还要感谢在我进行 毕业设计过程中给予我帮助的同学。 最后,对阅读和评审本论文的各位专家表示衷 心的感谢!