第八章电子邮件程序第八章电子邮件程序在本章中,我们将系统的讨论关于电子邮件的,电子邮件是目前Internet上最重要的应用之一,它和我们在上一章介绍的几种网络应用一样,依赖于应用层的协议,但它分为两个部分,发送一部分,接收一部分,使用不同的协议进行工作,我们将分别介绍这两种协议,并着重于实际的编程应用。
本章重点:z了解关于电子邮件的基本知识z熟悉WINSOCK处理电子邮件的方法;z熟悉MAPI处理电子邮件的方法z了解其它较为深入的网络编程问题8.1 电子邮件与电子邮件协议8.1.1 电子邮件概述随着网络技术的发展和网络的广泛使用,电子邮件已经逐渐的进入许多人的生活,它的简单方便使它成为所有网络服务中最重要的一部分,尤其是随着网络上各种免费电子信箱的提供和众多电子刊物的发行,使得收发电子邮件已经成为许多人上网的主要目的。
互联网最初用于方便科学家与政府技术人员间的通信。
虽然电子邮件并不是他们采用的第一种通信方式,但它是通信的终极目标。
自从互联之日起,它就孕育了电子邮件传输机制。
目前,电子邮件完成大部分数据传输工作。
统计表明,所有TCP连接中大约一半是用于简单邮件传送协议SMTP。
早期的电子邮件系统仅是将消息拷贝到用户邮箱的程序。
那时,用户均使用同一台机器。
多用户系统的某个用户使用电子邮件向同一台机器的其他用户发消息。
经过一段时期,网关组件的出现允许用户使用一个电子邮件服务器向其他电子邮件服务器发送或者接收邮件。
网关允许不同类型的电子邮件系统相互通信。
进一步的发展最终促使了电子邮件标准的制定。
电子邮件标准主要有以下两个:X .400,由国际远程通信—通信标准化组织及国际标准化组织制定。
简单邮件传输协议(SMTP),由IETF根据早期的研究及开发成果制定。
目前最流行的协议就是SMTP。
本节,我们着重介绍的是电子邮件的发送流程,即电子邮件是如何发出的,这是我们学习协议和进行编程的基础。
发送邮件的过程可以参考图8-1,由图中可以看出,用T C P 进行的邮件交换是由报文传送代理完成的,用户甚至不需要和代理打交道。
用户仅仅和用户代理相接触。
我们考虑的重点是在两个报文传送代理之间邮件是如何传递的。
334图8-1 电子邮件传递过程示意电子邮件中除了包括从一个用户传递到另一个用户的信息之外,还应该包括许多别的信息,SMTP服务器利用这些信息来传递邮件,而客户端的邮件接收软件则利用这些信息来对邮件进行分类。
这些附加的数据用信头的形式被包含在邮件主体中。
邮件正文则紧随其后。
如果你是用Outlook Express,用你的鼠标右键点一封邮件,然后选取“属性”,你就可以看到信头是什么样的了。
为一个典型的信头:Received: by (Postfix, from userid 500)id D4EE4A47A6; Sun, 3 Mar 2002 20:43:18 +0800 (CST)From: arty@To: artyty@Cc: yanfeng@Subject: bakDate: Sun, 3 Mar 2002 20:44:54 +0800X-Priority: 3X-MSMail-Priority: NormalMIME-V ersion: 1.0X-Mailer: XMail-1.0Content-Type: multipart/mixed;boundary="----=NextPart_263Mail-XMAIL-000-000-1015159494Th8"Message-Id: <20020303124318.D4EE4A47A6@>在我们使用电子邮件的过程中,我们当然不需要知道这些东西,因为应用软件已经替我们做好了这些工作,但是,如果我们进行开发,就必须了解这些,在我们的程序中遵守这些规则。
下面就接收一下这些规则。
每封邮件都有两个部分:信头和主体。
邮件主体就是你发送给收件人的数据(包括文本或文件)信头是一系列的字段(Fields)。
一个空字符串将主体同信头分开,也就是说一个空字符串标记了信头的结束。
在VB中,空字符串可写成vbCrLf + vbCrLf. 通过InStr函数你可以很方便地把它找出来。
例如:intBorderLine = InStr(1, strMessage, vbCrLf + vbCrLf)第八章电子邮件程序335信头部分的字段可分为两类。
一类是由你的电子邮件程序产生的,另一类是邮件通过SMTP服务器时被加上的。
在所有被SMTP服务器加上的字段中,对我们而言最重要的是Message-Id字段。
这个字段是由你传向的SMTP服务器加上的。
这个一个唯一的ID号。
你可用这个号码作为邮件的编号。
下面列出了可由用户的邮件程序控制的信头字段。
这并不意味着所有的字段都是必须的。
实际上可以忽略形成信头这一步骤而只发送正文。
让你的SMTP服务器为你加上最起码的必需字段。
From :邮件作者Sender :发信人Reply-To :回邮地址To :收信人地址CC :另一个收信人地址BCC :收信人地址,但这个收信人看不到其它收信人的地址。
Subject :主题Comments :备注Keywords :关键字,用来进一步搜索邮件In-Reply-To :被当前邮件回复的邮件的IDReferences :几乎同In-Reply-To一样Encrypted :加密邮件的加密类型Date :发信日期建立信头的规则很简单。
用冒号将字段名同字段值分开。
每个字段从一个新的字符串开始,但是字段值可能会占用几个字符串,这取决于SMTP服务器对字符串长度的限制。
不幸的是,RFC822推荐的日期和时间格式同VB不兼容。
当我们编辑邮件时,我们得用FORMAT函数例如:Format(Now,"ddd, dd mmm yyyy hh:mm:ss") & " GMT +0400"尽管如此,为了将Internet的日期/时间转换成VB的日期类型,你有必要开发你自己的函数或是调用WinInet API中的InternetTimeToSystemTime函数。
如果想知道更多这方面的规定,请参考RFC822。
除了标准字段外,信头还可以包含用户自定义的字段。
这些用户自定义的字段名必须由X 开始。
例如:X-Mailer: Microsoft Outlook Express 4.72.2106.4了解电子邮件的标准格式,我们就可以进入协议的学习了。
8.1.2 SMTP与POP3协议简单邮件传输协议(Simple Mail Transport Protocol ,S M T P )是电子邮件的互联网标准。
它也是一个应用层协议,使用端口25。
这是一个非常简单的协议,我们要做的仅仅是在了解电子邮件工作过程和电子邮件格式的基础上,了解SMTP中的命令和服务器返回的状态码就可以了。
整个过程无非是一个客户端计算机向服务器发送命令,然后服务器向客户端计算机返回一些信息。
客房端发送的命令以336及服务器的回应都是字符串,你并不需要特别的软件就能读出它们。
下面在表8-1中我们给出SMTP命令。
最常用的仅有九条(简单正是此协议的成功之处),但是我们给出了另外不常用的五条,供参考。
表8-1 SMTP命令命令 描述HELO 呼叫Helo命令向接收者标识发送者,命令必须与发送方主机名结合使用。
MAIL 初始化邮件传输。
参数包括“from”字段或邮件发送者字段RCPT 标识邮件接收方DATA 声明邮件数据开始(消息的主体)。
数据可包含128位ASCII代码,并以包含圆点“.”的行结束RSET 中止当前的传输VRFY 用于确认接收用户NOOP 无操作命令QUIT 关闭连接SEND 使接收主机知道消息必须送到另一个终端不常用的几条命令SOML 发送或邮寄。
通知接收主机消息必须发送到其他终端或邮箱SAML 发送并邮寄。
通知接收主机消息必须发送到其他终端和邮箱EXPN 用于展开邮件列表HELP 请求帮助信息TURN 请求接收主机向发送方主机返回消息与我们在上一章遇到的HTTP等协议中的命令相同,这些也是我们进程邮件客户端编程的基础。
读者同样没有必要记住它们,但是在编程中必须正确的使用它们。
这些我们在后面的示例中会给出。
当发送报文传送代理向接收报文传送代理发送SMTP命令时,接收MTA返回特定的状态码使发送者了解命令是否正确执行。
这些状态码按状态分组,其中第一位表示组含义(5XX表示失败,4XX表示临时问题,1XX-3XX表示成功)。
请参考表8-2中,了解这些状态码,在我们的应用程序中,通过这些状态码可以清楚的了解服务器与我们所编写客户端互相作用的状态,从而采取相应的动作。
第八章电子邮件程序337表8-2 SMTP状态码编码 描述211 帮助返回系统状态214 帮助信息220 服务准备就绪221 关闭连接250 请求操作就绪251 用户不在本地,转寄到<Path>354 开始邮件输入421 服务不可用450 操作未执行,邮箱忙451 操作中止452 操作未执行500 命令不可识别或语法错501 参数语法错502 命令不支持503 命令顺序错504 命令参数不支持550 操作未执行,邮箱不可用551 非本地用户552 中止,存储空间不足553 操作未执行,邮箱名不正确554 本地错误传输失败,存储空间不足需要注意的是,实际应用中有可能某个状态码并非一定是这个含义,需要查阅相应的文档来确定。
具体到编程中,如果是针对一般系统,比如常用的163等免费信箱的访问通常是相同的;如果是针对某种特定的系统,就需要注意了。
下面我们在来看接收邮件的协议。
POP3协议也就是所谓的Post Office Protocol 3是我们在收信时所采用的协议,POP3协议的工作过程大致可分为以下三步:① 授权过程:用户需要收发电子邮件时,通过拨号网络与ISP提供的服务器建立TCP连接,当连接成功时,服务器要求你输入用户名和密码以“验明正身”,如果被授权使用,POP3服务器会对你的邮箱建立一个“独占锁定”,以方便服务器能够“不受打扰”地工作,同时也是为了在意外时避免邮件被删除。
② 传输过程:成功连接后,服务器便进入了传输过程:服务器首先启动“无响应自动退出计时器”,如果用户在规定的时限内没有和服务器进行通信,服务器便自动和用户断开TCP 连接,等待下一次连接。
用户每当成功地和服务器通信一次,“无响应自动退出计时器”自动清零。
用户首先得到的是由服务器检索到的有关邮件的基本信息(比如邮件的份数),每当成功338传输完一份邮件之后,服务器便对该邮件做上一个删除标记。
如果整个传输过程一帆风顺,传输完之后便直接进入更新状态。