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

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

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

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

    3.支持正文中放图片

    4.支持附件

    5.线程池异步处理

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

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

         <dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-mail</artifactId>
		</dependency>

即可。

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

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

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<String> list = new ArrayList<String>();
    		for(File f : bodyImgs){
    			list.add(f.getName());
    		}
    		params.put("bodyImgs", list);
    	}
    	if(attachDocs != null && attachDocs.length > 0){
    		List<String> list = new ArrayList<String>();
    		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("<html><body>");
			s.append(text );
			if(bodyImgs != null){
				for(int i = 0;i<bodyImgs.length;i++){
					s.append("<img src='cid:pic"+i+"' />");
				}
			}
			s.append("</body></html>");
			help.setText(s.toString(), true);
			//展示在正文的图片
			if(bodyImgs != null && bodyImgs.length > 0){
				for(int i = 0;i<bodyImgs.length;i++){
					help.addInline("pic"+i, bodyImgs[i]);
				}
			}
		  //添加附件
		  if(attachDocs != null && attachDocs.length > 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 = "XXX@163.com";
//		String sendUserPassword = "XXXX";//授权码
		String sendUserAccount = "XXXX@qq.com";
		String sendUserPassword = "zhnbgndydwuxbjdg";
		
		String sendUserNickName = "XXXX";
		String[] receiveUsers =new String[]{ "XXXX@163.com"};
		String[] copyUsers = new String[]{"XXXX@qq.com"};
		String[] darkUsers = new String[]{"XXXX@qq.com"};
		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授权

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

qq授权码

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

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

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

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

 

 

  • 1
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
您可以使用以下步骤来实现通过Spring Boot查询数据库生成Excel并通过邮件发送多个人: 1. 配置数据库连接:在Spring Boot的配置文件中,配置数据库连接信息,如数据库URL、用户名和密码。 2. 查询数据库:使用Spring Boot提供的数据库操作库(如Spring Data JPA)编写查询数据库的代码,获取需要导出的数据。 3. 生成Excel文件:使用Java的Excel处理库(如Apache POI或EasyExcel)编写代码,将查询到的数据写入Excel文件中。 4. 发送邮件:使用Java的邮件发送库(如JavaMail或Spring Mail)编写代码,将生成的Excel文件作为附件发送多个收件人。 下面是一个简单的示例代码,展示了如何实现上述功能: ```java // 导入所需的库 // 查询数据库 @Repository public interface UserRepository extends JpaRepository<User, Long> { // 自定义查询方法 List<User> findByStatus(String status); } // 生成Excel文件 public class ExcelGenerator { public static void generateExcel(List<User> users, String filePath) { // 创建工作簿 Workbook workbook = new XSSFWorkbook(); Sheet sheet = workbook.createSheet("Users"); // 创建表头 Row headerRow = sheet.createRow(0); headerRow.createCell(0).setCellValue("ID"); headerRow.createCell(1).setCellValue("Name"); headerRow.createCell(2).setCellValue("Email"); // 填充数据 int rowNum = 1; for (User user : users) { Row row = sheet.createRow(rowNum++); row.createCell(0).setCellValue(user.getId()); row.createCell(1).setCellValue(user.getName()); row.createCell(2).setCellValue(user.getEmail()); } // 写入文件 try (FileOutputStream outputStream = new FileOutputStream(filePath)) { workbook.write(outputStream); } catch (IOException e) { e.printStackTrace(); } } } // 发送邮件 @Service public class EmailService { @Autowired private JavaMailSender mailSender; public void sendEmailWithAttachment(String[] recipientEmails, String subject, String body, String attachmentPath) { MimeMessage message = mailSender.createMimeMessage(); try { MimeMessageHelper helper = new MimeMessageHelper(message, true); helper.setTo(recipientEmails); helper.setSubject(subject); helper.setText(body); // 添加附件 FileSystemResource file = new FileSystemResource(attachmentPath); helper.addAttachment("Users.xlsx", file); mailSender.send(message); } catch (MessagingException e) { e.printStackTrace(); } } } // 在业务逻辑中使用 @Service public class UserService { @Autowired private UserRepository userRepository; @Autowired private EmailService emailService; public void exportUsersAndSendEmail(String[] recipientEmails) { // 查询数据库 List<User> users = userRepository.findByStatus("active"); // 生成Excel文件 String excelFilePath = "path/to/excel/Users.xlsx"; ExcelGenerator.generateExcel(users, excelFilePath); // 发送邮件 String subject = "Users Report"; String body = "Please find the attached Users report."; emailService.sendEmailWithAttachment(recipientEmails, subject, body, excelFilePath); } } ``` 请根据实际需求进行适当的修改和配置,并确保相关的库已添加到项目的依赖中。这样,您就可以通过调用`UserService`中的`exportUsersAndSendEmail`方法来实现查询数据库、生成Excel文件并发送邮件的功能。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值