JSP企业快信系统的设计与实现【源码+文档】

news/2024/12/21 15:51:56/

目 录

 

Abstract

1  绪论

1.1  开发背景

1.2  国内外发展概况

1.3  研究目的和意义

1.4  研究主要内容

2  系统分析

2.1  需求分析

2.2  可行性研究

2.2.1  经济可行性

2.2.2  技术可行性

2.3  开发环境

3  系统总体设计

3.1  系统目标

3.2  系统功能结构

3.3  业务流程图

3.4  系统预览

3.5  文件夹组织结构

4  系统详细设计

4.1  数据库设计

4.1.1  数据库分析

4.1.2  数据库概念设计

4.1.3  数据库逻辑结构设计

4.2  公共模块设计

4.2.1  数据库连接及操作类的编写

4.2.2  字符串处理类的编写

4.2.3  配置Struts

4.3  主页设计

4.3.1  主页概述

4.3.2  主页技术分析

4.4  名片夹管理模块设计

4.4.1  名片夹管理模块概述

4.4.2  名片夹管理模块技术分析

4.4.3  查看客户信息列表的实现过程

4.4.4  添加客户信息的实现过程

4.4.5  删除客户信息的实现过程

4.5  发送短信模块设计

4.5.1  发送短信模块功能概述

4.5.2  发送短信的实现过程

4.5.3  发送短信模块技术分析

4.5.4  单元测试

4.6  发送邮件模块设计

4.6.1  发送邮件模块功能概述

4.6.2  发送邮件模块技术分析

4.6.3  发送邮件模块实现过程

4.6.4  单元测试

5  技术分析

5.1  开发技巧与难点分析

5.1.1  添加收信人

5.1.2  插入短信

5.2  使用Java Mail 组件

5.2.1  Session

5.2.2  Address

5.2.3  Authenticator

5.2.4  Transport

结论

参考文献

   

外文原文

外文翻译

1  绪论

1.1  开发背景

在企业信息化的今天,效率决定成败,企业内、外部沟通的及时性将直接影响企业的运作效率。现在多数企业的办公自动化系统(即OA)的信息传递仅限于计算机内部网络,如果用户不在线,将无法知道是否有新的工作或紧急通知,为了确认是否有待办工作,不得不经常去访问OA,检索是否有新任务,而事实上这种检索的结果经常是徒劳。这样一来,不仅造成了机器资源的浪费,也造成了人力资源的浪费。因此急需一套成型的企业快信系统解决上述问题。

1.2  国内外发展概况

短消息服务市场近来如此火爆,让许多人始料未及,预示着短消息的巨大市场空间。短消息(Short Message Service)是手机通过移动网进行个人简易数据通信的一种方式,具有覆盖范围广、双向寻呼、使用经济、可缓存处理等优点,满足了人们爆炸性增长的信息需求,使人们可以以低廉的价格、便捷的方式,随时随地得到充满个性化的信息,是无线通信在 20 世纪末所做的一次重要飞跃。这使得移动网络不仅可以传送音频,也可以传送数据,而数据传输是互联网技术的根本。

在国外,短消息业务占移动运营商收入的很大比例。国内移动通信在保持较高增长速度的同时,数据业务正在成为运营商的重要收入来源,几大电信公司不约而同地把目光盯住了手机短信。据统计,从 2000 年第四季度开始,全国短消息业务量以每月几千万条的数量突然激增,已经成为一个不容忽视的巨大的市场!

而随着中国移动通信用户的不断增长,如何最大程度地利用现有网络,挖掘网络潜力,方便灵活地开展增值服务,拓展网络应用服务领域,满足用户日益增长的服务需求成为网络运营商所要考虑的重点,因此,短消息增值服务已成为吸引用户和增加收入的有效手段。开展增值服务不仅可以直接增加业务收入,而且通过提供不同种类的服务,可以吸引更多的顾客群体,对于拓展用户、提高市场应用效率具有非常重要的意义,潜在的收益更为巨大。

1.3  研究目的和意义

本课题通过对企业快信系统的开发主要达到以下两个目的:

1)企业快信系统面对成千上万用户的连接以及同时的数据库请求,对数据库访问的效率和安全成了必须解决的问题。通过对JAVA 平台下数据库存取机制的深入研究,找出一条效率,性能与安全平衡的道路。

2)Web 开发的实例,对如何把 B/S 与 C/S 相结合进行了研究,并对面向对象对多层结构的支持进行了详细的分析。

企业快信主要是高效和安全的对企业提供企业级快信和服务,基于JAVA的多层结构来进行 web 开发必然是今后的主流,并且由于同时面对多用户及多连接,对数据库存取效率及性能,安全都有很高要求,因此,文中对数据库的高效安全的存取进行了深入研究并且获得了有效的进展。通过对其具体应用进行研究对相关开发人员和以后的软件开发及应用都有十分重要的意义。

1.4  研究主要内容

在一个提供企业级短信的系统的设计与实现中,把 C/S 和 B/S 架构根据实际情况进行结合,着重对数据库存取中的各种机制进行了深入地研究并且根据系统自身特点进行了选择和加强,采用了MySQL 数据供应器池化,并使用 Windows7 自带的性能监视器来监视链接池,最后讨论了设置链接池大小的各种问题,选择合适的大小,实现高效与安全有效的结合。并且结合 web 开发的实例,对面向对象对多层结构的支持进行了详细的分析。

基于JAVA的 B/S 架构来进行 web 开发必然是今后的主流,并且由于同时面对多用户及多连接,对数据库存取效率及性能,安全都有很高要求,因此,通过对其具体应用进行研究对相关开发人员和以后的软件开发及应用都有十分重要的意义。


2  系统分析

2.1  需求分析

企业快信的作用是帮助企业解决企业内部、企业与外部沟通难、信息不能及时传播等问题。为此,企业快信系统需要提供邮件群发、短信群发等功能。通过对多数企业日常业务的考察、分析,并结合短信及邮件自身的特点,得出本系统要求具有以下功能。

þ 用于管理客户和员工信息的名片夹管理功能。

þ 用于对常用短语及其类别进行管理的信息库管理功能。

þ 短信群发功能。

þ 邮件群发功能。

þ 发送邮件附件的功能。

2.2  可行性研究

开发任何一个基于计算机的系统,都会受到时间和资源上的限制。因此,在接受任何一个项目开发任务之前,必须根据客户可能提供的时间和资源条件进行可行性分析,以减少项目开发风险,避免人力、物力和财力的浪费。可行性分析与风险分析在很多方面是相互关联的,项目风险越大,开发高质量的软件的可行性就越小。

2.2.1  经济可行性

采用短信作为企业的移动通信手段,将给企业对内、对外进行信息传递与沟通带来革命性的变化,从而使得移动办公、客户服务、员工沟通等运作效率显著提升,而成本则显著下降。值得说明的是,虽然短信有以上诸多优点,但它还是有一定的不足,例如信息内容单一和受到字数限制等。为解决这一问题,在企业快信中提供了邮件群发功能。通过邮件进行沟通也是目前比较流行的方式,它也具备实用、方便和廉价等优点。

2.2.2  技术可行性

开发一个企业快信系统,涉及到的技术问题不会太多,主要用到的技术就是使用短信猫和Java Mail组件来实现收发短信和群发邮件等功能。Java Mail 组件是Sun 公司发布的一种用于读取、编写和发送电子邮件的包,利用它可以方便地实现邮件群发。

2.3  开发环境

在开发企业快信时,需要具备下面的软件环境。

服务器端:

þ 操作系统:Windows 7。

þ Java 开发包:JDK 1.5 以上。

þ Web服务器:Tomcat6.0。

þ Java Mail 开发包:Java Mail 1.4。

þ 数据库:MYSQL。

þ 浏览器:IE 10.0。

þ 分辨率:最佳效果为1024×768 像素。

客户端:

þ 浏览器:IE 10.0。

þ 分辨率:最佳效果为1024×768 像素。

由于本系统中需要使用Java Mail 组件,下面将详细介绍如何配置及Java Mail 的开发环境。

由于目前Java Mail 还没有被加在标准的Java 开发工具中,所以在使用前必须另外下载Java MailAPI,以及Sun 公司的JAFJavaBeans Activation Framework),Java Mail 的运行必须信赖于JAF 的支持。

þ 下载并构建Java Mail API

Java Mail API 是发送和接收E-mail 的核心API。需自行下载后解压缩到硬盘上,并在系统的环境变量CLASSPATH 中指定activation.jar 文件的放置路径。

þ 下载并构建JAF

目前Java Mail API 的所有版本都需要JAFJavaBeans Activation Framework)的支持。JAF 为输入的任意数据块提供了支持,并能相应地对其进行处理。下载后解压缩到硬盘上,并在系统的环境变量CLASSPATH 中指定activation.jar 文件的放置路径。

如果不想更改环境变量,也可以把activation.jar 添加到工程的构建路径中。


3  系统总体设计

3.1  系统目标

根据前面所作的需求分析及用户的需求可知,企业快信属于小型的企业通信软件,在系统实施后,应达到以下目标。

þ 界面设计友好、美观。

þ 操作灵活、方便。

þ 提供功能强大的信息库管理,方便用户进行短信息的编写。

þ 提供邮件群发功能,提高工作效率。

þ 在发送短信时,可以直接从现有信息库中获取信息内容。

þ 对用户输入的数据,进行严格的数据检验,尽可能地避免人为错误。

þ 数据存储安全、可靠。

3.2  系统功能结构

根据企业快信的特点,可以将其分为名片夹管理、信息库管理、短信群发、邮件群发、系统参数设置、系统设置6个部分,其中各个部分及其包括的具体功能模块如图3-1 所示。

图3-1 系统功能结构

3.3  业务流程图

企业快信的系统流程如图3-2 所示。

图3-2 系统流程图

3.4  系统预览

企业快信由多个程序页面组成,下面仅列出几个典型界面。

系统登录页面如图3-3所示,该页面用于实现管理员登录功能;主页如图3-4所示,该页面用于实现显示系统导航、操作业务流程和版权信息等功能。

图3-3 系统登录页面

图3-4 主 页

发送短信页面如图3-5所示,该页面用于实现将短信息同时发给多个接受者的功能;同时,为方便用户还提供了从客户及员工列表中选择接收者及从信息库中选择指定信息的功能。

图3-5 发送短信页面

邮件群发页面如图3-6所示,该页面用于实现将邮件同时发给多个接受者的功能;同时,为方便用户还提供了从客户及员工列表中选择接收者的功能。

图3-6 邮件群发

3.5  文件夹组织结构

在编写代码之前,需要把系统中可能用到的文件夹先创建出来(例如创建一个名为img 的文件夹,用来保存程序中使用的效果图片),这样不但方便以后的开发工作,也可以规范软件的整体架构。本人在开发企业快信时,设计了如图3-7 所示的文件夹架构。在开发时,只需要将所创建的文件保存在相应的文件夹中就可以了。

图3-7 企业快信文件夹组织结构


4  系统详细设计

4.1  数据库设计

4.1.1  数据库分析

由于本系统是一个小型实用的信息群发系统,提供了名片夹和信息库的功能,用户可以将常用的人员保存到名片夹中,将常用的短语保存到信息库中,以方便使用。基于这个特点以及语言特点,本系统将采用MySQL 数据库作为底层数据库,以方便用户使用本系统。

4.1.2  数据库概念设计

根据以上对系统所作的需求分析和系统设计,规划出本系统中使用的数据库实体分别为类型实体、档案实体、常用短语实体、管理员实体。下面将给出几个关键实体的E-R 图。

þ 档案实体

档案实体包括编号、客户名称、地址、邮政编码、所属区域、手机号码、邮件地址、银行账户、开户银行和联系人属性,档案实体的E-R 图如图4-1 所示

图4-1 档案实体E-R

þ 短信实体

短信实体包括编号、收信人的手机号码、短信内容、发信人和发送时间属性,短信实体的E-R 图如图4-2 所示。

þ 常用短语

4.1.3  数据库逻辑结构设计

在数据库概念设计中已经分析了档案实体、常用短语实体和类型实体,这些实体对象是数据表结的基本模型,最终的数据模型都要实施到数据库中,形成整体的数据结构。图4-4 为通过PowerDesigner创建完成的数据库模

4-4 数据库模型图

tb_customer 的表结构如表4-1 所示。

表4-1 tb_customer 的表结构

字 段 名

数 据 类 型

是 否 为 空

是 否 主 键

默 认 值

描  述

ID

int

No

Yes

ID(自动编号)

name

varchar(50)

No

NULL

客户名称

address

varchar(100)

No

NULL

地址

postcode

varchar(6)

No

NULL

邮政编码

area

varchar(20)

Yes

NULL

所属区域

mobileTel

avarchar(15)

No

NULL

手机号码

email

varchar(100)

No

NULL

邮件地址

bankNo

varchar(30)

Yes

NULL

银行帐号

bankName

varchar(20)

Yes

NULL

开户银行

linkName

varchar(10)

No

NULL

联系人

tb_shortLetter 的表结构如表4-2 所示。

表4-2 tb_shortLetter 的表结构

字 段 名

数 据 类 型

是 否 为 空

是 否 主 键

默 认 值

描  述

ID

int

No

Yes

ID(自动编号)

toMan

varchar(200)

No

NULL

发信人手机号码

content

varchar(500)

No

NULL

短信内容

fromMan

varchar(30)

No

NULL

发信人

sendTime

datetime

No

getdate()

发送时间

4.2  公共模块设计

在开发过程中,经常会用到一些公共模块,如数据库连接及操作的类、字符串处理的类及Struts配置等,因此,在开发系统前首先需要设计这些公共模块。下面将具体介绍企业快信系统中所需要的公共模块的设计过程。

4.2.1  数据库连接及操作类的编写

数据库连接及操作类通常包括连接数据库的方法getConnection()、执行查询语句的方法executeQuery()、执行更新操作的方法executeUpdate()、关闭数据库连接的方法close().下面将详细介绍如何编写企业快信系统中的数据库连接及操作的类ConnDB。

(1)定义ConnDB类

定义用于进行数据库连接及操作的类ConnDB,并将其保存到com.wgh.core包中,同时定义该类中所需的全局变量及构造方法。代码如下:

public class ConnDB {

public Connection conn = null; // 声明Connection对象的实例

public Statement stmt = null; // 声明Statement对象的实例

public ResultSet rs = null; // 声明ResultSet对象的实例

private static String propFileName = "/com/connDB.properties"; // 指定资源文件保存的位置

private static Properties prop = new Properties(); // 创建并实例化Properties对象实例

private static String dbClassName = " ";//定义保存数据库驱动的变量

private static String dbUrl =  " ";

private static String dbUser = "sa";

private static String dbPwd = "";

public ConnDB() { //定义构造方法

try { //捕捉异常

//将Properties文件读取到InputStream对象中

InputStream in = getClass().getResourceAsStream(propFileName);

prop.load(in); // 通过输入流对象加载Properties文件

dbClassName = prop.getProperty("DB_CLASS_NAME");//获取数据库驱动

dbUrl = prop.getProperty("DB_URL", dbUrl); //获取URL

dbUser = prop.getProperty("DB_USER", dbUser); //获取登录用户

dbPwd = prop.getProperty("DB_PWD", dbPwd); //获取密码

} catch (Exception e) {

e.printStackTrace(); // 输出异常信息

}

}

}

(2)将数据保存到资源文件中

为了方便程序移植,将数据库连接所需信息保存到properties文件中,并将该文件保存在com包中。connDB.properties文件的内容如下:

DB_CLASS_NAME=com.mysql.jdbc.Driver

DB_URL=jdbc:mysql://127.0.0.1:3306/db_expressLetter

DB_USER=sa

DB_PWD=

(3)创建数据库连接

创建连接数据库的方法getConnection(),该方法返回connection对象的一个实例。getConnection()方法的实现代码如下:

public static Connection getConnection() {

Connection conn = null;

try {

Class.forName(dbClassName).newInstance();

conn = DriverManager.getConnection(dbUrl, dbUser, dbPwd);

} catch (Exception ee) {

ee.printStackTrace();

}

if (conn == null) {

System.err.println("警告: DbConnectionManager.getConnection() 获得数据库链接失败.\r\n\r\n链接类型:"+ dbClassName+ "\r\n链接位置:" + dbUrl+ "\r\n用户/密码"+ dbUser + "/" + dbPwd);

}

return conn;

}

(4)创建查询方法

创建执行查询语句的方法exccuteQuery(),返回值为Resultset结果集。executeQuery()方法的代码如下:

public ResultSet executeQuery(String sql) {

try { // 捕捉异常

conn = getConnection(); // 调用getConnection()方法构造Connection对象的一个实例conn

stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,

ResultSet.CONCUR_READ_ONLY);

rs = stmt.executeQuery(sql);

} catch (SQLException ex) {

System.err.println(ex.getMessage()); // 输出异常信息

}

return rs; // 返回结果集对象

}

(5)创建更新操作方法

创建执行更新操作的方法executeUpdate(),返回值为int型的整数,代表更新的行数。executeUpdate()方法的代码如下:

public int executeUpdate(String sql) {

int result = 0; // 定义保存返回值的变量

try { // 捕捉异常

conn = getConnection(); // 调用getConnection()方法构造Connection对象的一个实例conn

stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,

ResultSet.CONCUR_READ_ONLY);

result = stmt.executeUpdate(sql); // 执行更新操作

} catch (SQLException ex) {

result = 0; // 将保存返回值的变量赋值为0

}

return result; // 返回保存返回值的变量

}

(6)关闭数据库连接

创建关闭数据库连接的方法close()close()方法的代码如下:

public void close() {

try { // 捕捉异常

if (rs != null) { // 当ResultSet对象的实例rs不为空时

rs.close(); // 关闭ResultSet对象

}

if (stmt != null) { // 当Statement对象的实例stmt不为空时

stmt.close(); // 关闭Statement对象

}

if (conn != null) { // 当Connection对象的实例conn不为空时

conn.close(); // 关闭Connection对象

}

} catch (Exception e) {

e.printStackTrace(System.err); // 输出异常信息

}

}

4.2.2  字符串处理类的编写

字符串处理类主要用于解决程序中经常出现的有关字符串处理的问题,包括将数据库中及页面中有中文问题的字符串进行正确地显示和对字符串中的空值进行处理的方法。其代码如下:

public class ChStr {

    public static String toChinese(String strvalue) {

    try {

        if (strvalue == null) {

            return "";

        } else {

            strvalue = new String(strvalue.getBytes("ISO8859_1"), "GBK").trim();

            return strvalue;

        }

    } catch (Exception e) {

        return "";

    }

}

//处理字符串中的空值

 public static final String nullToString(String v, String toV) {

     if (v == null || "".equals(v)) {

         v = toV;

     }

     return v;

}

4.2.3  配置Struts

Struts框架需要通过一个专门的配置文件来控制,就是struts-config.xml。那么网站是怎么找到这个Struts的配置文件的呢?只要在web.xml中配置一下就可以了。具体实现代码如下:

  <servlet>

    <servlet-name>action</servlet-name>

    <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>

  </servlet>

  <servlet>

    <servlet-name>action_tmp</servlet-name>

    <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>

    <init-param>

      <param-name>config</param-name>

      <param-value>/WEB-INF/struts-config.xml</param-value>

    </init-param>

  </servlet>

  <servlet-mapping>

    <servlet-name>action</servlet-name>

    <url-pattern>*.do</url-pattern>

  </servlet-mapping>

  <!-- 设置默认文件名称 -->

  <welcome-file-list>

    <welcome-file>login.jsp</welcome-file>

  </welcome-file-list>

在web.xml中配置Struts的配置文件,实际就是一个servlet的配置,即在配置serylet的config参数中定义struts的配置文件(包括相对路径)及在servlet的URL访问里使用后缀名。接下来的工作就是如何配置struts-config.xml文件。Struts-config.xml文件的关键代码如下:

<?xml version="1.0" encoding="UTF-8"?>

<struts-config>

  <data-sources />

  <form-beans >

    <form-bean name="managerForm" type="com.wgh.actionForm.ManagerForm" />

… //此处省略其他<form-bean>代码

  </form-beans>

  <action-mappings >

  <!-- 管理员 -->

 <action name="managerForm" path="/manager" scope="request" type="com.wgh.action.Manager" validate="true">

      <forward name="managerLoginok" path="/main.jsp" />

      <forward name="managerQuery" path="/manager.jsp" />

      <forward name="managerAdd" path="/manager_ok.jsp?para=1" />

      <forward name="pwdQueryModify" path="/pwd_Modify.jsp" />

      <forward name="managerDel" path="/manager_ok.jsp?para=3" />

      <forward name="modifypwd" path="/main.jsp" />

      <forward name="error" path="/error.jsp" />

    </action>

… //此处省略其他<action >代码

  </action-mappings>

</struts-config>

4.3  主页设计

4.3.1  主页概述

管理员通过系统登录模块的验证后,可以登录到企业快信的系统主页。系统主页主要包括系统导航栏、显示区和版权信息3部分。其中,导航栏中的功能菜单将根据登录管理员的权限进行显示。例如,系统管理员tsoft登录后,将拥有整个系统的全部功能,因为他是超级管理员。系统主页的运行效果如图4-5 所示。

4-5 企业快信主页运行效果

4.3.2  主页技术分析

在实现系统主页时,最关键的就是如何实现导航菜单.本系统中采用的方法是通过Javascript+CSS样式控制<div>标记来实现。其具体实现方法如下:

(1)在要显示导航菜单的位置添加相应的主菜单项。具体代码如下:

<a href="main.jsp">首页</a> |

<a  οnmοuseοver=showmenu(event,cardClip) οnmοuseοut=delayhidemenu() class='navlink' style="CURSOR:hand" >名片夹管理</a> |

<a  οnmοuseοver=showmenu(event,infoLibrary) οnmοuseοut=delayhidemenu() class='navlink' style="CURSOR:hand" >信息库管理</a> |

<a  οnmοuseοver=showmenu(event,shortLetter) οnmοuseοut=delayhidemenu() class='navlink' style="CURSOR:hand" >发送短信</a> |

<a  href="sendMail.do?action=addMail">邮件群发</a> |

<%if(purview.equals("1")){%>

<a  href="sysParameterSet.do?action=parameterQuery" >系统参数设定</a> |

<%}%>

<a οnmοuseοver=showmenu(event,sysSet) οnmοuseοut=delayhidemenu() class='navlink' style="CURSOR:hand">系统设置</a>

| <a href="#" onClick="quit()">退出系统</a>

在Javascript中指定各个子菜单的内容,并根据登录管理员的权限控制要显示的菜单项.关键代码如下:

<script language="javascript">

var cardClip='<table width=56><tr><td id=customer onMouseOver=overbg(customer) onMouseOut=outbg(customer)><a href=customer.do?action=customerQuery>客户管理</a></td></tr>\

<tr><td id=personnel onMouseOver=overbg(personnel) onMouseOut=outbg(personnel)><a href=personnel.do?action=personnelQuery>员工管理</a></td></tr>\

</table>'

var infoLibrary='<table width=86><tr><td id=infoType onMouseOver=overbg(infoType) onMouseOut=outbg(infoType)><a href=infoType.do?action=infoTypeQuery>信息类别管理</a></td></tr>\

<tr><td id=shortInfo onMouseOver=overbg(shortInfo) onMouseOut=outbg(shortInfo)><a href=shortInfo.do?action=shortInfoQuery>常用短语管理</a></td></tr>\

</table>'

<%if(purview.equals("1")){%>

var shortLetter='<table width=86><tr><td id=sendLetter onMouseOver=overbg(sendLetter) onMouseOut=outbg(sendLetter)><a href=sendLetter.do?action=addLetter>发送短信</a></td></tr>\

<tr><td id=historyQ onMouseOver=overbg(historyQ) onMouseOut=outbg(historyQ)><a href=sendLetter.do?action=historyQuery>查看发送日志</a></td></tr>\

</table>'

<%}else{%>

var shortLetter='<table width=56><tr><td id=sendLetter onMouseOver=overbg(sendLetter) onMouseOut=outbg(sendLetter)><a href=sendLetter.do?action=addLetter>发送短信</a></td></tr>\

</table>'

<%}if(purview.equals("1")){%>

var sysSet='<table width=70><tr><td id=manager onMouseOver=overbg(manager) onMouseOut=outbg(manager)><a href=manager.do?action=managerQuery>操作员管理</a></td></tr>\

<tr><td id=changePWD onMouseOver=overbg(changePWD) onMouseOut=outbg(changePWD)><a  href="manager.do?action=queryPWD">更改口令</a></td></tr>\

</table>'

<%}else{%>

var sysSet='<table width=70><tr><td id=changePWD onMouseOver=overbg(changePWD) onMouseOut=outbg(changePWD)><a   href="manager.do?action=queryPWD">更改口令</a></td></tr></table>'

<%}%>

</script>

4.4  名片夹管理模块设计

4.4.1  名片夹管理模块概述

名片夹管理模块主要包括客户信息管理和员工信息管理,其中,客户信息管理包括查看客户列表、添加客户信息、修改客户信息和删除客户信息4个功能:员工信息管理包括查看员工列表、添加员工信息、修改员工信息和删除员工信息4个功能。

4.4.2  名片夹管理模块技术分析

名片夹管理模块主要包括客户管理和员工管理两部分,由于这两部分的买现方法大致相同,所以本节将以客户管理为例介绍名片夹管理模块。在实现客户管理时,需要编写客户管理对应的ActionForm类和Action实现类。下面将详细介绍如何编写客户管理的ActionForm类和创建客户管理的Action实现类。

(1)编写客户管理的ActionForm类

在客户管理中,只涉及到一个数据表,即tb_customer(客户信息表),根据这个数据表可以得出客户管理的ActionForm类。客户管理的ActionForm类的名称为CustomerForm,具体代码如下:

public class CustomerForm extends ActionForm {

private String bankNo; //银行账号

private String area; //所属区域

private String email; //邮箱

private String address; //地址

private String mobileTel; //手机号码

private String name; //客户全称

private int ID; //编号

private String bankName; //开户银行

private String postcode; //邮政编码

private String linkName; //联系人

public String getBankNo() {

return bankNo;

}

public void setBankNo(String bankNo) {

this.bankNo = bankNo;

}

… //此处省略其他控制客户信息的get()和set()方法

}

(2)创建客户管理的Action实现类

客户管理的Action实现类Customer继承了Action类.在该类中,首先需要在该类的构造方法中实例化客户管理的CustomerDAO类(该类用于实现与数据库的交互)。Action实现类的主要方法是execute(),该方法会被自动执行其本身没有具体的事务,是根据通过HttpservletRequest的getParamer()方法获取的action参数值执行相应方法的。客户管理的Action实现类的关键代码如下:

public class Customer extends Action{

    private CustomerDAO customerDAO = null;

    private ChStr chStr=new ChStr();

    public Customer() {

        this.customerDAO = new CustomerDAO();

    }

public ActionForward execute(ActionMapping mapping,ActionForm form,HttpServletRequest request,HttpServletResponse response){

       String action = request.getParameter("action");

       System.out.println("获取的查询字符串:" + action);

       if (action == null || "".equals(action)) {

         request.setAttribute("error","您的操作有误!");

          return mapping.findForward("error");

       }else if ("customerQuery".equals(action)) {

            return customerQuery(mapping, form, request,response);

}else if("customerAdd".equals(action)){

 return customerAdd(mapping, form, request,response);

}

else if("customerModify".equals(action)){

            return customerModify(mapping, form, request,response);

        }

request.setAttribute("error", "操作失败!");

return mapping.findForward("error");

}

…… //此处省略了该类中其他方法,这些方法将在后面的具体过程中给出。

}

4.4.3  查看客户信息列表的实现过程

查看客户信息列表使用的数据表:tb_customer

管理员登录后,选择“名片夹管理/客户管理”命令,进入到查看客户列表页面,在该页面中将以列表形式显示全部客户信息,同时提供添加客户信息、修改客户信息、删除客户信息的超链接。查看客户信息列表页面的运行效果如图4-6 所示。

图4-6 客户信息列表页面

在查看客户信息列表的方法customerQuery()中,首先调用CustomerDAO类中的query()方法查询全部客户信息,再将返回的查询结果保存到HttpServletRequest对象的CustomerQuery参数中.查看客户信息列表的方法CustomerQuery()的具体代码如下:

private ActionForward customerQuery(ActionMapping mapping, ActionForm form,

        HttpServletRequest request,HttpServletResponse response) {

        request.setAttribute("customerQuery", customerDAO.query(0));

        return mapping.findForward("customerQuery");

}

查看客户信息列表使用的CustomerDAO类的方法是query()。该方法只有一个用于指定客户ID的参数id(如果记的值为null,则查询全部客户信息),然后将查询结果保存到List集合中并返回该集合的实例。Query()方法的具体代码如下:

public List query(int id) {

     List customerList = new ArrayList();

        CustomerForm cF = null;

        String sql="";

        if(id==0){

            sql = "SELECT * FROM tb_customer";

        }else{

         sql = "SELECT * FROM tb_customer WHERE ID=" +id+ "";

        }

        ResultSet rs = conn.executeQuery(sql);

        try {

            while (rs.next()) {

                cF = new CustomerForm();

                cF.setID(rs.getInt(1));

                cF.setName(rs.getString(2));

                ……//此处省略获取并设置其他属性的代码

                cF.setLinkName(rs.getString(10));

                customerList.add(cF);

            }

        } catch (SQLException ex) {}

        finally{

conn.close();//关闭数据库连接}

        return customerList;

    }

4.4.4  添加客户信息的实现过程

添加客户信息使用的数据表:tb_customer.

管理员登录后,选择“名片夹管理/客户管理”命令,进入到查看客户列表页面。在该页面中,单击“添加客户信息”超链接,进入到添加客户信息页面。添加客户信息页面的运行效果如图4-7 所示。

图4-7 添加客户信息页面

(1)设计添加客户信息页面

添加客户信息页面主要用于收集输入的客户信息及通过自定义的Javascript函数验证输入信息是否合法,该页面中所涉及的表单元素如表4-3 所示。

表4-3 表tb_customer的表结构

名  称

元 素 类 型

重 要 属 性

含义

title

form

action="customer.do?action=customerAdd" method="post" onSubmit="return checkform(form1)

表单

name

text

size=50

客户全称

area

text

size=30

所在区域

address

text

size=60

地址

postcode

text

size=6

邮政编码

linkName

text

size=20

联系人

mobileTel

text

size=30

手机号码

Email

text

size=50

邮箱

bankName

text

size=20

开户银行

bankNo

text

size=30

银行帐号

Submit

submit

value=提交

“提交”按钮

Submit2

reset

value=重置

“重置”按钮

Submit3

button

onClick="window.location.href='customer.do?action=customerQuery'" value="返回"

“返回”按钮

(2)修改客户的Action实现类

在添加客户信息页面中输入合法的客户信息后,单击“提交”按钮,网页会访问一个URL,即customer.do?action=customerAdd从该URL地址中可以知道添加客户信息模块涉及到的action的参数值为customerAdd,也就是当action=customerAdd时,会调用添加客户信息的方法customerAdd()。具体实现代码如下

if("customerAdd".equals(action)){

 return customerAdd(mapping, form, request,response);

}

在添加客户信息的方法customerAdd()首先需要将接收到的表单信息强制转换成ActionForm类型,并用获得指定属性的getXXX()重新设置该属性的setXXX()方法,然后调用customerDAO类中的insert()方法,将添加的客户信息保存到数据表中,并将返回值保存到变量ret中.如果返回值为l,表示信息添加成功,将页面重定向到添加信息成功页面:如果返回值为2,表示该客户信息己经添加,将错误提示信息“该客户信息己经添加!”保存到HttpServletRequest对象的error参数中,然后将页面重定向到错误提示信息页面;否则将错误提示信息“客户信息添加失败里”保存到HttpServletRequest对象的error参数中,并将页面重定向到错误提示页面.添加客户信息的方法customerAdd()的具体代码如下:

private ActionForward customerAdd(ActionMapping mapping, ActionForm form,

          HttpServletRequest request,HttpServletResponse response) {

      CustomerForm customerForm = (CustomerForm) form;

      //此处需要进行中文转码

      customerForm.setName(chStr.toChinese(customerForm.getName()));

      customerForm.setAddress(chStr.toChinese(customerForm.getAddress()));

      customerForm.setArea(chStr.toChinese(customerForm.getArea()));

customerForm.setBankName(chStr.toChinese(customerForm.getBankName()));

customerForm.setLinkName(chStr.toChinese(customerForm.getLinkName()));

      int ret = customerDAO.insert(customerForm);

      System.out.println("返回值ret:"+ret);

      if (ret == 1) {

          return mapping.findForward("customerAdd");

      } else if(ret==2){

          request.setAttribute("error","该客户信息已经添加!");

          return mapping.findForward("error");

      }else {

          request.setAttribute("error","添加客户信息失败!");

          return mapping.findForward("error");

      }

  }

(3)编写添加客户信息的CustomerDAO类的方法

添加客户信息使用的customerDAO类的方法是insert()。在insert()方法中,首先从数据表tb_customer中查询输入的客户全称是否存在,如果存在,将标志变最设置为2,否则将输入的信息保存到客户信息表中,并将返回值赋给标志变量,最后返回标志变量。Insert()方法的具体代码如下:

public int insert(CustomerForm cF) {

      String sql1="SELECT * FROM tb_customer WHERE name='"+cF.getName()+"'";

      ResultSet rs = conn.executeQuery(sql1);

      String sql = "";

      int falg = 0;

          try {

              if (rs.next()) { falg=2;} else {

                  sql = "INSERT INTO tb_customer (id,name,address,area,postcode,mobileTel,email,bankName,bankNo,linkName) values(null,'" + cF.getName() + "','" +cF.getAddress() +"','"+cF.getArea()+"','"+cF.getPostcode()+"','"+cF.getMobileTel()+"','"+ cF.getEmail()+"','"+cF.getBankName()+"','"+cF.getBankNo()+"','"+cF.getLinkName()+"')";

                  falg = conn.executeUpdate(sql);

                  System.out.println("添加客户信息的SQL:" + sql);

                    conn.close();

              }

          } catch (SQLException ex) { falg=0;}

      return falg;

  }

(4)Struts-config.xml文件配置

在struts-config.xml文件中配置添加客户信息所涉及的<forward>元素。代码如下:

<forward name="managerAdd" path="/manager_ok.jsp?para=1" />

4.4.5  删除客户信息的实现过程

在删除客户信息的方法customerDel()中,首先需要将接收到的表单信息强制转换成ActionForm类型,并用获得的记参数的值重新设置该ActionForm的setId()方法,再调用customerDAO类中的delete()方法,删除指定的客户信息,并根据执行结果将页面转到相应页面.删除客户信息的方法customerDel()的具体代码如下:

 private ActionForward customerDel(ActionMapping mapping, ActionForm form,

              HttpServletRequest request, HttpServletResponse response) {

     CustomerForm customerForm = (CustomerForm) form;

     customerForm.setID(Integer.parseInt(request.getParameter("id")));

     int ret = customerDAO.delete(customerForm);

     if (ret != 0) {

         request.setAttribute("error","删除客户信息失败!!");

         return mapping.findForward("error");

     } else { return mapping.findForward("customerDel"); }

 }

删除客户信息使用的CustomerDAO类的方法是delete()。在delete()方法中,将从客户信息表tb_customer中删除符合条件的数据,并返回执行结果。delete()方法的具体代码如下:

public int delete(CustomerForm customerForm) {

int flag=0;

try{

  String sql = "DELETE FROM tb_customer where id=" + customerForm.getID() +"";

    flag = conn.executeUpdate(sql);

}catch(Exception e){

System.out.println("删除客户信息时产生的错误:"+e.getMessage());

    }finally{ conn.close(); //关闭数据库连    }

    return flag;

}

在struts-config.xml文件中配置添加客户信息所涉及的<forward>元素。代码如下:

<forward name="managerDel" path="/manager_ok.jsp?para=3" />

4.5  发送短信模块设计

4.5.1  发送短信模块功能概述

发送短信模块主要包括发送短信、查看发送日志两个功能。这两个功能之间的业务流程如图4-8 所示。

图4-8 业务流程图

发送短信模块是企业快信系统的核心模块之一,操作员可以通过该模块对企业内部的所有或者部分员工,以短信的形式发送企业通知、工资条、具体技术、开会等信息,并且这个信息是群体发送的。

4.5.2  发送短信的实现过程

发送短信使用的数据表:tb_shortLetter、tb_shortIfo、tb_info、tb_infoType、tb_customer和tb_personnel。

管理员登录后,选择“发送短信”命令,进入到发送短信页面。在该页面中展开“名片夹”中的客户列表或员工列表,将显示相应的客户名称或员工姓名,单击指定的客户名称或员工姓名,系统会自动将该客户或员工的手机号码添加到右侧的“接收方手机号码”文本框中。如果用户想从信息库中选择常用短语直接添加到“短信内容”文本框中,可以先在“添加常用短语”下拉列表框中选择相应的类别,然后单击“确定”按钮,在打开的网页对话框中单击要添加的信息,即可将该信息添加到“短信内容”文本框中。短信内容填写完毕,单击“发送”按钮即可发送。发送短信页面的运行效果如图4-9 所示。

4-9 企业快信的短信发送界面

4.5.3  发送短信模块技术分析

在实现发送短信模块时,需要编写发送短信模块对应的ActionForm类和Action实现类。下面将详细介绍如何编写发送短信模块的ActionForm类和创建发送短信的Action实现类。

  1. 编写收发短信的ActionForm类

在发送短信模块中,涉及到tb_shortLetter(短信表)、tb_customer(客户信息表)、tb_personnel(员工信息表)、tb_shortInfo(常用短语表)、tb_infoType(信息类型表)和tb_Parameter(系统参数表)6个数据表,与这6个数据表相对应的ActionForm类分别为ShortLetterForm、CustomerForm、PerrsonnelForm、shortInfoForm、InfoTypyForm、ParameterForm,这些类都是由属性及对应的getXXX()和setXX()方法组成,不再详细介绍。

(2) 创建发送短信的Action类

收发短信模块的Action实现类SendLetter维承了Action类.在该类中.首先需要在该类的构造方法中分别实例化收发短信模块的SendLetterDAO类、员工管理摸块的PersonnelDAO类、客户管理模块的CustomerDAO类和信息类别管理模块的InfoTypeDAO类。Action实现类的主要方法是execute(),该方法会被自动执行其本身没有具体的事务,是根据HttpServletRequest的getParameter()方法获取的Action参数值执行相应方法的。发送短信模块Action实现类的关健代码如下:

public class SendLetter extends Action{

    private SendLetterDAO sendLetterDAO = null;

    private PersonnelDAO personnelDAO=null;

    private CustomerDAO customerDAO=null;

    private InfoTypeDAO infoTypeDAO=null;

    private ChStr chStr=new ChStr();

    public SendLetter() {

        this.sendLetterDAO = new SendLetterDAO();

        this.personnelDAO=new PersonnelDAO();

        this.customerDAO=new CustomerDAO();

        this.infoTypeDAO=new InfoTypeDAO();

    }

public ActionForward execute(ActionMapping mapping,ActionForm form,HttpServletRequest request,HttpServletResponse response){

        String action = request.getParameter("action");

        System.out.println("获取的查询字符串:" + action);

        if (action == null || "".equals(action)) {

         request.setAttribute("error","您的操作有误!");

            return mapping.findForward("error");

        }else if ("addLetter".equals(action)) {

            return addLetter(mapping, form, request,response);

        }else if("sendLetter".equals(action)){

            return sendLetter(mapping, form, request,response);

        }else if("historyQuery".equals(action)){

         return queryHistory(mapping, form, request,response);

        }

request.setAttribute("error", "操作失败!");

return mapping.findForward("error");

}

    //编写短信页面应用的查询方法,用于查询收信人列表信息类别

    private ActionForward addLetter(ActionMapping mapping, ActionForm form,

              HttpServletRequest request,HttpServletResponse response) {

        request.setAttribute("personnelQuery",personnelDAO.query(0));

        request.setAttribute("customerQuery",customerDAO.query(0));

        request.setAttribute("shortInfo",infoTypeDAO.query(0));

        return mapping.findForward("addLetter");

    }

    //群发短信

    private ActionForward sendLetter(ActionMapping mapping, ActionForm form,

               HttpServletRequest request,HttpServletResponse response){

     SendLetterForm sendLetterForm=(SendLetterForm) form;

     sendLetterForm.setContent(chStr.toChinese(sendLetterForm.getContent()));

     sendLetterForm.setFromMan(chStr.toChinese(sendLetterForm.getFromMan()));

        String ret=sendLetterDAO.sendLetter(sendLetterForm);

        if(ret.equals("ok")){

         return mapping.findForward("sendLetter");

        }else{

            request.setAttribute("error",ret);

            return mapping.findForward("error");

        }

    }

    //查看历史记录

    private ActionForward queryHistory(ActionMapping mapping, ActionForm form,

              HttpServletRequest request, HttpServletResponse response) {

        request.setAttribute("history",sendLetterDAO.query());

        return mapping.findForward("queryHistory");

    }

}

(3) 编写发送短信的SendLetterDAO类的方法

发送短信使用的sendLetterDAO类的方法是sendLetter()。在sendLettr()方法中,首先从数据表tb_parameter中查询出系统参数(即使用飞信接口发送短信所使用的端口、帐号、密码等参数),然后调用发送短信的方法mySend(),最后将发送短信的日志信息保存到数据表tbshortLetter中。sendLetter()方法的具体代码如下:

public class SendLetterDAO {

private ConnDB conn=new ConnDB();

List parameter = ParameterDAO.query();

ParameterForm parameterForm = (ParameterForm) parameter.get(0);

private smssend smssendinformation = null;

// 发送短信

public String sendLetter(SendLetterForm s) {

String ret = "";

String info="";

String sendnum="";

String flag="";

try {

String sql_p="SELECT  * FROM tb_parameter";

ResultSet rs=conn.executeQuery(sql_p);

if(rs.next()){

String phone=parameterForm.getDevice();

     String pwd=parameterForm.getBaud();

info=s.getContent();

sendnum=s.getToMan();

flag=mySend(phone,pwd,sendnum,info);//发送短信

if(flag.equals("ok")){

            String sql = "INSERT INTO tb_shortLetter values(null,'" +s.getToMan() +"','"+s.getContent()+"','"+s.getFromMan()+"',now())";

            int r= conn.executeUpdate(sql);

            System.out.println("添加短信发送历史记录的SQL:" + sql);

            if(r==0){

             ret="添加短信发送历史记录失败!";

            }else{

             ret="ok";

            }

}else{

ret=flag;

}

}else{

ret="发送短信失败!";

}

} catch (Exception e) {

System.out.println("发送短信产生的错误:" + e.getMessage());

ret = "发送短信失败!";

}finally{

conn.close();

}

return ret;

}

public static String mySend(String phone,String pwd,String to,String msg) throws HttpException, IOException{

String ret="";

        HttpClient client = new HttpClient();  

        PostMethod post = new PostMethod("http://quanapi.sinaapp.com/fetion.php");

post.addRequestHeader("Content-Type","application/x-www-form-urlencoded;charset=utf-8");//在头文件中设置转码   

        NameValuePair[] data ={   

               new NameValuePair("u", phone),  

               new NameValuePair("p", pwd),  

               new NameValuePair("to",to),  

               new NameValuePair("m",msg),  

               };  

        post.setRequestBody(data);  

        client.executeMethod(post);  

        Header[] headers = post.getResponseHeaders();  

        int statusCode = post.getStatusCode();  

        System.out.println("statusCode:"+statusCode);  

        for(Header h : headers){  

            System.out.println(h.toString());  

        }  

        post.releaseConnection();

        ret = "ok";

        return ret;}

    //中间省略查询日志的代码

}

(4) struts-config.xml文件配置

在struts-config.xml文件中配置发送短信所设计的<forward>元素。代码如下:

<forward name=”sendLetter” path=”/sendLetter_ok.jsp”/>

4.5.4  单元测试

在开发完收发短信模块后,为了保证程序正常运行,要对模块进行单元测试.单元测试在程序开发中非常重要,只有通过单元测试才能发现模块中的不足之处,才能及时地纠正程序中出现的错误。进入到发送短信页面,在“接收方手机号码”文本框中

输入相应的手机号码(多个手机号码间用逗号分隔),在“短信内容”文本框中输入短信内容后,单击“发送”按钮,正常情况下,会弹出“短信发送成功”的提示对话框,如果发送失败,则会弹出“短信发送失败”的提示对话框。

4.6  发送邮件模块设计

4.6.1  发送邮件模块功能概述

发送邮件模块也是企业快信系统的核心模块之一,操作员可以通过该模块对企业内部的所有或者部分员工,以E-mail 电子邮件的形式发送企业通知、工资条等。另外,由于E-mail 有信息容量大、包含附件的两大优点,使它支持更多的信息内容,可以携带更丰富的资料,比较适合发送技术信息、会议主题、工作内容等信息,并且这个信息是群体发送的。该模块的运行效果如图4-10 所示。

图4-10 企业快信的邮件发送界面

4.6.2  发送邮件模块技术分析

在实现邮件发送模块时,需要编写邮件发送模块对应的ActionForm类和Action实现类。下面将详细介绍如何编写邮件发送模块的ActionForm类和创建邮件发送的Action实现类。

(1) 编写邮件群发的ActionForm类

虽然在邮件发送模块中,只涉及到tb_customer(客户信息表)和tb_personnel(员工信息表)两个数据表,但是邮件群发并不是只涉及到与这两个数据表相对应的ActionForm类--CustomerForm和PcrsonnelForm,本模块中还涉及到用于获取发送邮件所需的表单信息的ActionForm类―sendMailForm. 

(2) 创建邮件发送的Action实现类

邮件发送模块的Action实现类SendMail继承了Action类。在该类中,首先需要在该类的构造方法中分别实例化邮件发送模块的SendMailDAO类、员工管理模块的PersonnelDAO类和客户管理模块的customerDAO类.Action实现类的主要方法是execute(),该方法会被自动执行.这个方法本身没有具体的事务,它是根据HttpServletRequest的getParameter()方法获取的action参数值执行相应方法的。邮件发送模块Action实现类的关键代码如下:

public class SendMail extends Action{

    private SendMailDAO sendMailDAO = null;

    private PersonnelDAO personnelDAO=null;

    private CustomerDAO customerDAO=null;

    private ChStr chStr=new ChStr();

    public SendMail() {

        this.sendMailDAO = new SendMailDAO();

        this.personnelDAO=new PersonnelDAO();

        this.customerDAO=new CustomerDAO();

    }

public ActionForward execute(ActionMapping mapping,ActionForm form,HttpServletRequest request,HttpServletResponse response){

        String action = request.getParameter("action");

        System.out.println("获取的查询字符串:" + action);

        if (action == null || "".equals(action)) {

     request.setAttribute("error","您的操作有误!"); //将错误信息保存到error中

            return mapping.findForward("error"); //转到显示错误信息的页面

        }else if ("addMail".equals(action)) {

            return addMail(mapping, form, request,response);

        }else if("sendMail".equals(action)){

            return sendMail(mapping, form, request,response);

        }

request.setAttribute("error", "操作失败!");

return mapping.findForward("error");

}

}

4.6.3  发送邮件模块实现过程

(1) 发送邮件的Action实现类

在邮件群发页面中填写相应的邮件信息后,单击“发送”按钮,网页会访问一个URL,即sendMail.do?action=sendMail。从该URL地址中可以知道发送邮件时涉及到的action的参数值为sendMail,也就是当action=sendMail时,会调用群发邮件的方法sendMail()。具体代码如下:

if("sendMail".equals(action)){

      return sendMail(mapping, form, request,response);

}

在发送邮件的方法sendMail()中,首先需要将接收到的表单信息强制转换成ActionForm类型,并用获得指定属性的getXXX()方法获取主题、附件、内容属性并进行转码后,再使用setXXX()方法重新设置该属性,然后调用SendMailDAO类中的sendMail()方法发送邮件,并将返回值保存到变量ret中。如果返回值为ok,则表示邮件发送成功,将页面重定向到邮件发送成功页面:否则,将错误提示信息保存到HttpservletRequest对象的errror参数中,并且将页面重定向到错误提示信息页面.群发邮件的方法sendMail()的具体代码如下:

private ActionForward sendMail(ActionMapping mapping, ActionForm form,

HttpServletRequest request,HttpServletResponse response){

     SendMailForm sendMailForm=(SendMailForm) form;

     sendMailForm.setTitle(chStr.toChinese(sendMailForm.getTitle()));

     sendMailForm.setAdjunct(chStr.toChinese(sendMailForm.getAdjunct()));

     sendMailForm.setContent(chStr.toChinese(sendMailForm.getContent()));

     int ret=sendMailDAO.sendMail(sendMailForm);

     if(ret==0){

         request.setAttribute("error","邮件发送失败!");

         return mapping.findForward("error");

     }else{

         return mapping.findForward("sendMail");

     }

}

(2) 编写发送邮件的SendMailDAO类的方法

发送邮件使用的SendMailDA0类的方法是sendMail()。具体代码如下:

public int sendMail(SendMailForm s) {

int ret = 0;

String from = s.getAddresser();

String to = s.getAddressee();

String subject = s.getTitle();

String content = s.getContent();

String password = s.getPwd();

String path = s.getAdjunct();

try {

String mailserver ="smtp."+from.substring(from.indexOf('@')+1,from.length()); //在Internet上发送邮件时的代码

Properties prop = new Properties();

prop.put("mail.smtp.host", mailserver);

prop.put("mail.smtp.auth", "true");

Session sess = Session.getDefaultInstance(prop);

sess.setDebug(true);

MimeMessage message = new MimeMessage(sess);

message.setFrom(new InternetAddress(from)); // 给消息对象设置发件人

//设置收件人

String toArr[]=to.split(",");

InternetAddress[] to_mail=new InternetAddress[toArr.length];

for(int i=0;i<toArr.length;i++){

to_mail[i]=new InternetAddress(toArr[i]);

}

   message.setRecipients(Message.RecipientType.BCC,to_mail);

//设置主题

message.setSubject(subject);

Multipart mul = new MimeMultipart(); // 新建一个MimeMultipart对象来存放多个BodyPart对象

BodyPart mdp = new MimeBodyPart(); // 新建一个存放内容的BodyPart对象

mdp.setContent(content, "text/html;charset=gb2312");

mul.addBodyPart(mdp); // 将含有信件内容的BodyPart加入到MimeMulitipart对象中

if(!path.equals("") && path!=null){ //当存在附件时

// 设置信件的附件(用本机上的文件作为附件)

mdp = new MimeBodyPart(); // 新建一个存放附件的BodyPart

String adjunctname = new String(path.getBytes("GBK"), "ISO-8859-1"); // 此处需要转码,否则附件中包括中文时,将产生乱码

path = (System.getProperty("java.io.tmpdir") + "/" + path).replace("\\", "/");

System.out.println("路径:" + path);

FileDataSource fds = new FileDataSource(path);

DataHandler handler = new DataHandler(fds);

mdp.setFileName(adjunctname);

mdp.setDataHandler(handler);

mul.addBodyPart(mdp);

}

message.setContent(mul); // 把mul作为消息对象的内容

message.saveChanges();

Transport transport = sess.getTransport("smtp");

// 以smtp方式登录邮箱,第1个参数是发送邮件用的邮件服务器SMTP地址,第2个参数为用户名,第3个参数为密码

transport.connect(mailserver, from, password);

transport.sendMessage(message, message.getAllRecipients());

transport.close();

ret = 1;

} catch (Exception e) {

e.printStackTrace();

System.out.println("发送邮件产生的错误:" + e.getMessage());

ret = 0; }

return ret;

}

4.6.4  单元测试

在开发完邮件群发模块后,为了保证程序正常运行,一定要对模块进行单元测试,下面是原始的实现邮件发送的代码:

if(!path.equals("") && path!=null){ //当存在附件时

// 设置信件的附件(用本机上的文件作为附件)

mdp = new MimeBodyPart(); // 新建一个存放附件的BodyPart

String adjunctname=path;

path = (System.getProperty("java.io.tmpdir") + "/" + path).replace("\\", "/");

System.out.println("路径:" + path);

FileDataSource fds = new FileDataSource(path);

DataHandler handler = new DataHandler(fds);

mdp.setFileName(adjunctname);

mdp.setDataHandler(handler);

mul.addBodyPart(mdp);

通过上面的代码实现的邮件群发会存在以下问题:当发送带有中文名称的邮件后.使用Outlook软件接收邮件时,附件的名称将产生乱码。这是因为在邮件群发的Action类中,己经将接收到的附件名称转换为GBK编码格式,而在OutLook接收附件时,采用的编码格式为ISO-8859-1,所以此处还需要将其转换为巧IOS-8859-1编码格式。那为什么还要在Action类中进行转码呢?这是因为如果不进行转换,在类中通过文件名获取文件路径时,将不能正常获取。修改后的完成邮件群发的代码如下:

if(!path.equals("") && path!=null){ //当存在附件时

// 设置信件的附件(用本机上的文件作为附件)

mdp = new MimeBodyPart(); // 新建一个存放附件的BodyPart

String adjunctname = new String(path.getBytes("GBK"), "ISO-8859-1"); // 此处需要转码,否则附件中包括中文时,将产生乱码

path = (System.getProperty("java.io.tmpdir") + "/" + path).replace("\\", "/");

System.out.println("路径:" + path);

FileDataSource fds = new FileDataSource(path);

DataHandler handler = new DataHandler(fds);

mdp.setFileName(adjunctname);

mdp.setDataHandler(handler);

mul.addBodyPart(mdp);


5  技术分析

5.1  开发技巧与难点分析

5.1.1  添加收信人

为了方便用户,系统中需要提供通过单击客户列表(或员工列表)中的客户全称(或员工姓名),即可将该客户(或员工)的联系手机号码添加到“接收方手机号码”文本框中的功能。实现该功能时.需要编写自定义的JavaScript函教add(),在该函数中需要对手机号码进行验证并实现累加手机号码到“接收方手机号码”文本框中的功能。Add()函数的具体代码如下:

function add(mobileTel){

if(checkTel(mobileTel)){

s=form1.toMan.value;

if(s.length>=11){

arrS=s.split(",");

flag=false; //标记是否已经添加

for(i=0;i<arrS.length;i++){

if(arrS[i]==mobileTel){ //判断该手机号码是否已经添加

flag=true;

break;

}

}

if(!flag){

form1.toMan.value=s+","+mobileTel;

}

}else{form1.toMan.value=mobileTel;}

}

}

5.1.2  插入短信

为了方便用户,系统中需要提供将信息库中保存的常用短语添加到“短信内容”文本框中的功能。实现该功能的具体步骤如下:

(1)在发送短信页面的“添加常用短语”下拉列表框的右侧添加一个“确定”按钮,在该按钮的onClick事件中调用自定义的Javascript函数deal()。关键代码如下:

function deal(infoType,text){

var someValue;

var str="window.showModalDialog('shortInfo.do?action=selectShortInfo&id="+infoType+"','','dialogWidth=520px;\

dialogHeight=430px;status=no;help=no;scrollbars=no')";

someValue=eval(str);

if(someValue!=undefined){text.value=text.value+someValue;

}

(2)创建选择指定类别的常用短语的页面selectShortInfo.jsp,并且在该页面中添加用于将选择的常用短语返回到打开该窗口的交量,并且关闭当前窗口的自定义JavaScript函数selectInfo().selectInfo()函数的具体代码如下:

<script language="javascript">

function selectInfo(info){

window.returnValue=info;

window.close();}

</script>

(3)在selectShortInfo.jsp中显示常用短语的代码上添加一个空的超链接,并且在其onClick事件中调用selectInfo()函数。具体代码如下:

<a href="#" onClick="selectInfo('<%=s.getContent()%>')"><%=s.getContent()%></a>

5.2  使用Java Mail 组件

Java Mail Sun 公司发布用来处理E-mail API,是一种可选的、用于读取、编写和发送电子消息的包(标准扩展)。使用Java Mail 可以创建MUAMail User Agent,邮件用户代理的简称)类型的程序,它类似于EudoraPine Microsoft Outlook 等邮件程序。其主要目的不是像发送邮件或提供MTAMail Transfer Agent,邮件传输代理)类型程序那样用于传输、发送和转发消息,而是可以与MUA 类型的程序交互,以阅读和撰写电子邮件。MUA 依靠MTA 处理实际的发送任务。Java Mail API 中提供很多用于处理E-mail 的类,其中比较常用的有Session(会话)类、Message(消息)类、Address(地址)类、 Authenticator(认证方式)类、Transport(传输)类、Store(存储)类和Folder(文件夹)类7 个类。这7 个类都可以在Java Mail API 的核心包mail.jar 中找到,下面进行详细介绍。

5.2.1  Session 类

Java Mail API 中提供了Session 类,用于定义保存诸如SMTP 主机和认证的信息的基本邮件会话。通过Session 会话可以阻止恶意代码窃取其他用户在会话中的信息(包括用户名和密码等认证信息),从而让其他工作顺利执行。

每个基于Java Mail 的程序都需要创建一个Session 或多个Session 对象。由于Session 对象利用java.util.Properties 对象获取诸如邮件服务器、用户名、密码等信息,以及其他可在整个应用程序中共享的信息, 所以在创建Session 对象前, 需要先创建java.util.Properties 对象的实例。创建java.util.Properties 对象的实例的代码如下:

Properties props=new Properties();

创建Session 对象可以通过以下两种方法,不过通常情况下会使用第二种方法创建共享会话。

1)使用静态方法创建Session 的语句如下:

Session session = Session.getInstance(props, authenticator);

2)创建默认的共享Session 的语句如下:

Session defaultSession = Session.getDefaultInstance(props, authenticator);

如果在进行邮件发送时,不需要指定认证方式,可以使用空值(null)作为参数authenticator 的值。例如创建一个不需要指定认证方式的Session 对象的代码如下:

Session mailSession=Session.getDefaultInstance(props,null);

5.2.2  Address 类

Address 类用于设置电子邮件的响应地址。Address 类是一个抽象类,要使用该抽象类可以使用其子类InternetAddress,该类保存在javax.mail.internet 包中,可以按照指定的内容设置电子邮件的地址。如果想对InternetAddress 类进行操作,首先要实例化该类的一个对象。在实例化该类的对象时,有以下两种方法。

创建带有电子邮件地址并显示其他标识信息的地址,可以将电子邮件地址和附加信息同时传递给InternetAddress 类的构造方法。代码如下:

InternetAddress address = new InternetAddress("wgh717@sohu.com","WangGuoHui");

5.2.3  Authenticator 类

Authenticator 类通过用户名和密码来访问受保护的资源。Authenticator 类是一个抽象类,要使用该抽象类首先需要创建一个Authenticator 的子类,并重载getPasswordAuthentication()方法。具体代码如下:

class WghAuthenticator extends Authenticator {

public PasswordAuthentication getPasswordAuthentication() {

String username = "wgh"; //邮箱登录账号

String pwd = "111"; //登录密码

return new PasswordAuthentication(username, pwd);

}

}

然后再通过以下代码实例化新创建的Authenticator 的子类,并将其与Session 对象绑定。

Authenticator auth = new WghAuthenticator ();

Session session = Session.getDefaultInstance(props, auth);

5.2.4  Transport 类

Transport 类用于使用指定的协议(通常是SMTP)发送电子邮件。Transport 类提供了以下两种发送电子邮件的方法:

1)只调用其静态方法send(),按照默认协议发送电子邮件。代码如下:

Transport.send(message);

2)首先从指定协议的会话中获取一个特定的实例,然后传递用户名和密码,再发送信息,最后关闭连接。代码如下:

Transport transport =sess.getTransport("smtp");

transport.connect(servername,from,password);

transport.sendMessage(message,message.getAllRecipients());

transport.close();

在发送多个消息时,建议采用第二种方法,因为它将保持消息间活动服务器的连接,而使用第一种方法时,系统将为每一个方法的调用建立一条独立的连接。


结 论

通过一个典型实用的企业快信应用系统,系统地介绍了如何利用JSP应用程序,实现群发手机短信和群发电子邮件的方法。在实现该企业快信系统时,还添加了几个方便用户使用的功能,例如利用名片夹管理名片信息,以及利用信息库管理信息模板,这样用户就不用反复地填写收信人列表以及编写重复的信息了。

该系统从问题定义到可行性研究、需求分析、总体设计、详细设计直到最后的系统测试,基本上实现了设计要求的各项功能。实现了名片夹管理、信息库管理、短信发送、邮件群发、系统设置等功能。每个模块都提供了相关的数据库操作,如增、删、查、改。在开发中,采用了 MySQL 数据库、JAVA MAIL 组件技术。短信群发,邮件群发能做到为企业提供实际的应用服务。

本系统的特点是利用飞信API的原理及方法,实现对单人或多人进行发送短信并利用 JAVA MAIL API 组件的一些类方法实现了邮件群发功能,方便了企业内部之间沟通交流更加方便快捷。但由于时间有限,系统还有很多不足之处。比如系统界面设计不够美观,我会在以后的学习和工作之余不断完善。


参考文献

[1]  刘春.企业级JavaMail在Oracle系统中部署[J]. 指挥信息系统与技术,2013,(01)

[2]  邱宏茂,许朝阳,盖磊. 基于JavaMail的Web Mail系统的实现 [J].计算机应用与软件, 2005,(06) 

[3]  王文帅,张红梅.基于JavaMail的点对点邮件批量发送系统 [D]. 第14届全国计算机、网络在现代科学技术领域的应用学术会议,2009

[4]  刘芳. 基于短信猫的短信发送平台的设计与实现 [J]. 电脑知识与技术,2013,(31)

[5]  原泉,蔡晶.针对短信猫接收短信的安全风险分析 [J]. 计算机安全, 2013,(06)

[6]  徐宇斐.企业快信系统的设计与实现 [D].吉林大学,(2013)

[7]  路高鹏.短信群发软件的设计与实现 [J].计算机与网络,2013,(05)

[8]  Ratecki, Krzysztof; Sakowicz, Bartosz.Configurable client email application working as web page [R] .MODERN PROBLEMS OF RADIO ENGINEERING, TELECOMMUNICATIONS AND COMPUTER SCIENCE, PROCEEDINGS,2006,(06)

[9]  Kuantama, Endrowednes; Mardjoko, Pono.Design and Construction of Early Flood Warning System Through SMS based on SIM300C GSMModem [R]. (ICICI-BME) ,2013,(03)

[10]  Lv, Fangxing; Xie, Xiaoyao; Zhang, Cuicui. Research and Development of E-mail Program Based on Java [J]. PROCEEDINGS OF THE 3RD INTERNATIONAL CONFERENCE ON ANTI-COUNTERFEITING, SECURITY, AND IDENTIFICATION IN COMMUNICATION,2009


致   谢

值此论文即将脱稿之际,我深刻地领悟到一篇论文的完成不仅仅包含着作者的劳动和付出,还凝结了其身边许多人的关心和支持。首先要感谢我的指导老师导师。本论文的研究工作是在他们精心的指导下完成的,论文从撰写、修改到定稿,无一不凝聚着恩师的心血与汗水。李老师不仅在论文的选题上给予方向性的指导,而且在论文进行当中,自始至终都给予了极大的支持。感谢导师为我提供了良好的学习和工作环境,并经常在工作上和生活中给予无微不至的关怀和极大的帮助。同时导师的严谨治学的态度、诲人不倦的品格、实事求是的工作作风和宽厚的待人品德,也使我受益匪浅,为我今后的人生道路树立了榜样。谨此向恩师表示深深的谢意和崇高的敬意!

同时向我的父母表达深深的谢意,是他们在精神和物质上一如既往地关爱和支持我,是他们殷殷期盼的目光,激励着我不断前行,不敢懈怠,是他们的爱使我满怀信心和希望。
外文原文

Research and Development of E-mail Program Based on Java

Abstract—This paper analyzes the working principle of the mail system, researches and develops on the three core modules of an E-mail system—E-mail sending module, E-mail receiving module, E-mail analysis and display module, and achieves the core function of an E-mail system using Java language.

Keywords-Java; E-mail; SMTP; POP3; IMAP; MIME

I. INTRODUCTION

With the computer and Internet technology’s development, e-mail has become an essential tool for life. Its simple use, rapid delivery, low-cost, easy preservation, including attachments and smooth in the world has greatly improved the way of people's exchange.

The core features of an e-mail system include e-mail sending, e-mail receiving and e-mail analysis. So, the development of e-mail system is difficult and complex. An email system is mostly a commercial software, whose code and realization is external confidential. Thus, its prices are extremely expensive.

In order to promote the e-mail technology’s open source and sharing, a lot of experiments aiming at the development of the e-mail system were done, and the core function aiming at the e-mail system was also analyzed and elaborated in this article, hoping to change e-mail systems into free open source software early, just like Linux.

II. THE WORKING PRINCIPLE OF E-MAIL

The e-mail’s transmission is a result of collaborative work among mail client program, SMTP server, DNS server and POP3/IMAP server [1]. Understanding the working principle of e-mail is the basis of e-mail program development.

A. Mail Transfer Protocol

The e-mail needs to be transmitted between mail client software and mail server software, as well as between the two mail servers. The e-mail delivery must follow certain rules which are called “Mail Transfer Protocol” [2]. They are defined in RFC documents as follows:

 SMTP Protocol

Its full name is Simple Mail Transfer Protocol, which defines the communication rules between mail client software and SMTP server, as well as between two SMTP servers.

 POP3 Protocol

Its full name is Post Office Protocol, which defines the communication rules between mail client software and POP3 server.

 IMAP Protocol

Its full name is Internet Message Access Protocol, which also defines the communication rules between mail client software and mail server. It is an extension of POP3 Protocol.

All of the mail server and the mail client program are compiled in the basis of above protocol.

B. Mail Transmission Process

Now, we illustrate the mail’s transmission process and working principle—taking google electronic mailbox and sina electronic mailbox as an example. Assuming that an account of sina mailbox is fangxinglv_1@sina.com and an account of sohu mailbox is fangxinglv_2@sohu.com, they send and receive mail as figure1.

The solid lines in figure1 represent that fangxinglv_1@sina.com account send a mail to fangxinglv_2@sohu.com account. While, the dotted lines represent that fangxinglv_1@ sohu.com account send a mail to fangxinglv_2@ sina.com account. Now, we specially explain all the involved steps from a mail sending to its receiving by analyzing the process that fangxinglv_1@sina.com account send a mail to fangxinglv_2@sohu.com account.

Figure 1. The schematic diagram of mail sending and receiving process

1) The mail client program of fangxinglv_1@sina.com account established network connection to sina’s SMTP server. Using fangxinglv_1’s user name and password, people can log in the system successfully. After that, the mail is sent to sina’s SMTP server by SMTP protocol.

2) After the SMTP server of sina received the e-mail fangxinglv_1@sina.com submitted, it determined whether the mail address of receiver is belong to the jurisdiction of its SMTP server according to the suffix of receiver’s mail address firstly. If it is, the mail is directly stored to the mailbox of receiver. Otherwise, the SMTP server of sina queries the domain name MX records expressed by the receiver's e-mail address suffix (sohu.com) to the DNS server. So, the information of sohu’s SMTP server is obtained. The connection to sohu’s SMTP server is established. Now, the mail is sent to sohu’s SMTP server.

3) After sohu’s SMTP server receives e-mail from sina’s SMTP server, it also need to determined whether the mail is belong to the jurisdiction of the SMTP server according to the mail address of receiver. If it is, the mail is directly stored to the mailbox of receiver. Otherwise, (Normally it will not happen),the SMTP server of sohu will continuous forward this e-mail, or it will discard this e-mail.

4) The user who owes fangxinglv_1@ sohu.com account establishes network connection to the POP3/IMAP server of sohu by mail client program. Using fangxinglv_1’s user name and password, people can log in the system successfully. Now, the user can check whether there is a new mail in the fangxinglv_2@sohu.com account by POP3/IMAP protocol. If there is, the mail can be read by POP3/IMAP protocol.

III. MAIL SENDING PROGRAM

When we receive an e-mail, the mail is sent from the SMTP server of this mail account. And the mail is sent to the SMTP server of the receiver by the address of the receiver.

A. The Architecture of Mail Sending API JavaMail API defines a java.mail.Transport class, which is dedicated to the implementation of e-mail task. Its instance objects encapsulate the bottom implementation details of some mail sending protocol. When application programs invoke the method of this class, the mail data encapsulated in Message Object is sent to the appointed SMTP server. The work relation of main APIs involved in sending mail by JavaMail is expressed in the following figure.

Figure 2. The work relation of JavaMail APIs in sending mail

1) Obtain and achieve a transport object of certain e-mail sending protocols from the Session object.

2) Use the Session object to create a Message object, and invoke methods of the Message object to encapsulate message datas.

3) Connect the specified SMTP server, and send the mail data encapsulated in Message Object using the mail sending method in the Transport object.

In the process of compiling the mail sending program, we query the information of DNS by JNDI, which is the English abbreviation of Java Naming and Directory Interface. It is an API (Application Programming Interface) providing naming and directory accessing for JAVA application program.

B. The Mail Sending Program with SMTP Server

The so-called mail sending program has SMTP server function. It is because that the program itself can directly send mail externally as a SMTP server. It doesn’t need to rely on other SMTP servers to send procedures externally.

The primary task of compiling mail sending program which has SMTP server function is to be able to obtain the name of its SMTP server according to the address of receiver. That is the MX records of receiver’s domain can be queried in DNS server, and the SMTP server’s name of the MX records can be analyzed. After obtaining the name of the SMTP server which contains the address of the receiver, the application programming can directly connect to this SMTP server to send mails, and sending mails does not require user authentication. The core code achieving SMTP server program is composed of the following components:

1) Set up the address of multiple receivers the mail will be mass sent to.

String [] to = {“UserName1@SeverName1.com”,

UserName2@ServerName2.com”, …}

2) Create the Session Object

Properties props = new Properties();

props.setProperty(“mail.smtp.localhost”,”mail.MySmtpServerName.com”);

Sesson session = Session.getInstance(props);

session.setDebug(true);

Message msg = createMessage(session);

for(int i=0; i<to.length; i++)

{

try{sentMessage(session, msg, to[i]);

}catch(Exception e){e.printStackTrance();}

}

3) Create the MimeMessage Object which represents the mail, not including the address of the receiver.

MimeMessage msg= new MimeMessage(session);

msg.setFrom(new InternetAddress(from));

msg.setSentDate(new Date());

msg.setSubject(subject);

msg.setText(body);

return msg;

4) Set up the receiver of e-mail contents and generate the contents of the message

msg.setRecipients(Message.RecipientType.TO,

InternetAddress.parse(to));

msg.saveChangs();

5) Connect to the SMTP server which contains the address of receivers and send the mail

Transport transport = session.getTransport(“smtp”);

String domain = to.substring(to.indexOf(“@”)+1);

String smtpServer = getSmtpServer(domain,null);

transport.connect(smtpServer,null,null);

transport.sentMessage(msg,msg.getRecipients(Message.Recip

ientType.To));

trasport.close();

C. Realizing E-mail Sending Function in Web Applications

Mail client software can be integrated in Web site, so that the registered users of Web sites can send and receive e-mails through Web pages. In order to realize the E-mail sending function in Web site, you need to rewrite the general E-mail sending procedure into a Web application. The process of Web site sending E-mail is described in the following figure.

Figure 3. The process of Web site sending E-mail

As can be seen from the figure above, the browser submits e-mail requests by visiting the e-mail sending program in the Web site. The e-mail sending program sends the E-mail to the SMTP server of its Web site. When the SMTP server receive the E-mail, it will deliver the E-mail to the local domain E-mail box or other domain SMTP server according to recipient’s Email address [3].

IV. E-MAIL RECEIVING PROGRAM

When an E-mail is sent to the mail recipient successfully, the recipient will use E-mail receiving program to login the POP3/IMAP server of his E-mail box and view mail list, and then select one E-mail to read [4].

A. The Architecture of E-mail Receiving API

A class named java.mail.Store is defined in JavaMail API. It is used to perform the task of receiving E-mail, and its object encapsulates the bottom implementation details of E-mail receiving protocol. The applications can get all the information of the mail folders in this user E-mail box by calling the methods in this class. Mail folders are represented with Folder object in JavaMail, and applications can get all information of the mail folder through the methods of Folder object. JavaMail use a Message object to encapsulate the information of an Email. The APIs involved in E-mail receiving in JavaMail are as follows:

The functions and mutual relations among the classes in the figure above are as follows:

1) Obtain a Store object which has implemented a certain E-mail protocol from Session object.

2) Connect to the POP3 or IMAP server with an E-mail account identity.

3) Obtain a Folder object which represents a mail folder in this E-mail account by calling getFolder method in Store object.

4) Obtain all mails or one mail by calling gatMessage or getMessage method in Folder object, and each mail is returned with a Message object.

B. The E-mail Receiving Program Based on Client

An E-mail receiving program has been wrote to receive Emails in a certain E-mail box, and to print subjects and senders of e-mail for user to browse. User can make the decision whether or not to read it, and if the user agrees to read it, then they can print the content of the E-mails.

1) Define the attributes of POP3 server connection

String pop3Server = “pop3.XXX.com”;

String protocol = “pop3”;

String username = “XXX”;

String password = “XXX”;

2) The authentication and login of POP3 server

Store store = mailSesson.getStore(protocol);

store.connect(pop3Server,username,password);

3) Obtain user’s E-mail account

Folder folder = store.getFolder(“inbox”);

4) Set the the access right to E-mail account

folder.open(Folder.READ_WRITE);

5) Obtain all E-mails in E-mail box

Message [] messages = folder.getMessages();

6) Obtain the subject of E-mail

String subject = messages[i].getSubject();

7) Obtain the address of E-mail sender

String from = (String) messages[i].getFrom()[0];

8) Output E-mail contents

messages[i].writeTo(System.out);

C. The E-mail Receiving Program Based on Web

An E-mail receiving program based on Web application has been wrote to receive E-mails which in a certain E-mail box, and to print subjects and senders of these e-mails for user to browse. Tomcat is chose to be Web server. The steps of writing and configuring the program are in the following:

1) Create a Web application named receivesMail in Tomcat server, and write a Servlet program named MsgInfo.java. The Core codes are offered as follows:

public class MsgInfo extends HttpServlet

{public void doGet(HttpServletRequest request,

HttpServletResponse response)throws ServletException,

IOException

{response.setContentType(“text/html;charset=gb2312”);

PrintWriter out = response.getWriter();

Properties prop = new Properties();

prop.setProperty(“mail.store.protocol”,”pop3”);

prop.setProperty(“mail.pop3.host”,”pop3.XXX.com”);

Session mailSession =

Session.getDefaultInstance(prop,null);

mailSession.setDebug(false);

try

{Store store = mailSession.getStore(“pop3”);

store.connect(“pop3.XXX.com”,”UserName”,”Passw

ord”);

Folder folder = store.getFolder(“inbox”);

folder.open(Folder.READ_WRITE);

Message messages[] = folder.getMessages();

String from = null;

String subject = null;

for(int i=0;i<messages.length;i++)

{from = message[i].getFrom()[0].toString();

subject = message[i].getSubject();

out.println(“From:” + from + “Subject:” + subject

+ “<br/>”);

}

}catch(MessagingException e)

{e.printStackTrace();}

}

}

2) Compile the Serlvet source program, and place the compiled class file to the directory "<Tomcat installation directory>\webapps\receivesMail\WEB-INF\classes\". Then add the mapping information of MsgInfo in the web.xml file.

3) Start the Tomcat server, and open the IE browser, then enter the URL “http://localhost:8080/receivesMail/MsgInfo” for testing.

D. Searching E-mail

JavaMail defines a class named SearchTerm in javax.mail.search package to create search conditions. After application creates the object of SearchTerm class, it can call Folder.search method to search all the E-mails which accord with the search conditions.

V. THE ANALYSIS AND DISPLAY OF E-MAIL

Analyzing and displaying an E-mail means analyzing the data which was encapsulated in Message object. These data contains the address of the E-mail sender in the E-mail head, the E-mail subject, the sending time, the text information in the E-mail text, the resources embedded, the mail attachments and so on, and then these data is sent to data displaying software to display.

A. The Organization Structure of MIME E-mailMIME protocol is used to define the format of complex Emailbody. It can express a number of text or non-text content.In addition, the data format accorded with MIME protocol can avoid the information loss in transmission Process. So, an Email using MIME protocol called MIME E-mail.

A MIME E-mail can be combined by many kinds of MIME messages. A MIME message represents a basic MIME resource or a combination of several basic MIME messages.Each MIME message includes two parts called the head and the body. In which, the MIME message body contains the specific content of the resources, and the MIME header contains the description information of resources. Some MIME message in the same level must be combined into a MIME combination message, and they are used as the body of MIME combination message together. They are separated by some separated identifiers, and the types and the separated identifiers of the combination must be described in the message head of MIME combination message. A MIME combination messagecan also combine with other MIME message to form a larger MIME combination message. Thus, they have formed a multilayer nested combination relation. A MIME E-mail is the most top-level MIME combination message formed in this combination mode. The MIME protocol can express complex contents in this multilayer combination mode [5].

There are three combination relationships among the MIME messages in a MIME E-mail: mixed, related, and alternative. And their corresponding MIME types are in the following:

 multipart /mixed

It represents the type of the content in the message body is mixed combination type. The content can be a mixing body which contains text, audio attachment and so on.

 multipart/related

It represents the type of the content in the message body is related combination type. In which, some resources are related to other resources.

 multipart/alternative

It represents the type of the content in the message body is alternative combination type. For example, when the main text of an E-mail is expressed by both HTML format and conventional text format, the two format text can be nested in a MIME combination message of  multipart/alternative type. The advantage of this method is that the text format among them can replace it, if the E-mail reading program does not support the HTML format.

The basic situation of the most complicated E-mail is: containing E-mail body and attachments. The main text of the E-mail can be expressed by both HTML format and conventional text format. And some embedded resources are related in the HTML format text. The MIME message structure of this kind of E-mail can be described in the following figure.

Figure 5. The MIME message structure of the complicated E-mail

B. The Flow of JavaMail Analyzing E-mail

1) Obtain the information of the E-mail, such as the subject of the E-mail and sender of the E-mail, by calling the getFrom method and the getSubject method in Message object.Get the E-mail type by the getContentType method.

2) Judge the type of the E-mail can according to the return value of the Message.getContentType method. And obtain the content of the E-mail by calling the Message.getContent method. If the type of the E-mail is “text/plain” or “text/html”, it expresses the type of the E-mail is pure text.The content of the E-mail can be obtained by calling the getContent method in Message object. Then convert the type of the return object to String type and output it to the display software. If the type of the E-mail is “mutlipart/*”, it expresses The content of the E-mail is compound type, then we need to convert the type of the return object to Multipart type.

3) Detect the number of BodyPart objects encapsulated in the Multipart object by calling the getCount method in the Multipart object, and then fetch and process each BodyPart object in Mutlipart object one by one by using for cycle.

VI. CONCLUSION

A complete E-mail system has a large scale, because of the limited space, this paper only realized the core functions of using Java language    based on SMTP protocol, POP3/IMAP protocol, and MIME protocol.
外文翻译

基于Java的电子邮件程序的研究和开发

摘要:本文分析了电子邮件系统的工作原理,研究和发展了E-mail系统的发送模块,接收模块,分析和显示三个核心模块,并实现使用Java语言实现电子邮件系统的核心功能。

关键词: Java ; E-mail ; SMTP ; POP3 ; IMAP ; MIME

I.引言

随着计算机和互联网技术的发展,电子邮件已经成为生活中不可或缺的工具。它使用简单,发送迅速,成本低,易保存,可以包括附件,大大提高了人们的交流方式。

电子邮件系统的核心功能包括邮件发送,邮件接收和邮件分析。因此,电子邮件系统的开发是困难和复杂的。一个电子邮件系统主要是一个商业软件,其代码和实现对外部保密。因此,它的价格是非常昂贵的。

为了促进电子邮件技术的开源和共享,已经在电子邮件系统上做了大量的实验,本文将对电子邮件系统的核心功能进行分析,希望变电子邮件系统为免费的开源软件,就像早期的Linux操作系统。

II.电子邮件的工作原理

电子邮件的传输是邮件客户端程序, SMTP服务器, DNS服务器和POP3/IMAP服务器协同工作的结果。了解电子邮件的工作原理是电子邮件程序开发的基础。

A.邮件传输协议

电子邮件需要被邮件客户端软件和邮件服务器软件,以及两个邮件服务器之间发送。该电子邮件传递必须遵循一定的规则,被称为“邮件传输协议” [ 2 ] 。它们是在RFC文档定义如下:

SMTP协议

它的全称是简单邮件传输协议,它定义了邮件客户端软件和SMTP服务器,以及两个SMTP服务器之间的通信规则。

POP3协议

它的全称是邮局协议,它定义了邮件客户端软件和POP3服务器之间的通信规则。

IMAP协议

它的全称是Internet消息访问协议,这也定义了邮件客户端软件和邮件服务器之间的通信规则。它是POP3协议的扩展。

上述协议是所有的邮件服务器和邮件客户端程序被编译的基础。

B.邮件传输过程

现在,我们说明一下邮件的传输过程和工作原理,我们用搜狐电子邮箱和新浪电子邮箱作为一个例子。假设新浪邮箱的帐户fangxinglv_1@sina.com和搜狐邮箱的帐户fangxinglv_2@sohu.com ,他们发送和接收邮件如图一。

图1中的实线代表从fangxinglv_1@sina.com帐户发送邮件到fangxinglv_2@sohu.com帐户。同时,虚线代表从fangxinglv_2@sohu.com帐户发送邮件到fangxinglv_1@sina.com帐户。现在,我们特地解释从fangxinglv_1@sina.com帐户发送邮件到fangxinglv_2@sohu.com帐户的过程中邮件发送其接收所有相关步骤。

1 ) fangxinglv_1@sina.com帐户的邮件客户端程序建立到新浪的SMTP服务器的网络链接。使用fangxinglv_1的用户名和密码登录系统。在此之后,该邮件是由SMTP协议发送到新浪的SMTP服务器。

2)在新浪的SMTP服务器收到提交的电子邮件fangxinglv_1@sina.com ,它确定是否接收的邮件地址是按照先接收方的邮件地址后缀属于它的SMTP服务器的司法管辖区。如果是,则该电子邮件被直接存储到接收器的邮箱。否则,新浪的SMTP服务器查询所接收的电子邮件地址后缀( sohu.com )到DNS服务器所表示的域名的MX记录。因此,获得搜狐的SMTP服务器的信息。要与搜狐的SMTP服务器建立链接。现在,该邮件被发送到搜狐的SMTP服务器。

3 )搜狐的SMTP服务器从新浪的SMTP服务器接收电子邮件后,还需要根据接收者的邮件地址的邮件判断是否属于SMTP服务器的司法管辖区。如果是,则该电子邮件被直接存储到接收器的邮箱。否则, (一般情况下也不会发生) ,搜狐的SMTP服务器将连续转发这个邮件,否则将丢弃此电子邮件。

4 )使用fangxinglv_1@sohu.com帐户的用户建立了从邮件客户端程序到搜狐的POP3/IMAP服务器的网络连接后,使用fangxinglv_1的用户名和密码登录成功。现在,用户可以检查是否有新邮件在fangxinglv_2@sohu.com账户通过POP3/IMAP协议。如果有,该邮件可以通过POP3/IMAP协议来读取。

III.邮件发送程序

当我们收到一封电子邮件时,该邮件从发送方的SMTP服务器发送给接收方的SMTP服务器的。

A.JavaMail API定义了一个java.mail.Transport类,它是专门用来完成发送电子邮件。它的实例对象封装了一些邮件发送协议的底部实现细节。应用程序调用该类将封装在MessageObject的邮件数据发送到指定的SMTP服务器。涉及通过JavaMail的发送邮件的主要API的工作关系是体现在如图2所示。

1)从会话对象中获得和实现运输对象的某些电子邮件发送协议。

2)使用会话对象来创建一个消息对象,并调用消息对象来封装消息数据的方法。

3)连接指定的SMTP传输对象服务器,使用邮件传输协议将邮件封装起来进行发送。

编译邮件发送程序的过程中,我们通过JNDI查询DNS的信息,这是Java命名和目录接口的英文缩写。这是一个API(应用程序编程接口)为JAVA应用程序提供命名和目录访问。

B.邮件发送程序和SMTP服务器

所谓的邮件发送程序SMTP服务器。因为程序本身可以直接发送邮件外部SMTP服务器,它不需要依靠其他SMTP服务器。

SMTP服务器主要功能是要能够根据接收方的地址获取其SMTP服务器的名称。这是接收器的域的MX记录,可以在DNS服务器上进行查询和分析。获得包含接收者的地址的SMTP服务器的名称后,应用程序编程可以直接连接到该SMTP服务器发送邮件,发送邮件并不需要用户身份验证。核心代码实现的SMTP服务器程序是由以下几部分组成:

1)设置多个接收者的邮件将被大规模发送到的地址。

String [] to = {“UserName1@SeverName1.com”,

UserName2@ServerName2.com”, …}

2)创建会话对象属性道具=新的属性() ;

Properties props = new Properties();

props.setProperty(“mail.smtp.localhost”,“mail.MySmtpServerName.com”);

Sesson session = Session.getInstance(props);

session.setDebug(true);

Message msg = createMessage(session);

for(int i=0; i<to.length; i++)

{

try{sentMessage(session, msg, to[i]);

}catch(Exception e){e.printStackTrance();}

}

3)创建的MimeMessage对象表示邮件,但不包括接收器的地址。

MimeMessage msg= new MimeMessage(session);

msg.setFrom(new InternetAddress(from));

msg.setSentDate(new Date());

msg.setSubject(subject);

msg.setText(body);

return msg;

4)设置的电子邮件内容的接收器,并生成该消息的内容

msg.setRecipients(Message.RecipientType.TO,

InternetAddress.parse(to));

msg.saveChangs();

5)连接到包含接收者地址的SMTP服务器并发送邮件

Transport transport = session.getTransport(“smtp”);

String domain = to.substring(to.indexOf(“@”)+1);

String smtpServer = getSmtpServer(domain,null);

transport.connect(smtpServer,null,null);

transport.sentMessage(msg,msg.getRecipients(Message.Recip

ientType.To));

trasport.close();

C.实现电子发送功能的Web应用程序

实现电子邮件在网络客户端发送的功能可以集成在网站上,从而使注册用户的网站都可以通过网页发送和接收电子邮件。为了实现在网站上的邮件发送功能,你需要重新在Web应用程序上编写邮件发送程序。网站发送电子邮件的过程如下图3所述。

从上面的图中可以看出,浏览器访问发送电子邮件的网站并提交电子邮件请求。电子邮件发送程序发送E-mail给自己网站的SMTP服务器。当SMTP服务器接收到邮件,它会根据收件人的电子邮件地址传送电子邮件到本地域的E-mail箱或其他域的SMTP服务器。

IV.邮件接收程序

当邮件成功发送给邮件接收这后,收件人将用邮件接收程序登录自己的电子信箱,查看POP3/IMAP服务器的邮件接收列表,然后选择一个邮箱阅读。

A.电子邮件接收的API架构

一个命名为java.mail.Stored的类定义存储在JavaMail API中。它是用来执行接收电子邮件的任务,它的对象封装了实现电子邮件接收协议的底层细节。应用程序可以通过用户的电子邮箱邮件文件夹获得调用该类的方法所有的信息。邮件文件夹通过JavaMail的文件夹对象来表示,应用程序可以通过文件夹对象获得邮件文件夹的所有信息。JavaMail使用一个消息对象来封装电子邮件的信息。参与电子邮件接收的JavaMail API如图4:

类在上图中的功能和相互关系如下:

1)从会话对象中获得一个执行某个电子邮件协议存储对象。

2)用一个电子邮件帐户连接到POP3和IMAP服务器。

3)电子邮件帐户通过调用getFolder方法存储对象获得一个代表邮箱文件夹的文件夹对象。

4)通过文件夹对象调用getMessage或getMessage方法获得所有邮件,并返回没有邮件的消息对象。

B.基于客户端的电子邮件接收程序

基于客户端的电子邮件接收程序可以接收电子邮件到一个文件中,并且打印出主题和发送者供用户浏览。用户可以决定是否要读它,如果用户同意读取它,那么他们就可以打印出电子邮件的内容。

1 )定义的POP3服务器连接的属性

String pop3Server = “pop3.XXX.com”;

String protocol = “pop3”;

String username = “XXX”;

String password = “XXX”;

2 )POP3服务器的认证和登录

Store store = mailSesson.getStore(protocol);

store.connect(pop3Server,username,password);

3 )获取用户的E -mail帐号

Folder folder = store.getFolder(“inbox”);

4)设置正确的E-mail帐号访问

folder.open(Folder.READ_WRITE);

5 )获得的所有电子邮件

Message [] messages = folder.getMessages();

6 )获取的电子邮件的主题

String subject = messages[i].getSubject();

7 )获得的电子邮件发件人的地址

String from = (String) messages[i].getFrom()[0];

8)输出电子邮件的内容

messages[i].writeTo(System.out);

C.基于Web 的电子邮件接收程序

基于Web的电子邮件接收程序接收电子邮件后打印这些电子邮件的主题和发件人供用户浏览。 Tomcat被选择做Web服务器。在写入和配置程序的步骤如下所示:

1 )在Tomcat服务器上创建一个接收邮件的Web应用程序,并编写一个名为MsgInfo.java一个Servlet程序。核心代码被提供如下:

public class MsgInfo extends HttpServlet

{public void doGet(HttpServletRequest request,

HttpServletResponse response)throws ServletException,

IOException

{response.setContentType(“text/html;charset=gb2312”);

PrintWriter out = response.getWriter();

Properties prop = new Properties();

prop.setProperty(“mail.store.protocol”,”pop3”);

prop.setProperty(“mail.pop3.host”,”pop3.XXX.com”);

Session mailSession =

Session.getDefaultInstance(prop,null);

mailSession.setDebug(false);

try

{Store store = mailSession.getStore(“pop3”);

store.connect(“pop3.XXX.com”,”UserName”,”Passw

ord”);

Folder folder = store.getFolder(“inbox”);

folder.open(Folder.READ_WRITE);

Message messages[] = folder.getMessages();

String from = null;

String subject = null;

for(int i=0;i<messages.length;i++)

{from = message[i].getFrom()[0].toString();

subject = message[i].getSubject();

out.println(“From:” + from + “Subject:” + subject

+ “<br/>”);

}

}catch(MessagingException e)

{e.printStackTrace();}

}

}

2 )编译Serlvet源程序,然后将编译后的class文件到目录<Tomcat安装目录>\webapps\receivesMail\WEB-INF\classes\"再在web.xml文件中加入MsgInfo的映射信息。

3 )启动Tomcat服务器,打开IE浏览器,然后输入网址“ http://localhost:8080/receivesMail/MsgInfo ”进行测试。

D.搜索E-mail

JavaMail在javax.mail.search包中定义了一个名为搜索关键词的类来创建搜索条件。之后应用程序创建搜索关键词类的对象,它可以调用Folder.search方法来搜索所有符合搜索条件的电子邮件。

五.电子邮件的分析和显示

分析和显示电子邮件是指分析封装在Message对象中的数据。这些数据包含电子邮件发件人的电子邮件头,电子邮件主题,发送时间,在E-mail文本中文本信息,内嵌的资源,邮件附件等,然后这些数据被发送到数据显示软件显示。

A.电子邮件的MIME协议的组织结构是用来定义复杂的电子邮件正文的格式。它能够表达许多文本或非文本。另外,赋予MIME协议的数据格式,可避免在传输过程中的信息丢失。因此,使用MIME协议的电子邮件被称为MIME电子邮件。

一个MIME邮件可以是多种MIME消息的组合。一个MIME消息表示一个基本的MIME资源或几个基本的MIME 信息.每个MIME消息的组合包括两个部分,称为头和身体。其中, MIME邮件正文包含邮件的具体内容,MIME头包含资源的描述信息。在相同的水平部分MIME消息必须被组合成一个MIME组合消息,它们被作为MIME组合消息体,一起使用。它们是由一些分开的标识符分离,将类型和组合的分开的标识符必须在MIME组合消息的消息头进行说明。一个MIME消息组合也与其他MIME消息结合起来,形成一个更大的MIME组合消息。因此,他们已经形成了多层嵌套的组合关系。一个MIME电子邮件是形成这种组合模式是最顶级的MIME组合消息。 MIME协议可以用这个多层组合方式表达复杂的内容。

MIME电子邮件三种组合关系:混合,相关和替代。相应的MIME类型是以下几点:

多重/混合

它代表在邮件正文的内容的类型是混合型的组合。内容可以是一个混合体,其中包含文字,音频附件等。

多重/相关

它代表在邮件正文的内容的类型是相关的组合类型。其中,一些资源相关的其它资源。

多重/替代

它代表在邮件正文的内容的类型是变体的组合类型。例如,当电子邮件的正文是由两个HTML格式和传统的文本格式表示,可以嵌套多重/替代型的MIME组合消息两种格式的文本。这种方法的优点是:如果电子邮件的读取程序不支持的HTML格式,它们之间的文本格式可以代替它。

最复杂的E-mail的基本情况是:含有的E-mail正文和附件。电子邮件的主文本可以由HTML格式和常规文本格式来表示。一些嵌入式资源放到HTML格式的文本中。这种电子邮件的MIME消息结构可以用图5来描述。

B.JavaMail分析电子邮件的流量

1 )获取E-mail ,如电子邮件主题和电子邮件的发送者,通过在消息体中调用getFrom方法和getSubject方法.获取电子邮件类型用getContentType方法。

2 )根据Message.getContentType方法的返回值判断E- mail的类型。并通过调用Message.getContent方法获得的E-mail的内容。如果电子邮件的类型是“ text / plain的”或“ text / html的” ,它所表达的电子邮件的类型是纯文本电子邮件.内容可以通过调用的getContent方法来获得。然后返回对象的类型转换为字符串类型,并将其输出到显示软件。如果电子邮件的类型是“ mutlipart / * ” ,它表示电子邮件的内容是复合型,那么我们就需要将返回对象的类型转换为多部分类型.

3 )通过在Multipart对象调用GetCount方法检测封装在Multipart对象中BodyPart类对象的数量,然后循环处理每一个BodyPart对象。

六。结论

一个完整的邮件系统规模庞大大,因为篇幅有限,本文只利用Java语言实现了基于SMTP协议, POP3/IMAP协议和MIME协议的邮件发送系统的核心功能。


http://www.ppmy.cn/news/1556957.html

相关文章

【RL】请问,在强化学习中,“observation空间”是不是“state空间”的子集呀?

Claude-3.5-sonnet-cursor: 这是一个很好的问题&#xff01;让我来详细解释一下 observation 和 state 的关系&#xff1a; 理论上的区别&#xff1a; State (状态) 是环境的完整描述包含环境的所有信息是马尔可夫的&#xff08;当前state包含预测未来所需的所有信息&#x…

企业如何选择媒体发稿平台及相关事项?媒介盒子分享

企业在选择媒体发稿平台时&#xff0c;需要综合考虑多个因素&#xff0c;以确保新闻稿能够精准传达给目标受众&#xff0c;并达到预期的传播效果。以下是一些关键步骤和注意事项&#xff1a; 一、明确新闻稿的传播目标 1、确定传播目标&#xff1a;企业首先要明确新闻稿的传播…

webpack常用配置讲解

Webpack 是一个强大的模块打包工具&#xff0c;用于将 JavaScript 文件及其依赖的其他资源&#xff08;如 CSS、图片等&#xff09;打包成最终的输出文件。配置 Webpack 时&#xff0c;你会用到一些常见的选项和功能&#xff0c;下面是一些常见的 Webpack 配置及其解释&#xf…

POD 存储、PV、PVC

目录 容器如何持久化存储&#xff1f; PV和PVC 为什么不能直接在 Pod 或容器中存储数据&#xff1f; 什么是 PV和 PVC&#xff1f; 可以使用本地磁盘空间创建PV吗&#xff1f; 如何让客户端通过ftp上传到远端服务器的POD里面&#xff1f; 另一个POD想访问ftp的POD里面的…

Pytorch应用实战(1)- 基于YOLO的视频人脸马赛克处理

免费链接: Blogger(需翻Q), Github 文章目录 本文介绍给图片的人脸打码给视频的人脸打码本文介绍 YoloV11(Github)提供了非常方便的API帮助用户实现目标检测(detect)、语义分割(segement)、肢体识别(Pose)等功能。 本文将基于YoloV11的目标检测来实现一个视频人脸马…

【前端面试】三次握手/http/https,是否跳转携带cookie,跨域

TCP三次握手 TCP三次握手是为了在客户端和服务器之间建立可靠的连接。首先&#xff0c;客户端向服务器发送一个SYN包&#xff0c;请求建立连接&#xff0c;并进入SYN_SENT状态&#xff1b;服务器收到SYN包后&#xff0c;回复一个SYNACK包&#xff0c;表示同意建立连接&#xf…

深入了解 MyBatis:简化 Java 数据库交互

引言 在现代软件开发中&#xff0c;数据库操作是不可或缺的一部分。为了简化 Java 应用程序与关系型数据库之间的交互&#xff0c;MyBatis 成为了一款非常受欢迎的持久层框架。本文将详细介绍 MyBatis 的核心概念、配置和使用方法&#xff0c;并分享一些最佳实践&#xff0c;帮…

国际抖音TikTok矩阵运营的关键要素有哪些?

在全球化的今天&#xff0c;TikTok作为新兴的社交媒体平台&#xff0c;为国际品牌提供了前所未有的营销机遇。通过构建TikTok矩阵&#xff0c;品牌可以迅速扩大国际影响力&#xff0c;精准触达目标受众&#xff0c;提升品牌认知度和用户粘性。本文将详细探讨国际抖音TikTok矩阵…