线程池异步发送邮件之MimeMessageHelper邮件发送支持自定义发送人/图片/附件/多个接收人/抄送人/暗送人

    项目中要发送邮件,写个工具类,小项目,并发量不高,但是要求:

    1.发件人是163邮箱或qq邮箱

    2.支持多个接收人/抄送人/暗送人

    3.支持正文中放图片

    4.支持附件

    5.线程池异步处理

    6.发送异常时,调用开发员自定义的异常处理类

    使用原生的java的mail.jar的API开发,需要自己调用组装很多API,MimeMessageHelper帮助类进行简化了很多步骤,用起来挺不错的。由于项目使用了spring boot,所以在pom.xml中只需添加

         
			org.springframework.boot
			spring-boot-starter-mail
		

即可。

  因为邮件发送有时耗时较长,所以代码中使用了线程池异步发送。下面先贴代码,再说需要注意的事项。

 异常接口,当邮件发送失败,需要做额外处理时,开发员实现该接口。

package com.nanhe.building.util;

import com.alibaba.fastjson.JSONObject;

/**
 * 邮件发送异常处理
 * @author Jfei
 *
 */
public interface MailSendExceptionHandler {

	/**
	 * 当邮件发送出现异常时,调用此方法
	 * @param e  异常类
	 * @param params  调用邮件工具类发送是传的参数,便于日志记录跟踪
	 */
	void doForException(Exception e,JSONObject params);
}

 工具类

package com.nanhe.building.util;

import java.io.File;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeUtility;

import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;

import com.alibaba.fastjson.JSONObject;

/**
 * 邮件发送(注意发送人的邮箱必须设置开通POP3/SMTP/IMAP,否则无法发送)
 * @author Jfei
 *
 */
public class MailUtil {
    /**
     * 线程池,最多同时3个线程在运行,其他的排队等候
     */
	private static ExecutorService executor = Executors.newFixedThreadPool(3);
	
	/**
	 *  发送邮件(注意发送人的邮箱必须设置开通POP3/SMTP/IMAP,否则无法发送)
	 * @param sendUserAccount 发送人email账号(163或者qq邮箱) (必填)
	 * @param sendUserPassword 发送人email的授权码(必填)
	 * @param sendUserNickName 发送人的昵称
	 * @param receiveUsers 接收人 (必填)
	 * @param copyUsers  抄送人
	 * @param darkUsers  暗送人
	 * @param title 标题 (必填)
	 * @param text 文本
	 * @param bodyImgs 正文图片
	 * @param attachDocs 附件
	 * @param exceptionHandler 邮件发送异常时,调用处理类处理
	 */
	public static void sendMail(String sendUserAccount,String sendUserPassword,String sendUserNickName,String[] receiveUsers,String[] copyUsers,String[] darkUsers,
			String title,String text,File[] bodyImgs,File[] attachDocs,MailSendExceptionHandler exceptionHandler){
		
		MailThread mail = new MailThread(sendUserAccount, sendUserPassword, sendUserNickName, receiveUsers, copyUsers, darkUsers, title, text,  bodyImgs, attachDocs,exceptionHandler);
		executor.execute(mail);
		executor.shutdown();
	}
	
	private static  class MailThread extends Thread{
		
		private String sendUserAccount;
		private String sendUserPassword;
		private String sendUserNickName;
		private String[] receiveUsers;
		private String[] copyUsers;
		private String[] darkUsers;
		private String title;
		private String text;
		private File[] bodyImgs;
		private File[] attachDocs;
		private MailSendExceptionHandler exceptionHandler;
		
		private JSONObject params;//参数集合
		
       public MailThread(String sendUserAccount, String sendUserPassword,
				String sendUserNickName, String[] receiveUsers,
				String[] copyUsers, String[] darkUsers, String title,
				String text, File[] bodyImgs,
				File[] attachDocs,MailSendExceptionHandler exceptionHandler) {
			super();
			this.sendUserAccount = sendUserAccount;
			this.sendUserPassword = sendUserPassword;
			this.sendUserNickName = sendUserNickName;
			this.receiveUsers = receiveUsers;
			this.copyUsers = copyUsers;
			this.darkUsers = darkUsers;
			this.text = text;
			this.title = title;
			this.bodyImgs = bodyImgs;
			this.attachDocs = attachDocs;
			this.exceptionHandler = exceptionHandler;
			
			setParams();
		}
 
    private void setParams(){
    	params = new JSONObject();
    	params.put("sendUserAccount", sendUserAccount);
    	params.put("sendUserPassword", sendUserPassword);
    	params.put("sendUserNickName", sendUserNickName);
    	params.put("receiveUsers", receiveUsers);
    	params.put("copyUsers", copyUsers);
    	params.put("darkUsers", darkUsers);
    	params.put("title", title);
    	params.put("text", text);
    	if(bodyImgs != null && bodyImgs.length > 0){
    		List list = new ArrayList();
    		for(File f : bodyImgs){
    			list.add(f.getName());
    		}
    		params.put("bodyImgs", list);
    	}
    	if(attachDocs != null && attachDocs.length > 0){
    		List list = new ArrayList();
    		for(File f : attachDocs){
    			list.add(f.getName());
    		}
    		params.put("attachDocs", list);
    	}
    }

	public void run(){
		 long startTime = System.currentTimeMillis();
		 try {
	    	 //获取邮件发送实例
			JavaMailSenderImpl mailSender = getJavaMailSenderImpl(sendUserAccount, sendUserPassword);
			//创建邮件帮助类
			MimeMessage mimeMessage = mailSender.createMimeMessage();
	        MimeMessageHelper messageHelper = new MimeMessageHelper(mimeMessage,true,"UTF-8");//必须true
			//设置邮件内容
			setMailContent(messageHelper, title, text, bodyImgs, attachDocs);
			
			//设置发送人
			setSenderUser(messageHelper, sendUserAccount,sendUserNickName);
			
			//设置接收人
			setReceiveUsers(messageHelper, receiveUsers, copyUsers, darkUsers);
			//发送
			mailSender.send(mimeMessage);
			
			
			
		 } catch (Exception e) {
			 //邮件发送失败,可以将发送失败日志记录到数据库进行相关处理
				e.printStackTrace();
				if(this.exceptionHandler != null){
					this.exceptionHandler.doForException(e, params);
				}
			}
		 
		 long endTime = System.currentTimeMillis();
		 String t = ((endTime-startTime)/(60*1000))+" 分 " + (((endTime -startTime)/1000.0)%60) + "秒";
		 System.out.println("邮件发送耗时:" + t);
       }
		
		private  JavaMailSenderImpl  getJavaMailSenderImpl(String sendUserAccount,String sendUserPassword){
			
			 //连接邮件服务器的参数配置
	        Properties props = new Properties();
	        //开启tls
	        props.setProperty("mail.smtp.auth","true");
	        props.setProperty("mail.smtp.ssl.enable", "true");
	    //    props.setProperty("smtp.starttls.required", "true");
			
			JavaMailSenderImpl impl = new JavaMailSenderImpl();
			
			impl.setHost(sendUserAccount.endsWith("163.com") ? "smtp.163.com":"smtp.qq.com");
			impl.setUsername(sendUserAccount);
			impl.setPassword(sendUserPassword);
			impl.setPort(465);
			impl.setDefaultEncoding("UTF-8");
			impl.setProtocol("smtp");
			impl.setJavaMailProperties(props);
			
			return impl;
		}
		
		
		/**
		 * 设置邮件内容
		 * @param help
		 * @param title
		 * @param plainText
		 * @param htmlText
		 * @param bodyImgs
		 * @param attachDocs
		 * @throws MessagingException
		 * @throws UnsupportedEncodingException 
		 */
		private void setMailContent(MimeMessageHelper help,String title,String text,File[] bodyImgs,File[] attachDocs) throws MessagingException, UnsupportedEncodingException {
			//设置标题
			help.setSubject(title);
			//设置文本内容
			StringBuffer s = new StringBuffer("");
			s.append(text );
			if(bodyImgs != null){
				for(int i = 0;i");
				}
			}
			s.append("");
			help.setText(s.toString(), true);
			//展示在正文的图片
			if(bodyImgs != null && bodyImgs.length > 0){
				for(int i = 0;i 0){
			  for(File file : attachDocs){
				  //解决附件中文乱码
				  help.addAttachment(MimeUtility.encodeWord(file.getName()), file);
			  }
		  }
		}
		/**
		 * 设置接收人,抄送人,暗送人
		 * @param help
		 * @param receiveUsers 接收人
		 * @param copyUsers  抄送人
		 * @param darkUsers  暗送人
		 * @throws MessagingException
		 */
		private void setReceiveUsers(MimeMessageHelper help,String[] receiveUsers,String[] copyUsers,String[] darkUsers) throws MessagingException{
			if(receiveUsers != null){
				help.setTo(receiveUsers);
			}
			if(copyUsers != null && copyUsers.length > 0){
				help.setCc(copyUsers);
			}
			if(darkUsers != null && darkUsers.length > 0){
				help.setBcc(darkUsers);
			}
		}
		/**
		 * 设置发送人
		 * @param help
		 * @param senderAccount 邮箱账号
		 * @param userName  昵称
		 * @throws MessagingException
		 * @throws UnsupportedEncodingException 
		 */
		private void setSenderUser(MimeMessageHelper help,String senderAccount,String userName) throws MessagingException, UnsupportedEncodingException{
			if(userName != null){
				help.setFrom(senderAccount,userName);
			}else{
				help.setFrom(senderAccount);
			}
		}
	}
	
	/**
	 * 测试
	 * @param args
	 */
	public static void main(String[] args) {
//		String sendUserAccount = "[email protected]";
//		String sendUserPassword = "XXXX";//授权码
		String sendUserAccount = "[email protected]";
		String sendUserPassword = "zhnbgndydwuxbjdg";
		
		String sendUserNickName = "XXXX";
		String[] receiveUsers =new String[]{ "[email protected]"};
		String[] copyUsers = new String[]{"[email protected]"};
		String[] darkUsers = new String[]{"[email protected]"};
		String title = "诗酒人生";
		String text = "落魄江南载酒行,楚腰肠断掌中轻。十年一觉扬州梦,赢得青楼薄幸名。";
		File[] bodyImgs = new File[]{new File("e:/1.jpg"),new File("e:/2.jpg")};
//		File[] bodyImgs = new File[]{new File("e:/1.jpg")};
//		File[] bodyImgs = null;
		//文件名不要出现空格
		File[] attachDocs = new File[]{new File("e:/文档2.docx"),new File("e:/文档.docx")};
//		File[] attachDocs = null;
		sendMail(sendUserAccount, sendUserPassword, sendUserNickName, receiveUsers, copyUsers, darkUsers, title, text, bodyImgs, attachDocs,null);
		
		System.out.println("已异步发送。。。");
	}
}

注意事项:

1.发送人的邮箱必须开通了SMTP服务,并把授权码记下

163授权

线程池异步发送邮件之MimeMessageHelper邮件发送支持自定义发送人/图片/附件/多个接收人/抄送人/暗送人_第1张图片

如果忘记了,可以在“客户端授权密码”通过短信找回。

qq授权码

线程池异步发送邮件之MimeMessageHelper邮件发送支持自定义发送人/图片/附件/多个接收人/抄送人/暗送人_第2张图片

在“设置”“账户”中找,qq的授权码是自动生成的,最好记下来。

2.如果发送人是qq邮箱的,则没遇到什么问题,但是如果是163邮箱,则经常出现554 DT异常。网上找到的解决方案是:

 (1)把邮件也抄送一份给发件人自己(经测试,没用)

 (2)在163的“设置”->“发垃圾/黑白名单”设置里,白名单添加上“smtp.163.com”,以及自己服务器的公网IP(直接百度IP,就可以看到自己的公网IP是多少了)(经测试,不稳定,仍然会有554 DT)

线程池异步发送邮件之MimeMessageHelper邮件发送支持自定义发送人/图片/附件/多个接收人/抄送人/暗送人_第3张图片

 

 

你可能感兴趣的:(spring,boot,JAVA基础,邮件,异步,自定义发送人,多个接收人)