java mail在发送纯文本附件时,当附件内容的编码和jvm缺省的编码不一致时,出现乱码。原因时java mail处理纯文本附件,使用text_plain这个datacontenthandler来处理,而text_plain又简单的使用jvm缺省编码来读取文件内容(可以使用file.encode和mail.mime.charset系统属性来更改),两者不一致时,自然就乱码了
找到的问题的原因,也就容易解决了,一种方法就是把所有的附件类新全部设成application/octet-stream,把附件作为二进制流,还有一种就是当附件是存文本时,通过BOM(byte order mark)来探测文件的编码类型。
扩展FileDataSource,处理ContentType类型:
public class MyFileDataSource extends FileDataSource { private static final String DEFAULT_CONTENT_TYPE = "application/octet-stream"; private final static Pattern pattern = Pattern.compile("^text/"); private String contentType ; private int head_count=0; public MyFileDataSource(File file) { super(file); determinateType(); } private void determinateType(){ contentType = super.getContentType(); Matcher m = pattern.matcher(contentType); if(m.find() && getFile().exists() && getFile().isFile()){ InputStream in = null; try { in = new FileInputStream(getFile()); if(is_utf_8(in)){ contentType = contentType + "; charset=utf-8"; head_count = 3; } else { contentType = DEFAULT_CONTENT_TYPE; } } catch (IOException e) { contentType = DEFAULT_CONTENT_TYPE; } finally { try { if(in!=null) { in.close(); } } catch (IOException e1) { } } } } public MyFileDataSource(String s) { this(new File(s)); } @Override public InputStream getInputStream() throws IOException { InputStream in = super.getInputStream(); for(int i=0;i<head_count;i++) in.read(); return in; } @Override public String getContentType() { return contentType; } private boolean is_utf_8(InputStream in) throws IOException{ byte[] b3 = new byte[3]; int count = in.read(b3, 0, 3); if(count<3) return false; int b0 = b3[0] & 0xFF; int b1 = b3[1] & 0xFF; int b2 = b3[2] & 0xFF; if (b0 == 0xEF && b1 == 0xBB && b2 == 0xBF){ return true; } return false; } }
使用:
public static void main(String[] args) throws Exception { String host = "your host"; String from = "mail from addr"; String to = "to addr"; Properties props = new Properties(); props.put("mail.smtp.host", host); props.put("mail.smtp.auth", "true"); props.put("mail.transport.protocol", "smtp"); Session session = Session.getInstance(props, null); session.setDebug(true); System.setProperty("mail.mime.charset", "utf-8"); MimeMessage message = new MimeMessage(session); message.setSentDate(new Date()); message.setFrom(new InternetAddress(from,"test")); message.setRecipients(Message.RecipientType.TO, new InternetAddress[] {new InternetAddress(to)}); message.setSubject("测试"); String html="<html><head></head>\r\n\r\n <body><h1>测试htmlmail</h1><img src=\"cid:aaaaaaa\"></body></html>"; MimeMultipart multipart = new MimeMultipart("related"); MimeBodyPart html_body = new MimeBodyPart(); html_body.setContent(html,"text/html; charset=utf-8"); multipart.addBodyPart(html_body); MimeBodyPart file = new MimeBodyPart(); //file.attachFile("d:\\aa.txt"); FileDataSource fds = new MyFileDataSource("d:\\test.txt"); file.setDataHandler(new DataHandler(fds)); multipart.addBodyPart(file); message.setContent(multipart); Transport transport = session.getTransport(); try { transport.connect(host, 25, "×××", "×××"); transport.sendMessage(message, message.getAllRecipients()); } finally { transport.close(); } }