# JavaMail 应用指南 - [简介](#简介) - [邮件相关的标准](#邮件相关的标准) - [JavaMail 简介](#javamail-简介) - [邮件传输过程](#邮件传输过程) - [Message 结构](#message-结构) - [JavaMail 的核心类](#javamail-的核心类) - [java.util.Properties 类(属性对象)](#javautilproperties-类属性对象) - [javax.mail.Session 类(会话对象)](#javaxmailsession-类会话对象) - [javax.mail.Transport 类(邮件传输)](#javaxmailtransport-类邮件传输) - [javax.mail.Store 类(邮件存储 )](#javaxmailstore-类邮件存储-) - [javax.mail.Message 类(消息对象)](#javaxmailmessage-类消息对象) - [javax.mail.Address 类(地址)](#javaxmailaddress-类地址) - [Authenticator 类(认证者)](#authenticator-类认证者) - [实例](#实例) - [发送文本邮件](#发送文本邮件) - [发送 HTML 格式的邮件](#发送-html-格式的邮件) - [发送带附件的邮件](#发送带附件的邮件) - [获取邮箱中的邮件](#获取邮箱中的邮件) - [转发邮件](#转发邮件) ## 简介 ### 邮件相关的标准 厂商所提供的 JavaMail 服务程序可以有选择地实现某些邮件协议,常见的邮件协议包括: - `SMTP(Simple Mail Transfer Protocol)` :即简单邮件传输协议,它是一组用于由源地址到目的地址传送邮件的规则,由它来控制信件的中转方式。 - `POP3(Post Office Protocol - Version 3)` :即邮局协议版本 3 ,用于接收电子邮件的标准协议。 - `IMAP(Internet Mail Access Protocol)` :即 Internet 邮件访问协议。是 POP3 的替代协议。 这三种协议都有对应 SSL 加密传输的协议,分别是 **SMTPS **, **POP3S **和 **IMAPS **。 `MIME(Multipurpose Internet Mail Extensions)` :即多用途因特网邮件扩展标准。它不是邮件传输协议。但对传输内容的消息、附件及其它的内容定义了格式。 ### JavaMail 简介 JavaMail 是由 Sun 发布的用来处理 email 的 API 。它并没有包含在 Java SE 中,而是作为 Java EE 的一部分。 - `mail.jar` :此 JAR 文件包含 JavaMail API 和 Sun 提供的 SMTP 、 IMAP 和 POP3 服务提供程序; - `activation.jar` :此 JAR 文件包含 JAF API 和 Sun 的实现。 JavaMail 包中用于处理电子邮件的核心类是: `Properties` 、 `Session` 、 `Message` 、 `Address` 、 `Authenticator` 、 `Transport` 、 `Store` 等。 ### 邮件传输过程 如上图,电子邮件的处理步骤如下: 1. 创建一个 Session 对象。 2. Session 对象创建一个 Transport 对象 /Store 对象,用来发送 / 保存邮件。 3. Transport 对象 /Store 对象连接邮件服务器。 4. Transport 对象 /Store 对象创建一个 Message 对象 ( 也就是邮件内容 ) 。 5. Transport 对象发送邮件; Store 对象获取邮箱的邮件。 ### Message 结构 - `MimeMessage` 类:代表整封邮件。 - `MimeBodyPart` 类:代表邮件的一个 MIME 信息。 - `MimeMultipart` 类:代表一个由多个 MIME 信息组合成的组合 MIME 信息。
## JavaMail 的核心类 JavaMail 对收发邮件进行了高级的抽象,形成了一些关键的的接口和类,它们构成了程序的基础,下面我们分别来了解一下这些最常见的对象。 ### java.util.Properties 类(属性对象) java.util.Properties 类代表一组属性集合。 它的每一个键和值都是 String **类型。** 由于 JavaMail 需要和邮件服务器进行通信,这就要求程序提供许多诸如服务器地址、端口、用户名、密码等信息, JavaMail 通过 Properties 对象封装这些属性信息。 例: 如下面的代码封装了几个属性信息: ```java Properties prop = new Properties(); prop.setProperty("mail.debug", "true"); prop.setProperty("mail.host", "[email protected]"); prop.setProperty("mail.transport.protocol", "smtp"); prop.setProperty("mail.smtp.auth", "true"); ``` 针对不同的的邮件协议, JavaMail 规定了服务提供者必须支持一系列属性, 下表是一些常见属性(属性值都以 String 类型进行设置,属性类型栏仅表示属性是如何被解析的): | 关键词 | 类型 | 描述 | | ----------------------- | ------- | --------------------------------------------- | | mail.debug | boolean | debug 开关。 | | mail.host | String | 指定发送、接收邮件的默认邮箱服务器。 | | mail.store.protocol | String | 指定接收邮件的协议。 | | mail.transport.protocol | String | 指定发送邮件的协议。 | | mail.debug.auth | boolean | debug 输出中是否包含认证命令。默认是 false 。 | 详情请参考官方 API 文档: https://javamail.java.net/nonav/docs/api/ 。 ### javax.mail.Session 类(会话对象) `Session` 表示一个邮件会话。 Session 的主要作用包括两个方面: - 接收各种配置属性信息:通过 Properties 对象设置的属性信息; - 初始化 JavaMail 环境:根据 JavaMail 的配置文件,初始化 JavaMail 环境,以便通过 Session 对象创建其他重要类的实例。 JavaMail 在 Jar 包的 META-INF 目录下,通过以下文件提供了基本配置信息,以便 session 能够根据这个配置文件加载提供者的实现类: - javamail.default.providers - javamail.default.address.map
**例:** ```java Properties props = new Properties(); props.setProperty("mail.transport.protocol", "smtp"); Session session = Session.getInstance(props); ``` ### javax.mail.Transport 类(邮件传输) 邮件操作只有发送或接收两种处理方式。 JavaMail 将这两种不同操作描述为传输( javax.mail.Transport )和存储( javax.mail.Store ),传输对应邮件的发送,而存储对应邮件的接收。 - `getTransport` - Session 类中的 getTransport **() **有多个重载方法,可以用来创建 Transport 对象。 - `connect` - 如果设置了认证命令—— mail.smtp.auth ,那么使用 Transport 类的 connect 方法连接服务器时,则必须加上用户名和密码。 - `sendMessage` - Transport 类的 sendMessage 方法用来发送邮件消息。 - `close` - Transport 类的 close 方法用来关闭和邮件服务器的连接。 ### javax.mail.Store 类(邮件存储 ) - `getStore` - Session 类中的 getStore () 有多个重载方法,可以用来创建 Store 对象。 - `connect` - 如果设置了认证命令—— mail.smtp.auth ,那么使用 Store 类的 connect 方法连接服务器时,则必须加上用户名和密码。 - `getFolder` - Store 类的 getFolder 方法可以 获取邮箱内的邮件夹 Folder 对象 - `close` - Store 类的 close 方法用来关闭和邮件服务器的连接。 ### javax.mail.Message 类(消息对象) - `javax.mail.Message` - 是个抽象类,只能用子类去实例化,多数情况下为 `javax.mail.internet.MimeMessage`。 - `MimeMessage` - 代表 MIME 类型的电子邮件消息。 要创建一个 Message ,需要将 Session 对象传递给 `MimeMessage` 构造器: ```java MimeMessage message = new MimeMessage(session); ``` 注意:还存在其它构造器,如用按 RFC822 格式的输入流来创建消息。 - setFrom - 设置邮件的发件人 - setRecipient - 设置邮件的发送人、抄送人、密送人 三种预定义的地址类型是: - `Message.RecipientType.TO` - 收件人 - `Message.RecipientType.CC` - 抄送人 - `Message.RecipientType.BCC` - 密送人 - `setSubject` - 设置邮件的主题 - `setContent` - 设置邮件内容 - `setText` - 如果邮件内容是纯文本,可以使用此接口设置文本内容。 ### javax.mail.Address 类(地址) 一旦您创建了 Session 和 Message ,并将内容填入消息后,就可以用 Address 确定信件地址了。和 Message 一样, Address 也是个抽象类。您用的是 javax.mail.internet.InternetAddress 类。 若创建的地址只包含电子邮件地址,只要传递电子邮件地址到构造器就行了。 **例:** ```java Address address = new InternetAddress("[email protected]"); ``` ### Authenticator 类(认证者) 与 java.net 类一样, JavaMail API 也可以利用 `Authenticator` 通过用户名和密码访问受保护的资源。对于 JavaMail API 来说,这些资源就是邮件服务器。`Authenticator` 在 javax.mail 包中,而且它和 java.net 中同名的类 Authenticator 不同。两者并不共享同一个 Authenticator ,因为 JavaMail API 用于 Java 1.1 ,它没有 java.net 类别。 要使用 Authenticator ,先创建一个抽象类的子类,并从 `getPasswordAuthentication()` 方法中返回 `PasswordAuthentication` 实例。创建完成后,您必需向 session 注册 `Authenticator` 。然后,在需要认证的时候,就会通知 `Authenticator` 。您可以弹出窗口,也可以从配置文件中(虽然没有加密是不安全的)读取用户名和密码,将它们作为 `PasswordAuthentication` 对象返回给调用程序。 **例:** ```java Properties props = new Properties(); Authenticator auth = new MyAuthenticator(); Session session = Session.getDefaultInstance(props, auth); ``` ## 实例 ### 发送文本邮件 ```java public static void main(String[] args) throws Exception { Properties prop = new Properties(); prop.setProperty("mail.debug", "true"); prop.setProperty("mail.host", MAIL_SERVER_HOST); prop.setProperty("mail.transport.protocol", "smtp"); prop.setProperty("mail.smtp.auth", "true"); // 1、创建session Session session = Session.getInstance(prop); Transport ts = null; // 2、通过session得到transport对象 ts = session.getTransport(); // 3、连上邮件服务器 ts.connect(MAIL_SERVER_HOST, USER, PASSWORD); // 4、创建邮件 MimeMessage message = new MimeMessage(session); // 邮件消息头 message.setFrom(new InternetAddress(MAIL_FROM)); // 邮件的发件人 message.setRecipient(Message.RecipientType.TO, new InternetAddress(MAIL_TO)); // 邮件的收件人 message.setRecipient(Message.RecipientType.CC, new InternetAddress(MAIL_CC)); // 邮件的抄送人 message.setRecipient(Message.RecipientType.BCC, new InternetAddress(MAIL_BCC)); // 邮件的密送人 message.setSubject("测试文本邮件"); // 邮件的标题 // 邮件消息体 message.setText("天下无双。"); // 5、发送邮件 ts.sendMessage(message, message.getAllRecipients()); ts.close(); } ``` ### 发送 HTML 格式的邮件 ```java public static void main(String[] args) throws Exception { Properties prop = new Properties(); prop.setProperty("mail.debug", "true"); prop.setProperty("mail.host", MAIL_SERVER_HOST); prop.setProperty("mail.transport.protocol", "smtp"); prop.setProperty("mail.smtp.auth", "true"); // 1、创建session Session session = Session.getInstance(prop); Transport ts = null; // 2、通过session得到transport对象 ts = session.getTransport(); // 3、连上邮件服务器 ts.connect(MAIL_SERVER_HOST, USER, PASSWORD); // 4、创建邮件 MimeMessage message = new MimeMessage(session); // 邮件消息头 message.setFrom(new InternetAddress(MAIL_FROM)); // 邮件的发件人 message.setRecipient(Message.RecipientType.TO, new InternetAddress(MAIL_TO)); // 邮件的收件人 message.setRecipient(Message.RecipientType.CC, new InternetAddress(MAIL_CC)); // 邮件的抄送人 message.setRecipient(Message.RecipientType.BCC, new InternetAddress(MAIL_BCC)); // 邮件的密送人 message.setSubject("测试HTML邮件"); // 邮件的标题 String htmlContent = "

Hello

" + "

显示图片1.jpg

"; MimeBodyPart text = new MimeBodyPart(); text.setContent(htmlContent, "text/html;charset=UTF-8"); MimeBodyPart image = new MimeBodyPart(); DataHandler dh = new DataHandler(new FileDataSource("D:\\05_Datas\\图库\\吉他少年背影.png")); image.setDataHandler(dh); image.setContentID("abc.jpg"); // 描述数据关系 MimeMultipart mm = new MimeMultipart(); mm.addBodyPart(text); mm.addBodyPart(image); mm.setSubType("related"); message.setContent(mm); message.saveChanges(); // 5、发送邮件 ts.sendMessage(message, message.getAllRecipients()); ts.close(); } ``` ### 发送带附件的邮件 ```java public static void main(String[] args) throws Exception { Properties prop = new Properties(); prop.setProperty("mail.debug", "true"); prop.setProperty("mail.host", MAIL_SERVER_HOST); prop.setProperty("mail.transport.protocol", "smtp"); prop.setProperty("mail.smtp.auth", "true"); // 1、创建session Session session = Session.getInstance(prop); // 2、通过session得到transport对象 Transport ts = session.getTransport(); // 3、连上邮件服务器 ts.connect(MAIL_SERVER_HOST, USER, PASSWORD); // 4、创建邮件 MimeMessage message = new MimeMessage(session); // 邮件消息头 message.setFrom(new InternetAddress(MAIL_FROM)); // 邮件的发件人 message.setRecipient(Message.RecipientType.TO, new InternetAddress(MAIL_TO)); // 邮件的收件人 message.setRecipient(Message.RecipientType.CC, new InternetAddress(MAIL_CC)); // 邮件的抄送人 message.setRecipient(Message.RecipientType.BCC, new InternetAddress(MAIL_BCC)); // 邮件的密送人 message.setSubject("测试带附件邮件"); // 邮件的标题 MimeBodyPart text = new MimeBodyPart(); text.setContent("邮件中有两个附件。", "text/html;charset=UTF-8"); // 描述数据关系 MimeMultipart mm = new MimeMultipart(); mm.setSubType("related"); mm.addBodyPart(text); String[] files = { "D:\\00_Temp\\temp\\1.jpg", "D:\\00_Temp\\temp\\2.png" }; // 添加邮件附件 for (String filename : files) { MimeBodyPart attachPart = new MimeBodyPart(); attachPart.attachFile(filename); mm.addBodyPart(attachPart); } message.setContent(mm); message.saveChanges(); // 5、发送邮件 ts.sendMessage(message, message.getAllRecipients()); ts.close(); } ``` ### 获取邮箱中的邮件 ```java public static void main(String[] args) throws Exception { // 创建一个有具体连接信息的Properties对象 Properties prop = new Properties(); prop.setProperty("mail.debug", "true"); prop.setProperty("mail.store.protocol", "pop3"); prop.setProperty("mail.pop3.host", MAIL_SERVER_HOST); // 1、创建session Session session = Session.getInstance(prop); // 2、通过session得到Store对象 Store store = session.getStore(); // 3、连上邮件服务器 store.connect(MAIL_SERVER_HOST, USER, PASSWORD); // 4、获得邮箱内的邮件夹 Folder folder = store.getFolder("inbox"); folder.open(Folder.READ_ONLY); // 获得邮件夹Folder内的所有邮件Message对象 Message[] messages = folder.getMessages(); for (int i = 0; i < messages.length; i++) { String subject = messages[i].getSubject(); String from = (messages[i].getFrom()[0]).toString(); System.out.println("第 " + (i + 1) + "封邮件的主题:" + subject); System.out.println("第 " + (i + 1) + "封邮件的发件人地址:" + from); } // 5、关闭 folder.close(false); store.close(); } ``` ### 转发邮件 例:获取指定邮件夹下的第一封邮件并转发 ```java public static void main(String[] args) throws Exception { Properties prop = new Properties(); prop.put("mail.store.protocol", "pop3"); prop.put("mail.pop3.host", MAIL_SERVER_POP3); prop.put("mail.pop3.starttls.enable", "true"); prop.put("mail.smtp.auth", "true"); prop.put("mail.smtp.host", MAIL_SERVER_SMTP); // 1、创建session Session session = Session.getDefaultInstance(prop); // 2、读取邮件夹 Store store = session.getStore("pop3"); store.connect(MAIL_SERVER_POP3, USER, PASSWORD); Folder folder = store.getFolder("inbox"); folder.open(Folder.READ_ONLY); // 获取邮件夹中第1封邮件信息 Message[] messages = folder.getMessages(); if (messages.length <= 0) { return; } Message message = messages[0]; // 打印邮件关键信息 String from = InternetAddress.toString(message.getFrom()); if (from != null) { System.out.println("From: " + from); } String replyTo = InternetAddress.toString(message.getReplyTo()); if (replyTo != null) { System.out.println("Reply-to: " + replyTo); } String to = InternetAddress.toString(message.getRecipients(Message.RecipientType.TO)); if (to != null) { System.out.println("To: " + to); } String subject = message.getSubject(); if (subject != null) { System.out.println("Subject: " + subject); } Date sent = message.getSentDate(); if (sent != null) { System.out.println("Sent: " + sent); } // 设置转发邮件信息头 Message forward = new MimeMessage(session); forward.setFrom(new InternetAddress(MAIL_FROM)); forward.setRecipient(Message.RecipientType.TO, new InternetAddress(MAIL_TO)); forward.setSubject("Fwd: " + message.getSubject()); // 设置转发邮件内容 MimeBodyPart bodyPart = new MimeBodyPart(); bodyPart.setContent(message, "message/rfc822"); Multipart multipart = new MimeMultipart(); multipart.addBodyPart(bodyPart); forward.setContent(multipart); forward.saveChanges(); Transport ts = session.getTransport("smtp"); ts.connect(USER, PASSWORD); ts.sendMessage(forward, forward.getAllRecipients()); folder.close(false); store.close(); ts.close(); System.out.println("message forwarded successfully...."); } ```