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

javaMail发送邮件

2013-03-14 27页 pdf 1MB 54阅读

用户头像

is_944245

暂无简介

举报
javaMail发送邮件 附录 A JavaMail 发送邮件 直接使用 JavaMail 编写邮件收发程序并不是一件轻松的事情,这归咎于 JavaMail 零散而 复杂的 API以及各种强制需要处理的检查型异常。Spring对使用 JavaMail发送邮件进行了很大 程度的简化,它为 80%的需求提供了简单的处理方法,剩下的需求则可以通过直接调用 JavaMail API完成。 本章主要内容: ¡ JavaMail基础知识的快速学习 ¡ Spring对发送邮件的支...
javaMail发送邮件
附录 A JavaMail 发送邮件 直接使用 JavaMail 编写邮件收发程序并不是一件轻松的事情,这归咎于 JavaMail 零散而 复杂的 API以及各种强制需要处理的检查型异常。Spring对使用 JavaMail发送邮件进行了很大 程度的简化,它为 80%的需求提供了简单的处理,剩下的需求则可以通过直接调用 JavaMail API完成。 本章主要内容: ¡ JavaMail基础知识的快速学习 ¡ Spring对发送邮件的支持 ¡ 使用 Spring邮件支持类发送各种类型的邮件 ¡ 在实际应用中发送邮件的经验 本章亮点: ¡ 对 JavaMail的基础知识进行了简明扼要的讲解 ¡ 总结了实际应用中发送邮件的受用经验 A A.1 JavaMail快速进阶 712 A.1 JavaMail快速进阶 在 Java 编程领域,JavaMail 是最知名的邮件解决方案。可以使用 JavaMail 在各种协议 环境下,收发各种或简单或复杂的电子邮件。但 JavaMail 本身的 API 比较难用,用户会发 现直接使用 JavaMail 发送一封简单的电子邮件并不是一件轻松的事。幸而,Spring 对 JavaMail 施展了它一贯的化繁为简的魔法,在降低使用难度的同时保留 JavaMail 本身的强 大功能。了解一下 JavaMail 的基础,有助于深刻理解 Spring 对 JavaMail 的支持。 A.1.1 JavaMail概述 JavaMail 是由 Sun 定义的一套收发电子邮件的 API,不同的厂商可以提供自己的实现 类。但它并没有包含在 JDK 中,而是作为 Java EE 的一部分。 厂商所提供的 JavaMail 服务程序可以有选择地实现某些邮件协议,常见的邮件协议 包括: y SMTP:简单邮件传输协议,用于发送电子邮件的传输协议; y POP3:用于接收电子邮件的标准协议; y IMAP:互联网消息访问协议,是 POP3 的替代协议。 这三种协议都有对应 SSL 加密传输的协议,分别是 SMTPS、POP3S 和 IMAPS。 除 JavaMail 的核心包之外,JavaMail 还需要 JAF(JavaBeans Activation Framework) 来处理不是纯文本的邮件内容。这包括 MIME(多用途互联网邮件扩展)、URL 页面和文 件附件等内容。图 A-1 描述了 JavaMail 的体系结构: JavaMail Java 应用程序 Java Mail API JAF STMP 提供者 IMAP 提供者 POP3 提供者 STMP 服务器 IMAP 服务器 POP3 服务器 图 A-1 JavaMail 体系结构 y mail.jar:此 JAR 文件包含 JavaMail API 和 Sun 提供的 SMTP、IMAP 和 POP3 服务 提供程序; y activation.jar:此 JAR 文件包含 JAF API 和 Sun 的实现。 713 附录 A JavaMail发送邮件 用户可以在 Spring 第三方依赖包 Spring/lib/j2ee 下找到对应的文件。 A.1.2 JavaMail的关键对象 JavaMail 对收发邮件进行了高级抽象,形成了一些关键的接口和类,它们构成了邮件 程序的基础,下面我们分别来了解一下这些核心的对象。 Properties:属性对象 第一个我们要认识的就是属性对象 java.util.Properties,由于 JavaMail 需要和邮件服务 器进行通信,这就要求程序提供许多诸如服务器地址、端口、用户名、密码等信息,JavaMail 通过 Properties 对象封装这些属性信息。如下面的代码封装了两个属性信息: Properties props = new Properties (); props.put("mail.smtp.host", "smtp.sina.com.cn"); props.put("mail.smtp.auth", "true"); 针对不同的邮件协议,JavaMail 规定了服务提供者必须支持一系列属性,表 A-1 是针 对 SMTP 协议的一些常见属性(属性值都以 String 类型进行设置,属性类型列仅表示属性 最终是如何被解析的): 表 A-1 JavaMail属性 属 性 名 属性类型 说 明 mail.smtp.host String SMTP 服务器地址,如 smtp.sina.com.cn mail.smtp.port int SMTP 服务器端口号,默认为 25 mail.smtp.auth boolean SMTP 服务器是否需要用户认证,默认为 false mail.smtp.user String SMTP 默认的登录用户名 mail.smtp.from String 默认的邮件发送源地址 mail.smtp.socketFactory.class String socket 工厂类类名,通过设置该属性可以覆盖提供者默认 的实现。必须实现 javax.net.SocketFactory 接口 mail.smtp.socketFactory.port int 指定 socket 工厂类所用的端口号,如果没有设定,则使用 默认的端口 mail.smtp.socketFactory.fallback boolean 设置为 true 时,当使用指定的 socket 类创建 socket 失败后, 将使用 java.net.Socket 创建 socket。默认为 true mail.smtp.timeout int I/O 连接超时时间,单位为毫秒,默认为永不超时 其他几个协议也有一系列类似的属性,如POP3的mail.pop3.host、mail.pop3.port以及 IMAP 的 mail.imap.host、mail.imap.port 等。更详细的信息请查看 com.sun.mail.smtp、com.sun.mail.pop3 和 com.sun.mail.imap 这三个包的 Javadoc:http://javamail.kenai.com/nonav/javadocs/index.html。 Session:会话对象 Session 是一个很容易被误解的类,这归咎于混淆视听的类名。乍一看,我们会以为 Session 像 HttpSession 一样代表真实的交互会话,但实际上创建 Session 对象时,并没有对 应的物理连接,它只不过是一堆配置信息的集合。Session 的主要作用包括两个方面: 1)接收各种配置属性信息:通过 Properties 对象设置的属性信息; A.1 JavaMail快速进阶 714 2)初始化 JavaMail 环境:根据 JavaMail 的配置文件,初始化 JavaMail 环境,以便通 过 Session 对象创建其他重要类的实例。 所以,如果把 Session 更名为 Configure 也许更容易理解一些。JavaMail 提供者在 JAR 包的 META-INF 目录下,通过以下文件提供了基本配置信息,以便 Session 能够根据这个 配置文件加载提供者的实现类: y javamail.providers 和 javamail.default.providers; y javamail.address.map 和 javamail.default.address.map。 下面是 Sun 提供者 javamail.default.providers 文件的配置信息(位于 mail.jar 包中): # JavaMail IMAP provider Sun Microsystems, Inc protocol=imap; type=store; class=com.sun.mail.imap.IMAPStore; vendor=Sun Microsystems, Inc; protocol=imaps; type=store; class=com.sun.mail.imap.IMAPSSLStore; vendor=Sun Microsystems, Inc; # JavaMail SMTP provider Sun Microsystems, Inc protocol=smtp; type=transport; class=com.sun.mail.smtp.SMTPTransport; vendor=Sun Microsystems, Inc; protocol=smtps; type=transport; class=com.sun.mail.smtp.SMTPSSLTransport; vendor=Sun Microsystems, Inc; # JavaMail POP3 provider Sun Microsystems, Inc protocol=pop3; type=store; class=com.sun.mail.pop3.POP3Store; vendor=Sun Microsystems, Inc; protocol=pop3s; type=store; class=com.sun.mail.pop3.POP3SSLStore; vendor=Sun Microsystems, Inc; 这个配置文件提供了以下四个方面的信息: y protocol:协议名称; y type:邮件操作类型; y class:对应该操作类型的实现类; y vendor:厂商名称。 Session 在加载配置文件时会按照以下优先级顺序进行: 1)首先使用/lib 中的 javamail.providers; 2)如果 1)不存在相应的配置文件,使用类路径下 mail.jar 中 META-INF 目录下的 javamail.providers; 3)如果 2)不存在相应的配置文件,使用类路径下 mail.jar 中 META-INF 目录下的 javamail.default.providers。 所以开发者可以在/lib 目录下提供配置文件覆盖 mail.jar/META-INF 目 录中厂商的配置。但是,一般情况下,我们无须这样做。 Session 通过 JavaMail 配置文件以及程序中设置的 Properties 对象建构一个邮件处理环 境,后续的处理将在 Session 基础上进行。Session 拥有多个静态工厂方法用于创建 Session 实例。 y static Session getDefaultInstance(Properties props, Authenticator authenticator):当 JVM 中已经存在默认的 Session 实例时,直接返回这个实例,否则创建一个新的 Session 实例,并将其作为 JVM 中默认 Session 实例。这个 API 方法很诡秘,我们将对它进 715 附录 A JavaMail发送邮件 行详细的讲解。由于这个默认 Session 实例可以被同一 JVM 所有的代码访问到,而 Session 中本身又可能包含密码、用户名等敏感信息在内的所有属性信息,所以后 续 调 用 也 必 须 传 入 和 第 一 次 相 同 的 Authenticator 实 例 , 否 则 将 抛 出 java.lang.SecurityException 异常。如果第一次调用时 Authenticator 入参为 null,则 后续调用通过 null 的 Authenticator 入参或直接使用 getDefaultInstance(Properties props)即可返回这个默认的 Session 实例。值得一提的是,虽然后续调用也会传入 Properties,但新属性值并不会起作用,如果希望采用新的属性值,则可以通过 getInstance(Properties props)创建一个新的 Session 实例达到目的。Authenticator 在这 里承当了两个功能:首先,对 JVM 中默认 Session 实例进行认证保护,后续调用执 行 getDefaultInstance(Properties props, Authenticator authenticator)方法时必须和第一 次一样;其次,在具体和邮件服务器交互时,又作为认证的信息; y static Session getDefaultInstance(Properties props):返回 JVM 中默认的 Session 实例, 如果第一次创建 Session 未指定 Authenticator 入参,后续调用可以使用该访问获取 Session; y static Session getInstance(Properties props, Authenticator authenticator):创建一个新的 Session 实例,它不会在 JVM 中被作为默认实例共享; y static Session getInstance(Properties props):根据相关属性创建一个新的 Session 实例, 未使用安全认证信息; Session 是 JavaMail 提供者配置文件以及设置属性信息的“容器”,Session 本身不会和 邮件服务器进行任何的通信。所以在一般情况下,我们仅需要通过 getDefaultInstance()获 取一个共享的 Session 实例就可以了,下面的代码创建了一个 Session 实例: Properties props = System.getProperties(); props.setProperty("mail.transport.protocol", "smtp "); … Session session = Session.getDefaultInstance(props);① Transport和 Store:传输和存储 邮件的操作只有发送或接收两种处理方式,JavaMail 将这两种不同操作描述为传输 (javax.mail.Transport)和存储(javax.mail.Store)两个类,传输对应邮件的发送,而存储对 应邮件的接收(又是两个容易因命名被误解的类)。 Session提供了几个用于创建Transport和 Store实例的方法,在具体讲解这些方法之前, 我们事先了解一下 Session 创建 Transport 和 Store 的内部机制。我们知道提供者在 javamail.providers 配置文件中为每一种支持的邮件协议定义了实现类,Session 根据协议类 型(stmp、pop3 等)和邮件操作方式(传输和储存)这两个信息就可以定位到一个实例类 上。比如,指定 stmp 协议和 transport 类型后,Session 就会使用 com.sun.mail.smtp. SMTPTransport 实现类创建一个 Transport 实例,而指定 pop3 协议和 store 类型时,则会使 用 com.sun.mail.pop3.POP3Store 实例类创建一个 Store 实例。Session 提供了多个重载的 getTransport()和 getStore()方法,这些方法将根据 Session 中 Properties 属性设置情况进行工 作,影响这两套方法工作的属性包括: 仅创建一个对象,并 不会产生任何通信 A.1 JavaMail快速进阶 716 属 性 名 说 明 mail.transport.protocol 默认的传输邮件协议,例如:stmp。 mail.store.protocol 默认的存储邮件协议,例如:pop3。 mail.host 默认的邮件服务器地址,例如:192.168.67.1。 mail.user 默认的登录用户名,例如:masterspring。 下面,我们再回过头来了解 Session 的 getTransport()和 getStore()的重载方法。 y Transport getTransport():当 Session 实例设置了 mail.transport.protocol 属性时,该方 法返回对应的 Transport 实例,否则抛出 javax.mail.NoSuchProviderException。 y Transport getTransport(String protocol):如果 Session 没有设置 mail.transport.protocol 属性,可以通过该方法返回指定类型的 Transport,如:transport = session.getTransport ("smtp")。 如果 Session 中未包含 Authenticator,以上两方法创建的 Transport 实例和邮件服务器 交互时必须显式提供的用户名/密码的认证信息。如果 Authenticator 非空,则可以在和邮件 服务器交互时被作为认证信息使用。除了以上两种提供认证信息的方式外,Session 还可以 使用以下的方法为 Transport 提供认证信息。 y Transport getTransport(URLName url):用户可以通过 URLName 入参指定邮件协议、 邮件服务器、端口、用户名和密码信息,请看下面的代码: URLName urln = new URLName("smtp"," smtp.sina.com.cn",25,null,"masterspring", "spring"); Transport transport = session.getTransport(urln); 这里,指定了邮件协议为 smtp,邮件服务器是 smtp.sina.com.cn,端口为 25,用户名/ 密码为 masterspring/spring。 getStore()也有和 getTransport()相似的重载方法: y Store getStore(); y Store getStore(String protocol); y Store getStore(URLName url)。 在从 Session 中获取 Transport 和 Store 时,也没有和邮件服务器发生任何通信,仅仅 是创建一个内存实例而已,因此即使用户名和密码是错误的,也不会抛出运行异常。 Transport 和 Store 都拥有 connect()和 close()方法,只有调用 connect()方法时,程序才 会和邮件服务器产生物理连接。服务器地址、端口以及用户名/密码等信息在此时才会真正 被使用。 如果用户没有在构建 Session 或 Transport/Store 时提供认证信息,JavaMail 允许用户在 调用 connect()方法时再提供连接信息:connect(String host, int port, String user, String password)。如果我们回顾一下 JDBC 的 API,就会发现 JavaMail 设置连接的认证信息确实 是比较灵活的,存在三种方式:1)在创建 Session 时通过 Authenticator 设置;2)在创建 Transport/Store 时通过 URLName 提供;3)在实际连接时通过 connect()方法入参提供。但是 这种过度的灵活性反而增强了理解的难度,造成使用上的不便。 Message:消息对象 javax.mail.Message 代表邮件信息,包含一系列的属性,其中 content 属性表示邮件的 717 附录 A JavaMail发送邮件 内容。Message 是一个抽象类,子类提供具体的实现。其中最重要的一个子类是 javax.mail.internet.MimeMessage,它可以构造出复杂的邮件信息。下面的代码演示了创建 一个简单邮件信息的过程: Message msg = new MimeMessage(session); msg.setSubject("Hello"); msg.setText("How are you"); msg.setSentDate(new Date()); 上面介绍的 5 个对象是 JavaMail 最重要的基础类,从中我们可以看出,JavaMail 的整 个体系比较复杂,甚至显得凌乱不堪,拥有太多属性需要设置(本该有默认的值),很多 API 的命名比较隐晦,没有直接地表现真实意图。这些缺点大大提高了 JavaMail 程序的使 用难度。不过不能否认的一点是,JavaMail 的功能是非常强大的,用户可以使用它解决几 乎任何的邮件问题。 A.1.3 使用 JavaMail发送邮件 下面,我们通过 JavaMail 发送一封简单的电子邮件,其代码如代码清单 A-1 所示: 代码清单 A-1 JavaMailSender package com.baobaotao.basic.javamail; import java.util.Date; import java.util.Properties; import javax.mail.*; public class JavaMailSender { public static void main(String[] args) { Transport transport = null; try { Properties props = new Properties(); ① props.put("mail.smtp.host", "smtp.163.com"); props.put("mail.smtp.auth", "true"); Authenticator auth = new Authenticator() {② protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication("masterspring", "spring"); } }; Session session = Session.getDefaultInstance(props); ③ Message msg = new MimeMessage(session); msg.setFrom(new InternetAddress("masterspring@163.com"));③-1 msg.setRecipient(Message.RecipientType.TO, ③-2 new InternetAddress("masterspring@sina.com")); msg.setSubject("Test Title"); msg.setText("How are you!"); msg.setSentDate(new Date()); transport = session.getTransport("smtp"); ④ transport.send(msg); ④-1 属性信息设置 创建认证匿名类实例,分 别指定用户名和密码 构造邮件信息 源地址 目标地址 发送邮件信息 A.1 JavaMail快速进阶 718 System.out.println("邮件发送成功!"); } catch (MessagingException m) { System.out.println("邮件发送失败!"); m.printStackTrace(); } finally { try { transport.close();⑤ } catch (Exception e) {} } } } Message 除了包含邮件本身的标题、内容等信息外,还包括源地址、接收地址的信息, 如③-1 和③-2 所示。用户可以同时将一封邮件发送到多个接收地址上,接收地址包括三种 类型:主送地址、抄送地址和暗送地址,这些地址类型在 Message.RecipientType 类中定义: y TO:主送地址; y CC:抄送地址; y BCC:暗送地址。 Message 提供了多个设置目标地址的方法: y void addRecipient(Message.RecipientType type, Address address):添加一个某一类型 的接收地址; y void addRecipients(Message.RecipientType type, Address[] addresses):添加一批某一 类型的接收地址; y void setRecipient(Message.RecipientType type,Address address):设置一个指定类型的 接收地址,相同类型原有的地址将被覆盖; y void addRecipients(Message.RecipientType type,Address[] addresses):设置一批某类型 的接收地址,相同类型的原有地址将被覆盖; 在④-1 处调用 Transport 的 send()方法时,在内部 Transport 会自动调用 connect()方法 创建连接,然后再发送邮件消息。任何一个接收地址被探测为非法时,该方法就抛出 SendFailedException 异常,邮件是否还会被发送到其他合法的地址上,则仰仗于邮件服务 器的具体实现。在程序结束后,需要关闭连接,如⑤所示。 轻松一刻 鸿雁是信的代称,有时亦指代邮递员。何以“鸿雁”指代 书信和邮递员?溯其源,来自于苏武牧羊。汉朝时,苏武出使匈 奴,被单于流放北海(今俄罗斯贝加尔湖)牧羊。19年后,汉朝 与匈奴和亲,但单于仍不让苏武回汉。与苏武一起出使匈奴的常 惠,把苏武的情况密告汉使,并让汉使对单于讲:汉朝皇帝 打猎射得一雁,雁足上绑有书信,叙说苏武在北海牧羊。单于听后,以为天意不可违, 只得让苏武回汉。后来,人们就用鸿雁比喻书信和传递书信的邮递员。 停止传输,关闭连接 719 附录 A JavaMail发送邮件 A.1.4 处理 SSL加密传输协议邮件 Sun 提供的 JavaMail 实现还支持 SSL 加密的邮件协议,只要设置好属性信息,处理 SSL 加密协议的邮件和未加密协议的邮件并无多大区别。google 的 Gmail 采用 SSL 加密传 输协议,下面的代码能够从 Gmail 服务器中获取某个邮箱内的信件信息: 代码清单 A-2 JavaMailSslReceiver package com.baobaotao.basic.javamail; import java.io.UnsupportedEncodingException; import java.util.Properties; import javax.mail.*; import javax.mail.internet.*; public class JavaMailSslReceiver { public static void main(String argv[]) throws Exception { Properties props = new Properties(); Session session = Session.getDefaultInstance(props); URLName urln = new URLName("pop3s", "pop.gmail.com", 995, null, ① "masterspring3", "masterspring"); Store store = session.getStore(urln); Folder inbox = null; try { store.connect(); ② inbox = store.getFolder("INBOX"); ③ inbox.open(Folder.READ_ONLY); FetchProfile profile = new FetchProfile(); profile.add(FetchProfile.Item.ENVELOPE); Message[] msgs = inbox.getMessages(); inbox.fetch(msgs, profile); System.out.println("收件箱的邮件数:" + msgs.length); for (int i = 0; i < msgs.length; i++) {④ String from = msgs[i].getFrom()[0].toString(); InternetAddress ia = new InternetAddress(from); System.out.println("-----------------------------"); System.out.println("发送者:" + ia.getPersonal() + "/"+ ia.getAddress()); System.out.println("标题:" + msgs[i].getSubject()); System.out.println("大小:" + msgs[i].getSize()); System.out.println("时间:" + msgs[i].getSentDate()); } } finally { try { inbox.close(false); ⑤ } catch (Exception e) {} try { store.close();⑥ } catch (Exception e) {} } } } 指定邮件协议为 pop3s, 并指定邮件服务器,端 口,用户名和密码的信息 连接邮件服务器 从邮件服务器中返 回邮箱内的信息 显示邮件信息 关闭打开的 Folder 关闭打开的存储对象 A.2 Spring的邮件支持 720 在①处,我们通过 URLName 对象指定了连接邮件服务器必要的信息,未采用 SSL 加 密传输协议的常用 POP3 协议默认端口为 110,使用 SSL 的 POP3S 的默认端口则为 995, 而使用 SSL 的 SMTP 端口为 465。 在②处,Store 通过显式的 connect()方法建立和服务器的连接,如②所示,处理完成后, 还必须关闭 Store,如⑥所示。JavaMail 通过类似于文件夹的方式操作邮箱中的信息,详细 内容请参见 JavaMail 的 Javadoc。 运行以上代码,将输出以下的信息: 收件箱的邮件数:3 ----------------------------- 发送者:Gmail 小组/mail-noreply@google.com 标题:在手机上使用 Gmail 大小:2384 时间:Sat Jun 18 16:05:39 CST 2011 ----------------------------- 发送者:Gmail 小组/mail-noreply@google.com 标题:导入联系人和过去的电子邮件 大小:2981 时间:Sat Jun 18 16:05:39 CST 2011 ----------------------------- 发送者:Gmail 小组/mail-noreply@google.com 标题:使用颜色和主题自定义 Gmail 大小:2879 时间:Sat Jun 18 16:05:39 CST 2011 是不是觉得已经有点邮件管理系统的味道了,只要在 JavaMail 基础上添加展现层的设 计,一个完善的电子邮局即可建立起来。 mail.jar中 SMTPS协议对应的实现类是 com.sun.mail.smtp.SMTPSSLTransport, 但使用该类发送邮件时,在有些邮件服务器下不能正常工作。这时,用户可以通过 mail.smtp.socketFactory.class 属性显式指定 javax.net.ssl.SSLSocketFactory作为 SSL Socket的操作类。 A.2 Spring的邮件支持 Spring 对发送电子邮件提供了一个抽象层,对接收电子邮件没有提供额外的支持。不 过这对于大多数企业应用来说已经足够了。因为在一般情况下,只有专门的邮件管理系统 才会有接收邮件的需求。JavaMail API 盘根错节,复杂凌乱,经过 Spring 大刀阔斧的整容, 蓬头垢面的邋遢虫出落成清新淡雅的美少女。 A.2.1 邮件发送高级抽象层 在编写邮件发送程序时,有两个最重要的内容:邮件消息和邮件发送者。Spring 在 org.springframework.mail 包里通过 MailMessage 和 MailSender 这两个高层抽象接口描述了 这两项内容。 721 附录 A JavaMail发送邮件 MailMessage:抽象的邮件消息 MailMessage 接口描述了邮件消息的通用模型,允许开发者通过多个简洁的属性设置 方法填充邮件消息的各项内容。 y void setTo(String to) :设置一个主送地址,如需设置多个地址,可以使用 setTo(String[] to)方法; y void setFrom(String from):设置发送地址; y void setReplyTo(String replyTo):设置回复地址; y void setCc(String cc):设置抄送地址,如需设置多个地址,可以使用 setCc(String[] cc); y void setBcc(String bcc):设置暗送地址,如需设置多个地址,可以使用 setBcc(String[] bcc); y void setSentDate(Date sentDate):设置发送邮件的时间; y void setSubject(String subject):设置邮件标题; y void setText(String text):设置邮件内容。 相对于 JavaMail Message 接口的 addRecipients()和 setRecipient()方法,MailMessage 接 口中定义的方法显得更加简洁明了,Spring 通过明确的属性设置方法规避 JavaMail 接口中 晦涩难懂的设计。 MailMessage 有两个实现类:SimpleMailMessage 和 MimeMailMessage,前者都是完 全符合 Bean 风格的实现类,后者通过内置 JavaMail 的 MimeMessage 提供实现。Spring 之所以需要提供这两个实现类,是因为 Spring 的高级抽象层并不局限在某一特定的实现 上,在 Spring 2.1 版本之前,Spring 同时支持 JavaMail 和 COS 两种邮件 API,不过在 Spring 2.1 中已经移除对 COS 的支持。在发送简单文本型邮件时,SimpleMailMessage 就可以满 足要求了,如果发送复杂的邮件,则可以利用 MimeMailMessage 或直接使用 MimeMessage。 MailSender:抽象的邮件发送者 邮件发送者负责将邮件发送到指定的地址上,该接口只用于发送简单的邮件。不同的 邮件系统可以提供各自的实现。如果需要发送复杂的邮件,则需要使用 JavaMailSender 子 接口。MailSender 接口很简单,只有两个方法。 y void send(SimpleMailMessage simpleMessage) throws MailException:发送一个邮件消 息,注意入参是 SimpleMailMessage 而非 MailMessage!为什么是这么一个奇怪的 入参类型呢?原因是 MailSender 只能发送简单的邮件类型,它和邮件实现者无关, 并不局限于 JavaMail。该接口根据邮件发送时的具体情况会抛出相应的异常,这些 异常也是 Spring 高级邮件抽象的一部分: ƒ MailParseException:当发生邮件消息解析错误时抛出; ƒ MailAuthenticationException:当认证失败时抛出; ƒ MailSendException:当发送邮件消息失败时抛出。 y void send(SimpleMailMessage[] simpleMessages) throws MailException:一次性发送 多个邮件消息。 A.2 Spring的邮件支持 722 Spring的邮件异常体系 Spring 定义了和邮件系统无关的邮件异常体系,Spring 为 JavaMail 提供的支持类会将 邮件系统相关的异常转化为 Spring 的邮件异常。Spring 提供的邮件异常都是运行期异常, 因此,用户可以有针对性地捕捉感兴趣的异常,而不像 JavaMail 中的检查型异常需要强制 编写捕捉代码。一般情况下,像认证失败、邮件消息解析错误等异常都是不可恢复的错误, 无须捕捉。在实际业务系统中,发送失败的异常可能会被关注,因为发送失败后,可能 需要再次尝试发送,或者发送到接收者的备用邮箱中。Spring 的邮件异常体系,如图 A-2 所示: 图 A-2 Spring 的邮件异常体系 MailException是邮件异常的根,4个子异常类分别概括了认证失败(MailAuthenticationException)、 解 析 错 误 ( MailParseException )、 发 送 失 败 ( MailSendException ) 和 准 备 错 误 (MailPreparationException)这 4 种典型的错误。由于 MailException 继承于 Spring 的 NestedRuntimeException,所以它们都是运行期异常。 MailPreparationException 异常一般在用户代码中抛出,表示准备邮件消息时发生了错 误 。 Spring 为 Velocity 和 FreeMarker 模 板 框 架 所 提 供 的 工 具 类 会 抛 出 MailPreparationException 异常: y VelocityEngineUtils#mergeTemplateIntoString(); y FreeMarkerTemplateUtils#processTemplateIntoString()。 A.2.2 Spring对 JavaMail的支持 Spring 在 org.springframework.mail.javamail 包下提供了对 JavaMail 邮件系统的支持, 通过这些支持类,编写 JavaMail 邮件发送程序变得轻松易行。体现在两个方面:首先,通 过 JavaMailSenderImpl 可以很方便地创建 JavaMail 环境;其次,通过 MimeMessageHelper 很容易构造出 MimeMessage 对象。 JavaMailSender及其实现类 Spring 通过 MailSender 的 JavaMailSender 子接口,提供了发送 JavaMail 复杂邮件的功 NestedRuntimeException MailException MailAuthenticationException MailParseException MailPreparationException MailSendException 723 附录 A JavaMail发送邮件 能。下面我们来了解一下 JavaMailSender 接口的方法: y void send(MimeMessage mimeMessage):发送一封 MimeMessage 类型的邮件,用户 可以通过 send(MimeMessage[] mimeMessages) 批量发送多封邮件; y void send(MimeMessagePreparator mimeMessagePreparator):通过 MimeMessagePreparator 回调接口发送 MimeMessage 类型的邮件,可以通过 send(MimeMessagePreparator[] mimeMessagePreparators)进行批量发送; y MimeMessage createMimeMessage():我们知道使用 JavaMail 原生 API 创建一个 MimeMessage 是比较麻烦的,用户必须获得 JavaMail 的 Session 实例。该接口方法 为调用者屏蔽了底层的复杂性,直接创建一个 MimeMessage 对象; y MimeMessage createMimeMessage(InputStream contentStream)throws MailException: 根据一个 InputStream 创建 MimeMessage,当发生消息解析错误时,抛出 MailParseException 异常。 JavaMailSenderImpl是 JavaMailSender的实现类,它同时支持 JavaMail的MimeMessage 和 Spring 的 MailMessage。通过在 Spring 配置文件中设置一些简单的属性就可以轻易地搭 建起 JavaMail 环境。此外,还可以通过 JNDI 获取 Java EE 服务器中的 JavaMail Session 实 例构建 JavaMail 环境。 下面代码配置了一个 JavaMailSenderImpl Bean: 代码清单 A-3 配置 JavaMailSender true JavaMailSenderImpl 将 JavaMail 中的属性通过 JavaBean 的方式开放出来方便设置,使 我们不必关心 JavaMail 复杂的属性名,JavaMailSenderImpl 提供的属性包括: y host:邮件服务器地址; y port:邮件服务器端口,如果邮件服务器采用默认的端口号,就无须显式设置; y protocol:协议类型,默认为 smtp; y username:用户名; y password:密码; y defaultEncoding:在创建 MimeMessage 时,采用的默认编码; y session:用户可以通过 session 指定一个已经存在的 Session 实例,如从 JNDI 中获 取的 Java EE 服务器的 JavaMail Session。 一般情况下,这些属性已经可以满足要求,如果需要对 JavaMail 其他属性进行设置, 其他的 JavaMail属性 用户名及密码 邮件服务器地址 A.2 Spring的邮件支持 724 则可以通过 javaMailProperties 属性达到目的。在③处,我们就通过 javaMailProperties 定义 了一个名为 mail.smtp.auth 的 JavaMail 属性。由于几乎所有的邮件服务器都要求进行身份 认证才可访问,所以需要将 mail.smtp.auth 属性设置为 true。 MimeMessageHelper MimeMessageHelper 是 MimeMessage 的封装类,它隐藏了构造 MimeMessage 对象的 复杂性,使 MimeMessage 实例的构建变得简单易行。该帮助类提供了设置 HTML 邮件内 容、内嵌的文件(如图片文件、音频文件等)以及邮件附件的方法。 MimeMessageHelper 通过构造函数接受一个 MimeMessage,让我们来了解一下 MimeMessageHelper 的几个常用构造函数: y MimeMessageHelper(MimeMessage mimeMessage):封装 MimeMessage 对象,默认 为简单非 multipart 的邮件消息,采用默认的编码; y MimeMessageHelper(MimeMessage mimeMessage, boolean multipart) : 封 装 MimeMessage 对象时,同时指定是否是 multipart 邮件消息,采用默认的编码; y MimeMessageHelper(MimeMessage mimeMessage, boolean multipart, String encoding): 采用指定编码的 MimeMessage。 MimeMessageHelper 所提供多个操作方法可
/
本文档为【javaMail发送邮件】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。 本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。 网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。

历史搜索

    清空历史搜索