JavaMail学习五 创建邮件内容

  • Post author:
  • Post category:java

1.基本原理:

JavaMail使用javax.mail.Message类来表示一封邮件,Message类是一个抽象类,应用程序需要使用其之类javax.mail.internet.MimeMessage来创建Message类的实例对象。如果要创建一封只包含文本内容的简单邮件,那么只需要使用到MimeMessage类就可以,但要创建一封包含内嵌资源或多个附件的复杂邮件时,那么则需要同时使用到JavaMailAPI中的MimeMessage,javax.mail.internet.MimeBodyPart和javax.mail.internet.MimeMultipart等类。

~~MimeMessage类表示整封邮件

~~MimeBodyPart类表示邮件的一个MIME消息

~~MimeMultipart类表示一个由多个MIME消息组合而成的组合MIME消息

 

这三个类的关系如下图所示:

 

 

 

 

1.复杂邮件和简单邮件一样的都是使用MimeMessage对象来表示整封邮件

2.对于复杂邮件的邮件体,不能在简单的调用MimeMessage.setText方法生成,而是要用一个MimeMultiPart对象来表示,并通过MimeMultiPart.setContent(MultiPar mp)方法设置到MimeMessage对象中。

3.MimeMultipart对象用来组合多个MIME消息,其中的每个MIME消息分别用一个MimeBodyPart对象来表示,并通过MimeMultipart.addBodyPart(BodyPart bp)方法加入到MimeMultipart对象中。

4.如果MimeBodyPart对象表示的MIME消息又是一个组合MIME消息,那么它的内容又需要使用一个MimeMultipart对象来表示,并通过MimeBodyPart.setContent(Multipart mp)

方法设置到MimeBodyPart对象中。与代表整封邮件的MimeMultipart对象一样,这个MimeMultipart对象中的每一个组成单元也可以分别由一个MimeBodyPart对象表示。

可见,不管邮件体中的数据层次关系如何复杂,我们都可以使用MimeBodyPart,MimeMultipart对象这种互相嵌套关系,来组织并且封装复杂邮件中的各个邮件数据。

 

2.与邮件内容相关的API类图:

虽然应用程序开发者在使用JavaMailAPI创建邮件内容时,通常只需要使用MimeMessage,MimeBodyPart和MimeMultipart这3个主要的类,但是了解他们的类继承关系也是必要的。下图列出了这三个类的继承关系以及常用方法。

 

 

从上图可以看出一些信息来:

1.MimeMessage类和MimeBodyPart类都实现了part接口,part接口代表了一个具体的MIME消息,它定义了一系列用于设置和获取消息头信息和消息体数据的方法,例如图中的setHeader,setContent方法分别用于设置消息头和消息体,getHeader和getContent分别用于获取消息头和消息体

2.MimeMessage类还继承了Message抽象类,Message类在Part接口的基础上增加了多个描述邮件信息的方法,例如setFrom和setSubject方法,分别用于设置邮件的发送人和邮件的主题。

3.MimeMultipart类用来组合多个MIME消息,它继承了抽象类MultiPart,MultiPart类中定义了addBodyPart和getBodyPart等方法,用于完成对MIME组合消息的相关操作。

 

3.InternetAddress类:

javax.mail.internet.InternetAddress类用于表示电子邮件的地址,邮件中的发件人和收件人地址都是用这个类表示的,下面是InternetAddress中常用的方法:

3.1构造函数:

InternetAddress类的构造函数有两种常用的重载形式,它们的语法定义如下:

~~public InternetAddress();

~~public InternetAddress(java.lang.String address)

第一个构造函数为类缺省的构造函数, 用这个构造函数创建的InternetAddress对象需要使用setAddress方法来设置邮件地址,第二个构造函数直接使用一个代表邮件地址的字符串创建InternetAddress类的实例对象。

3.2.getAddress方法:

getAddress方法的语法定义如下:

public java.lang.String  getAddress()

getAddress方法以字符串形式返回InternetAddress对象中定义的邮件地址。

3.3 parse方法

parse方法是一个静态方法,它的语义定义如下,

public static InternetAddress[] parse(public java.lang.String addressList)

parse方法以“,”号为解析分隔符,解析由多个邮件地址组成的字符串,并把解析出来的邮件地址保存到一个InternetAddress类型的数组对象中,参数addressList表示有多个邮件地址组成,并用“,”作为其分隔符的字符串。

 

3.4  MimeMessage类:

javax.mail.internet.MimeMessage类表示一封MIME邮件,它继承了抽象类Message并实现了MimePart接口。MimeMessage类不仅实现了顶层Part接口中定义的方法,它还从Message类中继承了多个setXX和getXX方法,这些方法用于设置和获取整封邮件中的邮件头字段,

 1.Message.RecipientType内部类:

Message.RecipientType类表示收件人的类型,它是Message类中的一个静态内部类。Message.RecipientType类中定义了如下三个变量:

~~TO代表邮件的主要接受者

~~CC代表邮件的抄送接收者

~~BCC代表邮件的暗送接受者

Message.RecipientType类中定义了TO,CC,BCC等三个常量的类型就是Message.RecipientType,这种应用于java.awt.Color类中定义的BLACK,BLUE常量相似,Color类中定义的BLACK,BLUE等常量的类型就是Color.

 

2.MimeMessage类的构造函数:

MimeMessage类的构造函数有多中重载形式,其中与创建新邮件相关的构造函数有两种重载形式,它们的语法定义如下:

~~public MimeMessage(Session session)

~~public MimeMessage(Session session,java.io.InputStream is)

第一个MimeMessage构造函数需要一个Session对象作为参数,JavaMail中定义的Session对象用于收集客户端与邮件服务器之间网络连接信息和定义整个邮件程序所需要的环境信息,这些信息作为Session对象的属性保存在Session对象中,例如,Seesion对象的“mail.smtp.host‘属性表示SMTP服务器的主机名,“mail.user”表示邮件用户等。第二个MimeMessage构造函数除了需要一个Session对象作为参数以外,它还接受一个InputStream类型的输入流对象,第二个MimeMessage构造函数创建的MimeMessage对象将从这个输入流对象中整封邮件的内容。

3.setFrom方法:

setFrom方法用于设置MimeMessage对象中的发件人地址,它有两种重载形式,它们的语法定义如下:

~~public  abstract  void setFrom();

~~public abstract  void setFrom(Address address);

第一个方法使用Session对象中的“mail.user”属性值来设置MimeMessage对象的from字段,第二个方法用于指定address对象来设置MimeMessage对象的from字段。

 

4.setRecipient与setRecipients方法:

setRecipient和setRecipients方法分别用于设置一个和一组收件人的地址,它们的语法定义如下:

~~public void setRecipient(Message.RecipientType type , Address address);

~~public abstract void setRecipients(Message.RecipientType type,Address[] address);

这两个方法的第一个参数都是type,用于指定收件人的类型,setRecipient方法的第二个参数用于指定一个收件人的地址,setRecipients方法的第二个参数address是一个数组,可以通过这个数组来指定多个收件人的地址,使用setRecipient和setRecipients方法设置收件人的地址时,设置的新地址将代替MimeMessage对象中原有的相同类型的地址。

 

5.addRecipient与addRecipients方法:

addRecipient和addRecipients方法分别用于增加一个和一组收件人的地址,他们的语法定义如下:

~~public void addRecipient(Message.RecipientType type , Address address);

~~public abstract void addRecipients(Message.RecipientType type,Address[] address);

使用addRecipient和addRecipients设置收件人地址时,设置的新地址将会追加到MimeMessage对象中的原有相同类型的地址上,而不是替代原有的相同类型的地址

 

6.setSendDate方法:

setSendDate方法用于设置MimeMessage对象中的邮件发送日期,它的语义如下:

~~public abstract void  setSendDate(java.util.Date date);

7.setSubject方法:

setSubject方法用于设置MimeMessage对象中的邮件主题,他有两种重载形式,他们的语法定义如下:

~~public void serSubject(java.lang.String subject);

~~public void serSubject(java.lang.String subject,java.lang.String charset);

如果邮件中含有非ASCII码的字符,那么在subject头字段中需要对邮件主题的原始内容进行BASE64和Quote-printable编码,BASE64或Quote-printable编码并不是对字符进行编码,而是对代表字符的某种字符集数据进行编码,由于同一个字符存在着多种字符集,因此在BASE64和Quote-printable编码时需要指定对字符的哪种字符集进行编码。第一个方法选择操作系统的缺省字符集,第二个方法可以让编程人员指定编码的字符集信息。

 

8.addHeader和setHeader方法:

addHeader和setHeader方法用于设置当前MIME消息的某个消息头信息,他们的语法定义如下:

~~public void addHeader(java.lang.String name,java.lang.String value);

~~public void setHeader(java.lang.String name,java.lang.String value);

其中参数name为要设置的消息头字段的名称,value为要设置的消息头字段的值

只是对于已经存在的某个名称的消息头,addHeader方法是在原有设置值的基础上加上新值,而setHeader方法则是使用新值代替原来的设置值,前面讲解的setFrom,setRecipient,和addRecipient,setSendDate,setSubject等方法内部都在调用addHeader和setHeader方法,他们是针对特定的头字段而对addHeader和setHeader方法调用提供的一种简化手段。

9.setContent方法:

setContent方法用于设置MimeMessage对象的邮件体,他有两种重载形式,他们的语法定义如下:

~~public void setContent(java.lang.Object obj,java.lang.String type);

~~public void setContent(Multipart mp);

这两个方法都是从part接口中继承过来的,第一个方法设置一个指定MIME类型java对象作为MimeMessage对象的邮件体,这个对象必须能为指定的MIME类型的数据处理器处理,读者只有熟悉JAF的有关知识,才能理解这个方法的使用,第二个方法设置一个Multipart类型的对象作为MimeMessage对象的邮件体,也就是将邮件体设置为主类型为“multipart”的某种MIME组合消息。

10.setText方法:

setText方法用于将MIME消息体设置为一个简单的纯文本内容,他的语法定义如下:

~~public void setText(java.lang.String text);

参数text用于指定作为消息体内容的字符串,这个方法也自动将消息体的MIME类型设置为“text/plain”。

11.setFlag方法:

setFlag方法主要用于在邮件接收程序中,它用于为邮件设置一个邮件标记,例如删除标记,已读标记。它的语法定义如下:

~~public void setFlag(Flags.Flag flag,boolean set);

参数flag表示设置的标记类别,它的类型为Flags.Flag,Flags.Flag是一个表示邮件标记的内部类,这个内部类定义了6个常量来表示6中不同的标记,例如后面表示删除标记的常量为Flags.Flag.DELETE,表示已读标记的常量为Flags.Flag.SEEN.参数set为“true”时表示设置邮件的指定标记,为“false”时表示清除邮件上的指定标记。

12.saveChanges方法:

saveChanges方法用于更新并保存MimeMessage对象中的数据,它的语法定义如下:

~~public abstract void saveChanges();

邮件发送程序发送MimeMessage对象中封装的邮件内容前,通常需要调用这个方法,以便根据MimeMessage对象中保存的信息生成最终的邮件内容。如果修改了这个MimeMessage对象中的内容,也需要注意调用saveChanges方法以便修改生效。

13.writeTo方法:

writeTo方法用于把MimeMessage对象中的数据输出到一个RFC822格式的输出流中,它有两种重载形式,它的语法定义如下:

~~public void writeTo(OutputStream os);

~~public void writeTo(OutputStream os,String[]  ingoreList);

第二个方法的第二个参数用于指定输出时忽略那些消息头字段。

 

下面我们来利用上面的理论知识来创建一个简单的纯文本邮件:

package com.jt.mail;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Date;
import java.util.Properties;

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

/**
 * @author jt
 *2016-1-11 下午7:07:21
 *创建简单的纯文本邮件
 */
public class TextMessage {

 
 
 /**
  * @param args
  * @throws MessagingException
  * @throws IOException
  * @throws FileNotFoundException
  */
 public static void main(String[] args) throws MessagingException, FileNotFoundException, IOException {
  //定义邮件的发送人,收件人,邮件主题和邮件正文
  String from=”发件人的邮件地址”;
  String to=”收件人的邮件地址”;
  String subject=”text”;
  String body=”text!!!”;
  
  //创建Session实例对象
  Session session=Session.getDefaultInstance(new Properties());
  //创建MimeMessage实例对象
  MimeMessage msg=new MimeMessage(session);
  //设置发件人
  msg.setFrom(new InternetAddress(from));
  //设置收件人
  msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse(to));
  //设置发送日期
  msg.setSentDate(new Date());
  //设置邮件主题
  msg.setSubject(subject);
  //设置邮件正文
  msg.setText(body);
  //保存最终生成的邮件内容
  msg.saveChanges();
  //把邮件内容写入到文件中
  msg.writeTo(new FileOutputStream(“E://test.eml”));
 }

}

 

创建HTML格式的邮件:

package com.jt.mail;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Date;
import java.util.Properties;

import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMessage.RecipientType;

/**
 * @author jt
 *2016-1-11 下午7:40:41
 *创建html格式的邮件
 */
public class HTMLMessage {

 /**
  * @param args
  * @throws MessagingException
  * @throws IOException
  * @throws FileNotFoundException
  */
 public static void main(String[] args) throws MessagingException, FileNotFoundException, IOException {
  String from=”发件人邮件地址”;
  String to=”收件人邮件地址”;
  String subject=”textHTML”;
  String body=”<h4>欢迎大家阅读我的邮件</h4>”+”<img src=’E:\\我的照片\\桂林\\aff\\jt.jpg’>”;
  
  //创建Session对象
  Session session=Session.getDefaultInstance(new Properties());
  //创建MimeMessage实例对象
  MimeMessage msg=new MimeMessage(session);
  //设置发件人
  msg.setFrom(new InternetAddress(from));
  //设置收件热
  msg.setRecipient(Message.RecipientType.TO, new InternetAddress(to));
  //设置发送邮件日期
  msg.setSentDate(new Date());
  //设置邮件主题
  msg.setSubject(subject);
  //设置邮件体
  msg.setContent(body,”text/html;charset=gb2312;”);
  //保存邮件
  msg.saveChanges();
  //将邮件写入文件中
  msg.writeTo(new FileOutputStream(“E://htmlTest.eml”));
 }

}

扩展怎么判断邮件是否被阅读?

由于HTML文档中引用的图片可以通过一个Web服务器端程序动态创建,因此,在HTML邮件正文中使用<img src=””>标签引用图片时,可以故意让标签的src属性指向一个用于记录访问者IP地址或者统计邮件被阅读次数的Web服务器。这样,当邮件的接受者使用邮件阅读程序阅读该邮件时,只要用户接受邮件正文中的图像引用,邮件阅读程序就会去访问<img src=””>标签中的src属性指向的Web服务器程序,在Web服务器程序中可以得知邮件已经被收件人阅读,并可进一步完成更多的功能。例如,记录邮件阅读者的IP地址,收集有效的邮件地址,统计群发邮件被阅读的次数,等等。关于如何让HTML文档中的<img src=””>标签中的src属性指向一个Web服务器程序的应用,请参看《深入体验javaWeb开发内幕–核心基础》一书中的5.6.5节“图像访问计数器的讲解”。

可见在HTMlL格式的邮件正文中使用一些特殊的HTML标签,可以是邮件完成一些特殊的功能。正因为如此,现在大多数的邮件阅读程序都屏蔽了这些特殊的HTML标签,例如在HTML格式的邮件中使用<link>标签应用外部的css文件就是一种无效行为。

 

 

7.MimeBodyPart类:ji

javax.mail.internet.MimeBodyPart类表示MIME邮件中的一个MIME消息,MimeBodyPart类和MimeMessage类一样,都实现了Part接口,它们都具有Part接口定义的方法。

7.1 构造函数:

MimeBodyPart类的构造函数有两种重载形式,它们的语法定义如下:

~~public MimeBodyPart();

~~public MimeBodyPart(java.io.InputStream  is);

第一个方法为MimeBodyPart类缺省的构造函数,第二个方法为从指定的输入流中读取数据,并使读取到的数据填充MimeBodyPart实例对象。

7.2 setDateHeader方法:

setDateHeader方法用于当前的MimeBodyPart对象设置一个DateHeader对象,MimeBodyPart对象在生成具体的MIME消息时,将调用DateHeader对象的方法获取所需的数据信息,setDateHeader的语法定义如下:

~~public void setDateHeader(javax.activation.DateHeader dh);

DateHeader是JAF中定义的一个类,它是一种数据访问接口,它可以读取各种数据源中的数据和返回数据源的MIME类型。

7.3setContentID方法:

setContentID方法用于设置消息头中的Content-ID头字段,它的语法定义如下:

~~public void setContentID(java.lang.String cid);

其中参数cid表示当前MIME消息指定的唯一标识号,即Content-ID头字段的值。

7.4  setDisposition方法:

setDisposition方法用于设置消息头中的Content-Disposition头字段,如果当前MIME消息作为邮件中的附件部分,那么就可以使用这个方法来进行设置。setDisposition方法的语法定义如下:

~~public void  setDisposition(java.lang.String disposition);

其中参数disposition为Content-Disposition头字段的值。

7.5 setFileName方法:

如果当前的MIME方法可以关联一个文件名,则可以使用setFileName方法来指定该文件名,setFileName的语法定义如下:

~~public void setFileName(java.lang.String filename);

setFileName方法通常由于设置邮件的附件名,即用于设置Content-Disposition头字段中的filename参数,如果没有提前设置Content-Disposition头字段,setFileName方法会自动生成相应的Content-Disposition头字段。

 

8.MimeMultipart类:

javax.mail.internet.MimeMultipart是抽象类Multipart的实现子类,它用来组合多个MIME消息,一个MimeMultipart实例对象代表一个主类型为multipart的组合MIME消息,其中可以保存多个代表MIME消息的MimeBodyPart对象。

8.1  构造函数:

MimeMultipart类有两种重载形式的构造函数,它们的语法定义如下:

~~public MimeMultipart();

~~public MimeMultipart(java.lang.String subtype);

第一个方法是MimeMultipart类的缺省函数,其实例对象的MIME类型为“multipart/mixed”,即该MimeMultipart对象代表的组合MIME消息的“Content-Type”属性值为“multipart/mixed”,第二个构造方法指定“multipart”的一个子类型来创建MimeMultipart类的实例对象。“multipart”有三中常用的子类型:“mixed”,”related”,”alternative”

8.2 addBodyPart方法:

addBodyPart方法有两种重载形式,它们的语法定义如下:

~~public void addBodyPart(BodyPart part);

~~public void addBodyPart(BodyPart part,int index);

第一个方法增加一个BodyPart对象到MimeMultipart对象中,新增的BodyPart对象位于MimeMultipart对象中原有的BodyPart对象列表的尾部。第二个方法将一个BodyPart对象增加到MimeMultipart对象中,参数index指定了该BodyPart对象插入到MimeMultipart对象中的原有BodyPart对象列表位置。

8.3 setSubType方法:

setSubType方法用于设置MimeMultipart对象的Content-Type属性的MIME子类型,该方法的语法定义如下:

~~setSubType(java.lang.String subType);

MimeMultipart对象对应的MIME消息的主类型固定为“multipat”,子类型有“mixed”,”related”,”alternative”三种。

8.4 getContentType方法:

getContentType方法由于返回MimeMultipart对象的Content-Type属性,它的语义定义如下:

~~public java.lang.String getContentType();

8.5 getBodyPart方法:

getBodyPart方法返回MimeMultipart对象中的某个BodyPart对象,它有两种重载形式:

~~public BodyPart  getBodyPart(int index);

~~public BodyPart  getBodyPart(java.lang.String CID);

第一个返回MimeMultipart对象中的位于某个位置的BodyPart 对象,第二个方法返回MimeMultipart对象中的具有某个指定的Content-ID头字段值的BodyPart 对象,即返回的BodyPart 对象的Content-ID头字段值和指定CID相同。

8.6  getContent方法:

getContent方法用于返回MimeMultipart对象中保存的BodyPart 对象的个数,它的语法定义如下:

~~public int getCount();

 

9.创建复杂的邮件体:

package com.jt.mail;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Date;
import java.util.Properties;

import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMessage.RecipientType;
import javax.mail.internet.MimeMultipart;

/**
 * @author jt
 *2016-1-11 下午10:00:31
 *创建内嵌图片的复杂的邮件
 */
public class PictureMessage {

 /**
  * @param args
  * @throws MessagingException
  * @throws AddressException
  * @throws IOException
  * @throws FileNotFoundException
  */
 public static void main(String[] args) throws AddressException, MessagingException, FileNotFoundException, IOException {
  //定义邮件的属性,如发件人,收件人,邮件主题,邮件日期
  String from=”651101060@qq.com“;
  String to=”jiangtao7913@sina.com“;
  String subject=”HTML邮件”;
  String body=”<a href=’http://www.baidu.com’>”
  +”欢迎大家来我们的网站”+”</a><br/>”
  +”<img src=\”cid:1\”>”;
  
  //创建Session对象
  Session session=Session.getDefaultInstance(new Properties());
  //创建MimeMessage对象
  MimeMessage msg=new MimeMessage(session);
  //设置邮件发送人
  msg.setFrom(new InternetAddress(from));
  //设置邮件收件人
  msg.setRecipient(Message.RecipientType.TO, new InternetAddress(to));
  //设置邮件日期
  msg.setSentDate(new Date());
  //设置邮件主题
  msg.setSubject(subject);
  //创建一个子类型为“related”的MimeMultipart对象
  MimeMultipart multipart=new MimeMultipart(“related”);
  //创建一个表示HTML正文的MimeBodyMultipart对象,并将它加入到MimeMultipart对象中
  MimeBodyPart htmlMultipart=new MimeBodyPart();
  htmlMultipart.setContent(body,”text/html;charset=gb2312;”);
  multipart.addBodyPart(htmlMultipart);
  
  //创建一个图片内容的MimeBodyPart对象,并将他们加入到前面创建的MimeMultipart中
  MimeBodyPart gifMultipart=new MimeBodyPart();
  FileDataSource fds=new FileDataSource(“E:\\我的照片\\桂林\\aff\\jt.jpg“);
  gifMultipart.setDataHandler(new DataHandler(fds));
  gifMultipart.setContentID(“1”);
  multipart.addBodyPart(gifMultipart);
  //将MimeMultipart对象设置为整个邮件的内容,要注意saveChanges进行更新
  msg.setContent(multipart);
  msg.saveChanges();
  
  //把文件写入到文件中
  msg.writeTo(new FileOutputStream(“E://pic.eml”));
  
 }

}

 

10.创建包含图片和附件的邮件

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


版权声明:本文为jiangtao7913原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。