首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >java: send mail using javamail 1.6.2

java: send mail using javamail 1.6.2

作者头像
geovindu
发布2026-06-18 18:01:19
发布2026-06-18 18:01:19
140
举报
代码语言:javascript
复制
/**
 *geovindu,Geovin Du,涂聚文
 *
 */
public static void sendEmail() {
    // 配置邮件服务器属性
    Properties properties = new Properties();
    properties.put("mail.smtp.host", "smtp.qq.com");
    properties.put("mail.smtp.port", "465");
    properties.put("mail.smtp.auth", "true");
    properties.put("mail.smtp.ssl.enable", "true");
    properties.put("mail.debug", "true");
 
    // 创建会话对象并提供身份验证
    Session session = Session.getInstance(properties, new Authenticator() {
        @Override
        protected PasswordAuthentication getPasswordAuthentication() {
            // 请替换为你的邮箱和授权码
            return new PasswordAuthentication("463588883@qq.com", "88888888");
        }
    });
 
    try {
        // 创建邮件消息
        MimeMessage message = new MimeMessage(session);
        message.setFrom(new InternetAddress("463588883@qq.com"));
        message.setRecipients(Message.RecipientType.TO,
                InternetAddress.parse("geovindu@163.com"));
        message.setSubject("JavaMail 测试邮件");
        message.setSentDate(new Date());
 
        // 1. 创建图片BodyPart
        MimeBodyPart imagePart = new MimeBodyPart();
        String imagePath = "resources/附件.jpg";
        File imageFile = new File(imagePath);
 
        if (!imageFile.exists()) {
            System.err.println("图片文件不存在: " + imageFile.getAbsolutePath());
            return;
        }
 
        DataHandler imageDataHandler = new DataHandler(new FileDataSource(imageFile));
        imagePart.setDataHandler(imageDataHandler);
        imagePart.setContentID("mailTestPic");
 
        // 2. 创建文本BodyPart
        MimeBodyPart textPart = new MimeBodyPart();
        String htmlContent = "这是一封通过 JavaMail 发送的测试邮件。<br><br>" +
                "测试内容这是一张图片<br/><a href='http://www.cnblogs.com/geovindu'>" +
                "<img src='cid:mailTestPic' alt='测试图片' border='0'/></a>";
        textPart.setContent(htmlContent, "text/html;charset=UTF-8");
 
        // 3. 创建文本+图片的related部分
        MimeMultipart relatedMultipart = new MimeMultipart("related");
        relatedMultipart.addBodyPart(textPart);
        relatedMultipart.addBodyPart(imagePart);
 
        // 4. 将related部分包装成一个BodyPart
        MimeBodyPart relatedBodyPart = new MimeBodyPart();
        relatedBodyPart.setContent(relatedMultipart);
 
        // 5. 创建附件BodyPart
        MimeBodyPart attachmentPart = new MimeBodyPart();
        String attachmentPath = "resources/附件.zip";
        File attachmentFile = new File(attachmentPath);
 
        if (!attachmentFile.exists()) {
            System.err.println("附件文件不存在: " + attachmentFile.getAbsolutePath());
            return;
        }
 
        DataHandler attachmentDataHandler = new DataHandler(new FileDataSource(attachmentFile));
        attachmentPart.setDataHandler(attachmentDataHandler);
 
        // 设置附件文件名
        String fileName = attachmentFile.getName();
        try {
            attachmentPart.setFileName(MimeUtility.encodeText(fileName, "UTF-8", "B"));
        } catch (Exception e) {
            attachmentPart.setFileName(fileName);
            e.printStackTrace();
        }
 
        // 6. 创建最终的mixed multipart(包含related部分和附件)
        MimeMultipart mixedMultipart = new MimeMultipart("mixed");
        mixedMultipart.addBodyPart(relatedBodyPart);
        mixedMultipart.addBodyPart(attachmentPart);
 
        // 7. 设置邮件内容
        message.setContent(mixedMultipart);
 
        // 8. 发送邮件
        Transport.send(message);
        System.out.println("邮件发送成功!");
 
    } catch (MessagingException e) {
        System.err.println("邮件发送失败: " + e.getMessage());
        e.printStackTrace();
    }
}

代码语言:javascript
复制
/**
     * 同步发送邮件(默认方式)
     * @param to
     * @param subject
     * @param content
     */
    public static void sendEmailSync(String to, String subject, String content) {
        Properties props = new Properties();
        props.put("mail.smtp.host", "smtp.qq.com");
        props.put("mail.smtp.port", "465");
        props.put("mail.smtp.auth", "true");
        props.put("mail.smtp.ssl.enable", "true");

        Session session = Session.getInstance(props, new Authenticator() {
            @Override
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication("463588883@qq.com", "888888888");
            }
        });

        try {
            Message message = new MimeMessage(session);
            message.setFrom(new InternetAddress("463588883@qq.com"));
            message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(to));
            message.setSubject(subject);
            message.setContent(content, "text/html;charset=UTF-8");

            // 同步发送 - 主线程等待
            long startTime = System.currentTimeMillis();
            Transport.send(message);
            long endTime = System.currentTimeMillis();

            System.out.println("邮件同步发送成功!耗时: " + (endTime - startTime) + "ms");

        } catch (MessagingException e) {
            System.err.println("邮件发送失败: " + e.getMessage());
            e.printStackTrace();
        }
    }

    // 创建线程池
    private static final ExecutorService executorService = Executors.newFixedThreadPool(5);

    /**
     * 异步发送邮件
     * @param to
     * @param subject
     * @param content
     * @return
     */
    public static Future<Boolean> sendEmailAsync(String to, String subject, String content) {
        return executorService.submit(() -> {
            Properties props = new Properties();
            props.put("mail.smtp.host", "smtp.qq.com");
            props.put("mail.smtp.port", "465");
            props.put("mail.smtp.auth", "true");
            props.put("mail.smtp.ssl.enable", "true");
            props.put("mail.debug", "false");

            Session session = Session.getInstance(props, new Authenticator() {
                @Override
                protected PasswordAuthentication getPasswordAuthentication() {
                    return new PasswordAuthentication("463588883@qq.com", "88888888");
                }
            });

            try {
                Message message = new MimeMessage(session);
                message.setFrom(new InternetAddress("463588883@qq.com"));
                message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(to));
                message.setSubject(subject);
                message.setContent(content, "text/html;charset=UTF-8");

                long startTime = System.currentTimeMillis();
                Transport.send(message);
                long endTime = System.currentTimeMillis();

                System.out.println(Thread.currentThread().getName() + " - 邮件异步发送成功!耗时: " +
                        (endTime - startTime) + "ms");
                return true;

            } catch (MessagingException e) {
                System.err.println(Thread.currentThread().getName() + " - 邮件发送失败: " + e.getMessage());
                e.printStackTrace();
                return false;
            }
        });
    }

    /**
     * 并行发送多封邮件
     * @param to
     * @param subject
     * @param content
     * @return
     */
    public static CompletableFuture<Boolean> sendEmail(String to, String subject, String content) {
        return CompletableFuture.supplyAsync(() -> {
            Properties props = new Properties();
            props.put("mail.smtp.host", "smtp.qq.com");
            props.put("mail.smtp.port", "465");
            props.put("mail.smtp.auth", "true");
            props.put("mail.smtp.ssl.enable", "true");
            props.put("mail.debug", "false");

            Session session = Session.getInstance(props, new Authenticator() {
                @Override
                protected PasswordAuthentication getPasswordAuthentication() {
                    return new PasswordAuthentication("463588883@qq.com", "88888888");
                }
            });

            try {
                Message message = new MimeMessage(session);
                message.setFrom(new InternetAddress("463588883@qq.com"));
                message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(to));
                message.setSubject(subject);
                message.setContent(content, "text/html;charset=UTF-8");

                long startTime = System.currentTimeMillis();
                Transport.send(message);
                long endTime = System.currentTimeMillis();

                System.out.println(Thread.currentThread().getName() + " - 邮件发送成功: " + to +
                        ", 耗时: " + (endTime - startTime) + "ms");
                return true;

            } catch (MessagingException e) {
                System.err.println(Thread.currentThread().getName() + " - 邮件发送失败: " + to +
                        ", 错误: " + e.getMessage());
                e.printStackTrace();
                return false;
            }
        }, executorService);
    }

    /**
     *
     * @param recipients
     * @param subject
     * @param content
     */
    public static void sendEmailsParallel(List<String> recipients, String subject, String content) {
        List<CompletableFuture<Boolean>> futures = recipients.stream()
                .map(recipient -> sendEmail(recipient, subject, content))
                .collect(Collectors.toList());

        // 等待所有邮件发送完成
        CompletableFuture<Void> allFutures = CompletableFuture.allOf(
                futures.toArray(new CompletableFuture[0])
        );

        // 获取所有结果
        CompletableFuture<List<Boolean>> allResults = allFutures.thenApply(v ->
                futures.stream()
                        .map(CompletableFuture::join)
                        .collect(Collectors.toList())
        );

        // 处理结果
        allResults.thenAccept(results -> {
            long successCount = results.stream().filter(Boolean::booleanValue).count();
            System.out.println("并行发送完成!成功: " + successCount + ", 失败: " + (results.size() - successCount));
        });
    }

修改一下:

代码语言:javascript
复制
/**
 * encoding: utf-8
 * 版权所有 2025 ©涂聚文有限公司 ®
 * 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
 * 描述:
 * Author    : geovindu,Geovin Du 涂聚文.
 * IDE       : IntelliJ IDEA 2024.3.6 Java 17
 * # database  : Oracle21c,MySQL 9.0,SQL Server 2019,PostgreSQL 17.1 Neo4j
 * # OS        : window10
 * Datetime  : 2025 - 2025/10/27 - 21:07
 * User      : geovindu
 * Product   : IntelliJ IDEA
 * Project   : swingdemo
 * File      : MailConfig.java
 * explain   : 学习  类
 **/

package com.example.mail.config;

import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.InputStream;
import java.util.concurrent.TimeUnit;

/**
 * 邮件配置类
 */
public class MailConfig {
    private SmtpConfig smtp;
    private SenderConfig sender;
    private ThreadPoolConfig threadPool;
    private RetryConfig retry;

    // 单例实例
    private static volatile MailConfig instance;

    private MailConfig() {
        // 私有构造方法
    }

    /**
     * 获取单例实例
     * @return MailConfig实例
     */
    public static MailConfig getInstance() {
        if (instance == null) {
            synchronized (MailConfig.class) {
                if (instance == null) {
                    instance = loadConfig();
                }
            }
        }
        return instance;
    }

    /**
     * 从配置文件加载配置
     * @return 加载的MailConfig对象
     */
    private static MailConfig loadConfig() {
        try {
            ObjectMapper objectMapper = new ObjectMapper();
            InputStream inputStream = MailConfig.class.getClassLoader().getResourceAsStream("mail-config.json");
            if (inputStream == null) {
                throw new RuntimeException("找不到邮件配置文件 mail-config.json");
            }
            return objectMapper.readValue(inputStream, MailConfig.class);
        } catch (Exception e) {
            throw new RuntimeException("加载邮件配置文件失败", e);
        }
    }

    // Getters
    public SmtpConfig getSmtp() {
        return smtp;
    }

    public SenderConfig getSender() {
        return sender;
    }

    public ThreadPoolConfig getThreadPool() {
        return threadPool;
    }

    public RetryConfig getRetry() {
        return retry;
    }

    /**
     * SMTP配置
     */
    public static class SmtpConfig {
        private String host;
        private String port;
        private boolean auth;
        private boolean sslEnable;
        private boolean debug;

        // Getters
        public String getHost() {
            return host;
        }

        public String getPort() {
            return port;
        }

        public boolean isAuth() {
            return auth;
        }

        public boolean isSslEnable() {
            return sslEnable;
        }

        public boolean isDebug() {
            return debug;
        }
    }

    /**
     * 发送者配置
     */
    public static class SenderConfig {
        private String email;
        private String password;
        private String name;

        // Getters
        public String getEmail() {
            return email;
        }

        public String getPassword() {
            return password;
        }

        public String getName() {
            return name;
        }
    }

    /**
     * 线程池配置
     */
    public static class ThreadPoolConfig {
        private int corePoolSize;
        private int maximumPoolSize;
        private long keepAliveTime;
        private String unit;
        private int queueCapacity;

        // Getters
        public int getCorePoolSize() {
            return corePoolSize;
        }

        public int getMaximumPoolSize() {
            return maximumPoolSize;
        }

        public long getKeepAliveTime() {
            return keepAliveTime;
        }

        public TimeUnit getUnit() {
            return TimeUnit.valueOf(unit);
        }

        public int getQueueCapacity() {
            return queueCapacity;
        }
    }

    /**
     * 重试配置
     */
    public static class RetryConfig {
        private int maxRetries;
        private long retryDelay;

        // Getters
        public int getMaxRetries() {
            return maxRetries;
        }

        public long getRetryDelay() {
            return retryDelay;
        }
    }
}
代码语言:javascript
复制
/**
 * encoding: utf-8
 * 版权所有 2025 ©涂聚文有限公司 ®
 * 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
 * 描述:
 * Author    : geovindu,Geovin Du 涂聚文.
 * IDE       : IntelliJ IDEA 2024.3.6 Java 17
 * # database  : Oracle21c,MySQL 9.0,SQL Server 2019,PostgreSQL 17.1 Neo4j
 * # OS        : window10
 * Datetime  : 2025 - 2025/10/27 - 21:16
 * User      : geovindu
 * Product   : IntelliJ IDEA
 * Project   : swingdemo
 * File      : MailCallback.java
 * explain   : 学习  类
 **/

package com.example.mail.core;

/**
 * 邮件发送回调接口
 */
public interface MailCallback {

    /**
     * 邮件发送成功回调
     * @param message 发送的邮件消息
     * @param duration 发送耗时(毫秒)
     */
    void onSuccess(MailMessage message, long duration);

    /**
     * 邮件发送失败回调
     * @param message 发送的邮件消息
     * @param throwable 失败原因
     */
    void onFailure(MailMessage message, Throwable throwable);
}



/**
 * encoding: utf-8
 * 版权所有 2025 ©涂聚文有限公司 ®
 * 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
 * 描述:
 * Author    : geovindu,Geovin Du 涂聚文.
 * IDE       : IntelliJ IDEA 2024.3.6 Java 17
 * # database  : Oracle21c,MySQL 9.0,SQL Server 2019,PostgreSQL 17.1 Neo4j
 * # OS        : window10
 * Datetime  : 2025 - 2025/10/27 - 21:17
 * User      : geovindu
 * Product   : IntelliJ IDEA
 * Project   : swingdemo
 * File      : MailMessage.java
 * explain   : 学习  类
 **/

package com.example.mail.core;

import java.io.File;

/**
 * 邮件消息类,封装邮件内容
 */
public class MailMessage {
    private String[] to;
    private String[] cc;
    private String[] bcc;
    private String subject;
    private String content;
    private boolean html;
    private File[] attachments;

    // 私有构造方法,通过Builder创建
    private MailMessage(Builder builder) {
        this.to = builder.to;
        this.cc = builder.cc;
        this.bcc = builder.bcc;
        this.subject = builder.subject;
        this.content = builder.content;
        this.html = builder.html;
        this.attachments = builder.attachments;
    }

    // Getters
    public String[] getTo() {
        return to;
    }

    public String[] getCc() {
        return cc;
    }

    public String[] getBcc() {
        return bcc;
    }

    public String getSubject() {
        return subject;
    }

    public String getContent() {
        return content;
    }

    public boolean isHtml() {
        return html;
    }

    public File[] getAttachments() {
        return attachments;
    }

    /**
     * 邮件消息构建器
     */
    public static class Builder {
        private String[] to;
        private String[] cc;
        private String[] bcc;
        private String subject;
        private String content;
        private boolean html = false;
        private File[] attachments;

        /**
         * 设置收件人
         * @param to 收件人邮箱数组
         * @return Builder
         */
        public Builder to(String... to) {
            this.to = to;
            return this;
        }

        /**
         * 设置抄送
         * @param cc 抄送邮箱数组
         * @return Builder
         */
        public Builder cc(String... cc) {
            this.cc = cc;
            return this;
        }

        /**
         * 设置密送
         * @param bcc 密送邮箱数组
         * @return Builder
         */
        public Builder bcc(String... bcc) {
            this.bcc = bcc;
            return this;
        }

        /**
         * 设置邮件主题
         * @param subject 邮件主题
         * @return Builder
         */
        public Builder subject(String subject) {
            this.subject = subject;
            return this;
        }

        /**
         * 设置邮件内容
         * @param content 邮件内容
         * @return Builder
         */
        public Builder content(String content) {
            this.content = content;
            return this;
        }

        /**
         * 设置是否为HTML邮件
         * @param html 是否为HTML邮件
         * @return Builder
         */
        public Builder html(boolean html) {
            this.html = html;
            return this;
        }

        /**
         * 设置附件
         * @param attachments 附件文件数组
         * @return Builder
         */
        public Builder attachments(File... attachments) {
            this.attachments = attachments;
            return this;
        }

        /**
         * 构建MailMessage对象
         * @return MailMessage
         */
        public MailMessage build() {
            if (to == null || to.length == 0) {
                throw new IllegalArgumentException("收件人不能为空");
            }
            if (subject == null || subject.trim().isEmpty()) {
                throw new IllegalArgumentException("邮件主题不能为空");
            }
            if (content == null || content.trim().isEmpty()) {
                throw new IllegalArgumentException("邮件内容不能为空");
            }
            return new MailMessage(this);
        }
    }
}



/**
 * encoding: utf-8
 * 版权所有 2025 ©涂聚文有限公司 ®
 * 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
 * 描述:
 * Author    : geovindu,Geovin Du 涂聚文.
 * IDE       : IntelliJ IDEA 2024.3.6 Java 17
 * # database  : Oracle21c,MySQL 9.0,SQL Server 2019,PostgreSQL 17.1 Neo4j
 * # OS        : window10
 * Datetime  : 2025 - 2025/10/27 - 21:17
 * User      : geovindu
 * Product   : IntelliJ IDEA
 * Project   : swingdemo
 * File      : MailSender.java
 * explain   : 学习  类
 **/

package com.example.mail.core;
import com.example.mail.config.MailConfig;
import com.example.mail.exception.MailException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

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;
import java.util.concurrent.*;
import java.util.stream.Collectors;

/**
 * 邮件发送工具类
 */
public class MailSender {
    private static final Logger logger = LoggerFactory.getLogger(MailSender.class);
    private static final MailConfig config = MailConfig.getInstance();
    private static final ExecutorService executorService;

    static {
        // 初始化线程池
        MailConfig.ThreadPoolConfig threadPoolConfig = config.getThreadPool();
        executorService = new ThreadPoolExecutor(
                threadPoolConfig.getCorePoolSize(),
                threadPoolConfig.getMaximumPoolSize(),
                threadPoolConfig.getKeepAliveTime(),
                threadPoolConfig.getUnit(),
                new LinkedBlockingQueue<>(threadPoolConfig.getQueueCapacity()),
                new ThreadPoolExecutor.CallerRunsPolicy()
        );
    }

    /**
     * 同步发送邮件
     * @param message 邮件消息
     * @throws MailException 邮件发送异常
     */
    public static void send(MailMessage message) throws MailException {
        long startTime = System.currentTimeMillis();
        try {
            doSend(message);
            long duration = System.currentTimeMillis() - startTime;
            logger.info("邮件同步发送成功,收件人: {}, 耗时: {}ms",
                    String.join(",",message.getTo()), duration);
        } catch (MessagingException e) {
            logger.error("邮件同步发送失败,收件人: {}",
                    String.join(",", message.getTo()), e);
            throw new MailException("邮件发送失败", e);
        }
    }

    /**
     * 异步发送邮件
     * @param message 邮件消息
     * @return Future对象,可用于获取发送结果
     */
    public static Future<Boolean> sendAsync(MailMessage message) {
        return executorService.submit(() -> {
            long startTime = System.currentTimeMillis();
            try {
                doSend(message);
                long duration = System.currentTimeMillis() - startTime;
                logger.info("邮件异步发送成功,收件人: {}, 耗时: {}ms",
                        String.join(",", message.getTo()), duration);
                return true;
            } catch (MessagingException e) {
                logger.error("邮件异步异步发送失败,收件人: {}",
                        String.join(",", message.getTo()), e);
                return false;
            }
        });
    }

    /**
     * 异步发送邮件(带回调)
     * @param message 邮件消息
     * @param callback 回调接口
     */
    public static void sendAsync(MailMessage message, MailCallback callback) {
        executorService.submit(() -> {
            long startTime = System.currentTimeMillis();
            try {
                doSend(message);
                long duration = System.currentTimeMillis() - startTime;
                logger.info("邮件异步发送成功,收件人: {}, 耗时: {}ms",
                        String.join(",", message.getTo()), duration);
                if (callback != null) {
                    callback.onSuccess(message, duration);
                }
            } catch (MessagingException e) {
                logger.error("邮件异步发送失败,收件人: {}",
                        String.join(",", message.getTo()), e);
                if (callback != null) {
                    callback.onFailure(message, e);
                }
            }
        });
    }

    /**
     * 并行发送多封邮件
     * @param messages 邮件消息列表
     * @return CompletableFuture,可用于获取所有邮件的发送结果
     */
    public static CompletableFuture<java.util.List<Boolean>> sendParallel(java.util.List<MailMessage> messages) {
        java.util.List<CompletableFuture<Boolean>> futures = messages.stream()
                .map(message -> CompletableFuture.supplyAsync(() -> {
                    long startTime = System.currentTimeMillis();
                    try {
                        doSend(message);
                        long duration = System.currentTimeMillis() - startTime;
                        logger.info("邮件并行发送成功,收件人: {}, 耗时: {}ms",
                                String.join(",", message.getTo()), duration);
                        return true;
                    } catch (MessagingException e) {
                        logger.error("邮件并行发送失败,收件人: {}",
                                String.join(",", message.getTo()), e);
                        return false;
                    }
                }, executorService))
                .collect(Collectors.toList());

        return CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]))
                .thenApply(v -> futures.stream()
                        .map(CompletableFuture::join)
                        .collect(Collectors.toList()));
    }

    /**
     * 批量发送邮件(同一内容,多个收件人)
     * @param to 收件人数组
     * @param subject 邮件主题
     * @param content 邮件内容
     * @param attachments 附件数组
     * @return CompletableFuture,可用于获取发送结果
     */
    public static CompletableFuture<Boolean> sendBatch(String[] to, String subject, String content, java.io.File[] attachments) {
        MailMessage message = new MailMessage.Builder()
                .to(to)
                .subject(subject)
                .content(content)
                .attachments(attachments)
                .build();

        return CompletableFuture.supplyAsync(() -> {
            long startTime = System.currentTimeMillis();
            try {
                doSend(message);
                long duration = System.currentTimeMillis() - startTime;
                logger.info("邮件批量发送成功,收件人数量: {}, 耗时: {}ms",
                        to.length, duration);
                return true;
            } catch (MessagingException e) {
                logger.error("邮件批量发送失败,收件人数量: {}",
                        to.length, e);
                return false;
            }
        }, executorService);
    }

    /**
     * 实际发送邮件的内部方法
     * @param message 邮件消息
     * @throws MessagingException 邮件发送异常
     */
    private static void doSend(MailMessage message) throws MessagingException {
        // 获取SMTP配置
        MailConfig.SmtpConfig smtpConfig = config.getSmtp();
        MailConfig.SenderConfig senderConfig = config.getSender();
        MailConfig.RetryConfig retryConfig = config.getRetry();

        // 创建Properties对象
        Properties props = new Properties();
        props.put("mail.smtp.host", smtpConfig.getHost());
        props.put("mail.smtp.port", smtpConfig.getPort());
        props.put("mail.smtp.auth", smtpConfig.isAuth());
        props.put("mail.smtp.ssl.enable", smtpConfig.isSslEnable());
        props.put("mail.debug", smtpConfig.isDebug());

        // 创建Session对象
        Session session = Session.getInstance(props, new Authenticator() {
            @Override
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication(
                        senderConfig.getEmail(),
                        senderConfig.getPassword()
                );
            }
        });

        // 创建MimeMessage对象
        MimeMessage mimeMessage = new MimeMessage(session);
        try {
            mimeMessage.setFrom(new InternetAddress(senderConfig.getEmail(), senderConfig.getName()));
        } catch (java.io.UnsupportedEncodingException e) {
            logger.error("设置发件人名称编码失败", e);
            throw new MessagingException("设置发件人失败", e);
        }

        // 设置收件人
        if (message.getTo() != null && message.getTo().length > 0) {
            mimeMessage.setRecipients(Message.RecipientType.TO,
                    InternetAddress.parse(String.join(",", message.getTo())));
        }

        // 设置抄送
        if (message.getCc() != null && message.getCc().length > 0) {
            mimeMessage.setRecipients(Message.RecipientType.CC,
                    InternetAddress.parse(String.join(",", message.getCc())));
        }

        // 设置密送
        if (message.getBcc() != null && message.getBcc().length > 0) {
            mimeMessage.setRecipients(Message.RecipientType.BCC,
                    InternetAddress.parse(String.join(",", message.getBcc())));
        }

        // 设置主题
        mimeMessage.setSubject(message.getSubject(), "UTF-8");

        // 创建Multipart对象
        Multipart multipart = new MimeMultipart();

        // 创建邮件正文部分
        MimeBodyPart contentPart = new MimeBodyPart();
        contentPart.setContent(message.getContent(),
                message.isHtml() ? "text/html;charset=UTF-8" : "text/plain;charset=UTF-8");
        multipart.addBodyPart(contentPart);

        // 添加附件
        if (message.getAttachments() != null && message.getAttachments().length > 0) {
            for (java.io.File attachment : message.getAttachments()) {
                if (attachment.exists() && attachment.isFile()) {
                    MimeBodyPart attachmentPart = new MimeBodyPart();
                    FileDataSource dataSource = new FileDataSource(attachment);
                    attachmentPart.setDataHandler(new DataHandler(dataSource));
                    try {
                        attachmentPart.setFileName(javax.mail.internet.MimeUtility.encodeWord(attachment.getName()));
                    } catch (java.io.UnsupportedEncodingException e) {
                        logger.error("附件文件名编码失败: {}", attachment.getName(), e);
                        throw new MessagingException("设置附件文件名失败", e);
                    }
                    multipart.addBodyPart(attachmentPart);
                } else {
                    logger.warn("附件不存在或不是文件: {}", attachment.getAbsolutePath());
                }
            }
        }

        // 设置邮件内容
        mimeMessage.setContent(multipart);

        // 发送邮件(带重试机制)
        int retryCount = 0;
        while (true) {
            try {
                Transport.send(mimeMessage);
                break;
            } catch (MessagingException e) {
                if (retryCount < retryConfig.getMaxRetries()) {
                    retryCount++;
                    logger.warn("邮件发送失败,正在重试第 {} 次...", retryCount, e);
                    try {
                        Thread.sleep(retryConfig.getRetryDelay());
                    } catch (InterruptedException ie) {
                        Thread.currentThread().interrupt();
                        throw e;
                    }
                } else {
                    logger.error("邮件发送失败,已达到最大重试次数: {}", retryConfig.getMaxRetries(), e);
                    throw e;
                }
            }
        }
    }

    /**
     * 关闭线程池
     */
    public static void shutdown() {
        executorService.shutdown();
        try {
            if (!executorService.awaitTermination(60, TimeUnit.SECONDS)) {
                executorService.shutdownNow();
            }
        } catch (InterruptedException e) {
            executorService.shutdownNow();
        }
        logger.info("邮件发送线程池已关闭");
    }
}
代码语言:javascript
复制
/**
 * encoding: utf-8
 * 版权所有 2025 ©涂聚文有限公司 ®
 * 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
 * 描述:
 * Author    : geovindu,Geovin Du 涂聚文.
 * IDE       : IntelliJ IDEA 2024.3.6 Java 17
 * # database  : Oracle21c,MySQL 9.0,SQL Server 2019,PostgreSQL 17.1 Neo4j
 * # OS        : window10
 * Datetime  : 2025 - 2025/10/27 - 21:18
 * User      : geovindu
 * Product   : IntelliJ IDEA
 * Project   : swingdemo
 * File      : MailException.java
 * explain   : 学习  类
 **/

package com.example.mail.exception;

/**
 * 邮件发送异常类
 */
public class MailException extends Exception {

    private static final long serialVersionUID = 1L;

    /**
     * 错误码
     */
    private String errorCode;

    /**
     * 构造方法
     * @param message 错误消息
     */
    public MailException(String message) {
        super(message);
    }

    /**
     * 构造方法
     * @param message 错误消息
     * @param cause 异常原因
     */
    public MailException(String message, Throwable cause) {
        super(message, cause);
    }

    /**
     * 构造方法
     * @param errorCode 错误码
     * @param message 错误消息
     */
    public MailException(String errorCode, String message) {
        super(message);
        this.errorCode = errorCode;
    }

    /**
     * 构造方法
     * @param errorCode 错误码
     * @param message 错误消息
     * @param cause 异常原因
     */
    public MailException(String errorCode, String message, Throwable cause) {
        super(message, cause);
        this.errorCode = errorCode;
    }

    // Getter
    public String getErrorCode() {
        return errorCode;
    }
}

调用:

代码语言:javascript
复制
 /**
     *
     * @param args
     */
    public static void main(String[] args) {

        //sendEmail();
        try {
            // 直接加载配置,验证是否成功
            MailConfig config = MailConfig.getInstance();
            System.out.println("SMTP主机: " + config.getSmtp().getHost());
            System.out.println("发送者邮箱: " + config.getSender().getEmail());
        } catch (Exception e) {
            e.printStackTrace(); // 打印具体异常原因
        }

        try {
            // 测试同步发送邮件
            testSyncSend();

            // 测试异步发送邮件
            testAsyncSend();

            // 测试并行发送邮件
            testParallelSend();

            // 测试批量发送邮件
            testBatchSend();

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 关闭线程池
            MailSender.shutdown();
        }


        // 初始化依赖
        //var userRepository = new InMemoryUserRepository();
        //var loginService = new LoginApplicationService(userRepository);

        // 启动应用 - 显示登录窗口
        //javax.swing.SwingUtilities.invokeLater(() -> new LoginWindow(loginService));

        //System.out.println("Hello, World!");
    }

    /**
     * 测试同步发送邮件
     */
    private static void testSyncSend() {
        System.out.println("=== 测试同步发送邮件 ===");
        try {
            MailMessage message = new MailMessage.Builder()
                    .to("geovindu@163.com")
                    .subject("测试同步发送邮件")
                    .content("这是一封测试同步发送的邮件")
                    .html(false)
                    .build();

            MailSender.send(message);
            System.out.println("同步发送邮件成功");
        } catch (MailException e) {
            System.err.println("同步发送邮件失败: " + e.getMessage());
        }
        System.out.println();
    }

    /**
     * 测试异步发送邮件
     */
    private static void testAsyncSend() throws InterruptedException, ExecutionException {
        System.out.println("=== 测试异步发送邮件 ===");
        MailMessage message = new MailMessage.Builder()
                .to("geovindu@163.com")
                .subject("测试异步发送邮件")
                .content("这是一封测试异步发送的邮件")
                .html(false)
                .build();

        Future<Boolean> future = MailSender.sendAsync(message);
        System.out.println("异步发送邮件任务已提交");

        // 等待发送完成并获取结果
        Boolean result = future.get();
        System.out.println("异步发送邮件结果: " + (result ? "成功" : "失败"));
        System.out.println();
    }

    /**
     * 测试并行发送邮件
     */
    private static void testParallelSend() throws InterruptedException, ExecutionException {
        System.out.println("=== 测试并行发送邮件 ===");
        MailMessage message1 = new MailMessage.Builder()
                .to("geovindu@163.com")
                .subject("测试并行发送邮件 1")
                .content("这是第一封测试并行发送的邮件")
                .html(false)
                .build();

        MailMessage message2 = new MailMessage.Builder()
                .to("413265257@qq.com")
                .subject("测试并行发送邮件 2")
                .content("这是第二封测试并行发送的邮件")
                .html(false)
                .build();

        MailMessage message3 = new MailMessage.Builder()
                .to("geovindu@hotmial.com")
                .subject("测试并行发送邮件 3")
                .content("这是第三封测试并行发送的邮件")
                .html(false)
                .build();

        List<MailMessage> messages = Arrays.asList(message1, message2, message3);
        System.out.println("并行发送邮件任务已提交");

        // 等待所有邮件发送完成并获取结果
        List<Boolean> results = MailSender.sendParallel(messages).get();
        long successCount = results.stream().filter(Boolean::booleanValue).count();
        System.out.println("并行发送邮件完成,成功: " + successCount + ", 失败: " + (results.size() - successCount));
        System.out.println();
    }

    /**
     * 测试批量发送邮件
     */
    private static void testBatchSend() throws InterruptedException, ExecutionException {
        System.out.println("=== 测试批量发送邮件 ===");
        String[] to = {"413265257@qq.com", "geovindu@hotmial.com", "geovindu@163.com"};
        String subject = "测试批量发送邮件";
        String content = "这是一封测试批量发送的邮件";

        // 可以添加附件测试
        // File[] attachments = {new File("test.txt"), new File("test.pdf")};

        System.out.println("批量发送邮件任务已提交");

        // 等待发送完成并获取结果
        Boolean result = MailSender.sendBatch(to, subject, content, null).get();
        System.out.println("批量发送邮件结果: " + (result ? "成功" : "失败"));
        System.out.println();
    }

实际邮件收的截图:

所需要的包:

代码语言:javascript
复制
<dependencies>
    <!-- JavaMail API -->
    <dependency>
        <groupId>com.sun.mail</groupId>
        <artifactId>javax.mail</artifactId>
        <version>1.6.2</version>
    </dependency>
    <dependency>
   <groupId>javax.activation</groupId>
   <artifactId>activation</artifactId>
   <version>1.1.1</version>
</dependency>
    <!-- Jackson JSON库 -->
  <!-- 已有的jackson-databind -->
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.13.0</version> <!-- 版本号需统一 -->
    </dependency>
    
    <!-- 添加jackson-annotations依赖 -->
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-annotations</artifactId>
        <version>2.13.0</version> <!-- 与databind版本一致 -->
    </dependency>

<!-- 添加jackson-core依赖(databind也依赖它,保险起见显式声明) -->
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-core</artifactId>
        <version>2.13.0</version> <!-- 与databind版本一致 -->
    </dependency>
    <!-- SLF4J日志框架 -->
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>1.7.32</version>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-simple</artifactId>
        <version>1.7.32</version>
        <scope>runtime</scope>
    </dependency>
</dependencies>

mail-config.json:

代码语言:javascript
复制
{
  "smtp": {
    "host": "smtp.qq.com",
    "port": "465",
    "auth": true,
    "sslEnable": true,
    "debug": false
  },
  "sender": {
    "email": "463588883@qq.com",
    "password": "your_auth_code",
    "name": "邮件发送者"
  },
  "threadPool": {
    "corePoolSize": 5,
    "maximumPoolSize": 10,
    "keepAliveTime": 60,
    "unit": "SECONDS",
    "queueCapacity": 100
  },
  "retry": {
    "maxRetries": 3,
    "retryDelay": 1000
  }
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-10-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档