JavaMail API - 快速指南

JavaMail API 提供了一个独立于平台和协议的框架来构建邮件和消息传递应用程序。JavaMail API 提供了一组抽象类,用于定义组成邮件系统的对象。它是一个可选包(标准扩展),用于阅读、撰写和发送电子邮件。

JavaMail 提供了用于构建消息传递系统接口的元素,包括系统组件和接口。虽然本规范没有定义任何特定的实现,但 JavaMail 确实包含几个实现 RFC822 和 MIME 互联网消息传递标准的类。这些类作为 JavaMail 类包的一部分提供。

以下是 JavaMail API 中支持的一些协议:

  • SMTP:简单邮件传输协议的缩写。它提供了一种发送电子邮件的机制。

  • POP:邮局协议的缩写。POP 是互联网上大多数人用来接收邮件的机制。它定义了对每个用户单个邮箱的支持。RFC 1939 定义了此协议。

  • IMAP:互联网消息访问协议的缩写。它是一种用于接收消息的高级协议。它为每个用户提供多个邮箱的支持,此外,邮箱可以由多个用户共享。它在 RFC 2060 中定义。

  • MIME:多用途互联网邮件扩展的缩写。它不是邮件传输协议。相反,它定义了传输的内容:消息的格式、附件等。这里有许多不同的文档生效:RFC 822、RFC 2045、RFC 2046 和 RFC 2047。作为 JavaMail API 的用户,您通常不需要担心这些格式。但是,这些格式确实存在,并且被您的程序使用。

  • NNTP 和其他:有许多由第三方提供商提供的协议。其中一些是网络新闻传输协议 (NNTP)、安全多用途互联网邮件扩展 (S/MIME) 等。

这些细节将在后续章节中介绍。

架构

如上所述,Java 应用程序使用 JavaMail API 来撰写、发送和接收电子邮件。下图说明了 JavaMail 的架构:

JavaMail API 架构

JavaMail API 的抽象机制与其他 J2EE API(如 JDBC、JNDI 和 JMS)类似。如上图所示,JavaMail API 分为两个主要部分:

  • 独立于应用程序的部分:应用程序编程接口 (API) 由应用程序组件用来发送和接收邮件消息,与所使用的底层提供程序或协议无关。

  • 服务相关部分:服务提供程序接口 (SPI) 使用特定于协议的语言,例如 SMTP、POP、IMAP 和网络新闻传输协议 (NNTP)。它用于将电子邮件服务提供程序插入到 J2EE 平台。

环境设置

使用 Java 应用程序发送电子邮件非常简单,但首先您应该在计算机上安装 JavaMail APIJava Activation Framework (JAF)

仅当您不使用 Java SE 6 或更新版本时,您才需要提供 javax.activation 包的 JavaBeans Activation Framework (JAF) 扩展。

下载并解压这些文件,在新创建的顶级目录中,您将找到两个应用程序的大量 jar 文件。您需要在 CLASSPATH 中添加 mail.jaractivation.jar 文件。

SMTP 服务器

要发送电子邮件,您必须拥有负责发送邮件的 SMTP 服务器。您可以使用以下技术之一来获取 SMTP 服务器:

  • 安装并使用任何 SMTP 服务器,例如 Postfix 服务器(适用于 Ubuntu)、Apache James 服务器(Java Apache Mail Enterprise Server)等。 (或)

  • 使用主机提供商提供的 SMTP 服务器,例如:JangoSMTP 站点提供的免费 SMTP 是 relay.jangosmtp.net (或)

  • 使用公司提供的 SMTP 服务器,例如 gmail、yahoo 等。

在后续章节中的示例,我们使用免费的 JangoSMTP 服务器发送电子邮件。您可以通过访问此站点创建帐户并配置您的电子邮件地址。

JavaMail API - 核心类

JavaMail API 包含一些用于发送、阅读和删除电子邮件的接口和类。尽管 JavaMail API 中有许多包,但本文将介绍 Java Mail API 中经常使用的两个主要包:javax.mailjavax.mail.internet 包。这些包包含所有 JavaMail 核心类。它们是:

描述
javax.mail.SessionAPI 的关键类。多线程对象表示连接工厂。
javax.mail.Message用于对电子邮件消息进行建模的抽象类。子类提供实际实现。
javax.mail.Address用于对消息中的地址(发件人和收件人地址)进行建模的抽象类。子类提供具体的实现。
javax.mail.Authenticator用于保护邮件服务器上的邮件资源的抽象类。
javax.mail.Transport为发送电子邮件消息而建模的消息传输机制的抽象类。
javax.mail.Store为存储和检索消息而建模的消息存储及其访问协议的抽象类。存储分为多个文件夹。
javax.mail.Folder表示邮件文件夹的抽象类。它可以包含子文件夹。
javax.mail.internet.MimeMessageMessage 是一个抽象类,因此必须与子类一起使用;在大多数情况下,您将使用 MimeMessage。MimeMessage 是一条可理解 MIME 类型和标头的电子邮件消息。
javax.mail.internet.InternetAddress此类表示使用 RFC822 语法的 Internet 电子邮件地址。典型的地址语法形式为 user@host.domain个人名称 <user@host.domain>

让我们详细研究这些类中的每一个,在后续章节中,我们将研究使用每个类的示例。

Session 类

Session 类是 JavaMail API 的主要类,它没有子类。Session 对象充当 JavaMail API 的连接工厂,它处理配置设置和身份验证。

Session 对象可以通过以下方式创建:

  • 通过查找存储在 JNDI 服务中的管理对象

    InitialContext ctx = new InitialContext();
    Session session = (Session) ctx.lookup("usersMailSession");
    

    usersMailSession 是用作 Session 对象的管理对象的 JNDI 名称对象。可以使用所需参数作为名称/值对来创建和配置 usersMailSession,包括邮件服务器主机名、发送邮件的用户帐户以及 Session 对象支持的协议等信息。

  • 创建 Session 对象的另一种方法是基于编程方法,您可以使用 java.util.Properties 对象覆盖一些默认信息,例如邮件服务器名称、用户名、密码和其他可在整个应用程序中共享的信息。

Session 类的构造函数是 private。因此,Session 类提供了两种方法(如下所列)来获取 Session 对象。

  • getDefaultInstance():有两种方法可以使用 getDefaultInstance() 方法获取会话对象。它返回默认会话。

    public static Session getDefaultInstance(Properties props)
    public static Session getDefaultInstance(Properties props,Authenticator auth)
    
  • getInstance():有两种方法可以使用 getInstance() 方法获取会话对象。它返回新会话。

    public static Session getInstance(Properties props)
    public static Session getInstance(Properties props,Authenticator auth)
    

Message 类

创建 Session 对象后,我们现在开始创建要发送的消息。消息类型为 javax.mail.Message

  • Message 是一个抽象类。因此,其子类 javax.mail.internet.MimeMessage 类被广泛使用。

  • 要创建消息,您需要在 MimeMessage 类构造函数中传递会话对象。例如:

    MimeMessage message=new MimeMessage(session);
    
  • 一旦创建了消息对象,我们就需要在其中存储信息。Message 类实现 javax.mail.Part 接口,而 javax.mail.internet. MimeMessage 实现 javax.mail.internet.MimePart。您可以使用 message.setContent() 或 mimeMessage.setText() 来存储内容。

  • MimeMessage 类的常用方法有

    方法说明
    public void setFrom(Address address)用于设置发件人标头字段。
    public void addRecipients(Message.RecipientType type, String address)用于将给定的地址添加到收件人类型。
    public void setSubject(String subject)用于设置主题标头字段。
    public void setText(String textmessage) 用于使用 text/plain MIME 将文本设置为消息内容类型。

Address 类

现在我们有了 Session 和 Message(其中存储了内容)对象,我们需要使用 Address 对象来为信件指定地址。

  • Address 是一个抽象类。因此,其子类 javax.mail.internet.InternetAddress 类最常使用。

  • Address 可以通过传递电子邮件地址来创建:

    Address address = new InternetAddress("manisha@gmail.com");
    
  • 创建 Address 的另一种方法是传递名称和电子邮件地址:

    Address address = new InternetAddress("manisha@gmail.com", Manisha); 
    
  • 您还可以设置收件人、发件人、抄送、密件抄送字段,如下所示

    • message.setFrom(address)

    • message.addRecipient(type, address)

    • 三种预定义地址类型是具有以下值之一的对象:

      • Message.RecipientType.TO

      • Message.RecipientType.CC

      • Message.RecipientType.BCC

Authenticator 类

Authenticator 类表示知道如何获取网络连接身份验证的对象。通常,它会通过提示用户输入信息来实现这一点。

  • Authenticator 是一个抽象类。您可以创建一个子类 PasswordAuthentication,并将用户名和密码传递给其构造函数。

  • 创建会话对象时,您必须向 Session 注册 Authenticator。

以下是 Authenticator 使用的示例:

Properties props = new Properties();
//使用任何自定义数据覆盖 props
PasswordAuthentication auth = new PasswordAuthentication("manisha", "pswrd")
Session session = Session.getDefaultInstance(props, auth);

Transport 类

Transport 类用作消息传输机制。此类通常使用 SMTP 协议发送消息。

  • 它是一个抽象类。

  • 只需调用静态 send() 方法即可使用该类的默认版本:

    Transport.send(message);
    
  • 发送消息的另一种方法是从会话中获取协议的特定实例,传递用户名和密码(如不需要则留空),发送消息并关闭连接:

    message.saveChanges(); // 隐式使用 send()
    //获取会话的传输
    Transport transport = session.getTransport("smtp");
    //连接
    transport.connect(host, username, password);
    //必要时重复
    transport.sendMessage(message, message.getAllRecipients());
    //完成,关闭连接
    transport.close();
    

Store 类

一个抽象类,用于模拟消息存储及其访问协议,用于存储和检索消息。子类提供实际实现。 Store 扩展了 Service 类,该类提供了许多常用方法来命名存储、连接存储和监听连接事件。

客户端通过获取实现数据库访问协议的 Store 对象来访问消息存储。大多数消息存储都要求用户在允许访问之前进行身份验证。connect 方法执行该身份验证。

Store store = session.getStore("pop3");
store.connect(host, username, password);

Folder 类

Folder 是一个抽象类,表示邮件消息的文件夹。子类实现特定于协议的文件夹。文件夹可以包含子文件夹以及消息,从而提供层次结构。

连接到商店后,您可以获得一个文件夹,必须先打开该文件夹,然后才能从中读取消息。

Folder folder = store.getFolder("INBOX");
folder.open(Folder.READ_ONLY);
Message message[] = folder.getMessages();

Folder 对象的 getFolder(String name) 方法返回指定的子文件夹。读取邮件完成后,关闭 Store 和 Folder 连接。

我们可以在下图中看到 Store 和 Folder 的关系:

JavaMail API Store and Folder Relation

我们可以看到,对于每个用户帐户,服务器都有一个用于存储用户消息的存储库。存储库分为多个文件夹,"收件箱"文件夹是包含电子邮件消息的主要文件夹。文件夹可以同时包含消息和子文件夹。

JavaMail API - 发送带附件的电子邮件

以下是从您的机器发送带附件的电子邮件的示例。本地机器上的文件是 file.txt,位于 /home/manisha/。这里我们使用了 JangoSMPT 服务器,通过该服务器将电子邮件发送到我们的目标电子邮件地址。该设置在环境设置一章中有说明。

要发送带有内嵌图像的电子邮件,请按照以下步骤操作:

  • 获取会话

  • 创建默认的 MimeMessage 对象,并在消息中设置 From、 To、 Subject

  • 按如下方式设置实际消息:

    messageBodyPart.setText("This is message body");
    
  • 创建 MimeMultipart 对象。将上述设置了实际消息的 messageBodyPart 添加到此多部分对象中。

  • 接下来,通过创建 Datahandler 来添加附件,如下所示:

    messageBodyPart = new MimeBodyPart();
    String filename = "/home/manisha/file.txt";
    DataSource source = new FileDataSource(filename);
    messageBodyPart.setDataHandler(new DataHandler(source));
    messageBodyPart.setFileName(filename);
    multipart.addBodyPart(messageBodyPart);
    
  • 接下来设置消息中的多部分,如下所示:

    message.setContent(multipart);
    
  • 使用 Transport 对象发送消息。

创建 Java 类

创建一个 Java 类文件 SendAttachmentInEmail,其内容如下:

package com.tutorialspoint;

import java.util.Properties;

import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.mail.BodyPart;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;

public class SendAttachmentInEmail {
   public static void main(String[] args) {
      // 需要提及收件人的电子邮件 ID。
      String to = "destinationemail@gmail.com";

      // 需要提及发件人的电子邮件 ID
      String from = "fromemail@gmail.com";

      final String username = "manishaspatil";//相应改变
      final String password = "******";//相应改变

      // 假设您通过relay.jangosmtp.net发送电子邮件
      String host = "relay.jangosmtp.net";

      Properties props = new Properties();
      props.put("mail.smtp.auth", "true");
      props.put("mail.smtp.starttls.enable", "true");
      props.put("mail.smtp.host", host);
      props.put("mail.smtp.port", "25");

      // 获取会话对象.
      Session session = Session.getInstance(props,
         new javax.mail.Authenticator() {
            protected PasswordAuthentication getPasswordAuthentication() {
               return new PasswordAuthentication(username, password);
            }
         });

      try {
         // 创建一个默认的 MimeMessage 对象。
         Message message = new MimeMessage(session);

         // 设置标头的 From: 标头字段。
         message.setFrom(new InternetAddress(from));

         // 设置为:标头的标头字段。
         message.setRecipients(Message.RecipientType.TO,
            InternetAddress.parse(to));

         // 设置主题:标题字段
         message.setSubject("Testing Subject");

         // Create the message part
         BodyPart messageBodyPart = new MimeBodyPart();

         // 现在设置实际消息
         messageBodyPart.setText("This is message body");

         // 创建 multipar 消息
         Multipart multipart = new MimeMultipart();

         // 设置文本消息部分
         multipart.addBodyPart(messageBodyPart);

         // 第二部分是附件
         messageBodyPart = new MimeBodyPart();
         String filename = "/home/manisha/file.txt";
         DataSource source = new FileDataSource(filename);
         messageBodyPart.setDataHandler(new DataHandler(source));
         messageBodyPart.setFileName(filename);
         multipart.addBodyPart(messageBodyPart);

         // 发送完整的消息部分
         message.setContent(multipart);

         // 发送消息
         Transport.send(message);

         System.out.println("Sent message successfully....");
  
      } catch (MessagingException e) {
         throw new RuntimeException(e);
      }
   }
}

由于我们使用主机提供商 JangoSMTP 提供的 SMTP 服务器,因此我们需要验证用户名和密码。javax.mail.PasswordAuthentication 类用于验证密码。

编译并运行

现在我们的类已准备就绪,让我们编译上述类。我已将类 SendAttachmentInEmail.java 保存到目录:/home/manisha/JavaMailAPIExercise。我们需要类路径中的 jar javax.mail.jaractivation.jar。从命令提示符执行以下命令来编译类(两个 jar 都放在 /home/manisha/ 目录中):

javac -cp /home/manisha/activation.jar:/home/manisha/javax.mail.jar: SendAttachmentInEmail.java

现在类已编译完毕,执行以下命令运行:

java -cp /home/manisha/activation.jar:/home/manisha/javax.mail.jar: SendAttachmentInEmail

验证输出

您应该在命令控制台上看到以下消息:

Sent message successfully....

当我通过 JangoSMTP 向我的 gmail 地址发送电子邮件时,我的 gmail 帐户收件箱中会收到以下邮件:

JavaMail API 发送带有附件的电子邮件

JavaMail API - 发送 HTML 电子邮件

以下是从您的机器发送 HTML 电子邮件的示例。这里我们使用了 JangoSMPT 服务器,通过该服务器将电子邮件发送到我们的目标电子邮件地址。环境设置一章中介绍了该设置。

此示例与发送简单电子邮件非常相似,不同之处在于,这里我们使用 setContent() 方法来设置内容,其第二个参数为"text/html",以指定 HTML 内容包含在消息中。使用此示例,您可以发送任意大小的 HTML 内容。

要发送包含 HTML 内容的电子邮件,请按照以下步骤操作:

  • 获取会话

  • 创建默认的 MimeMessage 对象并在消息中设置 From、 To、 Subject

  • 使用 setContent() 方法设置实际消息,如下所示:

    message.setContent("<h1>This is actual message embedded in 
       HTML tags</h1>", "text/html");
    
  • 使用 Transport 对象发送消息。

创建 Java 类

创建一个 Java 类文件 SendHTMLEmail,其内容如下:

package com.tutorialspoint;

import java.util.Properties;

import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

public class SendHTMLEmail {
   public static void main(String[] args) {
      // 需要提及收件人的电子邮件 ID。
      String to = "destinationemail@gmail.com";

      // 需要提及发件人的电子邮件 ID
      String from = "fromemail@gmail.com";
      final String username = "manishaspatil";//相应改变
      final String password = "******";//相应改变

      // 假设您通过relay.jangosmtp.net发送电子邮件
      String host = "relay.jangosmtp.net";

      Properties props = new Properties();
      props.put("mail.smtp.auth", "true");
      props.put("mail.smtp.starttls.enable", "true");
      props.put("mail.smtp.host", host);
      props.put("mail.smtp.port", "25");

      // 获取会话对象.
      Session session = Session.getInstance(props,
         new javax.mail.Authenticator() {
            protected PasswordAuthentication getPasswordAuthentication() {
               return new PasswordAuthentication(username, password);
            }
	});

      try {
            // 创建一个默认的 MimeMessage 对象。
            Message message = new MimeMessage(session);

   	   // 设置标头的 From: 标头字段。
	   message.setFrom(new InternetAddress(from));

	   // 设置为:标头的标头字段。
	   message.setRecipients(Message.RecipientType.TO,
              InternetAddress.parse(to));

	   // 设置主题:标题字段
	   message.setSubject("Testing Subject");

	   // 发送实际的 HTML 消息,大小由您决定
	   message.setContent(
              "<h1>This is actual message embedded in HTML tags</h1>",
             "text/html");

	   // 发送消息
	   Transport.send(message);

	   System.out.println("Sent message successfully....");

      } catch (MessagingException e) {
	   e.printStackTrace();
	   throw new RuntimeException(e);
      }
   }
}

由于我们使用主机提供商 JangoSMTP 提供的 SMTP 服务器,因此我们需要验证用户名和密码。javax.mail.PasswordAuthentication 类用于验证密码。

编译并运行

现在我们的类已准备就绪,让我们编译上述类。我已将类 SendHTMLEmail.java 保存到目录:/home/manisha/JavaMailAPIExercise。我们需要类路径中的 jar javax.mail.jaractivation.jar。从命令提示符执行以下命令来编译类(两个 jar 都放在 /home/manisha/ 目录中):

javac -cp /home/manisha/activation.jar:/home/manisha/javax.mail.jar: SendHTMLEmail.java

现在类已编译,执行以下命令运行:

java -cp /home/manisha/activation.jar:/home/manisha/javax.mail.jar: SendHTMLEmail

验证输出

您应该在命令控制台上看到以下消息:

Sent message successfully....

当我通过JangoSMTP,我的 gmail 帐户收件箱中将收到以下邮件:

JavaMail API 发送 HTML 电子邮件

JavaMail API - 发送带有内嵌图像的电子邮件

下面是一个从您的机器发送带有内嵌图像的 HTML 电子邮件的示例。这里我们使用了 JangoSMPT 服务器,通过该服务器将电子邮件发送到我们的目标电子邮件地址。设置在环境设置一章中进行了说明。

要发送带有内嵌图像的电子邮件,请遵循以下步骤:

  • 获取会话

  • 创建默认 MimeMessage 对象并在消息中设置 From、 To、 Subject

  • 创建 MimeMultipart 对象。

  • 在我们的示例中,我们将在电子邮件中包含 HTML 部分和图像。因此,首先创建 HTML 内容并将其设置为 multipart 对象:

    // 第一部分(html)
    BodyPart messageBodyPart = new MimeBodyPart();
    String htmlText = "<H1>Hello</H1><img src=\"cid:image\">";
    messageBodyPart.setContent(htmlText, "text/html");
    // 添加它
    multipart.addBodyPart(messageBodyPart);
    
  • 接下来通过创建 Datahandler 添加图像,如下所示:

    // 第二部分(图像)
    messageBodyPart = new MimeBodyPart();
    DataSource fds = new FileDataSource(
    "/home/manisha/javamail-mini-logo.png");
    
    messageBodyPart.setDataHandler(new DataHandler(fds));
    messageBodyPart.setHeader("Content-ID", "<image>");
    
  • 接下来设置消息中的多部分,如下所示:

    message.setContent(multipart);
    
  • 使用 Transport 对象发送消息。

创建 Java 类

创建一个 Java 类文件 SendInlineImagesInEmail,其内容如下:

package com.tutorialspoint;

import java.util.Properties;
import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.mail.BodyPart;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;

public class SendInlineImagesInEmail {
   public static void main(String[] args) {
      // 需要提及收件人的电子邮件 ID。
      String to = "destinationemail@gmail.com";

      // 需要提及发件人的电子邮件 ID
      String from = "fromemail@gmail.com";
      final String username = "manishaspatil";//相应改变
      final String password = "******";//相应改变

      // 假设您通过relay.jangosmtp.net发送电子邮件
      String host = "relay.jangosmtp.net";

      Properties props = new Properties();
      props.put("mail.smtp.auth", "true");
      props.put("mail.smtp.starttls.enable", "true");
      props.put("mail.smtp.host", host);
      props.put("mail.smtp.port", "25");

      Session session = Session.getInstance(props,
         new javax.mail.Authenticator() {
            protected PasswordAuthentication getPasswordAuthentication() {
               return new PasswordAuthentication(username, password);
            }
         });

      try {

         // 创建一个默认的 MimeMessage 对象。
         Message message = new MimeMessage(session);

         // 设置标头的 From: 标头字段。
         message.setFrom(new InternetAddress(from));

         // 设置为:标头的标头字段。
         message.setRecipients(Message.RecipientType.TO,
            InternetAddress.parse(to));

         // 设置主题:标题字段
         message.setSubject("Testing Subject");

         // 这封邮件有两部分:正文和嵌入的图片
         MimeMultipart multipart = new MimeMultipart("related");

         // 第一部分 (html)
         BodyPart messageBodyPart = new MimeBodyPart();
         String htmlText = "<H1>Hello</H1><img src=\"cid:image\">";
         messageBodyPart.setContent(htmlText, "text/html");
         // add it
         multipart.addBodyPart(messageBodyPart);

         // 第二部分(图像)
         messageBodyPart = new MimeBodyPart();
         DataSource fds = new FileDataSource(
            "/home/manisha/javamail-mini-logo.png");

         messageBodyPart.setDataHandler(new DataHandler(fds));
         messageBodyPart.setHeader("Content-ID", "<image>");

         // 将图像添加到 multipart 部分
         multipart.addBodyPart(messageBodyPart);

         // 把所有东西放在一起
         message.setContent(multipart);
         // 发送消息
         Transport.send(message);

         System.out.println("Sent message successfully....");

      } catch (MessagingException e) {
         throw new RuntimeException(e);
      }
   }
}

由于我们使用主机提供商 JangoSMTP 提供的 SMTP 服务器,因此我们需要验证用户名和密码。javax.mail.PasswordAuthentication 类用于验证密码。

编译并运行

现在我们的类已准备就绪,让我们编译上述类。我已将类 SendInlineImagesInEmail.java 保存到目录:/home/manisha/JavaMailAPIExercise。我们需要类路径中的 jar javax.mail.jaractivation.jar。从命令提示符执行以下命令来编译类(两个 jar 都放在 /home/manisha/ 目录中):

javac -cp /home/manisha/activation.jar:/home/manisha/javax.mail.jar: SendInlineImagesInEmail.java

现在类已编译,执行以下命令运行:

java -cp /home/manisha/activation.jar:/home/manisha/javax.mail.jar: SendInlineImagesInEmail

验证输出

您应该在命令控制台上看到以下消息:

Sent message successfully....

当我通过 JangoSMTP 向我的 gmail 地址发送电子邮件时,我的 gmail 帐户收件箱中会收到以下邮件:

JavaMail API Send Email With Inline Images

JavaMail API - 检查电子邮件

在继续阅读本章之前,需要了解两个方面。它们是检查获取

  • 在 JavaMail 中检查电子邮件是一个过程,我们打开邮箱中的相应文件夹并获取每封邮件。在这里,我们只检查每封邮件的标题,即发件人、收件人、主题。不读取内容。

  • 获取电子邮件是一个过程,我们打开邮箱中的相应文件夹并获取每封邮件。除了标题之外,我们还通过识别内容类型来读取内容。

要使用 JavaMail API 检查或获取电子邮件,我们需要 POP 或 IMAP 服务器。要检查和获取电子邮件,需要 Folder 和 Store 类。这里我们使用了 GMAIL 的 POP3 服务器(pop.gmail.com)。本章将学习如何使用 JavaMail API 检查电子邮件。获取将在后续章节中介绍。要检查电子邮件:

  • 获取会话

  • 创建 pop3 Store 对象并连接 pop 服务器。

  • 创建文件夹对象。打开邮箱中的相应文件夹。

  • 获取您的邮件。

  • 关闭 Store 和 Folder 对象。

创建 Java 类

创建一个 Java 类文件 CheckingMails,其内容如下:

package com.tutorialspoint;

import java.util.Properties;

import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.NoSuchProviderException;
import javax.mail.Session;
import javax.mail.Store;

public class CheckingMails {

   public static void check(String host, String storeType, String user,
      String password) 
   {
      try {

      //创建属性字段
      Properties properties = new Properties();

      properties.put("mail.pop3.host", host);
      properties.put("mail.pop3.port", "995");
      properties.put("mail.pop3.starttls.enable", "true");
      Session emailSession = Session.getDefaultInstance(properties);
  
      //创建 POP3 存储对象并连接 pop 服务器
      Store store = emailSession.getStore("pop3s");

      store.connect(host, user, password);

      //创建文件夹对象并打开它
      Folder emailFolder = store.getFolder("INBOX");
      emailFolder.open(Folder.READ_ONLY);

      // 从文件夹中检索数组中的消息并打印
      Message[] messages = emailFolder.getMessages();
      System.out.println("messages.length---" + messages.length);

      for (int i = 0, n = messages.length; i < n; i++) {
         Message message = messages[i];
         System.out.println("---------------------------------");
         System.out.println("Email Number " + (i + 1));
         System.out.println("Subject: " + message.getSubject());
         System.out.println("From: " + message.getFrom()[0]);
         System.out.println("Text: " + message.getContent().toString());

      }

      //关闭存储和文件夹对象
      emailFolder.close(false);
      store.close();

      } catch (NoSuchProviderException e) {
         e.printStackTrace();
      } catch (MessagingException e) {
         e.printStackTrace();
      } catch (Exception e) {
         e.printStackTrace();
      }
   }

   public static void main(String[] args) {

      String host = "pop.gmail.com";// 相应改变
      String mailStoreType = "pop3";
      String username = "yourmail@gmail.com";// 相应改变
      String password = "*****";// 相应改变

      check(host, mailStoreType, username, password);

   }

}

编译并运行

现在我们的类已准备就绪,让我们编译上述类。我已将 CheckingMails.java 类保存到目录:/home/manisha/JavaMailAPIExercise。我们需要类路径中的 jar 文件 javax.mail.jaractivation.jar。从命令提示符执行以下命令来编译类(两个 jar 都放在 /home/manisha/ 目录中):

javac -cp /home/manisha/activation.jar:/home/manisha/javax.mail.jar: CheckingMails.java

现在类已编译完毕,执行以下命令运行:

java -cp /home/manisha/activation.jar:/home/manisha/javax.mail.jar: CheckingMails

验证输出

您应该在命令控制台上看到以下消息:

messages.length---4
---------------------------------
Email Number 1
Subject: Test Mail--Fetch
From: <abcd@gmail.com>
Text: javax.mail.internet.MimeMultipart@327a5b7f
---------------------------------
Email Number 2
Subject: testing ----checking simple email
From: <abcd@gmail.com>
Text: javax.mail.internet.MimeMultipart@7f0d08bc
---------------------------------
Email Number 3
Subject: Email with attachment
From: <abcd@gmail.com>
Text: javax.mail.internet.MimeMultipart@30b8afce
---------------------------------
Email Number 4
Subject: Email with Inline image
From: <abcd@gmail.com>
Text: javax.mail.internet.MimeMultipart@2d1e165f

这里我们打印了收件箱中的邮件数量,在本例中为 4。我们还打印了每封电子邮件的主题、发件人地址和正文。

JavaMail API - 获取电子邮件

在上一章中,我们学习了如何检查电子邮件。现在让我们看看如何获​​取每封电子邮件并阅读其内容。让我们编写一个 Java 类 FetchingEmail,它将读取以下类型的电子邮件:

  • 简单电子邮件

  • 带附件的电子邮件

  • 带内嵌图像的电子邮件

代码中遵循的基本步骤如下:

  • 获取 Session 对象。

  • 创建 POP3 存储对象并连接到存储。

  • 创建 Folder 对象并打开邮箱中的相应文件夹。

  • 检索消息。

  • 分别关闭文件夹和存储对象。

创建 Java 类

创建一个 java 类文件FetchingEmail,其内容如下:

package com.tutorialspoint;

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Date;
import java.util.Properties;

import javax.mail.Address;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.NoSuchProviderException;
import javax.mail.Part;
import javax.mail.Session;
import javax.mail.Store;

public class FetchingEmail {

   public static void fetch(String pop3Host, String storeType, String user,
      String password) {
      try {
         // 创建属性字段
         Properties properties = new Properties();
         properties.put("mail.store.protocol", "pop3");
         properties.put("mail.pop3.host", pop3Host);
         properties.put("mail.pop3.port", "995");
         properties.put("mail.pop3.starttls.enable", "true");
         Session emailSession = Session.getDefaultInstance(properties);
         // emailSession.setDebug(true);

         // 创建 POP3 存储对象并连接 pop 服务器
         Store store = emailSession.getStore("pop3s");

         store.connect(pop3Host, user, password);

         // 创建文件夹对象并打开它
         Folder emailFolder = store.getFolder("INBOX");
         emailFolder.open(Folder.READ_ONLY);

         BufferedReader reader = new BufferedReader(new InputStreamReader(
	      System.in));

         // 从文件夹中检索数组中的消息并打印
         Message[] messages = emailFolder.getMessages();
         System.out.println("messages.length---" + messages.length);

         for (int i = 0; i < messages.length; i++) {
            Message message = messages[i];
            System.out.println("---------------------------------");
            writePart(message);
            String line = reader.readLine();
            if ("YES".equals(line)) {
               message.writeTo(System.out);
            } else if ("QUIT".equals(line)) {
               break;
            }
         }

         // 关闭存储和文件夹对象
         emailFolder.close(false);
         store.close();

      } catch (NoSuchProviderException e) {
         e.printStackTrace();
      } catch (MessagingException e) {
         e.printStackTrace();
      } catch (IOException e) {
         e.printStackTrace();
      } catch (Exception e) {
         e.printStackTrace();
      }
   }
   public static void main(String[] args) {

      String host = "pop.gmail.com";// 相应改变
      String mailStoreType = "pop3";
      String username = 
         "abc@gmail.com";// 相应改变
      String password = "*****";// 相应改变

      //Call method fetch
      fetch(host, mailStoreType, username, password);

   }

   /*
   * This method checks for content-type 
   * based on which, it processes and
   * fetches the content of the message
   */
   public static void writePart(Part p) throws Exception {
      if (p instanceof Message)
         //调用方法写信封
         writeEnvelope((Message) p);

      System.out.println("----------------------------");
      System.out.println("CONTENT-TYPE: " + p.getContentType());

      //检查内容是否是纯文本
      if (p.isMimeType("text/plain")) {
         System.out.println("This is plain text");
         System.out.println("---------------------------");
         System.out.println((String) p.getContent());
      } 
      //检查内容是否有附件
      else if (p.isMimeType("multipart/*")) {
         System.out.println("This is a Multipart");
         System.out.println("---------------------------");
         Multipart mp = (Multipart) p.getContent();
         int count = mp.getCount();
         for (int i = 0; i < count; i++)
            writePart(mp.getBodyPart(i));
      } 
      //检查内容是否是嵌套消息
      else if (p.isMimeType("message/rfc822")) {
         System.out.println("This is a Nested Message");
         System.out.println("---------------------------");
         writePart((Part) p.getContent());
      } 
      //检查内容是否为内联图像
      else if (p.isMimeType("image/jpeg")) {
         System.out.println("--------> image/jpeg");
         Object o = p.getContent();

         InputStream x = (InputStream) o;
         // 构造所需的字节数组
         System.out.println("x.length = " + x.available());
         while ((i = (int) ((InputStream) x).available()) > 0) {
            int result = (int) (((InputStream) x).read(bArray));
            if (result == -1)
         int i = 0;
         byte[] bArray = new byte[x.available()];

            break;
         }
         FileOutputStream f2 = new FileOutputStream("/tmp/image.jpg");
         f2.write(bArray);
      } 
      else if (p.getContentType().contains("image/")) {
         System.out.println("content type" + p.getContentType());
         File f = new File("image" + new Date().getTime() + ".jpg");
         DataOutputStream output = new DataOutputStream(
            new BufferedOutputStream(new FileOutputStream(f)));
            com.sun.mail.util.BASE64DecoderStream test = 
                 (com.sun.mail.util.BASE64DecoderStream) p
                  .getContent();
         byte[] buffer = new byte[1024];
         int bytesRead;
         while ((bytesRead = test.read(buffer)) != -1) {
            output.write(buffer, 0, bytesRead);
         }
      } 
      else {
         Object o = p.getContent();
         if (o instanceof String) {
            System.out.println("This is a string");
            System.out.println("---------------------------");
            System.out.println((String) o);
         } 
         else if (o instanceof InputStream) {
            System.out.println("This is just an input stream");
            System.out.println("---------------------------");
            InputStream is = (InputStream) o;
            is = (InputStream) o;
            int c;
            while ((c = is.read()) != -1)
               System.out.write(c);
         } 
         else {
            System.out.println("This is an unknown type");
            System.out.println("---------------------------");
            System.out.println(o.toString());
         }
      }

   }
   /*
   * This method would print FROM,TO and SUBJECT of the message
   */
   public static void writeEnvelope(Message m) throws Exception {
      System.out.println("This is the message envelope");
      System.out.println("---------------------------");
      Address[] a;

      // FROM
      if ((a = m.getFrom()) != null) {
         for (int j = 0; j < a.length; j++)
         System.out.println("FROM: " + a[j].toString());
      }

      // TO
      if ((a = m.getRecipients(Message.RecipientType.TO)) != null) {
         for (int j = 0; j < a.length; j++)
         System.out.println("TO: " + a[j].toString());
      }

      // SUBJECT
      if (m.getSubject() != null)
         System.out.println("SUBJECT: " + m.getSubject());

   }

}
您可以通过取消注释语句 emailSession.setDebug(true); 来启用调试

编译并运行

现在我们的类已准备就绪,让我们编译上述类。我已将类 FetchingEmail.java 保存到目录:/home/manisha/JavaMailAPIExercise。我们需要类路径中的 jar javax.mail.jaractivation.jar。从命令提示符执行以下命令来编译类(两个 jar 都放在 /home/manisha/ 目录中):

javac -cp /home/manisha/activation.jar:/home/manisha/javax.mail.jar: FetchingEmail.java

现在类已编译完毕,执行以下命令运行:

java -cp /home/manisha/activation.jar:/home/manisha/javax.mail.jar: FetchingEmail

验证输出

您应该在命令控制台上看到以下消息:

messages.length---3
---------------------------------
This is the message envelope
---------------------------
FROM: XYZ <xyz@gmail.com>
TO: ABC <abc@gmail.com>
SUBJECT: Simple Message
----------------------------
CONTENT-TYPE: multipart/alternative; boundary=047d7b343d6ad3e4ea04e8ec6579
This is a Multipart
---------------------------

----------------------------
CONTENT-TYPE: text/plain; charset=ISO-8859-1
This is plain text
---------------------------
Hi am a simple message string....

-- 
Regards
xyz

This is the message envelope
---------------------------
FROM: XYZ <xyz@gmail.com>
TO: ABC <abc@gmail.com>
SUBJECT: Attachement
----------------------------
CONTENT-TYPE: multipart/mixed; boundary=047d7b343d6a99180904e8ec6751
This is a Multipart
---------------------------

----------------------------
CONTENT-TYPE: text/plain; charset=ISO-8859-1
This is plain text
---------------------------
Hi I've an attachment.Please check

-- 
Regards
XYZ

----------------------------
CONTENT-TYPE: application/octet-stream; name=sample_attachement
This is just an input stream
---------------------------
Submit your Tutorials, White Papers and Articles into our Tutorials Directory. This is a tutorials database where we are keeping all the tutorials shared by the internet community for the benefit of others.

This is the message envelope
---------------------------
FROM: XYZ <xyz@gmail.com>
TO: ABC <abc@gmail.com>
SUBJECT: Inline Image
----------------------------
CONTENT-TYPE: multipart/related; boundary=f46d04182582be803504e8ece94b
This is a Multipart
---------------------------

----------------------------
CONTENT-TYPE: text/plain; charset=ISO-8859-1
This is plain text
---------------------------
Hi I've an inline image

[image: Inline image 3]

-- 
Regards
XYZ

----------------------------
CONTENT-TYPE: image/png; name="javamail-mini-logo.png"
content typeimage/png; name="javamail-mini-logo.png"

在这里您可以看到我们的邮箱中有三封电子邮件。第一封是一封简单的邮件,内容是"嗨,我是一个简单的消息字符串……"。第二封邮件有一个附件。附件的内容也打印出来,如上所示。第三封邮件有一个内嵌图像。

JavaMail API - 身份验证

在前面的章节检查电子邮件获取电子邮件中,我们在连接到邮箱存储时传递了授权凭据(用户和密码)以及主机。相反,我们可以配置属性以包含主机,并告知会话有关您的自定义身份验证器实例的信息。以下示例显示了这一点:

创建 Java 类

我们将修改检查电子邮件章节中的 CheckingMails.java。其内容如下:

package com.tutorialspoint;

import java.util.Properties;

import javax.mail.Authenticator;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.NoSuchProviderException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Store;

public class CheckingMails {

   public static void check(String host, String storeType, String user,
      String password) 
   {
      try {

      // 创建属性字段
      Properties properties = new Properties();

      properties.put("mail.pop3s.host", host);
      properties.put("mail.pop3s.port", "995");
      properties.put("mail.pop3s.starttls.enable", "true");

      // 设置身份验证,获取会话
      Session emailSession = Session.getInstance(properties,
         new javax.mail.Authenticator() {
            protected PasswordAuthentication getPasswordAuthentication() {
               return new PasswordAuthentication(
                  "manisha@gmail.com", "manisha123");
            }
         });
      // emailSession.setDebug(true);

      // 创建 POP3 存储对象并连接 pop 服务器
      Store store = emailSession.getStore("pop3s");
    
      store.connect();
    
      // 创建文件夹对象并打开它
      Folder emailFolder = store.getFolder("INBOX");
      emailFolder.open(Folder.READ_ONLY);
    
      // 从文件夹中检索数组中的消息并打印它
      Message[] messages = emailFolder.getMessages();
      System.out.println("messages.length---" + messages.length);

      for (int i = 0, n = messages.length; i < n; i++) {
         Message message = messages[i];
         System.out.println("---------------------------------");
         System.out.println("Email Number " + (i + 1));
         System.out.println("Subject: " + message.getSubject());
         System.out.println("From: " + message.getFrom()[0]);
         System.out.println("Text: " + message.getContent().toString());
      }

      // 关闭存储和文件夹对象
      emailFolder.close(false);
      store.close();

      } catch (NoSuchProviderException e) {
         e.printStackTrace();
      } catch (MessagingException e) {
         e.printStackTrace();
      } catch (Exception e) {
         e.printStackTrace();
      }
   }

   public static void main(String[] args) {

      String host = "pop.gmail.com";// 相应改变
      String mailStoreType = "pop3";
      String username = "abc@gmail.com";// 相应改变
      String password = "*****";// 相应改变

      check(host, mailStoreType, username, password);

   }

}
您可以通过取消注释语句 emailSession.setDebug(true);
来启用调试

编译并运行

现在我们的类已准备就绪,让我们编译上述类。我已将 CheckingMails.java 类保存到目录:/home/manisha/JavaMailAPIExercise。我们需要类路径中的 jar 文件 javax.mail.jaractivation.jar。从命令提示符执行以下命令来编译类(两个 jar 都放在 /home/manisha/ 目录中):

javac -cp /home/manisha/activation.jar:/home/manisha/javax.mail.jar: CheckingMails.java

现在类已编译完毕,执行以下命令运行:

java -cp /home/manisha/activation.jar:/home/manisha/javax.mail.jar: CheckingMails

验证输出

您可以在命令控制台上看到类似以下消息:

messages.length---3
---------------------------------
Email Number 1
Subject: Today is a nice day
From: XYZ <xyz@gmail.com>
Text: javax.mail.internet.MimeMultipart@45f676cb
---------------------------------
Email Number 2
Subject: hiiii....
From: XYZ <xyz@gmail.com>
Text: javax.mail.internet.MimeMultipart@37f12d4f
---------------------------------
Email Number 3
Subject: helloo
From: XYZ <xyz@gmail.com>
Text: javax.mail.internet.MimeMultipart@3ad5ba3a

JavaMail API - 回复电子邮件

在本章中,我们将了解如何使用 JavaMail API 回复电子邮件。以下程序中遵循的基本步骤如下:

  • 获取属性中包含 POP 和 SMPT 服务器详细信息的 Session 对象。我们需要 POP 详细信息来检索消息,需要 SMPT 详细信息来发送消息。

  • 创建 POP3 存储对象并连接到存储。

  • 创建文件夹对象并打开邮箱中的相应文件夹。

  • 检索消息。

  • 遍历消息并输入"Y"或"y"(如果要回复)。

  • 获取消息的所有信息(收件人、发件人、主题、内容)。

  • 使用 Message.reply() 方法构建回复消息。此方法使用适当的收件人和主题配置新消息。该方法采用布尔参数,指示是仅回复发件人(false)还是回复所有人(true)。

  • 在邮件中设置发件人、文本和回复,并通过 Transport 对象的实例发送。

  • 分别关闭 Transport、文件夹和存储对象。

这里我们使用了 JangoSMPT 服务器,通过该服务器将电子邮件发送到我们的目标电子邮件地址。设置在环境设置一章中有说明。

创建 Java 类

创建一个 Java 类文件 ReplyToEmail,其内容如下:

package com.tutorialspoint;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Date;
import java.util.Properties;

import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

public class ReplyToEmail {
   public static void main(String args[]) 
   {
      Date date = null;

      Properties properties = new Properties();
      properties.put("mail.store.protocol", "pop3");
      properties.put("mail.pop3s.host", "pop.gmail.com");
      properties.put("mail.pop3s.port", "995");
      properties.put("mail.pop3.starttls.enable", "true");
      properties.put("mail.smtp.auth", "true");
      properties.put("mail.smtp.starttls.enable", "true");
      properties.put("mail.smtp.host", "relay.jangosmtp.net");
      properties.put("mail.smtp.port", "25");
      Session session = Session.getDefaultInstance(properties);

      // session.setDebug(true);
      try 
      {
         // 获取 Store 对象并连接到当前主机
         Store store = session.getStore("pop3s");
         store.connect("pop.gmail.com", "xyz@gmail.com",
            "*****");//相应地更改用户和密码

         Folder folder = store.getFolder("inbox");
         if (!folder.exists()) {
            System.out.println("inbox not found");
               System.exit(0);
         }
         folder.open(Folder.READ_ONLY);

         BufferedReader reader = new BufferedReader(new InputStreamReader(
            System.in));

         Message[] messages = folder.getMessages();
         if (messages.length != 0) {

            for (int i = 0, n = messages.length; i < n; i++) {
               Message message = messages[i];
               date = message.getSentDate();
               // 从消息中获取所有信息
               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);
               }

               System.out.print("Do you want to reply [y/n] : ");
               String ans = reader.readLine();
               if ("Y".equals(ans) || "y".equals(ans)) {

                  Message replyMessage = new MimeMessage(session);
                  replyMessage = (MimeMessage) message.reply(false);
                  replyMessage.setFrom(new InternetAddress(to));
                  replyMessage.setText("Thanks");
                  replyMessage.setReplyTo(message.getReplyTo());

                  // 通过验证 SMTP 服务器来发送消息
                  // 创建一个 Transport 实例并调用 sendMessage
                  Transport t = session.getTransport("smtp");
                  try {
	   	     //使用传输实例连接到 smtp 服务器
		     //相应地更改用户和密码	
	             t.connect("abc", "****");
	             t.sendMessage(replyMessage,
                        replyMessage.getAllRecipients());
                  } finally {
                     t.close();
                  }
                  System.out.println("message replied successfully ....");

                  // 关闭存储和文件夹对象
                  folder.close(false);
                  store.close();

               } else if ("n".equals(ans)) {
                  break;
               }
            }//end of for loop

         } else {
            System.out.println("There is no msg....");
         }

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

   }

}
您可以通过取消注释语句 session.setDebug(true);
来启用调试

编译并运行

现在我们的类已准备就绪,让我们编译上述类。我已将 ReplyToEmail.java 类保存到目录:/home/manisha/JavaMailAPIExercise。我们需要类路径中的 jar javax.mail.jaractivation.jar。从命令提示符执行以下命令来编译类(两个 jar 都放在 /home/manisha/ 目录中):

javac -cp /home/manisha/activation.jar:/home/manisha/javax.mail.jar: ReplyToEmail.java

现在类已编译完毕,执行以下命令运行:

java -cp /home/manisha/activation.jar:/home/manisha/javax.mail.jar: ReplyToEmail

验证输出

您应该在命令控制台上看到以下消息:

From: ABC <abc@gmail.com>
Reply-to: abc@trioteksolutions.com
To: XYZ <xyz@gmail.com>
Subject: Hi today is a nice day
Sent: Thu Oct 17 15:58:37 IST 2013
Do you want to reply [y/n] : y
message replied successfully ....

检查邮件发送至的收件箱。在我们的例子中,收到的消息如下所示:

JavaMail API Reply Email

JavaMail API - 转发电子邮件

在本章中,我们将了解如何使用 JavaMail API 转发电子邮件。以下程序中遵循的基本步骤如下:

  • 获取属性中包含 POP 和 SMPT 服务器详细信息的 Session 对象。我们需要 POP 详细信息来检索消息,需要 SMPT 详细信息来发送消息。

  • 创建 POP3 存储对象并连接到存储。

  • 创建文件夹对象并打开邮箱中的相应文件夹。

  • 检索消息。

  • 遍历消息并键入"Y"或"y"(如果要转发)。

  • 获取消息的所有信息(收件人、发件人、主题、内容)。

  • 通过使用组成消息的各个部分来构建转发消息。第一部分是消息的文本,第二部分是要转发的消息。将两者合并为一个多部分。然后将多部分添加到正确寻址的消息并发送。

  • 分别关闭 Transport、folder 和 store 对象。

这里我们使用了 JangoSMPT 服务器,通过该服务器将电子邮件发送到我们的目标电子邮件地址。设置在环境设置一章中有说明。

创建 Java 类

创建一个 Java 类文件 ForwardEmail,其内容如下:

package com.tutorialspoint;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Date;
import java.util.Properties;

import javax.mail.BodyPart;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.Multipart;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;

public class ForwardEmail {

   public static void main(String[] args) {
      Properties properties = new Properties();
      properties.put("mail.store.protocol", "pop3");
      properties.put("mail.pop3s.host", "pop.gmail.com");
      properties.put("mail.pop3s.port", "995");
      properties.put("mail.pop3.starttls.enable", "true");
      properties.put("mail.smtp.auth", "true");
      properties.put("mail.smtp.host", "relay.jangosmtp.net");
      properties.put("mail.smtp.port", "25");
      Session session = Session.getDefaultInstance(properties);
      try {
         // session.setDebug(true);
         // 获取 Store 对象并连接到当前主机
         Store store = session.getStore("pop3s");
         store.connect("pop.gmail.com", "xyz@gmail.com",
            "*****");//相应地更改用户和密码

         // 创建一个 Folder 对象并打开该文件夹
         Folder folder = store.getFolder("inbox");
         folder.open(Folder.READ_ONLY);
         BufferedReader reader = new BufferedReader(new InputStreamReader(
            System.in));
         Message[] messages = folder.getMessages();
         if (messages.length != 0) {

         for (int i = 0, n = messages.length; i < n; i++) {
            Message message = messages[i];
            // 从消息中获取所有信息
            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);
            }
            System.out.print("Do you want to reply [y/n] : ");
            String ans = reader.readLine();
            if ("Y".equals(ans) || "y".equals(ans)) {
                Message forward = new MimeMessage(session);
                // 填写标题
                forward.setRecipients(Message.RecipientType.TO,
                InternetAddress.parse(from));
                forward.setSubject("Fwd: " + message.getSubject());
                forward.setFrom(new InternetAddress(to));
                
                // 创建消息部分
                MimeBodyPart messageBodyPart = new MimeBodyPart();
                // 创建多部分消息
                Multipart multipart = new MimeMultipart();
                // 设置内容
                messageBodyPart.setContent(message, "message/rfc822");
                // 将部分添加到多部分
                multipart.addBodyPart(messageBodyPart);
                // 将多部分与消息关联
                forward.setContent(multipart);
                forward.saveChanges();

               // 通过验证 SMTP 服务器来发送消息
               // 创建一个 Transport 实例并调用 sendMessage
               Transport t = session.getTransport("smtp");
               try {
                  //使用传输实例连接到 smtp 服务器
		  //相应地更改用户和密码
                  t.connect("abc", "*****");
                  t.sendMessage(forward, forward.getAllRecipients());
               } finally {
                  t.close();
               }

               System.out.println("message forwarded successfully....");

            // 关闭存储和文件夹对象
            folder.close(false);
            store.close();
            }// end if

         }// end for
   }// end if
   } catch (Exception e) {
      e.printStackTrace();
   }
}

}
您可以通过取消注释语句 session.setDebug(true);
来启用调试

编译并运行

现在我们的类已准备就绪,让我们编译上述类。我已将类 ForwardEmail.java 保存到目录:/home/manisha/JavaMailAPIExercise。我们需要类路径中的 jar javax.mail.jaractivation.jar。从命令提示符执行以下命令来编译类(两个 jar 都放在 /home/manisha/ 目录中):

javac -cp /home/manisha/activation.jar:/home/manisha/javax.mail.jar: ForwardEmail.java

现在类已编译完毕,执行以下命令运行:

java -cp /home/manisha/activation.jar:/home/manisha/javax.mail.jar: ForwardEmail

验证输出

您应该在命令控制台上看到以下消息:

From: ABC <abc@gmail.com>
Reply-to: abc@trioteksolutions.com
To: XYZ <xyz@gmail.com>
Subject: Hi today is a nice day
Sent: Thu Oct 17 15:58:37 IST 2013
Do you want to reply [y/n] : y
message forwarded successfully....

检查邮件发送至的收件箱。在我们的例子中,转发的消息如下所示:

JavaMail API Forward Email JavaMail API Forward Email

JavaMail API - 删除电子邮件

在本章中,我们将了解如何使用 JavaMail API 删除电子邮件。删除邮件涉及使用与邮件关联的标志。不同状态有不同的标志,一些是系统定义的,一些是用户定义的。预定义标志在内部类 Flags.Flag 中定义,如下所示:

  • Flags.Flag.ANSWERED

  • Flags.Flag.DELETED

  • Flags.Flag.DRAFT

  • Flags.Flag.FLAGGED

  • Flags.Flag.RECENT

  • Flags.Flag.SEEN

  • Flags.Flag.USER

POP 协议仅支持删除消息。

删除程序中遵循的基本步骤如下:

  • 获取属性中具有 POP 和 SMPT 服务器详细信息的 Session 对象。我们需要 POP 详细信息来检索消息,需要 SMPT 详细信息来发送消息。

  • 创建 POP3 存储对象并连接到存储。

  • 创建 Folder 对象并以 READ_WRITE 模式打开邮箱中的相应文件夹。

  • 从收件箱文件夹中检索消息。

  • 遍历消息,如果要删除消息,请通过在 Message 对象上调用方法 setFlag(Flags.Flag.DELETED, true) 来键入"Y"或"y"。

  • 标记为 DELETED 的消息实际上并没有被删除,直到我们在 Folder 对象上调用 expunge() 方法,或者在将 expunge 设置为 true 的情况下关闭文件夹。

  • 关闭存储对象。

创建 Java类

创建一个java类文件ForwardEmail,其内容如下:

package com.tutorialspoint;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Properties;

import javax.mail.Flags;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.NoSuchProviderException;
import javax.mail.Session;
import javax.mail.Store;

public class DeleteEmail {

   public static void delete(String pop3Host, String storeType, String user,
      String password) 
   {
      try 
      {
         // 获取会话对象
         Properties properties = new Properties();
         properties.put("mail.store.protocol", "pop3");
         properties.put("mail.pop3s.host", pop3Host);
         properties.put("mail.pop3s.port", "995");
         properties.put("mail.pop3.starttls.enable", "true");
         Session emailSession = Session.getDefaultInstance(properties);
         // emailSession.setDebug(true);

         // 创建 POP3 存储对象并连接 pop 服务器
         Store store = emailSession.getStore("pop3s");

         store.connect(pop3Host, user, password);

         // 创建文件夹对象并打开它
         Folder emailFolder = store.getFolder("INBOX");
         emailFolder.open(Folder.READ_WRITE);

         BufferedReader reader = new BufferedReader(new InputStreamReader(
            System.in));
         // 从文件夹中检索数组中的消息并打印
         Message[] messages = emailFolder.getMessages();
         System.out.println("messages.length---" + messages.length);
         for (int i = 0; i < messages.length; i++) {
            Message message = messages[i];
            System.out.println("---------------------------------");
            System.out.println("Email Number " + (i + 1));
            System.out.println("Subject: " + message.getSubject());
            System.out.println("From: " + message.getFrom()[0]);

            String subject = message.getSubject();
            System.out.print("Do you want to delete this message [y/n] ? ");
            String ans = reader.readLine();
            if ("Y".equals(ans) || "y".equals(ans)) {
	       // 将 DELETE 标志设置为 true
	       message.setFlag(Flags.Flag.DELETED, true);
	       System.out.println("Marked DELETE for message: " + subject);
            } else if ("n".equals(ans)) {
	       break;
            }
         }
         // 清除文件夹以删除标记为已删除的邮件
         emailFolder.close(true);
         store.close();

      } catch (NoSuchProviderException e) {
         e.printStackTrace();
      } catch (MessagingException e) {
         e.printStackTrace();
      } catch (IOException io) {
         io.printStackTrace();
      }
   }

   public static void main(String[] args) {

      String host = "pop.gmail.com";// 相应改变
      String mailStoreType = "pop3";
      String username = "abc@gmail.com";// 相应改变
      String password = "*****";// 相应改变

      delete(host, mailStoreType, username, password);

   }

}
您可以通过取消注释语句 emailSession.setDebug(true);
来启用调试

编译并运行

现在我们的类已准备就绪,让我们编译上述类。我已将类 DeleteEmail.java 保存到目录:/home/manisha/JavaMailAPIExercise。我们需要类路径中的 jar javax.mail.jaractivation.jar。从命令提示符执行以下命令来编译类(两个 jar 都放在 /home/manisha/ 目录中):

javac -cp /home/manisha/activation.jar:/home/manisha/javax.mail.jar: DeleteEmail.java

现在类已编译,请执行以下命令运行:

java -cp /home/manisha/activation.jar:/home/manisha/javax.mail.jar: DeleteEmail

验证输出

您应该在命令控制台上看到以下消息:

messages.length---1
---------------------------------
Email Number 1
Subject: Testing
From: ABC <abc@gmail.com>
Do you want to delete this message [y/n] ? y
Marked DELETE for message: Testing

JavaMail API - Gmail SMTP 服务器

在前面的所有章节中,我们都使用了 JangoSMPT 服务器来发送电子邮件。在本章中,我们将了解 Gmail 提供的 SMPT 服务器。Gmail(以及其他一些服务)免费提供其公共 SMTP 服务器的使用。

Gmail SMTP 服务器的详细信息可在此处找到。正如您在详细信息中看到的,我们可以使用 TLS 或 SSL 连接通过 Gmail SMTP 服务器发送电子邮件。

使用 Gmail SMTP 服务器发送电子邮件的过程与发送电子邮件章中所述类似,只是我们会更改主机服务器。作为先决条件,发件人电子邮件地址应为活跃的 gmail 帐户。让我们尝试一个例子。

创建 Java 类

创建一个 Java 文件 SendEmailUsingGMailSMTP,其内容如下:

package com.tutorialspoint;

import java.util.Properties;

import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

public class SendEmailUsingGMailSMTP {
   public static void main(String[] args) {
      // 需要提及收件人的电子邮件 ID。
      String to = "xyz@gmail.com";//相应改变

      // 需要提及发件人的电子邮件 ID
      String from = "abc@gmail.com";//相应改变
      final String username = "abc";//相应改变
      final String password = "*****";//相应改变

      // 假设您通过relay.jangosmtp.net发送电子邮件
      String host = "smtp.gmail.com";

      Properties props = new Properties();
      props.put("mail.smtp.auth", "true");
      props.put("mail.smtp.starttls.enable", "true");
      props.put("mail.smtp.host", host);
      props.put("mail.smtp.port", "587");

      // 获取会话对象.
      Session session = Session.getInstance(props,
      new javax.mail.Authenticator() {
         protected PasswordAuthentication getPasswordAuthentication() {
            return new PasswordAuthentication(username, password);
         }
      });

      try {
         // 创建一个默认的 MimeMessage 对象。
         Message message = new MimeMessage(session);

         // 设置标头的 From: 标头字段。
         message.setFrom(new InternetAddress(from));

         // 设置为:标头的标头字段。
         message.setRecipients(Message.RecipientType.TO,
         InternetAddress.parse(to));

         // Set Subject: header field
         message.setSubject("Testing Subject");

         // 现在设置实际消息
         message.setText("Hello, this is sample for to check send "
            + "email using JavaMailAPI ");

         // 发送消息
         Transport.send(message);

         System.out.println("Sent message successfully....");

      } catch (MessagingException e) {
            throw new RuntimeException(e);
      }
   }
}

此处主机设置为 smtp.gmail.com,端口设置为 587。此处我们已启用 TLS 连接。

编译并运行

现在我们的类已准备就绪,让我们编译上述类。我已将类 SendEmailUsingGMailSMTP.java 保存到目录:/home/manisha/JavaMailAPIExercise。我们需要类路径中的 jar javax.mail.jaractivation.jar。从命令提示符执行以下命令编译类(两个 jar 都放在 /home/manisha/ 目录中):

javac -cp /home/manisha/activation.jar:/home/manisha/javax.mail.jar: SendEmailUsingGMailSMTP.java

现在类已编译,执行以下命令运行:

java -cp /home/manisha/activation.jar:/home/manisha/javax.mail.jar: SendEmailUsingGMailSMTP

验证输出

您应该在命令控制台上看到以下消息:

Sent message successfully....

JavaMail API - 文件夹管理

到目前为止,我们在前面的章节中主要使用了 INBOX 文件夹。这是大多数邮件所在的默认文件夹。有些系统可能将其称为 INBOX,而有些系统可能将其称为其他名称。但是,您始终可以使用名称 INBOX 从 JavaMail API 访问它。

JavaMail API 将文件夹表示为抽象 Folder 类的实例:

public abstract class Folder extends Object

此类声明了从服务器请求命名文件夹、从文件夹中删除消息、在文件夹中搜索特定消息、在文件夹中列出消息等方法。

打开文件夹

我们无法直接创建文件夹,因为 Folder 类中唯一的构造函数是 protected。我们可以从以下位置获取 Folder:

  • 会话

  • 商店

  • 或其他文件夹

所有上述类都具有类似的 getFolder() 方法和类似的签名:

public abstract Folder getFolder(String name) throws MessagingException

有助于获取 Folder 对象的一些方法如下:

方法描述
boolean exists()检查文件夹是否真的存在存在。在获取 Folder 对象之前使用此方法。
abstract void open(int mode)当您获取 Folder 时,它是关闭的。使用此方法打开它。mode 可以是 Folder.READ_ONLY 或 Folder.READ_WRITE。
abstract boolean isOpen()如果文件夹打开,则此方法返回 true,如果文件夹关闭,则返回 false
abstract void close(boolean expunge)关闭文件夹。如果 expunge 参数为 true,则文件夹中所有已删除的邮件都将从服务器上的实际文件中删除。否则,它们只是被标记为已删除,但消息仍然可以恢复。

基本文件夹信息

以下是 Folder 类中的一些方法,它们返回有关文件夹的基本信息:

方法描述
abstract String getName()返回文件夹的名称,例如"TutorialsPoint Mail"
abstract String getFullName()从根目录返回完整的层次名称,例如"books/Manisha/TutorialsPoint Mail"。
URLName getURLName()返回表示此文件夹的 URLName。
abstract Folder getParent()返回包含此文件夹的文件夹的名称,即父文件夹。例如,上一个"TutorialsPoint Mail"示例中的"Manisha"。
abstract int getType()返回一个 int,指示文件夹是否可以包含消息和/或其他文件夹。
int getMode() 返回两个命名常量之一 Folder.READ_ONLY 或 Folder.READ_WRITE,如果模式未知,则返回 -1。
Store getStore()返回从中检索此文件夹的 Store 对象。
abstract char getSeparator()返回将此 Folder 的路径名与直接子文件夹名称分隔开的分隔符。

管理文件夹

以下是一些有助于管理文件夹的方法:

方法描述
abstract boolean create(int type)这将在此文件夹的存储中创建一个新文件夹。其中 type 为:Folder.HOLDS_MESSAGES 或 Folder.HOLDS_FOLDERS。如果文件夹创建成功,则返回 true,否则返回 false
abstract boolean delete(boolean recurse)仅当文件夹关闭时,才会删除文件夹。否则,它会抛出 IllegalStateException。如果 recursetrue,则删除子文件夹。
abstract boolean renameTo(Folder f)这会更改此文件夹的名称。必须关闭文件夹才能重命名。否则,将抛出 IllegalStateException。

管理文件夹中的消息

以下是一些有助于管理文件夹中消息的方法:

方法描述
abstract void appendMessages(Message[] messages)顾名思义,数组中的消息放在此文件夹的末尾。
void copyMessages(Message[] messages, Folder destination)这会将消息从此文件夹复制到指定的文件夹中,该文件夹以参数。
abstract Message[] expunge()要从文件夹中删除消息,请将其 Flags.Flag.DELETED 标志设置为 true。要从文件夹中物理删除已删除的邮件,您必须调用此方法。

列出文件夹的内容

有四种方法可以列出文件夹包含的文件夹:

方法说明
Folder[] list()这将返回一个数组,列出此文件夹包含的文件夹。
Folder[] listSubscribed()这将返回一个数组,列出此文件夹包含的所有订阅文件夹。
摘要Folder[] list(String pattern)该方法类似于 list() 方法,不同之处在于它允许您指定一个 模式。该模式是一个字符串,给出匹配文件夹的名称。
Folder[] listSubscribed(String pattern)该方法类似于 listSubscribed() 方法,不同之处在于它允许您指定一个模式。模式是一个字符串,给出匹配文件夹的名称。

检查邮件

方法描述
abstract int getMessageCount()可以在打开或关闭的文件夹上调用此方法。但是,如果文件夹已关闭,此方法可能会(也可能不会)返回 -1,以表明无法轻松获得确切的消息数量。
abstract boolean hasNewMessages()如果自上次打开文件夹以来,有新消息添加到文件夹中,则此方法返回 true
int getNewMessageCount()通过检查已设置 RECENT 标志的文件夹中的消息来返回新消息计数。
int getUnreadMessageCount()可以在打开或关闭的文件夹中调用此方法。但是,如果文件夹已关闭,则此方法可能会返回 -1,以表明获取真实答案的成本太高。

从文件夹获取消息

Folder 类提供了四种从打开的文件夹检索消息的方法:

方法说明
abstract Message getMessage(int messageNumber) 这将返回文件夹中的第 n 条消息。文件夹中的第一条消息是编号 1。
Message[] getMessages()这将返回一个 Message 对象数组,该数组表示此文件夹中的所有消息。
Message[] getMessages(int start, int end)这将返回文件夹中的 Message 对象数组,以 start 开始,以 end 结束(含)。
Message[] getMessages(int[] messageNumbers)这将返回一个数组,该数组仅包含 messageNumbers 数组中通过数字明确标识的那些消息。
void fetch(Message[] messages, FetchProfile fp)预取给定消息的 FetchProfile 中指定的项目。 FetchProfile 参数指定要预取邮件中的哪些标头。

搜索文件夹

如果服务器支持搜索(许多 IMAP 服务器支持搜索,而大多数 POP 服务器不支持),则可以轻松地在文件夹中搜索符合特定条件的邮件。这些条件编码在 SearchTerm 对象中。以下是两种搜索方法:

方法描述
Message[] search(SearchTerm term)在此文件夹中搜索符合指定搜索条件的邮件。返回包含匹配邮件的数组。如果未找到匹配项,则返回一个空数组。
Message[] search(SearchTerm term, Message[] messages)在给定的消息数组中搜索符合指定搜索条件的消息。返回包含匹配消息的数组。如果未找到匹配项,则返回一个空数组。指定的消息对象必须属于此文件夹。

标志

当您需要更改文件夹中整个消息集的标志时,标志修改非常有用。以下是 Folder 类中提供的方法:

方法说明
void setFlags(Message[] messages, Flags flag, boolean value)在数组中指定的消息上设置指定的标志。
void setFlags(int start, int end, Flags flag, boolean value)在从 start 到 end 编号的消息上设置指定的标志,包括 start 和 end。
void setFlags(int[] messageNumbers, Flags flag, boolean value)在消息编号位于数组中的消息上设置指定的标志。
abstract Flags getPermanentFlags()返回此文件夹支持的所有消息的标志。

JavaMail API - 配额管理

JavaMail 中的配额是电子邮件存储中有限或固定的消息数量。每个邮件服务请求都计入 JavaMail API 调用配额。电子邮件服务可以应用以下配额标准:

  • 发送邮件消息的最大大小,包括附件。

  • 接收邮件消息的最大大小,包括附件。

  • 管理员作为收件人时消息的最大大小

对于配额管理,JavaMail 具有以下类:

描述
public class Quota此类表示给定配额根的一组配额。每个配额根都有一组资源,由 Quota.Resource 类表示。每个资源都有一个名称(例如"STORAGE")、当前使用情况和使用限制。它只有一个方法 setResourceLimit(String name, long limit)
public static class Quota.Resource表示配额根中的单个资源。
public interface QuotaAwareStore由支持配额的 Stores 实现的接口。getQuotasetQuota 方法支持 IMAP QUOTA 扩展定义的配额模型。 GmailSSLStore、GmailStore、IMAPSSLStore、IMAPStore 是此接口的已知实现类。

让我们在以下部分中查看一个示例,该示例检查邮件存储名称、限制及其使用情况。

创建 Java 类

创建一个 Java 类文件 QuotaExample,其内容如下:

package com.tutorialspoint;

import java.util.Properties;

import javax.mail.Quota;
import javax.mail.Session;
import javax.mail.Store;

import com.sun.mail.imap.IMAPStore;

public class QuotaExample 
{
   public static void main(String[] args) 
   {
      try 
      {
         Properties properties = new Properties();
         properties.put("mail.store.protocol", "imaps");
         properties.put("mail.imaps.port", "993");
         properties.put("mail.imaps.starttls.enable", "true");
         Session emailSession = Session.getDefaultInstance(properties);
         // emailSession.setDebug(true);

         // 创建 IMAP3 存储对象并连接 pop 服务器
         Store store = emailSession.getStore("imaps");

         //相应地更改用户和密码
         store.connect("imap.gmail.com", "abc@gmail.com", "*****");
         IMAPStore imapStore = (IMAPStore) store;
         System.out.println("imapStore ---" + imapStore);

         //获取配额
         Quota[] quotas = imapStore.getQuota("INBOX");
         //遍历配额
         for (Quota quota : quotas) {
            System.out.println(String.format("quotaRoot:'%s'",
               quota.quotaRoot));
            //遍历配额资源
            for (Quota.Resource resource : quota.resources) {
               System.out.println(String.format(
                  "name:'%s', limit:'%s', usage:'%s'", resource.name,
                  resource.limit, resource.usage));
            }
         }
      } catch (Exception e) 
      {
         e.printStackTrace();
      }
   }
}

这里是通过 IMAP (imap.gmail.com) 服务器连接到 gmail 服务的,因为 IMAPStore 实现了 QuotaAwareStore。获取 Store 对象后,获取 Quota 数组并对其进行迭代,然后打印相关信息。

编译并运行

现在我们的类已准备就绪,让我们编译上述类。我已将 QuotaExample.java 类保存到目录:/home/manisha/JavaMailAPIExercise。我们需要类路径中的 jar javax.mail.jaractivation.jar。从命令提示符执行以下命令来编译类(两个 jar 都放在 /home/manisha/ 目录中):

javac -cp /home/manisha/activation.jar:/home/manisha/javax.mail.jar: QuotaExample.java

现在类已编译完毕,执行以下命令运行:

java -cp /home/manisha/activation.jar:/home/manisha/javax.mail.jar: QuotaExample

验证输出

您应该在命令控制台上看到类似的消息:

imapStore ---imaps://abc%40gmail.com@imap.gmail.com
quotaRoot:''
name:'STORAGE', limit:'15728640', usage:'513'

JavaMail API - 退回邮件

邮件可能因多种原因被退回。rfc1211 深入讨论了此问题。只有服务器才能确定特定邮箱或用户名是否存在。当服务器检测到错误时,它会向原始邮件的发件人返回一条消息,指出失败的原因。

有许多 Internet 标准涵盖了传递状态通知,但大量服务器不支持这些新标准,而是使用临时技术返回此类失败消息。因此,将退回消息与导致问题的原始消息关联起来变得非常困难。

JavaMail 包括对解析传递状态通知的支持。有许多技术和启发式方法可以处理此问题。其中一种技术是可变信封返回路径。您可以在信封中设置返回路径,如下例所示。这是退回邮件发送到的地址。您可能希望将其设置为通用地址,不同于 From: 标头,以便处理远程退回。这可以通过在 JavaMail 中设置 mail.smtp.from 属性来完成。

创建 Java 类

创建一个 Java 类文件 SendEmail,其内容如下:

import java.util.Properties;

import javax.mail.Message;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

public class SendEmail {
   public static void main(String[] args) throws Exception {
      String smtpServer = "smtp.gmail.com";
      int port = 587;
      final String userid = "youraddress";//相应改变
      final String password = "*****";//相应改变
      String contentType = "text/html";
      String subject = "test: bounce an email to a different address " +
				"from the sender";
      String from = "youraddress@gmail.com";
      String to = "bouncer@fauxmail.com";//一些无效的地址
      String bounceAddr = "toaddress@gmail.com";//相应改变
      String body = "Test: get message to bounce to a separate email address";

      Properties props = new Properties();

      props.put("mail.smtp.auth", "true");
      props.put("mail.smtp.starttls.enable", "true");
      props.put("mail.smtp.host", smtpServer);
      props.put("mail.smtp.port", "587");
      props.put("mail.transport.protocol", "smtp");
      props.put("mail.smtp.from", bounceAddr);

      Session mailSession = Session.getInstance(props,
         new javax.mail.Authenticator() {
            protected PasswordAuthentication getPasswordAuthentication() {
               return new PasswordAuthentication(userid, password);
            }
         });

      MimeMessage message = new MimeMessage(mailSession);
      message.addFrom(InternetAddress.parse(from));
      message.setRecipients(Message.RecipientType.TO, to);
      message.setSubject(subject);
      message.setContent(body, contentType);

      Transport transport = mailSession.getTransport();
      try {
         System.out.println("Sending ....");
         transport.connect(smtpServer, port, userid, password);
         transport.sendMessage(message,
            message.getRecipients(Message.RecipientType.TO));
         System.out.println("Sending done ...");
      } catch (Exception e) {
         System.err.println("Error Sending: ");
         e.printStackTrace();

      }
      transport.close();
   }// end function main()
}

在这里我们可以看到属性 mail.smtp.from 的设置与 from 地址不同。

编译并运行

现在我们的类已经准备好了,让我们编译上面的类。我已将类 SendEmail.java 保存到目录:/home/manisha/JavaMailAPIExercise。我们需要类路径中的 jar javax.mail.jaractivation.jar。从命令提示符执行以下命令来编译类(两个 jar 都放在 /home/manisha/ 目录中):

javac -cp /home/manisha/activation.jar:/home/manisha/javax.mail.jar: SendEmail.java

现在类已编译完毕,执行以下命令运行:

java -cp /home/manisha/activation.jar:/home/manisha/javax.mail.jar: SendEmail

验证输出

您应该在命令控制台上看到以下消息:

Sending ....
Sending done ...

SMTP 服务器

SMTP 是简单邮件传输协议的缩写。它是跨 Internet 协议 (IP) 网络传输电子邮件 (e-mail) 的 Internet 标准。SMTP 使用 TCP 端口 25。SSL 保护的 SMTP 连接简称为 SMTPS,尽管 SMTPS 本身不是一种协议。

JavaMail API 有包 com.sun.mail.smtp,它充当 SMTP 协议提供程序来访问 SMTP 服务器。下表列出了此包中包含的类:

描述
SMTPMessage此类是 MimeMessage 类的特化,允许您指定通过 SMTP 发送此消息时将使用的各种 SMTP 选项和参数。
SMTPSSLTransport此类使用 SMTP over SSL 实现 Transport 抽象类以进行消息提交和传输。
SMTPTransport此类使用 SMTP 实现 Transport 抽象类以进行消息提交和传输。

下表列出了抛出的异常:

异常描述
SMTPAddressFailedException当无法发送邮件时,会抛出此异常。
SMTPAddressSucceededExceptionmail.smtp.reportsuccess 属性为 true 时,会与 SendFailedException 关联。
SMTPSenderFailedException当无法发送邮件时,会抛出此异常。
SMTPSendFailedException当无法发送邮件时,会抛出此异常。异常包括发件人的地址,即邮件服务器拒绝。

com.sun.mail.smtp 提供程序可选择使用 SMTP 身份验证。要使用 SMTP 身份验证,您需要设置 mail.smtp.auth 属性,或在连接到 SMTP 服务器时为 SMTP 传输提供用户名和密码。您可以使用以下方法之一执行此操作:

  • 在创建邮件会话时提供 Authenticator 对象,并在 Authenticator 回调期间提供用户名和密码信息。可以设置 mail.smtp.user 属性以提供回调的默认用户名,但仍需要明确提供密码。此方法允许您使用静态 Transport 发送方法发送消息。例如:

  • Transport.send(message);
    
  • 使用用户名和密码参数显式调用 Transport connect 方法。例如:

    Transport tr = session.getTransport("smtp");
    tr.connect(smtphost, username, password);
    msg.saveChanges();
    tr.sendMessage(msg, msg.getAllRecipients());
    tr.close();
    

SMTP 协议提供程序支持以下属性,这些属性可在 JavaMail Session 对象中设置。这些属性始终设置为字符串。例如:

props.put("mail.smtp.port", "587");

IMAP 服务器

IMAP 是 Internet 消息访问协议 的缩写。它是一种应用层 Internet 协议,允许电子邮件客户端访问远程邮件服务器上的电子邮件。IMAP 服务器通常监听众所周知的端口 143。SSL 上的 IMAP (IMAPS) 被分配到端口号 993。

IMAP 支持在线和离线操作模式。使用 IMAP 的电子邮件客户端通常会将消息保留在服务器上,直到用户明确删除它们。

com.sun.mail.imap 是 JavaMail API 的 IMAP 协议提供程序,提供对 IMAP 消息存储的访问。下表列出了此提供程序的接口和类:

类/接口描述
IMAPFolder.ProtocolCommand这是用户定义的 IMAP 协议命令的简单接口
ACL这是一个类。特定身份验证标识符(用户或组)的访问控制列表条目。
IMAPFolder此类实现 IMAP 文件夹。
IMAPFolder.FetchProfileItem这是一个用于获取标头的类。
IMAPMessage此类实现 ReadableMime 对象。
IMAPMessage.FetchProfileCondition 此类实现对文件夹中每条消息进行的测试。
IMAPSSLStore此类提供对 SSL 上 IMAP 消息存储的访问。
IMAPStore此类提供对 IMAP 消息的访问存储。
Rights此类表示身份验证标识符(例如,用户或组)的权限集。
Rights.Right 此内部类表示个人权限。
SortTerm特定排序标准,由 RFC 5256 定义。

此提供程序上方需要注意的一些要点:

  • 此提供程序支持 IMAP4 和 IMAP4rev1 协议。

  • 连接的 IMAPStore 维护一个 IMAP 协议对象池,用于与 IMAP 服务器进行通信。当文件夹打开并需要新的 IMAP 协议对象时,IMAPStore 将从连接池中提供这些对象,如果没有可用的对象,则创建它们。当文件夹关闭时,如果池允许,则将其 IMAP 协议对象返回到连接池。

  • 连接的 IMAPStore 对象可能会或可能不会维护单独的 IMAP 协议对象,该对象为商店提供与 IMAP 服务器的专用连接。

POP3 服务器

邮局协议 (POP) 是一种应用层 Internet 标准协议,本地电子邮件客户端使用它通过 TCP/IP 连接从远程服务器检索电子邮件。POP 支持访问远程邮箱的简单下载和删除要求。POP3 服务器监听众所周知的端口 110。

com.sun.mail.pop3 是 JavaMail API 的 POP3 协议提供程序,提供对 POP3 消息存储的访问。下表列出了此包中的类:

名称说明
POP3FolderPOP3 文件夹(只能是"收件箱")。
POP3MessagePOP3 消息。
POP3SSLStore使用 SSL 的 POP3 消息存储。
POP3StorePOP3 消息存储。

此提供程序上方需要注意的一些要点:

  • POP3 提供程序仅支持单个名为 INBOX 的文件夹。由于 POP3 协议的限制,许多 JavaMail API 功能(如事件通知、文件夹管理、标志管理等)均不被允许。

  • 使用协议名称 pop3pop3://user:password@host:port/INBOX" 形式的 URL,可以通过 JavaMail API 访问 POP3 提供程序。

  • POP3 不支持永久标志。例如,永远不会为 POP3 消息设置 Flags.Flag.RECENT 标志。由应用程序确定 POP3 邮箱中的哪些消息是

  • POP3 不支持 Folder.expunge() 方法。要删除和清除消息,请在消息上设置 Flags.Flag.DELETED 标志,然后使用 Folder.close(true) 方法关闭文件夹。

  • POP3 不提供接收日期,因此 getReceivedDate 方法将返回 null。

  • 当访问 POP3 消息的标头时,POP3 提供程序使用 TOP 命令获取所有标头,然后缓存这些标头。

  • 当访问 POP3 消息的内容时,POP3 提供程序使用 RETR 命令获取整个消息。

  • 可以使用 POP3Message.invalidate 方法使缓存数据无效,而无需关闭文件夹。