Spring集成JavaMail并利用线程池发送邮件
我们系统存在大量发送邮件的需求,项目使用的是Spring框架而JavaMail也能很好的跟Spring进行集成,由于发送邮件最好还是使用异步进行发送,所以这里就采用线程池+JavaMail进行邮件发送,下面看具体代码实现:
Step1、引入JavaMail
<mail.version>1.4.7</mail.version> <dependency> <groupId>javax.mail</groupId> <artifactId>mail</artifactId> <version>${mail.version}</version> </dependency>
Step2、Spring配置文件中配置MailSender和线程池
<!--MailSender--> <bean id="javaMailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl"> <property name="host" value="${email.host}"/> <property name="username" value="${email.username}"/> <property name="password" value="${email.password}"/> <property name="javaMailProperties"> <props> <prop key="mail.smtp.auth">true</prop> <prop key="mail.smtp.timeout">25000</prop> <!-- <prop key="mail.smtp.starttls.enable">true</prop> <prop key="mail.smtp.socketFactory.class">javax.net.ssl.SSLSocketFactory</prop> --> </props> </property> </bean> <!--配置线程池--> <bean id="taskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor"> <!-- 核心线程数 --> <property name="corePoolSize" value="${executor.corePoolSize}" /> <!-- 最大线程数 --> <property name="maxPoolSize" value="${executor.maxPoolSize}" /> <!-- 最大队列数 --> <property name="queueCapacity" value="${executor.queueCapacity}" /> <!-- 线程池维护线程所允许的空闲时间 --> <property name="keepAliveSeconds" value="${executor.keepAliveSeconds}" /> </bean>
Step3、新建邮件实体类,方便业务处理
import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.util.Assert; import javax.mail.internet.AddressException; import java.util.Arrays; /** * <p> * <code>MailEntry</code> * </p> * Description: * 邮件实体类 * @author jianzh5 * @version 2017/3/31 17:00 * @since 1.0 */ public class MailEntry { /** * 收件人 */ private String[] recipients; /** * 抄送人 */ private String[] carbonCopy; /** * 主题 */ private String subject; /** * 内容 */ private String text; public String getSubject() { return subject; } public void setSubject(String subject) { this.subject = subject; } public String getText() { return text; } public void setText(String text) { this.text = text; } public String[] getRecipients() { return recipients.clone(); } public void setRecipients(String[] recipients) throws AddressException { Assert.isTrue(ArrayUtils.isNotEmpty(recipients),"收件人不能为空"); String[] addresses = new String[recipients.length]; for (int i = 0; i < addresses.length; i++) { addresses[i] = parseAddress(recipients[i]); } this.recipients = addresses; } public String[] getCarbonCopy() { if(ArrayUtils.isNotEmpty(carbonCopy)){ return carbonCopy.clone(); } return ArrayUtils.EMPTY_STRING_ARRAY; } public void setCarbonCopy(String[] carbonCopy) throws AddressException { String[] addresses = new String[carbonCopy.length]; for (int i = 0; i < addresses.length; i++) { addresses[i] = parseAddress(carbonCopy[i]); } this.carbonCopy = addresses; } /** * @desc 只要设定邮件接受人的域账号即可自动增加企业后缀 * @author jianzh5 * @date 2017/4/1 13:43 * @param recipient 收件人域账号 * @return 带企业后缀的邮箱地址 * @throws AddressException */ private String parseAddress(String recipient) throws AddressException { if(StringUtils.isEmpty(recipient)){ throw new AddressException("邮箱账号不能为空",recipient); } return recipient + "@company.com"; } @Override public String toString() { return "MailEntry{" + "recipients=" + Arrays.toString(recipients) + ", carbonCopy=" + Arrays.toString(carbonCopy) + ", subject='" + subject + '\'' + ", text='" + text + '\'' + '}'; } }
说明:由于我们是使用企业邮箱发送邮件,而一般业务都只能取到公司用户名而非真正的邮箱地址,所以在上面实体类里进行了一次转换,如果能直接拿到邮箱地址的话上面的转换是不需要的。收件人和抄送人都是支持数组形式的参数,所以在这里直接使用数组作为收件人、抄送人属性,发送邮件的时候只要直接设置成数组参数即可。
Step4、发送邮件业务层实现
import org.apache.commons.lang3.ArrayUtils; import org.springframework.core.task.TaskExecutor; import org.springframework.mail.javamail.JavaMailSender; import org.springframework.mail.javamail.MimeMessageHelper; import org.springframework.stereotype.Service; import javax.annotation.Resource; import javax.mail.MessagingException; import javax.mail.internet.MimeMessage; /** * <p> * <code>MailServiceImpl</code> * </p> * Description: * 邮件系统实现类 * @author jianzh5 * @version 2017/3/31 17:10 * @since 1.0 */ @Service public class MailServiceImpl implements IMailService{ private LoggerUtil logger = LoggerUtil.getLogger(this.getClass()); @Resource private TaskExecutor taskExecutor; @Resource private JavaMailSender javaMailSender; @Override public void sendMail(MailEntry mailEntry) { MimeMessage message = javaMailSender.createMimeMessage(); try { MimeMessageHelper helper = new MimeMessageHelper(message, true, "utf-8"); helper.setFrom("xxx@company.com"); helper.setTo(mailEntry.getRecipients()); //收件人 if(ArrayUtils.isNotEmpty(mailEntry.getCarbonCopy())){ helper.setCc(mailEntry.getCarbonCopy()); //抄送人 } helper.setSubject(mailEntry.getSubject()); helper.setText(mailEntry.getText(),true);//设置为TRUE则可以使用Html标记 addSendMailTask(message); } catch (MessagingException e) { // e.printStackTrace(); logger.error("邮件转换异常,邮件详细信息为{}",e.getMessage()); } } /** * @desc 使用多线程发送邮件 * @author jianzh5 * @date 2017/4/1 11:41 * @param message MimeMessage邮件封装类 */ private void addSendMailTask(final MimeMessage message){ try{ taskExecutor.execute(new Runnable() { @Override public void run() { javaMailSender.send(message); } }); }catch (Exception e){ logger.error("邮件发送异常,邮件详细信息为{}",e.getMessage()); } } }