java: send mail using javamail 1.6.2

 

 

<dependency>
   <groupId>javax.mail</groupId>
   <artifactId>mail</artifactId>
   <version>1.4.7</version>
</dependency>
<dependency>
   <groupId>javax.activation</groupId>
   <artifactId>activation</artifactId>
   <version>1.1.1</version>
</dependency>

  

    /**
     *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", "0000000");
            }
        });

        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();
        }
    }

  

9ba1566eb3659b2cf3be558e5ab7f6bc

 

image

 

在 Java 中发送邮件可以采用不同的执行模式,主要有同步、异步和并行三种方式。下面我将为你详细介绍每种方式的实现方法:

1. 同步发送邮件(默认方式)

同步发送是最简单的方式,主线程会一直等待邮件发送完成。
import javax.mail.*;
import javax.mail.internet.*;
import java.util.Properties;

public class SyncEmailSender {
    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("your-email@qq.com", "your-auth-code");
            }
        });

        try {
            Message message = new MimeMessage(session);
            message.setFrom(new InternetAddress("your-email@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();
        }
    }

    public static void main(String[] args) {
        System.out.println("开始发送邮件...");
        sendEmailSync("recipient@example.com", "同步邮件测试", "这是一封同步发送的邮件");
        System.out.println("邮件发送完成,继续执行其他任务...");
    }
}

  

2. 异步发送邮件

异步发送使用线程池,主线程不会等待邮件发送完成。
import javax.mail.*;
import javax.mail.internet.*;
import java.util.Properties;
import java.util.concurrent.*;

public class AsyncEmailSender {
    // 创建线程池
    private static final ExecutorService executorService = Executors.newFixedThreadPool(5);
    
    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("your-email@qq.com", "your-auth-code");
                }
            });

            try {
                Message message = new MimeMessage(session);
                message.setFrom(new InternetAddress("your-email@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;
            }
        });
    }

    public static void main(String[] args) throws InterruptedException, ExecutionException {
        System.out.println("开始异步发送邮件...");
        
        // 发送邮件但不等待结果
        sendEmailAsync("recipient1@example.com", "异步邮件测试1", "这是第一封异步邮件");
        
        // 发送邮件并获取结果
        Future<Boolean> future = sendEmailAsync("recipient2@example.com", "异步邮件测试2", "这是第二封异步邮件");
        
        // 主线程可以继续执行其他任务
        System.out.println("主线程继续执行其他操作...");
        
        // 等待邮件发送完成并获取结果
        Boolean result = future.get();
        System.out.println("第二封邮件发送结果: " + (result ? "成功" : "失败"));
        
        // 关闭线程池
        executorService.shutdown();
    }
}

  

3. 并行发送多封邮件

并行发送使用 CompletableFuture 实现真正的并行处理。
import javax.mail.*;
import javax.mail.internet.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.*;
import java.util.stream.Collectors;

public class ParallelEmailSender {
    private static final ExecutorService executorService = Executors.newFixedThreadPool(10);
    
    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("your-email@qq.com", "your-auth-code");
                }
            });

            try {
                Message message = new MimeMessage(session);
                message.setFrom(new InternetAddress("your-email@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);
    }

    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));
        });
    }

    public static void main(String[] args) throws InterruptedException {
        System.out.println("开始并行发送多封邮件...");
        
        // 准备收件人列表
        List<String> recipients = new ArrayList<>();
        recipients.add("recipient1@example.com");
        recipients.add("recipient2@example.com");
        recipients.add("recipient3@example.com");
        recipients.add("recipient4@example.com");
        recipients.add("recipient5@example.com");

        // 并行发送
        long startTime = System.currentTimeMillis();
        sendEmailsParallel(recipients, "并行邮件测试", "这是一封并行发送的邮件");
        long endTime = System.currentTimeMillis();
        
        System.out.println("并行发送任务提交完成!总耗时: " + (endTime - startTime) + "ms");
        
        // 等待所有任务完成
        executorService.shutdown();
        executorService.awaitTermination(1, TimeUnit.MINUTES);
    }
}

  

4. 三种方式的对比

特性同步发送异步发送并行发送
执行方式 主线程阻塞 线程池异步 多线程并行
响应性
资源占用 中等
适用场景 单封邮件 少量邮件 大量邮件
实现复杂度 简单 中等 较高

5. 推荐使用场景

同步发送

  • 发送单封重要邮件
  • 需要立即知道发送结果
  • 简单的命令行工具

异步发送

  • Web 应用中的邮件通知
  • 不需要立即知道结果的场景
  • 需要保持响应性的应用

并行发送

  • 批量邮件发送
  • 邮件营销
  • 需要同时发送多封邮件的场景

6. 最佳实践

线程池配置

// 根据系统资源和邮件服务器限制配置线程池
private static final ExecutorService executorService = new ThreadPoolExecutor(
    5,          // 核心线程数
    10,         // 最大线程数
    60,         // 空闲线程存活时间
    TimeUnit.SECONDS,
    new LinkedBlockingQueue<>(100),  // 任务队列
    new ThreadPoolExecutor.CallerRunsPolicy()  // 拒绝策略
);

  

错误处理和重试机制

public static CompletableFuture<Boolean> sendEmailWithRetry(String to, String subject, String content, int maxRetries) {
    return CompletableFuture.supplyAsync(() -> {
        for (int i = 0; i < maxRetries; i++) {
            try {
                // 发送邮件逻辑
                return true;
            } catch (Exception e) {
                if (i == maxRetries - 1) {
                    System.err.println("邮件发送失败,已重试" + maxRetries + "次: " + e.getMessage());
                    return false;
                }
                System.err.println("邮件发送失败,将重试(" + (i + 1) + "/" + maxRetries + "): " + e.getMessage());
                try {
                    Thread.sleep(1000 * (i + 1));  // 指数退避
                } catch (InterruptedException ie) {
                    Thread.currentThread().interrupt();
                    return false;
                }
            }
        }
        return false;
    });
}

  

 

posted @ 2025-10-26 14:51  ®Geovin Du Dream Park™  阅读(3)  评论(0)    收藏  举报