2024年3月

Java Mail发送邮件email 支持SSL加密、TSL加密

类型服务名称服务器地址SSL协议端口非SSL协议端口TSL协议端口
收件服务器POPpop.163.com995110
收件服务器IMAPmap.163.com993143
发件服务器SMTPsmtp.163.com465/99425587

POM依赖:
注意:不要依赖javax.mail javax.mail-api 1.6.2,不然会提示:java.lang.NoClassDefFoundError: com/sun/mail/util/MailLogger

<dependency>
    <groupId>com.sun.mail</groupId>
    <artifactId>javax.mail</artifactId>
    <version>1.6.2</version>
</dependency>

Java Mail代码如下:

/**
 * 发送邮件
 *
 * @param toEmails    收件人列表
 * @param ccEmails    抄送人列表
 * @param subject     主题
 * @param htmlContent 邮件正文
 * @param files       附件。Key:附件的文件 Value:显示文件名
 */
public void sendByJavaMail(String[] toEmails, String[] ccEmails, String subject, String htmlContent, Map<String, String> files) {
    // 获取邮件配置
    final String mailServerUsername = "{你的邮箱地址,例如:xxx@163.com}",
        mailServerPassword = "{你的邮箱密码或授权密码}",      
        mailFrom = "{你的邮箱发件人地址,例如:xxx@163.com}",
        mailFromDisplayName = "{希望收件人看到的发件人显示名称,例如:报警服务}";
    if (Strings.isBlank(mailServerUsername) || Strings.isBlank(mailServerPassword) || Strings.isBlank(mailFrom)) {
        throw new ApiException("Email sending service is not set up, please contact the platform if there are any issues.");
    }
    // 设置邮箱服务属性
    Properties props = new Properties();
    props.setProperty("mail.smtp.host", "smtp.163.com");
    props.setProperty("mail.smtp.auth", "true");
    // "mail.smtp.host":"smtp.gmail.com" "mail.smtp.auth":"true" "mail.smtp.port":"587" "mail.smtp.starttls.enable":"true" "mail.smtp.ssl.protocols":"TLSv1.2"
    // TLS需要内容项:"mail.smtp.starttls.enable":"true" "mail.smtp.port":"587"
    // SSL需要内容项:"mail.smtp.ssl.enable":"true" "mail.smtp.port":"465" "mail.smtp.socketFactory.class":"javax.net.ssl.SSLSocketFactory"
    props.setProperty("mail.smtp.ssl.enable", "true");
    props.setProperty("mail.smtp.port", "465");
    props.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");    

    // 获取默认的 Session 对象。
    Session session = Session.getInstance(props, new Authenticator() {
        @Override
        protected PasswordAuthentication getPasswordAuthentication() {
            return new PasswordAuthentication(mailServerUsername, mailServerPassword);
        }
    });
    // 是否配置debug打印日志信息
    session.setDebug(true);
    try {
        // 创建默认的 MimeMessage 对象。
        MimeMessage message = new MimeMessage(session);
        // 发送方邮箱
        Address fromAddress = Strings.isBlank(mailFromDisplayName) ? new InternetAddress(mailFrom) : new InternetAddress(mailFrom, mailFromDisplayName, "utf-8");
        message.setFrom(fromAddress);
        // 接收方邮箱
        for (String toEmail : toEmails) {
            message.addRecipient(Message.RecipientType.TO, new InternetAddress(toEmail));
        }
        // 抄送邮件列表
        if (null != ccEmails && ccEmails.length > 0) {
            for (String ccEmail : ccEmails) {
                message.addRecipient(Message.RecipientType.CC, new InternetAddress(ccEmail));
            }
        }
        // 设置主题
        message.setSubject(subject);

        /* 消息部分 */
        // 正文
        Multipart multipart = new MimeMultipart();
        // HTML消息
        BodyPart htmlBodyPart = new MimeBodyPart();
        htmlBodyPart.setContent(htmlContent, "text/html;charset=UTF-8");
        multipart.addBodyPart(htmlBodyPart);
        // 设置附件
        if (null != files && !files.isEmpty()) {
            for (Map.Entry<String, String> entry : files.entrySet()) {
                final String file = entry.getKey(), filename = entry.getValue();
                BodyPart fileBodyPart = new MimeBodyPart();
                DataSource source = new FileDataSource(file);
                fileBodyPart.setDataHandler(new DataHandler(source));
                // fileBodyPart.setFileName(filename);
                fileBodyPart.setFileName(MimeUtility.encodeText(filename, "UTF-8", "B"));
                multipart.addBodyPart(fileBodyPart);
            }
        }
        message.setContent(multipart);
        // 发送消息
        log.debug(">>>>>>>>>>sendByJavaMail---sending--<<<<<<<<<<<<<<");
        Transport.send(message);
    } catch (Exception e) {
        log.error("", e);
    } finally {
        // 根据业务需求,是否删除附件的文件
        if (null != files && !files.isEmpty()) {
            for (Map.Entry<String, String> entry : files.entrySet()) {
                Files.deleteQuietly(new File(entry.getKey()));
            }
        }
    }
}