news 2026/4/23 9:51:27

Java实战:通过QQ邮箱SMTP服务实现邮件自动化发送

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Java实战:通过QQ邮箱SMTP服务实现邮件自动化发送

1. 准备工作:获取QQ邮箱SMTP授权码

在开始编写Java代码之前,我们需要先获取QQ邮箱的SMTP授权码。这个授权码相当于一个专用密码,用于第三方应用通过SMTP协议登录你的QQ邮箱发送邮件。我刚开始接触这个功能时,也踩过直接用QQ密码登录的坑,结果一直报错,后来才发现必须使用独立的授权码。

具体操作步骤如下:

  1. 登录你的QQ邮箱网页版
  2. 点击右上角的"设置"按钮
  3. 选择"账户"选项卡
  4. 向下滚动找到"POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务"部分
  5. 点击"开启"按钮(如果已经开启会显示已开启状态)
  6. 按照页面提示发送短信验证
  7. 验证通过后会生成一个16位的授权码

重要提示:这个授权码只会显示一次,务必立即复制保存。我当初就是没及时保存,结果不得不重新生成,导致之前的代码配置都要跟着改。建议保存在安全的地方,比如密码管理器。

2. 项目配置:添加邮件发送依赖

现在我们来配置Java项目。根据我的经验,目前最常用的Java邮件库有两种选择:

  1. JavaMail API:Oracle官方提供的标准API
  2. Apache Commons Email:对JavaMail的简化封装

我个人更推荐使用JavaMail API,因为它是标准实现,功能更全面。下面是Maven项目的依赖配置:

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

如果你使用Gradle,可以这样添加:

implementation 'com.sun.mail:javax.mail:1.6.2'

对于Spring Boot项目,可以直接使用Spring提供的starter:

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-mail</artifactId> </dependency>

我曾经在一个老项目中使用过commons-email,虽然API确实简单一些,但在处理附件和HTML内容时遇到了不少限制,最后还是换回了JavaMail。

3. 基础实现:发送纯文本邮件

现在我们来编写最基本的邮件发送代码。先看一个完整的示例,然后我会逐步解释关键部分:

import java.util.Properties; import javax.mail.*; import javax.mail.internet.*; public class QQMailSender { public static void sendTextEmail(String to, String subject, String content) throws MessagingException { // 1. 配置连接参数 Properties props = new Properties(); props.put("mail.smtp.host", "smtp.qq.com"); props.put("mail.smtp.port", "587"); props.put("mail.smtp.auth", "true"); props.put("mail.smtp.starttls.enable", "true"); // 使用TLS加密 // 2. 创建Session实例 Session session = Session.getInstance(props, new Authenticator() { @Override protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication("你的QQ邮箱", "你的授权码"); } }); // 3. 创建邮件消息 Message message = new MimeMessage(session); message.setFrom(new InternetAddress("你的QQ邮箱")); message.setRecipient(Message.RecipientType.TO, new InternetAddress(to)); message.setSubject(subject); message.setText(content); // 4. 发送邮件 Transport.send(message); } }

关键点解析

  1. SMTP配置

    • mail.smtp.host:QQ邮箱的SMTP服务器地址
    • mail.smtp.port:可以使用465(SSL)或587(TLS)端口
    • mail.smtp.auth:必须开启认证
    • mail.smtp.starttls.enable:启用TLS加密
  2. 认证信息: 使用Authenticator匿名类提供邮箱账号和授权码。这里有个常见坑点:密码要填授权码而不是QQ密码!

  3. 邮件构建

    • setFrom:发件人地址,必须与认证邮箱一致
    • setRecipient:收件人地址,可以添加多个
    • setText:设置纯文本内容

测试代码

public static void main(String[] args) { try { QQMailSender.sendTextEmail( "recipient@example.com", "测试邮件主题", "这是一封测试邮件内容" ); System.out.println("邮件发送成功"); } catch (MessagingException e) { System.err.println("邮件发送失败: " + e.getMessage()); } }

4. 进阶功能:发送HTML格式邮件

在实际项目中,我们通常需要发送更丰富的HTML格式邮件。下面是如何修改代码来支持HTML:

public static void sendHtmlEmail(String to, String subject, String htmlContent) throws MessagingException { // ... 前面的配置代码与纯文本邮件相同 ... Message message = new MimeMessage(session); message.setFrom(new InternetAddress("你的QQ邮箱")); message.setRecipient(Message.RecipientType.TO, new InternetAddress(to)); message.setSubject(subject); // 设置HTML内容 message.setContent(htmlContent, "text/html;charset=UTF-8"); Transport.send(message); }

HTML内容示例

String html = "<html>" + "<body>" + "<h1 style='color:red'>重要通知</h1>" + "<p>尊敬的客户:</p>" + "<p>您的验证码是:<strong>123456</strong></p>" + "<p>请在10分钟内使用</p>" + "</body>" + "</html>"; sendHtmlEmail("user@example.com", "验证码通知", html);

实用技巧

  1. 可以使用Thymeleaf或FreeMarker模板引擎生成HTML内容
  2. 内联CSS比外部CSS更可靠,因为某些邮箱客户端会屏蔽外部样式
  3. 避免使用复杂的JavaScript,大多数邮箱会禁用脚本执行

5. 添加附件功能实现

发送带附件的邮件稍微复杂一些,需要使用MimeMultipart和MimeBodyPart:

public static void sendEmailWithAttachment(String to, String subject, String content, File attachment) throws MessagingException, IOException { // ... 配置代码与之前相同 ... Message message = new MimeMessage(session); message.setFrom(new InternetAddress("你的QQ邮箱")); message.setRecipient(Message.RecipientType.TO, new InternetAddress(to)); message.setSubject(subject); // 创建多部分消息 Multipart multipart = new MimeMultipart(); // 文本部分 BodyPart messageBodyPart = new MimeBodyPart(); messageBodyPart.setText(content); multipart.addBodyPart(messageBodyPart); // 附件部分 messageBodyPart = new MimeBodyPart(); DataSource source = new FileDataSource(attachment); messageBodyPart.setDataHandler(new DataHandler(source)); messageBodyPart.setFileName(attachment.getName()); multipart.addBodyPart(messageBodyPart); // 设置完整消息 message.setContent(multipart); Transport.send(message); }

使用示例

File file = new File("report.pdf"); sendEmailWithAttachment( "client@example.com", "月度报告", "请查收附件中的月度报告", file );

注意事项

  1. 附件大小限制:QQ邮箱单封邮件总大小不超过50MB
  2. 文件类型:某些类型可能被邮箱服务器拦截(如.exe文件)
  3. 中文文件名:建议使用MimeUtility.encodeText处理中文文件名

6. 实用技巧与常见问题解决

在实际使用中,我积累了一些实用技巧和问题解决方案:

1. 发送给多个收件人

// 替换单个收件人的设置 InternetAddress[] addresses = { new InternetAddress("user1@example.com"), new InternetAddress("user2@example.com") }; message.setRecipients(Message.RecipientType.TO, addresses);

2. 抄送和密送

// 抄送 message.setRecipients(Message.RecipientType.CC, InternetAddress.parse("cc1@example.com,cc2@example.com")); // 密送 message.setRecipients(Message.RecipientType.BCC, InternetAddress.parse("bcc@example.com"));

3. 常见错误及解决

  • 535错误:认证失败

    • 检查是否使用了授权码而非QQ密码
    • 确认邮箱账号是否正确(完整地址如123456@qq.com)
  • Could not connect to SMTP host

    • 检查网络连接
    • 尝试切换端口(465/587)
    • 确认防火墙未阻止出站连接
  • 554 DT:SPM:被识别为垃圾邮件

    • 优化邮件内容,减少敏感词
    • 添加退订链接
    • 控制发送频率

4. 性能优化

// 复用Session对象 private static final Session session = Session.getInstance(props, authenticator); // 使用连接池(Spring框架) @Bean public JavaMailSender mailSender() { JavaMailSenderImpl sender = new JavaMailSenderImpl(); sender.setHost("smtp.qq.com"); sender.setPort(587); sender.setUsername("你的QQ邮箱"); sender.setPassword("你的授权码"); Properties props = sender.getJavaMailProperties(); props.put("mail.transport.protocol", "smtp"); props.put("mail.smtp.auth", "true"); props.put("mail.smtp.starttls.enable", "true"); props.put("mail.debug", "true"); // 调试模式 return sender; }

7. 完整工具类封装

最后,我将分享一个经过实战检验的邮件工具类,包含以上所有功能:

import javax.mail.*; import javax.mail.internet.*; import javax.activation.*; import java.util.*; import java.io.*; public class EmailUtil { private static final String SMTP_HOST = "smtp.qq.com"; private static final int SMTP_PORT = 587; private static final String USERNAME = "你的QQ邮箱"; private static final String PASSWORD = "你的授权码"; private static Session getSession() { 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.starttls.enable", "true"); return Session.getInstance(props, new Authenticator() { protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication(USERNAME, PASSWORD); } }); } public static void sendTextEmail(String to, String subject, String text) throws MessagingException { sendEmail(to, subject, text, false, null); } public static void sendHtmlEmail(String to, String subject, String html) throws MessagingException { sendEmail(to, subject, html, true, null); } public static void sendEmailWithAttachment(String to, String subject, String text, File attachment) throws MessagingException, IOException { sendEmail(to, subject, text, false, new File[]{attachment}); } private static void sendEmail(String to, String subject, String content, boolean isHtml, File[] attachments) throws MessagingException { Message message = new MimeMessage(getSession()); message.setFrom(new InternetAddress(USERNAME)); message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(to)); message.setSubject(subject); if (attachments == null || attachments.length == 0) { // 无附件 message.setContent(content, isHtml ? "text/html;charset=UTF-8" : "text/plain"); } else { // 有附件 Multipart multipart = new MimeMultipart(); // 正文部分 MimeBodyPart textPart = new MimeBodyPart(); textPart.setContent(content, isHtml ? "text/html;charset=UTF-8" : "text/plain"); multipart.addBodyPart(textPart); // 附件部分 for (File file : attachments) { MimeBodyPart attachmentPart = new MimeBodyPart(); attachmentPart.setDataHandler(new DataHandler(new FileDataSource(file))); attachmentPart.setFileName(MimeUtility.encodeText(file.getName())); multipart.addBodyPart(attachmentPart); } message.setContent(multipart); } Transport.send(message); } }

这个工具类已经在我们公司的多个项目中稳定运行,每天处理上千封邮件。使用时只需要根据需求调用对应的简化方法即可。对于更复杂的场景,比如需要内嵌图片的HTML邮件,可以进一步扩展这个工具类。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/18 4:19:48

Kook Zimage真实幻想Turbo实操手册:幻想风格人物姿态+服饰+背景控制

Kook Zimage真实幻想Turbo实操手册&#xff1a;幻想风格人物姿态服饰背景控制 1. 为什么你需要这个“幻想风格精准控制器” 你有没有试过这样输入提示词&#xff1a;“一位穿银色铠甲的精灵少女&#xff0c;站在浮空花园里&#xff0c;月光洒在她发梢上”——结果生成的图里&…

作者头像 李华
网站建设 2026/3/13 11:52:43

用Z-Image-Turbo做了个AI头像生成器,效果超出预期

用Z-Image-Turbo做了个AI头像生成器&#xff0c;效果超出预期 1. 为什么是头像&#xff1f;一个被低估的刚需场景 你有没有过这样的经历&#xff1a;注册新平台时卡在头像上传环节——翻遍相册找不到一张既得体又不显老的照片&#xff1b;做个人品牌时反复修图却总差那么点“…

作者头像 李华
网站建设 2026/4/18 2:44:25

避坑指南:使用VibeThinker-1.5B的5个关键提示

避坑指南&#xff1a;使用VibeThinker-1.5B的5个关键提示 你是否刚部署完 VibeThinker-1.5B-WEBUI 镜像&#xff0c;满怀期待地点开网页界面&#xff0c;输入一道 LeetCode 中等题&#xff0c;却等来一段逻辑跳跃、缺少边界判断、甚至跑不通的代码&#xff1f;或者反复尝试中文…

作者头像 李华
网站建设 2026/4/13 8:05:10

造相 Z-Image 镜像使用实操:start.sh启动+7860端口+参数滑块调节

造相 Z-Image 镜像使用实操&#xff1a;start.sh启动7860端口参数滑块调节 1. 一句话搞懂这个镜像是干啥的 你不用装Python、不用配环境、不用下模型权重——只要点一下部署&#xff0c;等一分钟&#xff0c;打开浏览器&#xff0c;就能用上阿里通义万相团队开源的20亿参数文…

作者头像 李华
网站建设 2026/4/18 9:18:30

bailing.png示例:官方提供标准测试图片

bailing.png示例&#xff1a;官方提供标准测试图片 你是否遇到过这样的情况&#xff1a;刚部署好一个图像识别模型&#xff0c;却不确定它到底“认得准不准”&#xff1f;想验证效果&#xff0c;又苦于找不到一张既典型、又无版权风险、还能覆盖常见物体的标准图&#xff1f;别…

作者头像 李华
网站建设 2026/3/9 11:08:34

AI初学者福音:YOLO11一键环境真香体验

AI初学者福音&#xff1a;YOLO11一键环境真香体验 1. 为什么说YOLO11镜像是新手的“开箱即用神器” 你是不是也经历过这样的深夜&#xff1a; 想跑通一个目标检测模型&#xff0c;结果卡在环境配置上——CUDA版本不对、PyTorch和torchvision不兼容、ultralytics安装报错、yol…

作者头像 李华