前段时间猫哥遇到一个需求,通过java生成Excel后,利用javamail附件形式发送给相应邮箱。
查阅大量资料后发现,大部分的解决方案都是生成本地xls文件,再通过文件名和文件地址传给javamail的附件内。很明显,这样的解决方案不合理,会占用服务器大量的存储空间和IO,最理想的方法是不生成本地xls文件,直接通过流的形式传给javamail附件。
摸索了一阵后,猫哥找到了解决方案,在这里记录一下。
大致的思路就是:利用ByteArrayOutputStream直接将excel文件传入邮件附件。
代码如下:
ByteArrayOutputStream os = new ByteArrayOutputStream();
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet("new sheet");/**此处省去对EXCEL表内容和格式的详细编码过程**/try {wb.write(os);
} catch (IOException e) {e.printStackTrace();
}ByteArrayInputStream a = new ByteArrayInputStream(os.toByteArray());String uuid = "test.xls";
//指明让哪个smtp转发
SendMailService themail = new SendMailService("smtp.163.com");
//将ByteArrayInputStream直接存入mail的附件内
themail.addFileAffix(a,uuid)
邮件服务SendMailService 的具体代码如下:
package com.catchgo.devicejob.service;import com.xxl.job.core.log.XxlJobLogger;import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.mail.*;
import javax.mail.internet.*;
import javax.mail.util.ByteArrayDataSource;
import java.io.InputStream;
import java.util.Properties;/*** @Description:* @Author: Li Yacheng* @Date: 2020/6/24 14:06*/
public class SendMailService {private MimeMessage mimeMsg; //MIME邮件对象private Session session; //邮件会话对象private Properties props; //系统属性private boolean needAuth = false; //smtp是否需要认证private String username = ""; //smtp认证用户名和密码private String password = "";private Multipart mp; //Multipart对象,邮件内容,标题、附件等内容均添加到其中后在生成Multipart对象public SendMailService(String smtp) {setSmtpHost(smtp);createMimeMessage();}/**** @param hostName*/private void setSmtpHost(String hostName) {System.out.println("设置系统属性:mail.smtp.host = "+hostName);if(props == null){props = System.getProperties(); //获得系统属性对象}props.put("mail.smtp.host", hostName); //设置SMTP主机props.put("mail.smtp.port", "465");props.put("mail.smtp.socketFactory.port", "465");props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");props.put("mail.smtp.socketFactory.fallback", "false");}/**** @return boolean*/private boolean createMimeMessage() {try{System.out.println("准备获取邮件会话对象");session = Session.getDefaultInstance(props, null); //获取邮件会话对象}catch(Exception e){System.out.println("获取邮件会话对象错误!" + e);return false;}System.out.println("准备创建MIME邮件对象!");try{mimeMsg = new MimeMessage(session); //创建MIME邮件对象mp = new MimeMultipart("mixed"); //mp 一个multipart对象return true;}catch(Exception e){System.out.println("创建MIME邮件对象失败!" + e);return false;}}/**** @param need boolean*/public void setNeedAuth(boolean need){System.out.println("设置smtp身份认证:mail.smtp.auth =" + need);if(props == null){props = System.getProperties();}if(need){props.put("mail.smtp.auth", "true");props.put("mail.smtp.starttls.enable", "true");props.put("mail.smtp.starttls.required", "true");}else{props.put("mail.smtp.auth", "false");}}/**** @param name String* @param pass String*/public void setNamePass(String name,String pass){System.out.println("程序得到用户名和密码");username = name;password = pass;}/**** @param mailSubject String* @return boolean*/public boolean setSubject(String mailSubject){System.out.println("设置邮件主题!");try{mimeMsg.setSubject(MimeUtility.encodeText(mailSubject, "UTF-8", "B"));return true;}catch(Exception e){System.out.println("创建邮件主题失败!" + e);XxlJobLogger.log("创建邮件主题失败!" + e);return false;}}/**** @param mailBody String* @return boolean*/public boolean setBody(String mailBody){System.out.println("设置邮件主体!");try{BodyPart bp = new MimeBodyPart();bp.setContent(mailBody,"text/html;charset=gbk");mp.addBodyPart(bp);return true;}catch(Exception e){System.out.println("创建邮件正文发送失败!" + e);XxlJobLogger.log("创建邮件正文发送失败!" + e);return false;}}/**** @param InputStream attachmentByteArray* @param String tittle* @return boolean*/public boolean addFileAffix(InputStream attachmentByteArray, String tittle){try{MimeBodyPart bp = new MimeBodyPart();//DataSource files = new ByteArrayDataSource(attachmentByteArray, "application/msword");DataSource files = new ByteArrayDataSource(attachmentByteArray, "application/vnd.ms-excel;charset=UTF-8");bp.setDataHandler(new DataHandler(files));bp.setFileName(MimeUtility.encodeText(tittle));mp.addBodyPart(bp);return true;}catch(Exception e){//System.err.println("添加邮件:" + fileName +" 发生错误!"+ e);return false;}}public boolean setFrom(String from){System.out.println("设置发件人!");try{mimeMsg.setFrom(new InternetAddress(from)); //设置发件人return true;}catch(Exception e){XxlJobLogger.log("设置发件人失败!" + e);return false;}}/**** @param to String* @return boolean*/public boolean setTo(String to,String email){System.out.println("设置收件人!");if(to == null){return false;}try{mimeMsg.addRecipients(Message.RecipientType.TO, InternetAddress.parse(to)); //发送别人mimeMsg.addRecipients(Message.RecipientType.CC, InternetAddress.parse(email)); //抄送自己return true;}catch(Exception e){XxlJobLogger.log("设置收件人失败!"+e);return false;}}/**** @param copyto String* @return boolean*/public boolean setCopyTo(String copyto){System.out.println("发送附件到");if(copyto == null){return false;}try{mimeMsg.setRecipients(Message.RecipientType.CC, (Address[])InternetAddress.parse(copyto));return true;}catch(Exception e){return false;}}public boolean sendout(){try{mimeMsg.setContent(mp);mimeMsg.saveChanges();System.out.println("正在发送邮件...");Session mailSession = Session.getInstance(props,null);Transport transport = mailSession.getTransport("smtp");transport.connect((String)props.get("mail.smtp.host"), username,password);// transport.sendMessage(mimeMsg, mimeMsg.getRecipients(Message.RecipientType.TO));transport.sendMessage(mimeMsg, mimeMsg.getAllRecipients());System.out.println("邮件发送成功!");transport.close();return true;}catch(Exception e){System.out.println("邮件发送失败!" + e);XxlJobLogger.log("邮件发送失败!"+e);return false;}}
}
以上即可实现不生成本地文件,直接通过javamail附件发送邮件的功能。