1. JavaMail邮件发送的基本概念与背景JavaMail是Java平台处理电子邮件的标准API它提供了一套与协议无关的邮件发送和接收框架。在实际开发中我们经常需要实现系统自动发送邮件功能比如用户注册验证、密码找回、系统通知等场景。邮件发送的核心原理是基于SMTP协议Simple Mail Transfer Protocol。SMTP服务器就像现实中的邮局负责将你的邮件递送到收件人的邮箱服务器。JavaMail API实际上是对这些底层协议的封装让我们可以用面向对象的方式操作邮件。注意不同邮件服务商如163、QQ、Gmail等的SMTP服务器地址和端口各不相同使用时需要查阅对应服务商的文档。2. 环境准备与依赖配置2.1 添加JavaMail依赖对于Maven项目在pom.xml中添加以下依赖dependency groupIdcom.sun.mail/groupId artifactIdjavax.mail/artifactId version1.6.2/version /dependency如果你使用的是Gradle则添加implementation com.sun.mail:javax.mail:1.6.22.2 获取邮件服务商SMTP信息以QQ邮箱为例需要先开启SMTP服务登录QQ邮箱网页版进入设置→账户找到POP3/IMAP/SMTP服务项开启IMAP/SMTP服务按照提示获取授权码这个授权码将作为密码使用常见邮件服务商SMTP信息服务商SMTP服务器端口加密方式QQ邮箱smtp.qq.com465SSL163邮箱smtp.163.com465SSLGmailsmtp.gmail.com587TLS3. 基础邮件发送实现3.1 创建Session对象Session是JavaMail API的核心类它定义了邮件发送的基本环境Properties props new Properties(); props.put(mail.smtp.host, smtp.qq.com); // SMTP服务器地址 props.put(mail.smtp.port, 465); // 端口号 props.put(mail.smtp.auth, true); // 需要认证 props.put(mail.smtp.ssl.enable, true); // 启用SSL加密 // 创建Session实例 Session session Session.getInstance(props, new Authenticator() { Override protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication(your_emailqq.com, your_auth_code); } });3.2 构建邮件内容try { // 创建MimeMessage对象 MimeMessage message new MimeMessage(session); // 设置发件人 message.setFrom(new InternetAddress(your_emailqq.com)); // 设置收件人 message.setRecipient(Message.RecipientType.TO, new InternetAddress(recipientexample.com)); // 设置邮件主题 message.setSubject(测试邮件主题); // 设置邮件正文 message.setText(这是一封测试邮件的正文内容); // 发送邮件 Transport.send(message); System.out.println(邮件发送成功); } catch (MessagingException e) { e.printStackTrace(); }4. 进阶邮件功能实现4.1 发送HTML格式邮件要发送HTML格式的邮件需要使用setContent方法并指定MIME类型String htmlContent h1这是一封HTML邮件/h1 p stylecolor:red;红色文字/p a hrefhttps://example.com点击访问网站/a; message.setContent(htmlContent, text/html;charsetUTF-8);4.2 添加附件发送带附件的邮件需要用到MimeMultipart和MimeBodyPart// 创建多部分消息 MimeMultipart multipart new MimeMultipart(); // 创建文本部分 MimeBodyPart textPart new MimeBodyPart(); textPart.setText(这是邮件正文); // 创建附件部分 MimeBodyPart attachmentPart new MimeBodyPart(); attachmentPart.attachFile(new File(path/to/your/file.pdf)); // 将各部分添加到消息中 multipart.addBodyPart(textPart); multipart.addBodyPart(attachmentPart); // 设置消息内容 message.setContent(multipart);4.3 发送给多个收件人可以通过多次调用setRecipient方法或使用addRecipient方法// 主送 message.addRecipient(Message.RecipientType.TO, new InternetAddress(recipient1example.com)); // 抄送 message.addRecipient(Message.RecipientType.CC, new InternetAddress(recipient2example.com)); // 密送 message.addRecipient(Message.RecipientType.BCC, new InternetAddress(recipient3example.com));5. 实际开发中的注意事项5.1 连接超时设置在实际生产环境中建议设置连接超时参数props.put(mail.smtp.connectiontimeout, 5000); // 连接超时5秒 props.put(mail.smtp.timeout, 10000); // 读写超时10秒5.2 异常处理完善的异常处理可以帮助我们更好地排查问题try { Transport.send(message); } catch (AuthenticationFailedException e) { System.err.println(认证失败请检查用户名和授权码); } catch (MessagingException e) { System.err.println(邮件发送失败 e.getMessage()); // 可以在这里添加重试逻辑 }5.3 性能优化对于频繁发送邮件的系统可以考虑以下优化措施复用Session对象避免每次发送都创建新Session使用连接池如JavaMail的mail.smtp.connectionpool属性异步发送邮件避免阻塞主线程6. 常见问题排查6.1 认证失败可能原因用户名或授权码错误未开启SMTP服务IP被服务商限制解决方案仔细检查用户名和授权码确认已开启SMTP服务尝试更换网络环境6.2 连接超时可能原因网络问题SMTP服务器地址或端口错误防火墙限制解决方案检查网络连接确认SMTP服务器信息正确检查防火墙设置6.3 邮件被识别为垃圾邮件可能原因邮件内容包含敏感词发送频率过高发件人域名未做SPF记录解决方案优化邮件内容控制发送频率配置域名的SPF记录7. 完整示例代码下面是一个完整的JavaMail发送邮件示例包含HTML内容、附件和多个收件人import javax.mail.*; import javax.mail.internet.*; import java.util.Properties; import java.io.File; public class AdvancedEmailSender { public static void main(String[] args) { // 配置参数 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.smtp.connectiontimeout, 5000); props.put(mail.smtp.timeout, 10000); // 创建Session Session session Session.getInstance(props, new Authenticator() { protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication(your_emailqq.com, your_auth_code); } }); try { // 创建消息 MimeMessage message new MimeMessage(session); message.setFrom(new InternetAddress(your_emailqq.com)); message.addRecipient(Message.RecipientType.TO, new InternetAddress(recipient1example.com)); message.addRecipient(Message.RecipientType.CC, new InternetAddress(recipient2example.com)); message.setSubject(测试邮件 - 带附件和HTML); // 创建多部分消息 MimeMultipart multipart new MimeMultipart(); // HTML正文部分 MimeBodyPart htmlPart new MimeBodyPart(); String htmlContent h1HTML内容/h1p这是一封测试邮件/p; htmlPart.setContent(htmlContent, text/html;charsetUTF-8); multipart.addBodyPart(htmlPart); // 附件部分 MimeBodyPart attachmentPart new MimeBodyPart(); attachmentPart.attachFile(new File(example.pdf)); attachmentPart.setFileName(示例文件.pdf); multipart.addBodyPart(attachmentPart); // 设置完整消息内容 message.setContent(multipart); // 发送邮件 Transport.send(message); System.out.println(邮件发送成功); } catch (Exception e) { e.printStackTrace(); } } }在实际项目中我通常会将这些邮件发送逻辑封装成一个工具类提供简洁的API供业务代码调用。比如可以设计一个EmailSender类提供sendTextEmail、sendHtmlEmail等方法内部处理所有的JavaMail细节。这样既提高了代码复用性也降低了业务代码的复杂度。