进入正题:之所以要写个Java Mail邮件发送的功能。是因为早先有个需求,需要我写个定时任务,使用芝麻代理提供的接口定时去查询余额(数据团队做爬虫会用到芝麻代理),如果余额不足,就发送提醒邮件给专门的负责人。我们公司用的是阿里的企业邮箱,我写的发送件代码使用的是SMTP的协议。
遇到的问题:本地、测试环境都可以正常发送邮件,但一发到线上环境,就无法正常发送邮件。
问题原因:我们公司用的是阿里云服务器,而阿里云封禁了25端口的对内对外的访问。所以就需要使用安全协议,用加密的端口。
Java Mail邮件发送demo:
用到的mail依赖
<!-- email -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
外部配置 mailConfig.properties
#服务器
mailHost=smtp.qiye.aliyun.com
#端口号
mailPort=465
#邮箱账号
mailUsername=your_email@mail.com
#邮箱授权码
mailPassword=your_password(该密码为授权密码,需在对应邮箱中配置,不懂的可以自行百度)
#时间延迟
mailTimeout=1000
#发送人
mailFrom=your_email@mail.com
MailConfig(如果不用mailConfig.properties外部配置,可以直接写Hard Code到此代码中)
package com.zero.testing.util;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
/**
* 读取邮件配置
*
* @author Zero
* @date 2019/3/21
*/
@Component
public class MailConfig {
private static final String MAIL_CONFIG_PROPERTIES = "mailConfig.properties";
private static String host;
private static String port;
private static String username;
private static String password;
private static String from;
private static String timeout;
static {
init();
}
/**
* 初始化
*/
private static void init() {
Properties properties = new Properties();
try (InputStream inputStream = MailConfig.class.getClassLoader().getResourceAsStream(MAIL_CONFIG_PROPERTIES)) {
properties.load(inputStream);
host = properties.getProperty("mailHost");
port = properties.getProperty("mailPort");
username = properties.getProperty("mailUsername");
password = properties.getProperty("mailPassword");
from = properties.getProperty("mailFrom");
timeout = properties.getProperty("mailTimeout");
} catch (IOException e) {
e.printStackTrace();
}
}
public static String getHost() {
return host;
}
public static String getPort() {
return port;
}
public static String getUsername() {
return username;
}
public static String getPassword() {
return password;
}
public static String getFrom() {
return from;
}
public static String getTimeout() {
return timeout;
}
}
邮件发送工具
package com.zero.testing.util;
import com.sun.mail.util.MailSSLSocketFactory;
import lombok.extern.slf4j.Slf4j;
import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import java.util.Properties;
/**
* 邮件发送工具
*
* @author Zero
* @date 2019/3/21
*/
@Slf4j
public class MailSender {
/**
* MIME邮件对象
*/
private MimeMessage mimeMsg;
/**
* 系统属性
*/
private Properties props;
/**
* Multipart对象,邮件内容、标题、附件等内容
*/
private Multipart mp;
/**
* 邮件会话对象
*/
private Session session;
private static final String HOST = MailConfig.getHost();
private static final String PORT = MailConfig.getPort();
private static final String USERNAME = MailConfig.getUsername();
private static final String PASSWORD = MailConfig.getPassword();
private static final String EMAIL_FROM = MailConfig.getFrom();
private static final String TIMEOUT = MailConfig.getTimeout();
private MailSender() {
initProperties();
initMimeMessage();
}
private void initProperties() {
//属性设置
props = new Properties();
props.put("mail.smtp.host", HOST);
props.put("mail.smtp.port", PORT);
props.put("mail.smtp.timeout", TIMEOUT);
props.put("mail.smtp.auth", true);
//开启安全协议
try {
MailSSLSocketFactory sf = new MailSSLSocketFactory();
sf.setTrustAllHosts(true);
props.put("mail.smtp.ssl.enable", "true");
props.put("mail.smtp.ssl.socketFactory", sf);
} catch (Exception e1) {
e1.printStackTrace();
}
}
private void initMimeMessage() {
log.info("获取邮件会话对象");
try {
session = Session.getDefaultInstance(props);
} catch (Exception e) {
System.err.println("获取邮件会话对象时发生错误!" + e);
return;
}
log.info("创建MIME邮件对象");
try {
mimeMsg = new MimeMessage(session);
log.info("设置发信人");
mimeMsg.setFrom(new InternetAddress(EMAIL_FROM));
mp = new MimeMultipart();
} catch (Exception e) {
System.err.println("创建MIME邮件对象失败" + e);
}
}
private void setSubject(String mailSubject) {
log.info("设置邮件主题");
try {
mimeMsg.setSubject(mailSubject);
} catch (Exception e) {
log.error("设置邮件主题发生错误" + e);
}
}
private void setBody(String mailBody) {
log.info("设置邮件正文");
try {
BodyPart bp = new MimeBodyPart();
bp.setContent(mailBody, "text/html;charset=utf-8");
mp.addBodyPart(bp);
} catch (Exception e) {
log.error("设置邮件正文发生错误" + e);
}
}
/**
* 添加邮件附件
*
* @param pathname 文件地址
*/
public void addFileAffix(String pathname) {
log.info("增加邮件附件:" + pathname);
try {
BodyPart bp = new MimeBodyPart();
FileDataSource fields = new FileDataSource(pathname);
bp.setDataHandler(new DataHandler(fields));
bp.setFileName(fields.getName());
mp.addBodyPart(bp);
} catch (Exception e) {
log.error("增加邮件附件" + pathname + "发生错误:" + e);
}
}
private void setTo(String to) {
log.info("设置邮件发送对象");
if (to == null) {
return;
}
try {
mimeMsg.setRecipients(Message.RecipientType.TO, InternetAddress.parse(to));
} catch (Exception e) {
log.error("设置邮件发送对象发生错误" + e);
}
}
private void setCc(String cc) {
log.info("设置邮件抄送对象");
if (cc == null) {
return;
}
try {
mimeMsg.setRecipients(Message.RecipientType.CC, InternetAddress.parse(cc));
} catch (Exception e) {
log.error("设置邮件抄送对象发生错误" + e);
}
}
private void sendOut() {
try {
mimeMsg.setContent(mp);
mimeMsg.saveChanges();
log.info("正在发送邮件....");
Transport transport = session.getTransport("smtp");
transport.connect(HOST, USERNAME, PASSWORD);
transport.sendMessage(mimeMsg, mimeMsg.getAllRecipients());
log.info("发送邮件成功!");
transport.close();
} catch (Exception e) {
log.error("邮件发送失败!" + e);
}
}
/**
* 发送提醒邮件
*
* @param to 发送目标
* @param cc 抄送目标
* @param title 主题
* @param mailBody 内容
*/
public static void sendNoticeEmail(String to, String cc, String title, String mailBody) {
//创建发送邮件对象
MailSender mailSender = new MailSender();
mailSender.setTo(to);
mailSender.setCc(cc);
mailSender.setSubject(title);
mailSender.setBody(mailBody);
mailSender.sendOut();
}
}
邮件发送Job
package com.zero.testing.job;
import com.zero.testing.util.MailSender;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.Async;
/**
* 邮件发送Job
*
* @author Zero
* @date 2019/2/28
*/
@Slf4j
@Configuration
public class MailSenderJob {
/**
* 发送提醒邮件
*
* @param to 发送目标
* @param cc 抄送目标
* @param title 主题
* @param mailBody 内容
*/
@Async
public void sendEmail(String to, String cc, String title, String mailBody) {
MailSender.sendNoticeEmail(to, cc, title, mailBody);
}
}
启动时执行代码
package com.zero.testing;
import com.zero.testing.job.MailSenderJob;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import javax.annotation.Resource;
/**
* @author Zero
* @date 2019/3/20
*/
@SpringBootApplication
@Slf4j
public class TestApp implements CommandLineRunner {
@Resource
private MailSenderJob mailSenderJob;
public static void main(String[] args) {
SpringApplication.run(TestApp.class, args);
}
/**
* Callback used to run the bean.
*
* @param args incoming main method arguments
* @throws Exception on error
*/
@Override
public void run(String... args) throws Exception {
log.info("{}", "启动完成");
long a1 = System.currentTimeMillis();
mailSenderJob.sendEmail("your_email@mail.com", "another_email@mail.com", "title", "body");
long a2 = System.currentTimeMillis();
log.error("cost time {}", (a2 - a1));
}
}
--------------------------------------------------华丽的分割线--------------------------------------------------------------
文笔不好,望见谅! ^ _ ^
如有任何问题或者意见,欢迎留言交流。