为了正常的体验网站,请在浏览器设置里面开启Javascript功能!

JAVA邮件发送

2011-11-29 8页 pdf 106KB 83阅读

用户头像

is_807640

暂无简介

举报
JAVA邮件发送 本文介绍了如何利用 Java 的网络 API 来实现一个电子邮件工具程序。通常 Email 工具都是 使用 SMTP(简单邮件传输协议, Simple Mail Transfer Protocol)来发送邮件,使用 POP3 协议来接受电子邮件。在本文中只对这两个协议作简单介绍。如果有兴趣的读者可以参考以 下站点: POP3: ftp://ftp.isi.edu/in-notes/rfc1939.txt SMTP: ftp://ftp.isi.edu/in-notes/rfc2821.txt ...
JAVA邮件发送
本文介绍了如何利用 Java 的网络 API 来实现一个电子邮件工具程序。通常 Email 工具都是 使用 SMTP(简单邮件传输, Simple Mail Transfer Protocol)来发送邮件,使用 POP3 协议来接受电子邮件。在本文中只对这两个协议作简单介绍。如果有兴趣的读者可以参考以 下站点: POP3: ftp://ftp.isi.edu/in-notes/rfc1939.txt SMTP: ftp://ftp.isi.edu/in-notes/rfc2821.txt Java 中虽然提供了 JavaMail API,但是由于在这篇文章中我将从底层来探讨电子邮件软件是 如何工作的,因此不会使用 JavaMail API。本文中的例子是在 J2SE 1.4 下开发的。 电子邮件的格式 在 开 发 Email 软 件 之 前 , 你 需 要 了 解 电 子 邮 件 的 格 式 。 根 据 RFC 2882 (http://www.faqs.org/rfcs/rfc2822.html)的,电子邮件由很多行组成,每行由〈CRLF〉 (ASCII 代码 13 和 ASCII 代码 10)结束。每行的最大长度为 998 个字符。其中有些行提供 了收发电子邮件所必需的信息,这些行被称为头(Header),所有的头构成了头域(Header Field)。其他的行用于保存邮件的具体内容。 头域提供了很多信息,其中包括邮件的来源;邮件的目的地和邮件的主题等。每个头由名称 和冒号加上相应的值构成。例如 From:、Send:和 Reply-To:中记录了邮件的来源。在 From: 中记录的是邮件的作者;在 Sender:中指定了发送邮件的代理(可以是邮件地址,也可以是 机器名称);Reply-To:中指定了接受回信的邮箱地址。 一封邮件可能有多个作者,因此 From:中可以指定一个或多个邮箱地址。下面给出了一个个 From:的例子: From: Ray Feng 〈rayfeng@yahoo.com.cn〉, bogus@yahoo.com.cn 在一封电子邮件中只能有一个 Sender。因此 Sender:的值只能包含一个邮箱地址。如果在 From: 中只有一个作者,而且 Sender:的值和 From:的值相同,则 Sender:就不会出现在电子邮件中, 否则会出现信息冗余;反之 Sender:则应该出现在邮件中。下面是一个 Sender:的例子: Sender: Ray Feng rayfeng@yahoo.com.cn 在电子邮件中可以指定将回信发送到多个邮箱地址中。因此 Reply-To:中可以包含一个或多 个邮箱地址,每个地址之间用逗号隔开。如果邮件中有 Reply-To:,回信会被发送到罗列在 Reply-To:中的所有地址;如果邮件中没有 Reply-To:,则回信会被发送到罗列在 From:中的地 址。那么谁会收到邮件呢?To:和 Cc:中保存了接受邮件的邮箱地址。两者的值都可以包含多 个邮箱地址。 除了邮件的来源和接受者,RFC 2882 中还定义了其他一些头,例如 Subject:中包含了电子邮 件的主题。下面是一个电子邮件头域的例子: From: Ray Feng 〈rayfeng@yahoo.com.cn〉 To: bogus 〈bogus@yahoo.com.cn〉 Cc: John 〈John@yahoo.com.cn〉 Subject: Test Email 附件 在 MIME 中允许在电子邮件中添加二进制文件,被添加的文件叫做附件。附件的内容可以 作为邮件的一部分进行传输。MIME 是如果实现这个功能的呢?在 MIME 中引入了很多头, 其中和附件相关的最重要的就是 Content-Type:和 Content-Tracnsfer-Encoding:。为了在一封电 子邮件中区分不同的部分,MIME 要求在 Content-Type: multipart/mixed 头中包含一个边界参 数。边界参数的值是一个在双引号中的字符串。通过这个字符串,程序就可以区分电子邮件 的不同部分。在传输电子邮件的内容前,程序先传输一个〈CRLF〉,两个连字符和边界参数。 当完成 Email 内容的传输后,程序会在最后传输边界参数和两个连字符。 下面的电子邮件中包含了两个部分,一个部分是由 iso-8859-1 字符组成的文本,一部分是名 为 file.txt 的附件。这里没有包含 Content-Transfer-Encoding:头,表明使用缺省的 7 位 ASCII 字符。 Content-Type: multipart/mixed; boundary="***" --*** Content-Type: text/plain; charset="iso-8859-1" This message has an attachment. --*** Content-Type: text/plain; name="file.txt" Attachment text. --***-- 发送电子邮件 screen.width-333)this.width=screen.width-333;"> 基于互联网的电子邮件通常是利用 SMTP 网络协议进行传输的。根据 SMTP,当电子邮件程 序需要发送电子邮件时,该程序首先同一个 SMTP 服务程序建立起双向的通讯通道(通常 是通过套接字建立这种通道的)。这个基本的 SMTP 服务程序或许是这份电子邮件的最终目 的地,也可能只是通向另一个 SMTP 服务程序的跳板。总而言之,当电子邮件程序同 SMTP 服务程序建立起双相的传输通道后,电子邮件程序会向 SMTP 服务程序发送一系列基于 ASCII 字符的命令,而 SMTP 服务程序会对这些命令产生相应的回应来表明相应的操作是成 功还是失败了。 让我们假设所有的操作都成功了,那么电子邮件程序将把邮件发送到 SMTP 服务程序,如 果电子邮件的接收地址正好是该 SMTP 服务程序运行的服务器,那么 SMTP 服务程序就会 将邮件加入邮件数据库中,否则 SMTP 服务程序将把邮件转发到在其他 SMTP 服务器上的 SMTP 服务程序,直到到达目的地为止。图二通过图示说明了这一点。 SMTP 可以识别很多电子邮件用来与 SMTP 服务程序通讯的命令。某些命令需要参数,某些 命令则不需要。但是每个命令后必须跟一个〈CRLF〉。最常用的六个命令是 HELO,MAIL, RCPT,DATA,RSET 和 QUIT。 按照上面的顺序给出这六个命令并非偶然。除了 RSET 外,其他的命令必须按照特定的顺序 发送,这是因为 SMTP 服务程序是基于状态的。对于每一个建立了双向通讯通道的电子邮 件程序,SMTP 服务程序都会保存当前的通讯状态。 当一个电子邮件程序和 SMTP 服务程序建立联系后,SMTP 服务程序将向电子邮件程序发送 初始化消息。该消息包含了一个三位回应码,这个回应码是用来标识 SMTP 服务程序的。 除此之外,在 SMTP 服务程序发送给电子邮件程序的消息的头部也带有回应码,它们被用 来表示操作成功或者失败。电子邮件程序接收到这些回应码后,可以根据其中包含的信息完 成相应的工作。而消息的文本部分是给人看的,电子邮件程序可以忽略文本部分。 在收到初始化消息后,电子邮件程序通过发送 HELO 命令来开始传输邮件。HELO 命令有 一个参数,该参数标志了 SMTP 服务程序所在服务器的域名。它将在 SMTP 服务程序中标 识出 SMTP 服务程序。作为回应,SMTP 服务程序进行一些初始化工作,将自己设定到初始 状态以接收电子邮件。当这些工作成功完成后,它发送回一条成功的回应消息给电子邮件程 序,该回应消息以回应码 250 开头。 在 HELO 命令之后,电子邮件程序会发送 MAIL 命令。MAIL 命令将在 SMTP 服务程序中 标识出发送者,它有两个参数:FROM:和一个电子邮件地址。如果 SMTP 服务程序能够成 功地解析电子邮件地址的话,通常它将返回以 250 开头的回应消息;否者将发送回表示操作 失败的回应消息。 在 MAIL 之后是 RCPT 命令。RCPT 命令在 SMTP 服务程序中标识出一个邮件的接收者,它 也有两个参数:TO:和一个电子邮件地址。如果邮件由多个接收者,则程序需要多次发送 RCPT 命令。 RCPT 命令之后,程序需要发送电子邮件本身了。程序先发送一个 DATA 命令,当接收到表 示成功的回应消息后,将电子邮件逐行发送给 SMTP 服务程序,当所有的行都发送完毕后, 程序发送一行由句号组成的行。在此之后,电子邮件程序等待 SMTP 服务程序的回应消息, 以确定邮件被 SMTP 服务程序正常接收了。这一切都成功后,程序可以发送 RSET 命令来 退出邮件传输过程。最后,当要断开和 SMPT 服务程序建立的连接时,程序发送 QUIT 命令。 主要提醒的一点是,虽然上面的命令都是大写的,但是在实际的协议对大小写不敏感。 现在也许你关心的问题是回应码的格式是怎样的。最左边的一位数字代表操作是否成功,1 代表收到命令,2 代表操作成功完成,3 代表等待后续命令,4 代表操作临时未能完成(电 子邮件程序可以在当前的邮件传输过程中重新发送命令),5 代表操作不能完成(电子邮件 程序不能在当前的邮件传输过程中重新发送命令)。第二位数字代表回应的领域,0 代表语 法错误,1 代表消息请求,2 代表传输通道,3 和 4 没有指定,5 代表与邮件系统相关。最有 一位数字对第二位数字做补充说明,这里就不再详述。根据上面的信息,我们可以看出 250 代表请求的命令已经成功完成;220 代表 SMTP 服务程序正在等待 HELO 命令;而 503 代表 命令顺序错误。有兴趣的朋友可以参见 RFC 2821。 下面提供了一个基于命令行的例子 SMTPDemo,这个例子可以帮助你理解基于 SMTP 的邮 件传输机制。这个程序将利用端口 25 连接到一个 SMTP 服务程序上。为了使程序能够 运行,你需要将 home 更改为你使用的邮件服务器的地址。 // SMTPDemo.java import java.io.*; import java.net.*; class SMTPDemo { public static void main (String [] args) { String SMTPServer = "home int SMTPPort = 25; Socket client = null; try { // 向 SMTP 服务程序建立一个套接字连接。 client = new Socket (SMTPServer, SMTPPort); // 创建一个 BufferedReader 对象,以便从命令行读取用户输入。 BufferedReader stdin; stdin = new BufferedReader (new InputStreamReader (System.in)); // 创建一个 BufferedReader 对象,以便从套接字读取输出。 InputStream is = client.getInputStream (); BufferedReader sockin; sockin = new BufferedReader (new InputStreamReader (is)); // 创建一个 PrintWriter 对象,以便向套接字写入内容。 OutputStream os = client.getOutputStream (); PrintWriter sockout; sockout = new PrintWriter (os, true); // 显示同 SMTP 服务程序的握手过程。 System.out.println ("S:" + sockin.readLine ()); while (true) { System.out.print ("C:"); // 读取用户输入。 String cmd = stdin.readLine (); // 将用户输入的命令发送到 SMTP 服务程序。 sockout.println (cmd); // 从套接字读取 SMTP 服务程序的回应消息并显示在屏幕上。 String reply = sockin.readLine (); System.out.println ("S:" + reply); // 如果发送了 DATA 命令并且获得成功的回应消息,从输入设备读取行, // 直到读取到完全由句号组成的行时停止, 这些行构成了电子邮件。 if (cmd.toLowerCase ().startsWith ("data") && reply.substring (0, 3).equals ("354")) { do { cmd = stdin.readLine (); if (cmd != null && cmd.length () 〉 1 && cmd.charAt (0) == .´ )´ cmd = "."; sockout.println (cmd); if (cmd.equals (".")) break; } while (true); // 从 SMTP 服务程序中读取回应消息并显示。 reply = sockin.readLine (); System.out.println ("S:" + reply); continue; } // 如果用户输入 QUIT 命令,则退出程序。 if (cmd.toLowerCase ().startsWith ("quit")) break; } } catch (IOException e) { System.out.println (e.toString ()); } finally { try { if (client != null) client.close (); } catch (IOException e) { } } } } 当运行 SMTPDemo 时,你将会看到下面的输出。其中 C:后面是用户的输入,S:后面是 SMTP 服务程序返回的信息。 S:220 home.digital.com Microsoft ESMTP MAIL Service, Version: 4.0.2195.2966 ready at Fri, 13 Dec 2002 15:06:58 +0800 当运行 SMTPDemo 后,邮件服务程序返回了初始化信息。 C:helo digital.com S:250 home.digital.com Hello [23.2.254.53] 通过发送 helo digital.com 命令开始邮件传输过程。digital.com 是邮件服务器所在域的域名。 然后邮件服务程序返回了以 250 开头的欢迎信息。 C:mail from: rayfeng@digital.com S:250 2.1.0 rayfeng@digital.com....Sender OK 接下来是输入邮件发送者的信息 mail from:。邮件服务程序返回了成功信息。 C:rcpt to: rayfeng@digital.com S:250 2.1.5 rayfeng@digital.com 然后是通过 rcpt to:指定邮件的接收者。 C:data S:354 Start mail input; end with 〈CRLF〉.〈CRLF〉 Subject: Test Email This is the test Email. . S:250 2.6.0 HOMEOulkEZ00VNuHKDy00000002@home.digital.com Queued mail for delivery 接下来是输入邮件的内容。发送 DATA 命令后,等待服务器发送回命令被成功接收的回应消 息。当接收到以 354 开头的回应消息时,就可以输入电子邮件的内容了。完成后以〈CRLF〉. 〈CRLF〉结束。 C:quit S:221 2.0.0 home.digital.com closing connection 最后退出发送电子邮件的过程。请注意回应码 221,最左边的 2 代表操作成功,中间的 2 表 示传输通道,1 表示连接关闭。 前面我曾讨论过关于附件的问题。通过 SMTPDemo 也可以发送附件。通过向邮件服务程序 发送下面的命令,就可以在邮件中加入 file.txt 作为附件。 helo digital.net mail from: rayfeng@digital.com rcpt to: rayfeng@digital.com data Subject: Attachment Demo Content-Type: multipart/mixed; boundary="***" --*** Content-Type: text/plain; charset="iso-8859-1" This message has an attachment. --*** Content-Type: text/plain; name="file.txt" Attachment text. --***-- quit 到此为止,我们介绍了如何用 Java 实现 Email 工具的发送功能,并从地层了邮件发送 的机制,不知您是否已经掌握了这些内容。在下一篇文章中,我们将一起来研究 Email 工具 的接收功能。 http://www.beijianbest.com/ 阀门 不锈钢阀门 碳钢阀门
/
本文档为【JAVA邮件发送】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。 本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。 网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
热门搜索

历史搜索

    清空历史搜索