Java搭建邮件服务器并发送Excel附件
1.配置文件yml (这里读取的是配置文件的发送邮箱账号,可以自行取值)
server: port: 8888 servlet: # # 项目contextPath context-path: /mailserv spring: application: name: mailserv #设置静态资源路径,多个以逗号分隔 spring.resources.static-locations: classpath:static/,file:static/ # 日志配置 logging: level: mail: debug org.springframework: WARN org.spring.springboot.dao: debug mail: #发送方 from: xxxx@qq.com #登录的公司邮箱 username: xxx@qq.com #这里如果有独立密码的要用独立密码,没有的使用登录密码 password: xxxxxx
2.bean和Properties
package mail.bean; import lombok.Data; import java.io.Serializable; import java.util.List; @Data public class MailInfo implements Serializable { private static final long serialVersionUID = 4280650483975256784L; // 邮件发送者的标示 private String key; // 邮件发送者的邮箱 private String from; //登陆邮件发送服务器的用户名和密码(授权码) private String mailAccount; private String mailPassword; //收件人名字 private String senderAlias; // 邮件接收者的地址数组 private List<String> receiveAddressArray; // 邮件主题 private String subject; // 邮件的文本内容 private String content; // 邮件附件的文件名 private String[] attachFileNames; //发送邮件用到的Excel相关信息和数据 private List<ExcelFile> excelFiles; /** * 发送邮件用到的Excel相关信息和数据 */ @Data public static class ExcelFile { //文件名 private String fileName; //字节数组 private byte[] byteArray; //html格式内容 private String htmlContent; } }
// 读取配置文件中我们自定义的发送邮件的参数 @Data @Configuration @ConfigurationProperties(prefix = "mail") public class MailProperties { //登录的公司邮箱 private String from; //登录的公司邮箱 private String username; //这里用客户端的密码,不是登录密码 private String password; }
3.工具类
import javax.activation.DataHandler; import javax.activation.DataSource; import javax.mail.*; import javax.mail.Authenticator; import javax.mail.internet.*; import javax.mail.util.ByteArrayDataSource; import java.util.List; import java.util.Properties; /** * 发送腾讯企业邮件工具类 */ public class SendUtil { // 腾讯企业邮箱的smtp服务器 public final static String HOST = "smtp.exmail.qq.com"; public final static String PORT = "465"; /** * 发送邮件 * * @param mailInfo 邮件相关参数配置和数据信息 * @throws Exception */ public static void send(MailInfo mailInfo) throws Exception { //excel附件相关信息 List<ExcelFile> excelFiles = mailInfo.getExcelFiles(); Properties props = new Properties(); props.put("mail.smtp.auth", "true"); props.put("mail.smtp.host", HOST); props.put("mail.smtp.port", PORT); props.put("mail.smtp.ssl.enable", "true"); //用户的公司邮箱 String username = mailInfo.getMailAccount(); //这里用客户端的密码,不是登录密码 String password = mailInfo.getMailPassword(); //发送方 String from = mailInfo.getFrom(); //接收方 List<String> recipients = mailInfo.getReceiveAddressArray(); //内容(前面位置) String content = mailInfo.getContent(); //主题 String subJect = mailInfo.getSubject(); //认证 Authenticator smtpAuth = new PopupAuthenticator(from, password); Session session = Session.getDefaultInstance(props, smtpAuth); session.setDebug(true); MimeMessage message = new MimeMessage(session); message.setFrom(new InternetAddress(from)); //多个收件人 int num = recipients.size(); InternetAddress[] rece_addresses = new InternetAddress[recipients.size()]; for (int i = 0; i < num; i++) { rece_addresses[i] = new InternetAddress(recipients.get(i)); } message.setRecipients(Message.RecipientType.TO, rece_addresses); /*附件*/ // 容器类 附件 MimeMultipart mimeMultipart = new MimeMultipart(); // 可以包装文本,图片,附件 MimeBodyPart mimeBodyPart = new MimeBodyPart(); // 设置内容 mimeBodyPart.setContent(content, "text/html; charset=UTF-8"); mimeMultipart.addBodyPart(mimeBodyPart); /*读取excelFiles的信息并添加到邮件*/ if (CollectionUtils.isNotEmpty(excelFiles)) { for (ExcelFile excelFile : excelFiles) { byte[] byteArray = excelFile.getByteArray(); String fileName = excelFile.getFileName(); String htmlContent = excelFile.getHtmlContent(); //添加读取到的excel内容到邮件 if (StringUtils.isNotBlank(htmlContent)) { MimeBodyPart mimeBodyPartExcelText = new MimeBodyPart(); mimeBodyPartExcelText.setContent(htmlContent, "text/html; charset=UTF-8"); mimeMultipart.addBodyPart(mimeBodyPartExcelText); } /*添加附件*/ if (byteArray != null) { MimeBodyPart fileBody = new MimeBodyPart(); DataSource source = new ByteArrayDataSource(byteArray, "application/msexcel"); fileBody.setDataHandler(new DataHandler(source)); if (StringUtils.isBlank(fileName)) { fileName = "未命名文件"; } // 中文乱码问题 fileBody.setFileName(MimeUtility.encodeText(fileName)); mimeMultipart.addBodyPart(fileBody); } } } message.setContent(mimeMultipart); message.setSubject(subJect); message.saveChanges(); Transport transport = session.getTransport("smtp"); transport.connect(HOST, username, password); transport.sendMessage(message, message.getAllRecipients()); transport.close(); } } class PopupAuthenticator extends Authenticator { String username = null; String password = null; public PopupAuthenticator() { } public PopupAuthenticator(String username, String password) { this.username = username; this.password = password; } PasswordAuthentication performCheck(String user, String pass) { username = user; password = pass; return getPasswordAuthentication(); } @Override protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication(username, password); } }
4.发送邮件的Service帮助类
/** * 发送邮件的Service帮助类 * * @author admin */ @Service public class MailServiceHelper { private static final Logger logger = LoggerFactory.getLogger(MailServiceHelper.class); @Autowired private MailProperties mailProperties; /** * 发送邮件,这里账号密码写到配置文件中 * @param mailInfo */ public void sendMail(MailInfo mailInfo) throws Exception { //添加发送人,账号和密码 mailInfo.setFrom(mailProperties.getFrom()); mailInfo.setMailAccount(mailProperties.getUsername()); mailInfo.setMailPassword(mailProperties.getPassword()); SendUtil.send(mailInfo); } }
5.controller
@Controller public class SendMailController { private static final Logger logger = LoggerFactory.getLogger(SendMailController.class); @Autowired private MailServiceHelper mailServiceHelper; /** * 发送邮件 * * @param mailInfo * @return */ @ResponseBody @RequestMapping(value = "sendMail", method = RequestMethod.POST) public Map<String, Object> sendMail(@RequestBody MailInfo mailInfo) { String msg = null; logger.info("发送邮件开始"); if (mailInfo == null) { msg = "发送邮件失败!原因:数据为空!!!"; logger.error(msg); return RespUtils.badResponse(msg); } try { //发送 mailServiceHelper.sendMail(mailInfo); } catch (Exception e) { logger.error("发送邮件失败!!", e); return RespUtils.badResponse("发送邮件失败!!"); } System.out.println("mailInfo :" + mailInfo); return RespUtils.sucResp("发送成功!", null); } }
6. 测试
@Test public void sendPostToAttach() throws Exception { Properties props = new Properties(); String host = "smtp.exmail.qq.com"; // 腾讯企业邮箱的smtp服务器 String to = "611766xxx@qq.com"; // 邮件要发送到的邮箱地址 props.put("mail.smtp.auth", "true"); props.put("mail.smtp.host", host); String content = "hello"; String subJect = "这是一个好消息1"; //发送邮件VO MailInfo mailInfo = new MailInfo(); mailInfo.setSubject( subJect); mailInfo.setContent(content); //收件人 List<String> receiveAddressArray = new ArrayList<>(); receiveAddressArray.add(to); mailInfo.setReceiveAddressArray(receiveAddressArray); //获取excel MailInfo.ExcelFile excelFile = TestWrite.writeToMail(); ArrayList<MailInfo.ExcelFile> list = Lists.newArrayList(); list.add(excelFile); mailInfo.setExcelFiles(list); String json = JSONObject.toJSONString(mailInfo); //远程调用接口 http://localhost:8888/mailserv/sendMail String res = HttpJson.httpPostWithjson("http://localhost:8888/mailserv/sendMail", json); System.out.println("res :" + res); }
/** * 使用byte数组写入excle发送邮件***重点是红色部分**这里使用eazyexcel * * @throws IOException */ public static MailInfo.ExcelFile writeToMail() { //输出流放excel数据 ByteArrayOutputStream os = new ByteArrayOutputStream(); //获取头和内容的策略 HorizontalCellStyleStrategy horizontalCellStyleStrategy = getHorizontalCellStyleStrategy(); //列宽的策略,宽度是小单位 Integer columnWidthArr[] = {3000, 6000}; List<Integer> columnWidths = Arrays.asList(columnWidthArr); CustomSheetWriteHandler customSheetWriteHandler = new CustomSheetWriteHandler(columnWidths); // 根据用户传入字段 假设我们只要导出 string date String[] filds = {"string", "date"}; //获取模拟的实体数据集合 List<DemoData> demoDataList = getDemoDataList(); //创建工作簿到流中 //这里需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭 EasyExcel.write(os, DemoData.class) .registerWriteHandler(horizontalCellStyleStrategy) .registerWriteHandler(customSheetWriteHandler) //这个是导出需要展示的列 .includeColumnFiledNames(Arrays.asList(filds)) .sheet("模板") .doWrite(demoDataList); //保存字节数组 MailInfo.ExcelFile excelFile = new MailInfo.ExcelFile(); excelFile.setByteArray(os.toByteArray()); return excelFile; }