java 实现邮件发送功能 包含(标题、正文、本地文件、远程文件,多个收件人,多个抄送人等等)
1、pom.xml配置,我这里配置的是1.4.4版本,
*****重点提示,你可以用其他版本的,但假如后续出现文件名过长导致出现 文件名变成.bin,.bat之类的问题,请改回1.4.4版本。
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>javax.mail</artifactId>
<version>${mail-version}</version>
</dependency>
2、控制层
这里主要是发送远程文件做附件,其他的也可以,加在sendEmail方法里。
/**
* 邮件发送,附件是doc/docx/png..等各种文件
* @param map
* @param request
*/
@ResponseBody
@RequestMapping("/sendMail")
public R sendtestmail(@RequestBody HashMap<String, Object> map, HttpServletRequest request) {
String subject="智能文书";
String content="您好:<br>  您有一份智能文书,请查收!";
String toAddress = map.get("toAddress")==null?null:map.get("toAddress").toString();
// 附件处理
String remoteFile = map.get("remoteFile") == null ? null : map.get("remoteFile").toString();
List<String> remoteFileList = new ArrayList<>();
if (StringUtil.isNotEmpty(remoteFile))
{
remoteFileList = Arrays.asList(remoteFile.split(","));
}
try {
SendMailUtil.sendEmail(subject,content,null,remoteFileList,toAddress,null);
} catch (Exception e) {
logger.error(e);
return R.error(ResponseCode.SENDEMAIL_ERROR);
}
return R.ok();
}
3、邮件发送工具类
package com.yz.robot.utils;
import com.sun.mail.util.MailSSLSocketFactory;
import com.yz.robot.utils.vcode.MyAuthenticator;
import org.springframework.util.CollectionUtils;
import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.activation.URLDataSource;
import javax.mail.*;
import javax.mail.internet.*;
import java.net.URL;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Properties;
public class SendMailUtil {
/**
* 发送邮件
* @param subject 主题
* @param content 正文内容
* @param file 附件 本地文件list
* @param remoteFile 附件 远程文件list
* @param toAddress 收件人 多个时参数形式:"[email protected],[email protected],[email protected]"
* @param ccAddress 抄送人 多个时参数形式:"[email protected],[email protected],[email protected]"
* @throws Exception
*/
public static void sendEmail(String subject, String content, List<String> file, List<String> remoteFile, String toAddress, String ccAddress) throws Exception {
//1、发送方的邮件地址和密码
ConfigRead conf = ConfigRead.getInstance();
String emailaddress = conf.getConfigItem("emailaddress");
String emailpassword = conf.getConfigItem("emailpassword");
// 2、获取相关配置,创建session
Properties properties = getProperties();
Session session = Session.getDefaultInstance(properties, new MyAuthenticator(emailaddress, emailpassword));
// 开启Session的debug模式,这样就可以查看到程序发送Email的运行状态,后续可关闭
session.setDebug(true);
// 3. 创建邮件对象message,设置标题、日期、发件人等等
MimeMessage message = new MimeMessage(session);
message.setSubject(subject);
message.setSentDate(new Date());
message.setFrom(new InternetAddress(emailaddress));
message.setContent(getMultipart(content,file,remoteFile));
// 4、收件人、抄送人
if (StringUtil.isNotEmpty(toAddress))
{
message.setRecipients(Message.RecipientType.TO, new InternetAddress().parse(toAddress));
}
if (StringUtil.isNotEmpty(ccAddress))
{
message.setRecipients(Message.RecipientType.CC, new InternetAddress().parse(ccAddress));
}
// 4、发送
Transport.send(message, message.getAllRecipients());
}
/**
* 获取properties
* @return
* @throws Exception
*/
public static Properties getProperties() throws Exception{
//1. 用于存放 SMTP 服务器地址等参数
Properties properties = new Properties();
// 主机地址
properties.setProperty("mail.smtp.host", "smtp.exmail.qq.com");
//properties.setProperty("mail.smtp.host", conf.getConfigItem("mail.smtp.host"));
// 邮件协议
properties.setProperty("mail.transport.protocol", "smtp");
// 认证
properties.setProperty("mail.smtp.auth", "true");
// 端口
properties.setProperty("mail.smtp.port", "465");
MailSSLSocketFactory sf = new MailSSLSocketFactory();
sf.setTrustAllHosts(true);
properties.put("mail.smtp.ssl.enable", "true");
properties.put("mail.smtp.ssl.socketFactory", sf);
return properties;
}
/**
* 获取Multipart对象,包含正文内容、附件
* @return
*/
private static Multipart getMultipart(String content, List<String> file, List<String> remoteFile) throws Exception {
Multipart multipart = new MimeMultipart();
// 1、向multipart中添加正文
BodyPart contentBodyPart = new MimeBodyPart();
contentBodyPart.setContent(content, "text/html;charset=UTF-8");
multipart.addBodyPart(contentBodyPart);
// 2、向multipart中添加附件
if (!CollectionUtils.isEmpty(file))
{
for (String url : file) {
multipart.addBodyPart(getBodyPart(url,FileUtil.getNameByUrl(url),1));
}
}
// 3、向multipart中添加远程附件
if (!CollectionUtils.isEmpty(remoteFile))
{
for (String url : remoteFile){
multipart.addBodyPart(getBodyPart(FileUtil.encodeURI(url),FileUtil.getNameByUrl(url),2));
}
}
return multipart;
}
/**
* 获取 bodyPart
* @param path 文件路径
* @param fileName 文件名称
* @param pathType 1、本地文件;2、远程文件
* @return
*/
public static BodyPart getBodyPart(String path,String fileName,int pathType) throws Exception{
BodyPart bodyPart = new MimeBodyPart();
// 根据附件路径获取文件,
DataHandler dh = null;
if (pathType == 1){
dh = new DataHandler(new FileDataSource(path));
}else if (pathType == 2){
dh = new DataHandler(new URLDataSource(new URL(path)));
}
bodyPart.setDataHandler(dh);
//MimeUtility.encodeWord可以避免文件名乱码
System.out.println(MimeUtility.encodeWord(fileName));
bodyPart.setFileName(MimeUtility.encodeWord(fileName,"gb2312",null));
//bodyPart.setFileName(MimeUtility.encodeWord(fileName));
return bodyPart;
}
}
4、以上就是邮件发送全部代码了,有以下几个注意的地方
a.远程文件在生成dh之前 (dh = new DataHandler(new URLDataSource(new URL(path)))) ,需要对url进行编码,不能包含中文,例如:
编码前:http://www.baidu.com/api/resource/robot/word/2/婚前协议.doc
编码后:http://v.shiduai.com/api/resource/robot/word/2/%E5%A9%9A%E5%89%8D%E5%8D%8F%E8%AE%AE.doc
这里付上方法:你们有好的方法可以用自己的,目的达到就可以了
package com.yz.robot.utils;
import org.springframework.web.multipart.MultipartFile;
import java.net.URLEncoder;
/**
* @Description: 文件相关工具类
* @Auther: wuyp
* @Date: 2018/5/22 10:04
*/
public class FileUtil {
/**
* 对文件fileUrl进行编码 类似于浏览器的encodeURI编码
* 例子:编码前:http://www.baidu.com/api/resource/robot/word/2/婚前协议.doc
* 编码后:http://www.baidu.com/api/resource/robot/word/2/%E5%A9%9A%E5%89%8D%E5%8D%8F%E8%AE%AE.doc
* @param url
* @return
*/
public static String encodeURI(String url) throws Exception
{
String encode = URLEncoder.encode(url, "UTF-8");
return encode.replace("%3A",":").replace("%2F","/");
}
/**
* 根据fileUrl获取 带后缀的文件名称
*
* @param url
* @return
*/
public static String getNameByUrl(String url)
{
if (StringUtil.isEmpty(url))
{
return null;
}
return url.substring(url.lastIndexOf("/")+1);
}
}
b.就是设置文件名的时候要避免乱码,
bodyPart.setFileName(MimeUtility.encodeText(fileName));
这个倒是可以处理乱码问题,但是偶尔会出现文件名变成了tcmime.1829.2125.50468.bin等,此时附件下载下来另存为doc也是没问题的,这种处理本地测试完全没问题,但是linux不行,而且不是绝对不行,是偶尔出现。同样是docx文件,一个出现这样,一个文件名正常,目前不知道啥原因,有哪位大佬知道告诉我。。。
(已经知道是文件名过长问题,把文件名改为一个字,立马正常,解决这个问题方法是改为1.4.4版本)
下面这个是解决办法,设置成gb2312后,一切问题都没有了。
bodyPart.setFileName(MimeUtility.encodeWord(fileName,"gb2312",null));
---------------------------------------------------------------结束---------------------------------------------------------------------