James+Javamail构建邮箱服务

James简介

Apache JamesJava Apache Mail Enterprise Server)是 Apache 组织的子项目之一,完全采用纯Java技术开发,实现了 SMTP、POP3 与 NNTP 等多种邮件相关协议

James 也是一个邮件应用平台,可以通过 Mailet 扩充其功能,如 Mail2SMS(邮件到短信)、Mail2Fax(邮件到传值)。James 提供了比较完善的配置方案,尤其是关于邮件内容存储和用户信息存储部分,可以选择在文件、数据库或其他介质中保存。

James 是基于Avalon应用程序框架主干版本构建的。该框架鼓励一系列良好的开发实践,例如面向组件的编程和控制反转。James 的标准发行版包括 Phoenix Avalon Framework 容器。这种稳定可靠的容器为 James 服务器奠定了坚实的基础。

组件:

通用电子邮件发送协议: SMTP,LMTP,POP3,IMAP,ManageSieve,JMAP

Mailet的容器:独立的,可扩展和可插拔的电子邮件处理剂

存储API:邮箱API /搜索API /用户API

存储实现:卡桑德拉/ PostgreSQL的/ HSQLDB / MySQL的/ ElasticSearch ...

管理: JMX / REST /命令行

James 核心

Java Mail 简介

常见的邮件协议包括:

1、SMTP(Simple Mail Transfer Protocol):即简单邮件传输协议,它是一组用于由源地址到目的地址传送邮件的规则,由它来控制信件的中转方式。

2、POP3(Post Office Protocol - Version 3):即邮局协议版本 3 ,用于接收电子邮件的标准协议。

3、IMAP(Internet Mail Access Protocol) :即 Internet 邮件访问协议。是 POP3 的替代协议。

这三种协议都有对应SSL加密传输的协议,分别是 SMTPS,POP3S 和 IMAPS 。

MIME(Multipurpose Internet Mail Extensions) :即多用途因特网邮件扩展标准。它不是邮件传输协议。但对传输内容的消息、附件及其它的内容定义了格式

简述发送和收取邮件的协议

SMTP

简单邮件传输协议(Simple Mail Transfer Protocol,SMTP)由RFC 821定义。它定义了发送电子邮件的机制。在 JavaMail API 环境中,您基于 JavaMail 的程序将和您的公司或因特网服务供应商的(Internet Service Provider's,ISP's)SMTP 服务器通信。SMTP 服务器会中转消息给接收方 SMTP服务器以便最终让用户经由 POP 或 IMAP 获得。这不是要求 SMTP 服务器成为开放的中继,尽管 SMTP 服务器支持身份验证,不过还是得确保它的配置正确。像配置服务器来中继消息或添加删除邮件账号这类任务的实现,JavaMail API 中并不支持。

POP

POP 代表邮局协议(Post Office Protocol)。目前用的是版本 3,也称 POP3,RFC 1939定义了这个协议。POP 是一种机制,因特网上大多数人用它得到邮件。它规定每个用户一个邮箱的支持。这就是它所能做的,而这也造成了许多混淆。使用 POP 时,用户熟悉的许多性能并不是由 POP 协议支持的,如查看有几封新邮件消息这一性能。这些性能内建于如 Eudora 或 Microsoft Outlook 之类的程序中,它们能记住一些事,诸如最近一次收到的邮件,还能计算出有多少是新的。所以当使用 JavaMail API 时,如果您想要这类信息,您就必须自己算。

IMAP

IMAP 是更高级的用于接收消息的协议。在RFC 2060中被定义,IMAP 代表因特网消息访问协议(Internet Message Access Protocol),目前用的是版本 4,也称 IMAP4。在用到 IMAP 时,邮件服务器必需支持这个协议。不能仅仅把使用 POP 的程序用于 IMAP,并指望它支持 IMAP 所有性能。假设邮件服务器支持 IMAP,基于 JavaMail 的程序可以利用这种情况 — 用户在服务器上有多个文件夹(folder),并且这些文件夹可以被多个用户共享。

因为有这一更高级的性能,您也许会认为所有用户都会使用 IMAP。事实并不是这样。要求服务器接收新消息,在用户请求时发送到用户手中,还要在每个用户的多个文件夹中维护消息。这样虽然能将消息集中备份,但随着用户长期的邮件夹越来越大,到磁盘空间耗尽时,每个用户都会受到损失。使用 POP,就能卸载邮件服务器上保存的消息了。

MIME

MIME 代表多用途因特网邮件扩展标准(Multipurpose Internet Mail Extensions)。它不是邮件传输协议。但对传输内容的消息、附件及其它的内容定义了格式。这里有很多不同的有效文档:RFC 822、RFC 2045、RFC 2046和RFC 2047。作为一个 JavaMail API 的用户,您通常不必对这些格式操心。无论如何,一定存在这些格式而且程序会用到它。

JavaMail

JavaMail 是由 Sun(现 Oracle) 发布的用来处理 email 的 API 。它并没有包含在 Java SE 中,而是作为 Java EE 的一部分。JavaMail下载地址

下载的文件内容如下:

README.txt:整体介绍JavaMail,需要看一下
docs/javadocs:The JavaMail API javadocs,需要看一下
mail.jar:包括JavaMail API和所有service providers,大部分用户只需要该jar包
lib/mailapi.jar :只有JavaMail API
lib/imap.jar:The IMAP service provider
lib/smtp.jar:The SMTP service provider
lib/pop3.jar:The POP3 service provider
lib/dsn.jar:multipart/report DSN message support
demo:demo示例,简单了解,有需要再看

邮件传输过程

邮件的传输过程如下图:

transport

可以看出,收发邮件的步骤如下:

创建一个 Session 对象。

Session 对象创建一个 Transport 对象 /Store 对象,用来发送 / 保存邮件。

Transport 对象 /Store 对象连接邮件服务器。

Transport 对象 /Store 对象创建一个 Message 对象 ( 也就是邮件内容 ) 。

Transport 对象发送邮件; Store 对象获取邮箱的邮件。

可以看出,JavaMail 核心类包括:

javax.mail.Session:上下文环境信息,如服务器的主机名、端口号、协议名称等
javax.mail.Message:邮件模型,发送邮件和接收邮件的媒介,封装了邮件的信息,如发件人、收件人、邮件标题、邮件内容等
javax.mail.Transport:连接邮件SMTP服务器,发送邮件
javax.mail.Store:连接邮件POP3、IMAP服务器,收取邮件

1、电子邮件是如何工作的?   

原则上,电子邮件很简单。使用邮件用户代理(MUAMail User Agent,相当于邮递员)。MUA有多种形式,包括基于文本的、基于Web的和GUI应用程序;MicrosoftOutlook和Netscape Messenger属于最后一类。每个电子邮件客户端被配置为将邮件发送到邮件传送代理(MTA,相当于邮局)(通过MTA发送邮件),并可用于轮询MTA以获取发送到当前用户地址的电子邮件(通过MTA接收邮件)。为此,您需要邮件服务器上的电子邮件帐户(技术上是MTA),并且可以使用标准的Internet协议,或者脱机处理电子邮件(使用POP 3),或者将电子邮件保留在服务器上(使用IMAP)用于从客户端向MTA发送邮件以及在MTA之间发送邮件的协议是SMTP(简单邮件传输协议)。

MTA之间真正发生的事情只是稍微有趣一些。电子邮件服务器严重依赖dns和特定于电子邮件的记录。邮件传送(或MX)记录MX记录与用于解析URL的DNS记录略有不同,后者包含一些用于更有效地路由邮件的附加优先级信息。我不会在这里深入研究这些细节,但重要的是要理解DNS是成功和高效地路由电子邮件的关键。James是一个MTA,而JavaMailAPI为MUA提供了一个框架。在本文中,我们将使用JavaMail为我们的James安装设置一个测试。在本系列文章中,我们将使用JamesMailetAPI来展示如何开发您自己的James应用程序。

2、Javamail快速入门 

进行Javamail开发需要用到两个包:mail.jar和activation.jar,在开始Javamail编程之前,请自己将这两个包添加到IDE的Build path中或将这两个包的路径配置到环境变量中。 

2.1、使用Javamail向James的邮箱帐户发送邮件 

2.1.1、业务描述 

本例将使用Javamail实现邮件的发送功能。发送邮件需要配置邮件服务器属性信息配置邮件接收地址使用SMTP认证获得会话(Session)构建邮件体(MimeMessage)发送邮件。具体编码如下: 

2.1.2、编码实现 

发送邮件需要两个类:一个是SMTP用户身份认证类(James在默认情况下,是需要SMTP身份认证的);另一个就是我们的邮件发送类,为简单起见,我们直接将邮件的相关信息,如:标题、内容、发送者、接收者等信息直接写在类中,运行main()函数即发送。当然,你同样可以为自己的邮件发送系统构造一个邮件发送界面,通过Servlet将相关参数传递至后台进行处理与发送。其主要代码也就是此main()函数中的内容,故不赘述。请各位按需修改,demo代码是截图,不便之处请谅解,可以到我的git获取代码。

 记得提供get、set方法

 SendMail.java发送邮件代码:

 

值得一提的是,本程序已经实现了带附件邮件的发送功能,如果要发送带附件的邮件,则只需要将附件的路径传到fileAttachment变量中就可以了。邮件发送成功后,程序将在后台打印出“发送成功”,这样我们就完成了邮件发送功能。那么,我们应该如何检验服务器是否确实收到我们发送的测试邮件呢?Javamail可以发送邮件,当然也能接收邮件啦,下面让我们一起使用Javamail编写邮件接收功能来检验吧。 

2.2、使用Javamail接收邮件 

2.2.1、业务描述 

在上一节,我们已经向James的accidentaly用户发送了一封测试邮件,我们应该如何使用Javamail来收取这封邮件呢? 

为读取邮件,必须首先设置服务器属性(Properties),获取一个会话(Session),然后获取并连接邮箱所在的存储器(Store对象),打开该用户的邮箱(Folder),获取所希望阅读的消息,最后关闭目录和连接。 

下面的程序实现了接收accidentaly@dascomyun邮箱中所有邮件,并将发送人和主题打印出来

程序运行成功后,将会把accidentaly用户的邮件从James服务器中取出,并将此邮箱中所有邮件的发件人、主题打印在后台。若要打印该邮件的内容等信息,则只要将message[i]对象中的邮件内容等信息读取出来就可以了。 

注:鉴于邮件的存储结构(将在第五章介绍),读取邮件附件是一个比较复杂的过程,因为邮件的文本内容和附件信息都是保存在BodyPart对象中的,BodyPart用于标识类型的标记不明确,造成对附件的判断较为复杂。对于附件的操作本人将在今后的改进版本中加以介绍。

3、Mailet快速入门 

Mailet API是一个用来创建邮件处理程序的简单的API,它被配置在邮件服务器端执行,分匹配器Matcher和Mailet的接口两种,匹配器根据特定的条件匹配邮件消息,并触发相应的Mailet。

Mailet这个词是跟Servlet相似,功能也相似,他们的共同之处都是在服务器端触发并执行,只是Servlet的Matcher通常是url的pattern,跟Servlet的接口一样,Mailet也有init()方法,service()方法和destroy()方法。即他们都有类似的生命周期。Mailet的简单可编程接口可以用来做一些邮件处理,比如反垃圾邮件,检查邮件病毒以及邮件博客等等,利用移动设备可发送email的功能,可以做到手机通过mail发送信息到邮件服务器交给Mailet处理,形成移动博客的模型。

Mailet的运行需要mailet-2.3.jar和mailet-api-2.3.jar两个包的支持,James本身就有这两个包,可不作修改,但在开发的时候还是需要开发者自己将这两个包导入到工程的Build path中或配置到系统环境变量中。 

3.1、用Mailet做一个Hello的例子 

3.1.1、业务描述 

我们要实现当外部发送给James服务器中名字含accidentaly的邮箱时,服务器在这封邮件的主题前加入“Hello”,并在服务器后台输出“Received a piece of Email”。如前所述,Mailet包括匹配器Matcher和Mailet两种接口,现在就让我们用Mailet API实现这两个接口吧。 

匹配器BizMatcher.java 

BizMaillet.java 

3.1.3、配置部署 

Mailet跟Servlet一样,是服务器端程序,是不能直接在客户端运行的,必须要部署到服务器端方可生效。部署具体步骤如下: 

1、 将我们编写的Matcher和Mailet打包成jar文件; 

2、 在\james-2.3.1\apps\james\SAR-INF目录下新建一个lib文件夹; 

3、 将打包好的jar文件复制到刚刚新建的lib文件夹下; 

4、 打开config.xml配置文件,找到以下这段代码: 

XML代码:

前半部分是用于配置Mailet包所在位置,后半部分是用于配置Matcher包所在位置,我们把我们刚编写的Mailet和Matcher所在位置配置进去就可以了。配置后的结果如下: 

Xml代码 

这样就完成了包的配置。我们都知道,Mailet的工作过程是:首先由Matcher来匹配所接收到的邮件,然后提交给相应的Mailet处理,但是哪个匹配器对应哪个Mailet呢?我们还需要配置Mailet的对应关系。同样在config.xml中找到下面的代码,并在这段代码下面加入我们自己的Mailet:

Xml代码  

<mailet  match="All" class="PostmasterAlias" />

Xml代码  

<mailet  match="BizMatcher" class="BizMaillet" />

 这样就完成了我们自定义的Mailet的配置部署工作了。重启James服务器,则此Mailet即可生效。 

3.1.4、测试Mailet 

前面我们已经完成了Mailet的编码和部署工作,现在就让我们来测试一下我们的Mailet是否生效吧。首先,需要在James服务器上新建一个名称含accidentaly的用户。前面已介绍过新建用户的方法了,在此就不重复叙述了。 

使用adduser accidentaly 881213命令新建一个accidentaly用户。 

使用上面所谈及的“使用Javamail向James的邮箱帐户发送邮件”来向accidentaly@dascomyun发送一封邮件(当然,你同样可以使用Foxmail或Outlook向此地址发送邮件),邮件发送成功后,James服务器后台将输出“Receive a piece of email”。运行效果如下图所示: 

4 常用Javamail API简介 

核心JavaMail API可以分为两部分,一部分由七个类组成:Session、Message、Address、Authenticator、Transport、Store及Folder,它们都来自Javamail API顶级包(但开发者需要使用的具体子类可能在javax.mail.internet包内)。可以用这些类完成大量常见的电子邮件任务,包括发送消息、检索消息、删除消息、认证、回复消息、转发消息、管理附件、处理基于HTML文件格式的消息以及搜索或过滤邮件列表,这类任务主要属于MTA范畴。下图描绘了Javamail邮件收发过程。 

下面给出这七个核心类的简单介绍,以使读者能对Javamail框架有一个大体了解: 

4.1、javax.mail.Session 

Session类定义了一个基本邮件会话,它是Javamail API最高层入口类,所有其它类都必须经由Session对象才得以生效(先建立会话,才能进行交互)。Session对象管理配置选项和用于与邮件系统交互的用户认证信息,它使用java.util.Properties对象获取信息,如邮件服务器、用户名、密码及整个应用程序中共享的其它信息。 

Session类的构造器是私有的,它不能被继承,也不能使用new语句来创建实例,但它提供了两个表态方法getInstance和getDefaultInstance来获取Session实例,前者创建一个独立的会话,否则获取缺省的共享会话。 

API明细:/javamail-1.4.1/docs/javadocs/javax/mail/Session.html 

4.2、javax.mail.Message 

获得Session对象后,可以开始继续创建要发送的邮件消息,这由Message类来完成,Message实现了Part接口,它表示一个邮件消息,包含一系列属性(attribute)和一个消息内容(content)。消息属性标识了消息地址信息,定义了消息内容的结构(包括内容类型);消息内容使用DataHandler对象包装实际数据。当邮件消息位于目录(folder)中时,系统还使用一个标志位集合来描述它的状态。 

Message是抽象类,实际使用时必需用一个子类代替以表示具体的邮件格式。比如说,Javamail API提供了MimeMessage(位于javax.mail.internet.MimeMessage包)类,该类扩展自Message,实现了RFC822和MIME标准。Message的子类通常通过字节流构建其实例,相应的,它们也可以生成字节流来传输自身。 

API明细:/javamail-1.4.1/docs/javadocs/javax/mail/Message.html 

4.3、javax.mail.Address 

Address类表示电子邮件地址,它是一个抽象类。其子类(最经常使用的子类是javax.mail.internet.InternetAddress)提供具体实现,且通常可串行化。 

在创建了Session和Message,并设置了消息内容后,可以用Address确定邮件消息的发送者和接收者地址。 

API明细:/javamail-1.4.1/docs/javadocs/javax/mail/Address.html 

4.4、javax.mail.Authenticator 

Authenticator代表一个可以为网络连接获取认证信息的对象,它通常通过提示用户输入用户名和密码来收集认证(认识和证明)信息,使连接可以访问受保护的资源。对于Javamail API来说,这些资源就是邮件服务器。Javamail Authenticator在javax.mail包中,它和java.net中同名的类Authenticator不同。 

要使用Authenticator,必须先创建一个它的子类实例,并且在会话对象创建时为会话注册该Authenticator对象。在需要认证的时候,就会通知Authenticator。程序可以弹出窗口,也可以从配置文件中(虽然没有加密是不安全的)读取用户名和密码,并使用它们作为构造函数参数创建一个PasswordAuthentication对象返回给调用程序。 

API明细:/javamail-1.4.1/docs/javadocs/javax/mail/Authenticator.html 

4.5、javax.mail.Transport 

消息发送的最后步骤是使用Transport类。该类使用指定协议发送消息(通常是SMTP)。Transport是抽象类,它的工作方式与Session有些类似,可以通过静态方法或实例方法发送消息。Transport继承自Service类,而后者提供了很多通用方法,如命名传输、连接服务器、监听传输事件等等。 

API明细:/javamail-1.4.1/docs/javadocs/javax/mail/Transport.html 

4.6、javax.mail.Store 

Store是一个抽象类,它模拟了消息存储器及其内部目录(Folder)访问协议,以存储和读取消息,其子类提供具体实现。 

Store定义的存储器包括一个分层的目录体系,消息存储在目录内。客户程序可以通过获取一个实现了数据库访问协议的Store对象来访问消息存储器,绝大多数存储器要求用户在访问前提供认证信息,connect方法执行了该认证过程。   

Store store = session.getStore("pop3");//指定协议 
store.connect(host,usename,password);// 

API明细:/javamail-1.4.1/docs/javadocs/javax/mail/Store.html 

4.7、javax.mail.Folder 

Folder是一个抽象类,用于分级组织邮件,其子类提供针对具体协议的实现。Folder代表的目录可以容纳消息或子目录,存储在目录内的消息被顺序计数(从1开始到消息总数),该顺序被称为“邮箱顺序”,通常基于邮件消息到达目录的顺序。邮件顺序的变动将改变消息的序列号,这种情况仅发生在客户程序调用Expunge方法擦除目录内设置了Flags.Flag.DELETED标志位的消息时。执行擦除操作后,目录内消息将重新编号。 

客户程序可以通过消息序列号或直接通过相应的Message对象应用目录中的消息,由于消息序列号在会话中很可能改变,因此应尽可能保存Message对象而非序列号来反复引用对象。 

连接到Store之后,接下来可以获取一个文件夹(Folder)。该文件夹必须先使用open()方法打开,然后才能读取里面的消息: 

Folder folder = store.getDefaultFolder(); 
//或 : Folder folder = store.getFolder("inbox"); 
folder.open(Folder.READ_WRITE); 
Message message[] = folder.getMessage(); 

open()方法指定了要打开的文件夹及打开方式(如Folder.READ_WRITE)。 inbox是POP3唯一可以使用的文件夹。如果使用IMAP,还可以用其它的文件夹。获得Message之后,就可以用getContent()获得其内容,或者用writeTo()将内容写入输出流。getContent()方法之能得到消息内容,而writeTo()的输出却包含消息头。读完邮件之后要关闭与Folder和Store的连接: 

folder.close(aBoolean); 
store.close(); 

API明细:/javamail-1.4.1/docs/javadocs/javax/mail/Folder.html 

5、常用Mailet API简介 

Mailet主要包含两个包:org.apache.mailet和org.apache.mailet.dates 

5.1、org.apache.mailet 

此包主要用于匹配器和Mailet的编写。自定义的Mailet类需要继承org.apache.mailet.GenericMailet,自定义的Matcher类需要继承org.apache.mailet.GenericMatcher或org.apache.mailet.GenericRecipientMatcher。例子详见第四章Mailet快速入门。 

API明细:/MailetSDK/javadocs/org/apache/mailet/package-summary.html 

5.2、org.apache.mailet.dates 

此包主要用于邮件中的日期格式的转换。 

API明细:/MailetSDK/javadocs/org/apache/mailet/dates/package-summary.html 

码云:https://gitee.com/AccidentalyAcross/projects

参考:

https://www.jianshu.com/p/0d1fc72d3414

https://www.jianshu.com/p/04a930f91d8f

James首页、文档和下载 - Java 邮件服务器 - OSCHINA - 中文开源技术交流社区

https://www.jianshu.com/p/2840f490b1a4

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

顺其自然~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值