邮件发送工具类

本文介绍了一个用于发送邮件的工具类实现,包括检查参数、发送邮件等核心功能,并提供了异常处理逻辑来确保邮件能被正确发送。此外,还展示了如何通过示例调用该工具类。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


工具类

package com.morning.star.pt.common.component;

import com.morning.star.exception.CODE;
import com.morning.star.exception.MorningStarException;
import com.morning.star.pt.common.entity.EmailAttachmentVo;
import com.morning.star.pt.common.entity.EmailInfoVo;
import com.morning.star.pt.common.entity.MailAccount;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.mail.*;
import javax.mail.internet.*;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.*;

/**
 * 邮件发送工具类
 *
 */
public class EmailUtils {

    private static final String MAIL_SMTP_HOST = "smtp.exmail.qq.com";
    private static final String MAIL_SMTP_PORT = "465";

    private static Logger logger = LoggerFactory.getLogger(EmailUtils.class);

    public static boolean sendMail(EmailInfoVo mailInfo) {
        try {
            sendMailWithEx(mailInfo);
        }
        catch (Exception ex) {
            logger.warn("发送邮件时出现异常:{}", ex);
            return false;
        }
        return true;
    }

    public static void sendMailWithEx(EmailInfoVo mailInfo) {
        checkParams(mailInfo);
        logger.info("邮件发送参数: 主题 [{}],发件人 [{}],密码 [{}],收件人 [{}],发件人昵称 [{}],smtpServer [{}],smtpPort [{}],邮件内容 [{}],附件个数 [{}]",
                new Object[]{mailInfo.getSubject(), mailInfo.getUserName(), mailInfo.getPassword(),
                        Arrays.asList(mailInfo.getTos()), mailInfo.getSendName(),
                        mailInfo.getSmtpServer(), mailInfo.getSmtpPort(),
                        mailInfo.getContent(),
                        mailInfo.getAttachmentList() != null ? mailInfo.getAttachmentList().size() : 0}
        );

        mailInfo.setFrom(mailInfo.getUserName());
        if (StringUtils.isBlank(mailInfo.getSendName())) {
            mailInfo.setSendName("技术部智能机器人");
        }
        MailAccount account = new MailAccount(mailInfo.getUserName(), mailInfo.getPassword(),
                StringUtils.isBlank(mailInfo.getSmtpServer()) ? MAIL_SMTP_HOST : mailInfo.getSmtpServer(),
                StringUtils.isBlank(mailInfo.getSmtpPort()) ? MAIL_SMTP_PORT : mailInfo.getSmtpPort(),
                true);
        try {
            sendMail(mailInfo, account, false);  //false不用debug模式发送
        } catch (UnsupportedEncodingException e) {
            logger.error("邮件发送出错:", e);
            throw new MorningStarException(new CODE(CODE.FAIL.getIndex(),
                    e.getClass().getSimpleName() + ": " + e.getMessage()));
        } catch (SendFailedException e) {
            //如果发送失败,找出发送失败的邮箱并跳过,只发送有效的邮箱
            //取出失效的邮箱地址,日志记录
            Address[] inVaild = e.getInvalidAddresses();
            if (inVaild != null) {
                for (Address address : inVaild) {
                    logger.error("无效的邮箱:"+address);
                }
            }
            //取出有效且未发送的地址,重新发送一次
            Address[] vaild = e.getValidUnsentAddresses();
            if (vaild != null && vaild.length > 0) {
                String[] new_emails = address2emails(vaild);
                mailInfo.setTos(new_emails);
                try {
                    sendMail(mailInfo, account, false);  //false不用debug模式发送
                } catch (Exception e1) {
                    logger.error("重新发送邮件出错:", e1);
                    throw new MorningStarException(new CODE(CODE.FAIL.getIndex(),
                            e1.getClass().getSimpleName() + ": " + e1.getMessage()));
                }
            }
        } catch (MessagingException |IOException e) {
            logger.error("邮件发送出错:", e);
            throw new MorningStarException(new CODE(CODE.FAIL.getIndex(),
                    e.getClass().getSimpleName() + ": " + e.getMessage()));
        }
    }

    /**
     * 底部发送邮件方法不直接对外调用
     *
     * @param mailInfo 邮件信息
     * @param mailAccount 邮箱账号地址信息
     * @param debug 是否debug打印出发送过程
     *
     * @throws SendFailedException
     * @throws MessagingException
     * @throws IOException
     */
    private static void sendMail(EmailInfoVo mailInfo, MailAccount mailAccount, boolean debug)
            throws SendFailedException, MessagingException, IOException {

        final String userName = mailAccount.getUserName();
        final String password = mailAccount.getPassword();

        String mial_transport_protocol = "smtp";
        Properties props = new Properties();
        if (debug) {
            props.setProperty("mail.debug", "true"); // 开启debug调试
        }
        props.setProperty("mail.transport.protocol", mial_transport_protocol);  // 发送邮件协议名称
        props.setProperty("mail.smtp.auth", "true");                            // 发送服务器需要身份验证
        props.setProperty("mail.smtp.host", mailAccount.getMail_smtp_host());   // 发送邮件服务器

        // 端口
        String mail_smtp_port = mailAccount.getMail_smtp_port();
        if (mail_smtp_port != null && mail_smtp_port.length() > 0) {
            props.setProperty("mail.smtp.port", mail_smtp_port);
        }

        // 使用ssl
        if (mailAccount.isSsl()) {
            String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory";
            props.setProperty("mail.smtp.socketFactory.port", mail_smtp_port);
            props.setProperty("mail.smtp.socketFactory.class", SSL_FACTORY);
            props.setProperty("mail.smtp.socketFactory.fallback", "false");
            props.setProperty("mail.smtp.ssl.enable", "true");
        }

        // 设置环境信息
        Session session = Session.getInstance(props, new Authenticator() {
            @Override
            protected javax.mail.PasswordAuthentication getPasswordAuthentication() {
                return new javax.mail.PasswordAuthentication(userName, password);
            }
        });

        // 定义邮件信息
        Message msg = new MimeMessage(session);
        msg.setSubject(encodeText(mailInfo.getSubject()));                                      // 邮件主题
        msg.setFrom(new InternetAddress(mailInfo.getFrom(), mailInfo.getSendName(), "UTF-8"));  // 发件人
        msg.setRecipients(Message.RecipientType.TO, emails2address(mailInfo.getTos()));         // 收件人
        msg.setSentDate(new Date());                                                            // 发送时间

        // 邮件内容+附件
        MimeMultipart partList = new MimeMultipart();
        msg.setContent(partList);
        // 邮件内容
        MimeBodyPart contentPart = new MimeBodyPart();
        contentPart.setContent(
                (mailInfo.getContent() == null) ? "" : mailInfo.getContent(),
                "text/html;charset=utf-8");
        partList.addBodyPart(contentPart);
        // 附件
        List<File> attachFileList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(mailInfo.getAttachmentList())) {
            for (EmailAttachmentVo attach : mailInfo.getAttachmentList()) {
                // 将附件内容写入临时文件
                File attachFile = createFile(attach);
                attachFileList.add(attachFile);

                MimeBodyPart attachPart = new MimeBodyPart();
                attachPart.attachFile(attachFile);
                if (!StringUtils.isBlank(attach.getFileName())) {
                    attachPart.setFileName(encodeText(attach.getFileName()));
                }
                else {
                    attachPart.setFileName(encodeText(attachFile.getName()));
                }
                partList.addBodyPart(attachPart);
            }
        }

        // 发送邮件
        Transport.send(msg);

        // 删除临时文件
        if (!CollectionUtils.isEmpty(attachFileList)) {
            deleteFile(attachFileList);
        }
    }

    private static void checkParams(EmailInfoVo mailInfo) {
        if (mailInfo==null) {
            logger.error("参数对象为null!");
            throw new MorningStarException(new CODE(CODE.PARAMERROR.index, "EmailInfoVo不能为null"));
        }
        if (StringUtils.isBlank(mailInfo.getUserName())) {
            logger.error("发送邮箱为null!");
            throw new MorningStarException(new CODE(CODE.PARAMERROR.index, "发送邮箱为null"));
        }
        if (mailInfo.getTos() == null || mailInfo.getTos().length < 1) {
            logger.error("收件人邮箱列表为空!");
            throw new MorningStarException(new CODE(CODE.PARAMERROR.index, "收件人邮箱列表为空"));
        }
        if (StringUtils.isBlank(mailInfo.getPassword())) {
            logger.error("发送邮箱密码异常!");
            throw new MorningStarException(new CODE(CODE.PARAMERROR.index, "发送邮箱密码异常"));
        }
        if (!StringUtils.isBlank(mailInfo.getSmtpPort())) {
            int smtpPort;
            try {
                smtpPort = Integer.valueOf(mailInfo.getSmtpPort());
                if (!(0 <= smtpPort && smtpPort <= 65535)) {
                    throw new RuntimeException();
                }
            }
            catch (Exception ex) {
                throw new MorningStarException(new CODE(CODE.PARAMERROR.getIndex(), "发送服务器SMTP端口错误"));
            }
        }
    }

    // 邮件Address数组转为字符串的邮箱数组
    private static String[] address2emails(Address[] address) {
        if(address == null || address.length == 0){
            return new String[]{};
        }

        String[] emails = new String[address.length];
        for (int i = 0; i < address.length; ++i) {
            emails[i] = address[i].toString();
        }
        return emails;
    }

    private static Address[] emails2address(String[] emails) throws AddressException {
        if (emails == null || emails.length == 0) {
            return new Address[]{};
        }

        Address[] address = new Address[emails.length];
        for (int i = 0; i < emails.length; ++i) {
            address[i] = new InternetAddress(emails[i]);
        }
        return address;
    }

    private static String encodeText(String text) throws UnsupportedEncodingException {
        return MimeUtility.encodeText(text, "UTF-8", "B");
    }

    private static File createFile(EmailAttachmentVo attach) throws IOException {
        File attachFile = null;
        attachFile = File.createTempFile("message-email.", ".attach");
        try (FileOutputStream fileout = new FileOutputStream(attachFile)) {
            fileout.write(attach.getFileContent());
            fileout.flush();
            return attachFile;
        }
    }

    private static void deleteFile(File file) {
        if (file != null) {
            try {
                file.delete();
            }
            catch (Exception ex) {
            }
        }
    }

    private static void deleteFile(List<File> fileList) {
        if (!CollectionUtils.isEmpty(fileList)) {
            for (File file : fileList) {
                deleteFile(file);
            }
        }
    }

}


实体EmailInfoVo

package com.morning.star.pt.common.entity;


import java.io.Serializable;
import java.util.List;

public class EmailInfoVo implements Serializable {
    private static final long serialVersionUID = -6814843971004397989L;

    private String subject;     // 邮件主题
    private String content;     // 邮件内容
    private String[] tos;       // 收件人邮箱地址
    private String userName;    // 发送邮件地址
    private String password;    // 发送邮箱密码

    private String from;        // 发件人邮箱地址,非必填
    private String sendName;    // 昵称,非必填
    private String smtpServer;  // 发件服务器SMTP地址,非必填,默认使用 smtp.exmail.qq.com
    private String smtpPort;    // 发件服务器SMTP端口,非必填,默认使用 465
    private List<EmailAttachmentVo> attachmentList; // 附件列表,非必填

    get set 方法省略

}


实体EmailInfoVo

package com.morning.star.pt.common.entity;

import java.io.Serializable;

public class MailAccount implements Serializable {
    /**
     * 邮箱用户名
     */
    private String userName;
    /**
     * 邮箱用户密码
     */
    private String password;
    /**
     * 发送邮件服务器
     */
    private String mail_smtp_host;
    /**
     * 发送邮件端口 (使用默认端口请填null,否则填邮件服务器对应端口;如启用ssl方式发送邮件,请设置邮件服务器ssl端口)
     */
    private String mail_smtp_port;

    /**
     * SSL:使用SSL加密方式发送 true; 否则false
     */
    private boolean ssl;

    public MailAccount() {
    }

    public MailAccount(String userName, String password, String mail_smtp_host,
                       String mail_smtp_port, boolean ssl) {
        this.userName = userName;
        this.password = password;
        this.mail_smtp_host = mail_smtp_host;
        this.mail_smtp_port = mail_smtp_port;
        this.ssl = ssl;
    }

    get set 方法省略


实体EmailAttachmentVo

package com.morning.star.pt.common.entity;

import java.io.Serializable;

public class EmailAttachmentVo implements Serializable {
    private static final long serialVersionUID = 7316991294294102884L;

    private String fileName;
    private byte[] fileContent;

    public EmailAttachmentVo() {
        super();
    }

    public EmailAttachmentVo(String fileName, byte[] fileContent) {
        super();
        this.fileName = fileName;
        this.fileContent = fileContent;
    }

    get set 方法省略
}


调用示例


    @RequestMapping("/testSendEmail")
    @ResponseBody
    public WebJsonBean testSendEmail() {
        EmailInfoVo emailInfoVo = new EmailInfoVo();
        emailInfoVo.setSubject("订单清单");
        emailInfoVo.setContent("测试一下邮件发送");
        emailInfoVo.setTos(new String[]{"x812603834@qq.com"});
        emailInfoVo.setUserName("aaa@hah.com");
        emailInfoVo.setPassword("123456");
        EmailUtils.sendMail(emailInfoVo);
        return new WebJsonBean(CODE.SUCCESS, true);
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值