本文目录导读:

下面是一个完整的Java邮件群发案例,包含SMTP配置、HTML邮件、附件发送、多收件人处理以及异常处理。
Maven依赖
<dependencies>
<!-- JavaMail -->
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>javax.mail</artifactId>
<version>1.6.2</version>
</dependency>
<!-- 或使用Jakarta Mail(适用于新版本) -->
<!-- <dependency>
<groupId>org.eclipse.angus</groupId>
<artifactId>angus-mail</artifactId>
<version>2.0.1</version>
</dependency> -->
</dependencies>
邮件配置类
import java.util.Properties;
public class MailConfig {
// SMTP服务器配置
public static final String SMTP_HOST = "smtp.qq.com";
public static final String SMTP_PORT = "465";
public static final String SMTP_SSL = "true";
public static final String AUTH_USERNAME = "your-email@qq.com";
public static final String AUTH_PASSWORD = "your-authorization-code";
public static Properties getMailProperties() {
Properties props = new Properties();
props.put("mail.smtp.host", SMTP_HOST);
props.put("mail.smtp.port", SMTP_PORT);
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.ssl.enable", SMTP_SSL);
props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
props.put("mail.smtp.socketFactory.port", SMTP_PORT);
props.put("mail.smtp.connectiontimeout", 5000);
props.put("mail.smtp.timeout", 5000);
props.put("mail.smtp.writetimeout", 5000);
return props;
}
}
邮件实体类
import java.util.List;
import java.util.Map;
public class EmailMessage {
private List<String> toRecipients; // 收件人列表
private List<String> ccRecipients; // 抄送人列表
private List<String> bccRecipients; // 密送人列表
private String subject; // 邮件主题
private String htmlContent; // HTML内容
private String textContent; // 纯文本内容
private Map<String, byte[]> attachments; // 附件列表
// 构造函数、getter和setter
public EmailMessage() {}
public EmailMessage(List<String> toRecipients, String subject, String content) {
this.toRecipients = toRecipients;
this.subject = subject;
this.htmlContent = content;
}
// Getters and Setters
public List<String> getToRecipients() { return toRecipients; }
public void setToRecipients(List<String> toRecipients) { this.toRecipients = toRecipients; }
public List<String> getCcRecipients() { return ccRecipients; }
public void setCcRecipients(List<String> ccRecipients) { this.ccRecipients = ccRecipients; }
public List<String> getBccRecipients() { return bccRecipients; }
public void setBccRecipients(List<String> bccRecipients) { this.bccRecipients = bccRecipients; }
public String getSubject() { return subject; }
public void setSubject(String subject) { this.subject = subject; }
public String getHtmlContent() { return htmlContent; }
public void setHtmlContent(String htmlContent) { this.htmlContent = htmlContent; }
public String getTextContent() { return textContent; }
public void setTextContent(String textContent) { this.textContent = textContent; }
public Map<String, byte[]> getAttachments() { return attachments; }
public void setAttachments(Map<String, byte[]> attachments) { this.attachments = attachments; }
}
邮件发送服务类
import javax.mail.*;
import javax.mail.internet.*;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class EmailSenderService {
private static EmailSenderService instance;
private final Session session;
private final ExecutorService executorService;
private EmailSenderService() {
Properties props = MailConfig.getMailProperties();
session = Session.getInstance(props, new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(
MailConfig.AUTH_USERNAME,
MailConfig.AUTH_PASSWORD
);
}
});
// 开启调试模式(生产环境建议关闭)
// session.setDebug(true);
// 创建线程池用于异步发送
executorService = Executors.newFixedThreadPool(10);
}
public static synchronized EmailSenderService getInstance() {
if (instance == null) {
instance = new EmailSenderService();
}
return instance;
}
/**
* 异步发送邮件
*/
public void sendEmailAsync(EmailMessage emailMessage) {
executorService.submit(() -> {
try {
sendEmail(emailMessage);
} catch (MessagingException e) {
e.printStackTrace();
}
});
}
/**
* 同步发送邮件
*/
public void sendEmail(EmailMessage emailMessage) throws MessagingException {
Message message = createMessage(emailMessage);
Transport.send(message);
System.out.println("邮件发送成功!");
}
/**
* 创建邮件消息
*/
private Message createMessage(EmailMessage emailMessage) throws MessagingException {
MimeMessage message = new MimeMessage(session);
// 发件人
message.setFrom(new InternetAddress(MailConfig.AUTH_USERNAME));
// 收件人
List<String> toList = emailMessage.getToRecipients();
if (toList != null && !toList.isEmpty()) {
InternetAddress[] toAddresses = new InternetAddress[toList.size()];
for (int i = 0; i < toList.size(); i++) {
toAddresses[i] = new InternetAddress(toList.get(i));
}
message.setRecipients(Message.RecipientType.TO, toAddresses);
}
// 抄送
List<String> ccList = emailMessage.getCcRecipients();
if (ccList != null && !ccList.isEmpty()) {
InternetAddress[] ccAddresses = new InternetAddress[ccList.size()];
for (int i = 0; i < ccList.size(); i++) {
ccAddresses[i] = new InternetAddress(ccList.get(i));
}
message.setRecipients(Message.RecipientType.CC, ccAddresses);
}
// 密送
List<String> bccList = emailMessage.getBccRecipients();
if (bccList != null && !bccList.isEmpty()) {
InternetAddress[] bccAddresses = new InternetAddress[bccList.size()];
for (int i = 0; i < bccList.size(); i++) {
bccAddresses[i] = new InternetAddress(bccList.get(i));
}
message.setRecipients(Message.RecipientType.BCC, bccAddresses);
}
// 邮件主题
message.setSubject(emailMessage.getSubject(), "UTF-8");
// 邮件内容
MimeMultipart multipart = new MimeMultipart();
// HTML内容
if (emailMessage.getHtmlContent() != null && !emailMessage.getHtmlContent().isEmpty()) {
BodyPart htmlPart = new MimeBodyPart();
htmlPart.setContent(emailMessage.getHtmlContent(), "text/html;charset=UTF-8");
multipart.addBodyPart(htmlPart);
}
// 纯文本内容
if (emailMessage.getTextContent() != null && !emailMessage.getTextContent().isEmpty()) {
BodyPart textPart = new MimeBodyPart();
textPart.setText(emailMessage.getTextContent());
multipart.addBodyPart(textPart);
}
// 附件
Map<String, byte[]> attachments = emailMessage.getAttachments();
if (attachments != null && !attachments.isEmpty()) {
for (Map.Entry<String, byte[]> entry : attachments.entrySet()) {
BodyPart attachmentPart = new MimeBodyPart();
attachmentPart.setFileName(entry.getKey());
attachmentPart.setContent(entry.getValue(), "application/octet-stream");
multipart.addBodyPart(attachmentPart);
}
}
message.setContent(multipart);
return message;
}
/**
* 关闭线程池
*/
public void shutdown() {
executorService.shutdown();
}
}
模板渲染服务
import java.util.Map;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
public class TemplateService {
/**
* 简单的模板渲染(支持占位符替换)
* Hello ${name}, welcome!
*/
public static String renderTemplate(String template, Map<String, String> variables) {
for (Map.Entry<String, String> entry : variables.entrySet()) {
template = template.replace("${" + entry.getKey() + "}", entry.getValue());
}
return template;
}
/**
* 创建一个默认的HTML模板
*/
public static String getDefaultTemplate(String title, String content, String footer) {
return String.format("""
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>%s</title>
<style>
body {
font-family: Arial, sans-serif;
background-color: #f4f4f4;
margin: 0;
padding: 20px;
}
.container {
background-color: #ffffff;
border-radius: 8px;
padding: 30px;
margin: auto;
max-width: 600px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
h1 {
color: #333;
text-align: center;
}
p {
color: #666;
line-height: 1.6;
}
.footer {
color: #999;
font-size: 12px;
text-align: center;
margin-top: 20px;
border-top: 1px solid #eee;
padding-top: 15px;
}
</style>
</head>
<body>
<div class="container">
<h1>%s</h1>
%s
<div class="footer">%s</div>
</div>
</body>
</html>
""", title, title, content, footer);
}
}
批量发送工具类
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
public class BulkEmailSender {
/**
* 批量发送个性化邮件
* @param recipientList 收件人列表
* @param subject 邮件主题模板
* @param contentTemplate 内容模板(使用${name}等占位符)
* @param variablesList 每个收件人对应的变量列表
*/
public static void sendBulkEmails(List<String> recipientList,
String subject,
String contentTemplate,
List<Map<String, String>> variablesList) {
EmailSenderService sender = EmailSenderService.getInstance();
List<CompletableFuture<Void>> futures = new ArrayList<>();
for (int i = 0; i < recipientList.size(); i++) {
String recipient = recipientList.get(i);
Map<String, String> variables = variablesList.get(i);
// 渲染个性化内容
String personalizedContent = TemplateService.renderTemplate(contentTemplate, variables);
String personalizedSubject = TemplateService.renderTemplate(subject, variables);
// 发送邮件(异步)
EmailMessage email = new EmailMessage();
List<String> recipients = new ArrayList<>();
recipients.add(recipient);
email.setToRecipients(recipients);
email.setSubject(personalizedSubject);
email.setHtmlContent(personalizedContent);
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
try {
sender.sendEmail(email);
} catch (Exception e) {
System.err.println("发送到 " + recipient + " 失败: " + e.getMessage());
}
});
futures.add(future);
}
// 等待所有邮件发送完成
CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]))
.join();
}
/**
* 分批发送(避免一次发送过多)
*/
public static void sendBulkEmailsInBatches(List<String> recipients,
String subject,
String content,
int batchSize) {
int total = recipients.size();
int batchCount = (total + batchSize - 1) / batchSize;
for (int i = 0; i < batchCount; i++) {
int fromIndex = i * batchSize;
int toIndex = Math.min((i + 1) * batchSize, total);
List<String> batchRecipients = recipients.subList(fromIndex, toIndex);
List<Map<String, String>> variablesList = new ArrayList<>();
for (String recipient : batchRecipients) {
Map<String, String> vars = new HashMap<>();
vars.put("recipient", recipient);
variablesList.add(vars);
}
String batchSubject = TemplateService.renderTemplate(subject,
Map.of("batch", String.valueOf(i + 1), "total", String.valueOf(batchCount)));
sendBulkEmails(batchRecipients, batchSubject, content, variablesList);
// 批次之间暂停
try {
Thread.sleep(5000); // 5秒后发送下一批
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
}
使用示例
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class EmailDemo {
public static void main(String[] args) {
// 示例1:发送简单邮件
simpleEmailDemo();
// 示例2:批量个性化邮件
bulkEmailDemo();
// 示例3:带附件的邮件
attachmentEmailDemo();
}
/**
* 简单邮件发送
*/
public static void simpleEmailDemo() {
EmailMessage email = new EmailMessage();
List<String> recipients = new ArrayList<>();
recipients.add("recipient1@example.com");
recipients.add("recipient2@example.com");
email.setToRecipients(recipients);
email.setSubject("【测试邮件】欢迎使用Java邮件服务");
email.setHtmlContent("""
<html>
<body>
<h1>欢迎使用Java邮件服务</h1>
<p>这是一封测试邮件,如果您收到此邮件,说明配置成功。</p>
<p>发送时间:<span style="color: blue;">%s</span></p>
</body>
</html>
""".formatted(new java.util.Date().toString()));
EmailSenderService sender = EmailSenderService.getInstance();
try {
sender.sendEmail(email);
System.out.println("简单邮件发送成功!");
} catch (Exception e) {
System.err.println("发送失败: " + e.getMessage());
}
}
/**
* 批量个性化邮件
*/
public static void bulkEmailDemo() {
// 收件人列表
List<String> recipients = new ArrayList<>();
recipients.add("user1@example.com");
recipients.add("user2@example.com");
recipients.add("user3@example.com");
recipients.add("user4@example.com");
recipients.add("user5@example.com");
// 邮件模板
String subjectTemplate = "【${company}】${name},您的专属优惠来了!";
String contentTemplate = """
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>优惠通知</title>
</head>
<body>
<h2>亲爱的 ${name}:</h2>
<p>您好!${company} 为您准备了专属优惠。</p>
<p>您的专属优惠码:<strong style="color: red;">${coupon}</strong></p>
<p>有效期至:${expireDate}</p>
<p>立即使用:<a href="${website}">点击访问</a></p>
<br>
<p>感谢您的支持!</p>
</body>
</html>
""";
// 每个收件人的个性化变量
List<Map<String, String>> variablesList = new ArrayList<>();
for (int i = 1; i <= recipients.size(); i++) {
Map<String, String> vars = new HashMap<>();
vars.put("name", "用户" + i);
vars.put("company", "Java邮件服务");
vars.put("coupon", "SAVE" + (100 + i * 10));
vars.put("expireDate", "2024年12月31日");
vars.put("website", "https://www.example.com");
vars.put("batch", "1");
vars.put("total", "1");
variablesList.add(vars);
}
// 发送批量邮件
BulkEmailSender.sendBulkEmails(recipients, subjectTemplate, contentTemplate, variablesList);
System.out.println("批量邮件发送完成!");
}
/**
* 带附件的邮件
*/
public static void attachmentEmailDemo() {
EmailMessage email = new EmailMessage();
List<String> recipients = new ArrayList<>();
recipients.add("recipient@example.com");
email.setToRecipients(recipients);
email.setSubject("【资料文件】2014年项目报告");
email.setHtmlContent("""
<html>
<body>
<h2>项目报告</h2>
<p>请查收附件中的项目报告。</p>
<p>如有问题,请随时联系我们。</p>
</body>
</html>
""");
// 添加附件
Map<String, byte[]> attachments = new HashMap<>();
attachments.put("报告文档.txt", "这是文档内容".getBytes());
attachments.put("财务数据.csv", "日期,收入,支出\n2024-01,10000,5000".getBytes());
email.setAttachments(attachments);
EmailSenderService sender = EmailSenderService.getInstance();
try {
sender.sendEmail(email);
System.out.println("带附件邮件发送成功!");
} catch (Exception e) {
System.err.println("发送失败: " + e.getMessage());
}
}
}
配置文件示例 (application.properties)
# SMTP配置 mail.smtp.host=smtp.qq.com mail.smtp.port=465 mail.smtp.auth=true mail.smtp.ssl.enable=true mail.smtp.socketFactory.class=javax.net.ssl.SSLSocketFactory # 账号信息 mail.username=your-email@qq.com mail.password=your-authorization-code # 邮件发送配置 mail.batch.size=50 mail.batch.delay=5000 mail.default.encoding=UTF-8
注意事项
-
SMTP服务器配置:不同的邮箱服务商(QQ邮箱、163邮箱、Gmail等)有不同的SMTP服务器配置,需要根据实际情况调整。
-
授权码:不要使用邮箱密码,使用邮箱服务商提供的授权码(如QQ邮箱的授权码)。
-
发送限制:各大邮件服务商对每日发送数量有限制,请合理控制发送频率和数量。
-
线程安全:
EmailSenderService使用单例模式,并提供了异步发送方法。 -
错误处理:在实际项目中,建议添加完善的日志记录和重试机制。
-
敏感信息:授权码等敏感信息不要硬编码,应该从配置文件或环境变量中读取。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播