Servlet 发送电子邮件
Servlet 发送电子邮件讲解
Servlet 可以实现发送电子邮件的功能,这在 Web 应用中很常见,例如用户注册确认、密码重置或通知服务。Servlet 通过 JavaMail API 来发送邮件,需要引入相关依赖。以下用中文详细讲解 Servlet 发送电子邮件的过程,包括基本概念、代码示例、处理中文内容和注意事项。
1. 什么是 JavaMail API?
JavaMail 是 Java 平台用于处理电子邮件的标准 API,它支持 SMTP、POP3 和 IMAP 等协议。在 Servlet 中,我们主要使用 SMTP 协议发送邮件。
- 用途:
- 发送文本邮件、HTML 邮件或带附件的邮件。
- 支持群发、抄送等功能。
- 依赖:
- 需要添加
javax.mail
库(在 Maven 中添加依赖:<dependency><groupId>javax.mail</groupId><artifactId>mail</artifactId><version>1.4.7</version></dependency>
)。 - 如果使用 Jakarta EE,依赖为
jakarta.mail:jakarta.mail-api
和实现库如com.sun.mail:jakarta.mail
。
注意:JavaMail 不直接发送邮件,而是通过邮件服务器(如 Gmail、QQ 邮箱)中转。需要配置服务器的 SMTP 主机、端口、用户名和密码。
2. Servlet 发送邮件的基本步骤
- 导入必要类:
import javax.mail.*;
等。 - 创建 Session:配置邮件服务器属性。
- 创建 Message:设置发件人、收件人、主题和内容。
- 发送邮件:使用 Transport 发送。
(1) 配置邮件服务器
常用邮件服务器配置示例:
- Gmail:主机
smtp.gmail.com
,端口 465(SSL)或 587(TLS),需要启用“允许不安全应用”或使用应用专用密码。 - QQ 邮箱:主机
smtp.qq.com
,端口 465(SSL),需要授权码。
(2) 代码示例:发送简单文本邮件
以下是 Servlet 中发送纯文本邮件的示例。假设从表单提交接收收件人邮箱和内容。
Servlet 代码(SendMailServlet)
import javax.servlet.http.*;
import javax.mail.*;
import javax.mail.internet.*;
import java.io.IOException;
import java.util.Properties;
public class SendMailServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws IOException {
// 设置响应内容类型
response.setContentType("text/html;charset=UTF-8");
request.setCharacterEncoding("UTF-8");
// 获取表单数据
String to = request.getParameter("to"); // 收件人邮箱
String subject = request.getParameter("subject"); // 主题
String content = request.getParameter("content"); // 内容
// 邮件服务器配置(以 QQ 邮箱为例)
final String from = "your_email@qq.com"; // 发件人邮箱
final String password = "your_auth_code"; // 授权码(非密码)
String host = "smtp.qq.com"; // SMTP 主机
int port = 465; // 端口
// 配置 Properties
Properties props = new Properties();
props.put("mail.smtp.host", host);
props.put("mail.smtp.port", String.valueOf(port));
props.put("mail.smtp.auth", "true"); // 需要认证
props.put("mail.smtp.ssl.enable", "true"); // 启用 SSL(或 TLS)
// 创建 Session
Session session = Session.getInstance(props, new Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(from, password);
}
});
try {
// 创建 Message
MimeMessage message = new MimeMessage(session);
message.setFrom(new InternetAddress(from)); // 发件人
message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(to)); // 收件人
message.setSubject(subject); // 主题
message.setText(content); // 内容(纯文本)
// 发送邮件
Transport.send(message);
response.getWriter().write("邮件发送成功!");
} catch (MessagingException e) {
response.getWriter().write("邮件发送失败:" + e.getMessage());
e.printStackTrace();
}
}
}
HTML 表单(发送页面)
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>发送邮件</title>
</head>
<body>
<form action="/sendMail" method="post">
收件人:<input type="text" name="to"><br>
主题:<input type="text" name="subject"><br>
内容:<textarea name="content"></textarea><br>
<input type="submit" value="发送">
</form>
</body>
</html>
说明:
- 使用
Properties
配置服务器。 Authenticator
提供认证信息。MimeMessage
支持 MIME 类型,setText()
设置纯文本内容。Transport.send()
发送邮件。
3. 发送 HTML 邮件或带附件邮件
(1) 发送 HTML 邮件
使用 MimeMultipart
创建多部分消息,将内容设置为 HTML。
代码片段(替换 setText)
// 创建多部分消息
MimeMultipart multipart = new MimeMultipart();
// HTML 部分
MimeBodyPart htmlPart = new MimeBodyPart();
htmlPart.setContent("<h1>欢迎!</h1><p>这是 HTML 邮件内容。</p>", "text/html;charset=UTF-8");
multipart.addBodyPart(htmlPart);
// 设置到 Message
message.setContent(multipart);
(2) 发送带附件邮件
添加附件部分。
代码片段(添加到 multipart)
// 附件部分
MimeBodyPart attachmentPart = new MimeBodyPart();
attachmentPart.attachFile("/path/to/file.txt"); // 文件路径
multipart.addBodyPart(attachmentPart);
完整示例:结合 HTML 和附件。
- 在
try
块中替换message.setText(content);
为上述 multipart 代码。
4. 处理中文邮件
中文邮件容易出现乱码问题,需要确保编码一致。
- 主题和内容编码:
- 使用
MimeUtility.encodeText()
对主题编码。 - 内容使用
"text/html;charset=UTF-8"
或"text/plain;charset=UTF-8"
。
代码示例:处理中文主题和内容
// 设置主题(支持中文)
message.setSubject(MimeUtility.encodeText(subject, "UTF-8", "B"));
// 设置内容(纯文本,支持中文)
message.setText(content, "UTF-8");
// 或 HTML 内容
htmlPart.setContent(content, "text/html;charset=UTF-8");
附件文件名中文:
// 附件文件名编码
attachmentPart.setFileName(MimeUtility.encodeText("中文附件.txt", "UTF-8", "B"));
说明:
"B"
表示 Base64 编码,适合中文。- 确保 Servlet 的
request.setCharacterEncoding("UTF-8");
和响应编码一致。
5. 常用属性和扩展
- 收件人类型:
Message.RecipientType.TO
:收件人。Message.RecipientType.CC
:抄送。Message.RecipientType.BCC
:密送。- 群发:
InternetAddress.parse("email1@example.com,email2@example.com")
。 - 调试模式:
session.setDebug(true);
输出日志。 - TLS 支持(非 SSL):
props.put("mail.smtp.starttls.enable", "true");
props.put("mail.smtp.ssl.enable", "false");
6. 注意事项
- 安全性和认证:
- 不要在代码中硬编码密码,使用配置文件或环境变量。
- 对于 Gmail/QQ 等,需启用 SMTP 并使用授权码(非登录密码)。
- 生产环境使用 SSL/TLS 加密传输。
- 中文编码问题:
- 始终指定
charset=UTF-8
。 - 测试不同邮件客户端(如 Outlook、Webmail)显示效果。
- 异常处理:
- 捕获
MessagingException
,常见错误:认证失败、主机不可达、端口错误。 - 检查防火墙或网络是否允许 SMTP 端口。
- 性能和限制:
- 发送邮件是阻塞操作,建议异步处理(如使用线程或消息队列)。
- 邮件服务器有发送限额(如 Gmail 每日 500 封),避免滥用。
- 依赖和兼容性:
- 在 Tomcat 等容器中,确保 JavaMail JAR 在 classpath。
- Java 9+ 可能需
--add-opens
参数处理反射问题。
- 测试:
- 先用本地邮件服务器测试(如 Apache James)。
- 验证收件箱和垃圾箱。
- 常见问题解决:
- 认证失败:检查用户名/密码/授权码。
- 连接超时:确认主机/端口,检查网络。
- 乱码:统一使用 UTF-8,编码主题/内容。
- 附件丢失:确保文件路径正确,权限允许。
7. 完整示例:注册确认邮件
假设用户注册后发送确认邮件。
RegisterServlet
import javax.servlet.http.*;
import javax.mail.*;
import javax.mail.internet.*;
import java.io.IOException;
import java.util.Properties;
public class RegisterServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws IOException {
response.setContentType("text/html;charset=UTF-8");
request.setCharacterEncoding("UTF-8");
String email = request.getParameter("email");
String username = request.getParameter("username");
// 邮件配置(同上)
final String from = "your_email@qq.com";
final String password = "your_auth_code";
Properties props = new Properties();
// ... 配置 props(如上)
Session session = Session.getInstance(props, new Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(from, password);
}
});
try {
MimeMessage message = new MimeMessage(session);
message.setFrom(new InternetAddress(from));
message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(email));
message.setSubject(MimeUtility.encodeText("注册确认", "UTF-8", "B"));
message.setContent("<h1>欢迎," + username + "!</h1><p>您的注册已成功。</p>", "text/html;charset=UTF-8");
Transport.send(message);
response.getWriter().write("注册成功,确认邮件已发送!");
} catch (Exception e) {
response.getWriter().write("邮件发送失败:" + e.getMessage());
}
}
}
说明:
- 从表单获取邮箱和用户名,发送 HTML 确认邮件。
- 支持中文用户名和主题。
8. 总结
- Servlet 通过 JavaMail API 发送邮件,核心是配置 Session、创建 Message 和 Transport 发送。
- 处理中文时,使用 UTF-8 编码和
MimeUtility
。 - 注意安全、性能和异常处理,适合用于通知类功能。
- 对于高级需求,可扩展到带附件或模板引擎(如 FreeMarker 生成 HTML 内容)。
如果需要更多细节(如带附件的完整代码、与其他技术的整合),或调试特定问题,请告诉我!