使用Java发送MIME电子邮件

MIME介绍详见:https://www.w3school.com.cn/media/media_mimeref.asp

通过Java发送电子邮件需要导入如下包:

javax-mail.jar:https://mvnrepository.com/artifact/javax.mail/mail/1.4.7

以下通过QQ邮箱进行演示:

发送纯文本消息

  1. 创建Properties文件,配置协议、地址、端口、SSL认证
  2. 创建session对象
  3. 创建邮件消息对象
  4. 设置发件人、标题、正文、收件人、抄送人、密送人、发件时间
  5. 获取连接对象,并使用发件人账号与邮箱服务器建立连接
  6. 发送邮件
/**
    * 创建邮件方法
    * @param session javax.mail.session对象
    * @param sender 发件人地址
    * @param receive 收件人地址
    * @param cReceive 抄送人
    * @param bReceive 密送人
    * @return
    */
public static MimeMessage createMIMEMessage(Session session,String sender,
        String receive,String cReceive,String bReceive) {
    MimeMessage message = new MimeMessage(session);
    try {
        // 标题、正文、发件人、收件人
        message.setSubject("Title","UTF-8");// 标题、标题编码
        Address addr = new InternetAddress(sender,"Hero","UTF-8");// 构建发件人对象
        message.setFrom(addr);// 设置发件人
        message.setContent("Hello World", "text/html;charset=utf-8");// 设置正文内容
        /**
            * 设置收件人
            * 收件人:MimeMessage.RecipientType.TO
            * 抄送:MimeMessage.RecipientType.CC
            * 密送:MimeMessage.RecipientType.BCC
            */
        message.setRecipient(MimeMessage.RecipientType.TO, 
                new InternetAddress(receive,"A","UTF-8"));// 收件人
        message.setRecipient(MimeMessage.RecipientType.CC, 
                new InternetAddress(cReceive,"B","UTF-8"));// 抄送人
        message.setRecipient(MimeMessage.RecipientType.BCC, 
                new InternetAddress(bReceive,"C","UTF-8"));// 密送人
        message.setSentDate(new Date());// 设置发件时间
        message.saveChanges();// 保存邮件
    } catch (Exception e) {
        e.printStackTrace();
    }
    return message;
}
public static void main(String[] args) {
    Properties props = new Properties();
    props.setProperty("mail.transport.protocol", "smtp");// 使用协议:smtp
    props.setProperty("mail.smtp.host", "smtp.qq.com");// 协议地址
    props.setProperty("mail.smtp.port", "465");// 协议端口
    
    props.setProperty("mail.smtp.auth", "true");// 开启授权(QQ邮箱)
    // QQ开启SSL安全认证
    props.setProperty("mail.smtp.socketFactory.class", 
            "javax.net.ssl.SSLSocketFactory");// 配置SSL认证类
    props.setProperty("mail.smtp.socketFactory.fallback",
            "false");// 是否处理非SSL认证请求
    props.setProperty("mail.smtp.socketFactory.port", 
            "465");// 配置SSL认证端口
    Session session = Session.getInstance(props);// 产生session对象
    session.setDebug(true);
    // 创建邮件对象
    MimeMessage message = createMIMEMessage(session, "邮箱1", "邮箱2", "邮箱3", "邮箱4");
    try {
        Transport transport = session.getTransport();// 创建连接对象
        transport.connect("用户名", "授权码");// 建立连接(用户名、授权码)
        transport.sendMessage(message, message.getAllRecipients());
        transport.close();// 发送完毕关闭连接对象
    } catch (Exception e) {
        e.printStackTrace();
    }
}

发送带附件邮件

邮件内容都是由单节点MimeBodyPart构成,通过将这些单节点组合成复合节点MimeMultipart从而实现附件操作。

实现步骤:

  1. 创建纯文本子节点(构造正文)
  2. 创建内嵌资源子节点(构造正文)
  3. 将正文子节点合并为复合节点(合并正文子节点)
  4. 将复合对象转换为子节点(正文只有拆分为子节点才能传输)
  5. 创建附件子节点
  6. 将正文子节点与附件子节点合并为复合节点
  7. 将合并后的复合节点内容作为邮件内容发送

代码实现:

由于邮件需要配置的信息较多,这里使用一个对象Mail来承载邮件配置信息。

private String subject;// 邮件标题
private String senderMail;// 发件人邮箱
private String senderName;// 发件人名字
private String content;// 正文内容
private String sourcePath;// 内嵌资源路径
private String attachPath;// 附件路径
private String rReceive;// 收件人邮箱
private String ccReceive;// 抄送人邮箱
private String bccReceive;// 密送人邮箱

public Mail() {
    super();
}

// 只有收件人的构造方法
public Mail(String subject, String senderMail, String senderName, String content, String sourcePath,
        String attachPath, String rReceive) {
    super();
    this.subject = subject;
    this.senderMail = senderMail;
    this.senderName = senderName;
    this.content = content;
    this.sourcePath = sourcePath;
    this.attachPath = attachPath;
    this.rReceive = rReceive;
}

public Mail(String subject, String senderMail, String senderName, String content, String sourcePath,
        String attachPath, String rReceive, String ccReceive, String bccReceive) {
    super();
    this.subject = subject;
    this.senderMail = senderMail;
    this.senderName = senderName;
    this.content = content;
    this.sourcePath = sourcePath;
    this.attachPath = attachPath;
    this.rReceive = rReceive;
    this.ccReceive = ccReceive;
    this.bccReceive = bccReceive;
}
// 省略getter and setter
/**
    * 创建复杂邮件方法
    * @param session javax.mail.Session对象
    * @param sender 发件人
    * @param rReceive 收件人
    * @return MimeMessage
    */
public static MimeMessage createCompMail(Session session,Mail mail) {
    MimeMessage message = new MimeMessage(session);// 构建邮件对象
    try {
        message.setSubject("Multipart Mail","UTF-8");// 标题
        Address addr = new InternetAddress(mail.getSenderMail(),mail.getSenderName(),"UTF-8");
        message.setFrom(addr);// 发件人
        // 生成正文内容
        MimeBodyPart contentPart = createContent(
                mail.getContent(), mail.getSourcePath());
        // 创建附件节点
        MimeBodyPart attachmentPart = createAttachment(mail.getAttachPath());
        // 将附件与正文关联
        MimeMultipart part = new MimeMultipart();
        part.addBodyPart(contentPart);
        part.addBodyPart(attachmentPart);
        /**
            * Content-Type中MIME子类型
            *  附件:mixed
            *  内嵌资源:related
            *  超文本:alternative
            */
        part.setSubType("mixed");// 设置边界标识(附件与正文)
        
        message.setContent(part,"text/html;charset=utf-8");// 邮件内容
        message.setRecipient(MimeMessage.RecipientType.TO, new InternetAddress(mail.getrReceive(),"UTF-8"));// 收件人
        // 判断抄送人是否填写
        if(mail.getCcReceive() != null && mail.getCcReceive() != "") {
            message.setRecipient(MimeMessage.RecipientType.CC, new InternetAddress(mail.getCcReceive(),"UTF-8"));// 抄送人
        }
        // 判断密送人是否填写
        if(mail.getBccReceive() != null && mail.getBccReceive() != "") {
            message.setRecipient(MimeMessage.RecipientType.BCC, new InternetAddress(mail.getBccReceive(),"UTF-8"));// 密送人
        }
        message.setSentDate(new Date());// 发件时间
        message.saveChanges();// 保存邮件内容
    } catch (Exception e) {
        e.printStackTrace();
    }
    return message;
}
/**
    * 创建正文内容方法
    * @param str 正文内容
    * @return MimeBodyPart
    */
public static MimeBodyPart createContent(String str) {
    MimeBodyPart part = new MimeBodyPart();
    try {
        part.setContent(str, "text/html;charset=utf-8");
    } catch (Exception e) {
        e.printStackTrace();
    }
    return part;
}
/**
    * 创建正文内容方法
    * @param str 文本内容
    * @param source 图片路径
    * @return MimeBodyPart
    */
public static MimeBodyPart createContent(String str,String source) {
    MimeBodyPart part = null;
    String uuid = UUID.randomUUID().toString().replace("-", "").toLowerCase();// 生成UUID
    try {
        // 加载内嵌资源节点
        MimeBodyPart sourcePart = new MimeBodyPart();
        DataHandler dh = new DataHandler(new FileDataSource(source));
        sourcePart.setDataHandler(dh);
        sourcePart.setContentID(uuid);
        // 加载正文内容节点
        MimeBodyPart contentPart = new MimeBodyPart();
        contentPart.setContent(str + "<img src=cid:" + uuid + "/>", "text/html;charset=utf-8");
        // 构造复合对象
        MimeMultipart multiplePart = new MimeMultipart();
        multiplePart.setSubType("related");// 设置分界标识
        multiplePart.addBodyPart(sourcePart);
        multiplePart.addBodyPart(contentPart);
        // 将复合节点转换为子节点
        part = new MimeBodyPart();
        part.setContent(multiplePart);
    } catch (Exception e) {
        e.printStackTrace();
    }
    return part;
}
/**
    * 创建附件内容方法
    * @param filePath 附件文件路径
    * @return MimeBodyPart
    */
public static MimeBodyPart createAttachment(String filePath) {
    MimeBodyPart attachmentPart = new MimeBodyPart();
    DataHandler handler = new DataHandler(new FileDataSource(filePath));
    try {
        attachmentPart.setDataHandler(handler);// 加载附件文件
        attachmentPart.setFileName(handler.getName());// 设置附件文件名称
    } catch (Exception e) {
        e.printStackTrace();
    }
    return attachmentPart;
}
/**
    * 配置Properties对象方法
    * @return
    */
public static Properties configProps() {
    Properties props = new Properties();
    props.setProperty("mail.transport.protocol", "smtp");// 使用协议:smtp
    props.setProperty("mail.smtp.host", "smtp.qq.com");// 协议地址
    props.setProperty("mail.smtp.port", "465");// 协议端口

    props.setProperty("mail.smtp.auth", "true");// 开启授权(QQ邮箱)
    // QQ开启SSL安全认证
    props.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");// 配置SSL认证类
    props.setProperty("mail.smtp.socketFactory.fallback", "false");// 是否处理非SSL认证请求
    props.setProperty("mail.smtp.socketFactory.port", "465");// 配置SSL认证端口
    return props;
}
public static void main(String[] args) {
    Properties props = configProps();// 创建配置文件
    Session session = Session.getInstance(props);// 创建Session对象
    session.setDebug(true);// 开启邮件debug
    Mail mail = new Mail();
    mail.setSubject("Hello World");// 邮件标题
    mail.setSenderName("Mystery Man");// 发件人名字
    mail.setSenderMail("xxx@qq.com");// 发件人邮箱
    mail.setContent("<h1>这是正文内容,这是一个网址:https://www.baidu.com,这是我的LOGO:</h1>");// 正文文本内容
    mail.setSourcePath("src/icon.png");// 正文内嵌资源
    mail.setAttachPath("src/icon.png");// 附件
    mail.setrReceive("xxx@qq.com");// 收件人
    mail.setCcReceive("xxx@qq.com");// 抄送人
    mail.setBccReceive("xxx@qq.com");// 密送人
    MimeMessage message = createCompMail(session,mail);
    try {
        Transport transport = session.getTransport();// 获取连接对象
        transport.connect("xxx@qq.com", "xxx");// 通过用户名、授权码
        transport.sendMessage(message, message.getAllRecipients());
        transport.close();// 关闭连接
    } catch (Exception e) {
        e.printStackTrace();
    }
}

注意:

在正文中显示的内容需要将复合节点MimeMultipart组装成单节点MimeBodyPart,否则,不需要将复合节点MimeMultipart组装成单节点MimeBodyPart

加载内嵌资源时需要通过DataHandler加载内嵌资源,并设置ContentID。该内嵌资源作为图片引用时,src路径设置为以下格式:cid:ContentID,如果内嵌图片资源无法加载,请检查src路径是否设置正确。

加载附件资源时需要通过DataHandler加载附件资源,并设置FileName。

以上并不完善,邮件中可能会包含多个内嵌资源、多个附件,这里只是演示包含单个内嵌资源及附件的情况。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值