047-Java 发送邮件_java发送邮件
Java 提供了强大的邮件发送功能,可以通过 JavaMail API 处理邮件的发送、接收和转发。以下是 Java 发送邮件的详细教程,包括基础用法、常见配置和高级场景。
1. 准备工作
1.1 添加 JavaMail 依赖
Maven 项目
在 Maven 项目的 pom.xml
文件中添加以下依赖:
com.sun.mail javax.mail 1.6.2
非 Maven 项目
如果不是 Maven 项目,可以下载以下 JAR 文件并添加到项目的 classpath
:
- javax.mail
1.2 常见邮件协议
- SMTP (Simple Mail Transfer Protocol):用于发送邮件。
- IMAP (Internet Message Access Protocol):用于接收邮件。
- POP3 (Post Office Protocol 3):另一种接收邮件的协议。
本教程主要讲解如何通过 SMTP 发送邮件。
2. 发送邮件的基本代码
以下是发送简单邮件的标准实现。
2.1 基本示例:发送纯文本邮件
代码实现
import javax.mail.*;import javax.mail.internet.*;import java.util.Properties;public class EmailSender { public static void main(String[] args) { // 发件人邮箱 final String fromEmail = \"your-email@example.com\"; // 邮箱密码或授权码(视邮箱服务商要求) final String password = \"your-email-password\"; // 收件人邮箱 final String toEmail = \"recipient-email@example.com\"; // 配置 SMTP 服务器属性 Properties properties = new Properties(); properties.put(\"mail.smtp.host\", \"smtp.example.com\"); // SMTP 主机名(如 Gmail: smtp.gmail.com) properties.put(\"mail.smtp.port\", \"587\"); // SMTP 端口号 properties.put(\"mail.smtp.auth\", \"true\"); // 是否需要认证 properties.put(\"mail.smtp.starttls.enable\", \"true\"); // 启用 STARTTLS // 创建会话 Session session = Session.getInstance(properties, new Authenticator() { @Override protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication(fromEmail, password); } }); try { // 创建邮件内容 Message message = new MimeMessage(session); message.setFrom(new InternetAddress(fromEmail)); // 设置发件人 message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(toEmail)); // 设置收件人 message.setSubject(\"测试邮件\"); // 设置邮件主题 message.setText(\"这是通过 Java 发送的测试邮件。\"); // 设置邮件正文 // 发送邮件 Transport.send(message); System.out.println(\"邮件发送成功!\"); } catch (MessagingException e) { e.printStackTrace(); } }}
2.2 配置说明
-
SMTP 主机和端口:
- 不同邮箱服务商的 SMTP 主机名和端口不同:
- Gmail:
smtp.gmail.com
,端口587
(STARTTLS)或465
(SSL)。 - Outlook/Hotmail:
smtp.office365.com
,端口587
。 - QQ 邮箱:
smtp.qq.com
,端口587
或465
。 - 163 邮箱:
smtp.163.com
,端口25
或465
。
- Gmail:
- 不同邮箱服务商的 SMTP 主机名和端口不同:
-
授权码:
- 部分邮箱(如 Gmail、QQ)需要使用授权码代替密码。授权码可以在邮箱设置中获取。
-
TLS 和 SSL:
STARTTLS
是一种升级现有不安全连接为加密连接的方式,常用于端口587
。SSL
是直接建立加密连接的方式,常用于端口465
。
3. 发送带附件的邮件
可以通过 MimeMultipart
类实现发送带附件的邮件。
代码实现
import javax.mail.*;import javax.mail.internet.*;import java.util.Properties;import java.io.File;public class EmailWithAttachment { public static void main(String[] args) { final String fromEmail = \"your-email@example.com\"; final String password = \"your-email-password\"; final String toEmail = \"recipient-email@example.com\"; Properties properties = new Properties(); properties.put(\"mail.smtp.host\", \"smtp.example.com\"); properties.put(\"mail.smtp.port\", \"587\"); properties.put(\"mail.smtp.auth\", \"true\"); properties.put(\"mail.smtp.starttls.enable\", \"true\"); Session session = Session.getInstance(properties, new Authenticator() { @Override protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication(fromEmail, password); } }); try { // 创建邮件内容 Message message = new MimeMessage(session); message.setFrom(new InternetAddress(fromEmail)); message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(toEmail)); message.setSubject(\"带附件的测试邮件\"); // 创建邮件正文 MimeBodyPart bodyPart = new MimeBodyPart(); bodyPart.setText(\"这是带附件的邮件,请查收!\"); // 创建附件部分 MimeBodyPart attachmentPart = new MimeBodyPart(); attachmentPart.attachFile(new File(\"path/to/your/file.txt\")); // 替换为实际文件路径 // 组合邮件内容 Multipart multipart = new MimeMultipart(); multipart.addBodyPart(bodyPart); multipart.addBodyPart(attachmentPart); // 设置邮件内容 message.setContent(multipart); // 发送邮件 Transport.send(message); System.out.println(\"带附件的邮件发送成功!\"); } catch (Exception e) { e.printStackTrace(); } }}
4. 发送HTML格式的邮件
可以通过 setContent
方法发送 HTML 格式的邮件。
代码实现
import javax.mail.*;import javax.mail.internet.*;import java.util.Properties;public class EmailWithHTML { public static void main(String[] args) { final String fromEmail = \"your-email@example.com\"; final String password = \"your-email-password\"; final String toEmail = \"recipient-email@example.com\"; Properties properties = new Properties(); properties.put(\"mail.smtp.host\", \"smtp.example.com\"); properties.put(\"mail.smtp.port\", \"587\"); properties.put(\"mail.smtp.auth\", \"true\"); properties.put(\"mail.smtp.starttls.enable\", \"true\"); Session session = Session.getInstance(properties, new Authenticator() { @Override protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication(fromEmail, password); } }); try { // 创建邮件内容 Message message = new MimeMessage(session); message.setFrom(new InternetAddress(fromEmail)); message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(toEmail)); message.setSubject(\"HTML 格式测试邮件\"); // 设置 HTML 内容 String htmlContent = \"欢迎使用 Java 发送邮件!
\" + \"这是通过 HTML 格式发送的测试邮件。
\"; message.setContent(htmlContent, \"text/html; charset=utf-8\"); // 发送邮件 Transport.send(message); System.out.println(\"HTML 格式的邮件发送成功!\"); } catch (MessagingException e) { e.printStackTrace(); } }}
5. 常见问题及解决方案
5.1 无法连接 SMTP 服务器
- 确保使用了正确的 SMTP 主机名和端口。
- 检查是否启用了防火墙或网络限制。
- 如果使用 Gmail,确保启用了“低安全性应用访问”或使用 OAuth。
5.2 身份验证失败
- 确保使用正确的邮箱账号和密码。
- 部分服务商要求使用授权码代替密码(如 Gmail、QQ 邮箱)。
5.3 SSL/TLS 配置问题
- 如果使用端口
465
,需要添加以下配置:properties.put(\"mail.smtp.socketFactory.port\", \"465\");properties.put(\"mail.smtp.socketFactory.class\", \"javax.net.ssl.SSLSocketFactory\");
5.4 邮件被标记为垃圾邮件
- 使用真实的发件人地址。
- 避免在邮件正文中使用敏感词(如“免费”、“优惠”等)。
- 配置 DKIM、SPF 等邮件认证机制。
6. 总结
-
基本功能:
- 通过 SMTP 发送纯文本邮件、HTML 邮件和带附件的邮件。
-
高级功能:
- 支持多收件人、抄送(CC)、密送(BCC)。
- 支持发送带图片和样式的邮件。
-
注意事项:
- 确保正确配置 SMTP 主机和端口。
- 使用授权码或密码登录。
- 避免触发垃圾邮件过滤机制。
JavaMail 是一个功能强大的邮件发送工具,结合 SMTP 和 MIME,可以满足绝大多数邮件发送的需求。在实际项目中,建议对邮件的异常处理和安全性进行充分考虑,以确保服务的稳定性和可靠性。
7. Java 发送邮件的高级应用
在掌握了基本的邮件发送功能之后,可以进一步探索更高级的应用场景,例如群发邮件、多附件、多线程发送邮件、嵌入图片等。
7.1 群发邮件
群发邮件可以通过在邮件中设置多个收件人 (TO
、CC
、BCC
) 来实现。
代码示例:群发邮件
import javax.mail.*;import javax.mail.internet.*;import java.util.Properties;public class EmailMassSender { public static void main(String[] args) { final String fromEmail = \"your-email@example.com\"; final String password = \"your-email-password\"; // 多个收件人 String[] recipients = {\"recipient1@example.com\", \"recipient2@example.com\", \"recipient3@example.com\"}; Properties properties = new Properties(); properties.put(\"mail.smtp.host\", \"smtp.example.com\"); properties.put(\"mail.smtp.port\", \"587\"); properties.put(\"mail.smtp.auth\", \"true\"); properties.put(\"mail.smtp.starttls.enable\", \"true\"); Session session = Session.getInstance(properties, new Authenticator() { @Override protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication(fromEmail, password); } }); try { Message message = new MimeMessage(session); message.setFrom(new InternetAddress(fromEmail)); // 添加所有收件人 Address[] addresses = new Address[recipients.length]; for (int i = 0; i < recipients.length; i++) { addresses[i] = new InternetAddress(recipients[i]); } message.setRecipients(Message.RecipientType.TO, addresses); message.setSubject(\"群发邮件测试\"); message.setText(\"这是一封群发的测试邮件。\"); Transport.send(message); System.out.println(\"群发邮件成功!\"); } catch (MessagingException e) { e.printStackTrace(); } }}
注意
-
TO
、CC
、BCC
的区别:TO
:直接发送给主要收件人。CC
(抄送):发送给次要收件人,所有收件人都能看到抄送列表。BCC
(密送):发送给隐秘的收件人,其他收件人不会看到密送列表。
-
隐私保护:
- 如果需要保护收件人隐私,建议使用
BCC
。
- 如果需要保护收件人隐私,建议使用
7.2 多附件邮件
可以通过向 MimeMultipart
中添加多个 MimeBodyPart
来实现多附件邮件。
代码示例:发送多附件邮件
import javax.mail.*;import javax.mail.internet.*;import java.util.Properties;import java.io.File;public class MultiAttachmentEmail { public static void main(String[] args) { final String fromEmail = \"your-email@example.com\"; final String password = \"your-email-password\"; final String toEmail = \"recipient@example.com\"; Properties properties = new Properties(); properties.put(\"mail.smtp.host\", \"smtp.example.com\"); properties.put(\"mail.smtp.port\", \"587\"); properties.put(\"mail.smtp.auth\", \"true\"); properties.put(\"mail.smtp.starttls.enable\", \"true\"); Session session = Session.getInstance(properties, new Authenticator() { @Override protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication(fromEmail, password); } }); try { Message message = new MimeMessage(session); message.setFrom(new InternetAddress(fromEmail)); message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(toEmail)); message.setSubject(\"多附件测试邮件\"); // 创建正文部分 MimeBodyPart bodyPart = new MimeBodyPart(); bodyPart.setText(\"这是包含多个附件的测试邮件,请查收!\"); // 创建附件 1 MimeBodyPart attachment1 = new MimeBodyPart(); attachment1.attachFile(new File(\"path/to/attachment1.txt\")); // 创建附件 2 MimeBodyPart attachment2 = new MimeBodyPart(); attachment2.attachFile(new File(\"path/to/attachment2.jpg\")); // 组合正文和附件 Multipart multipart = new MimeMultipart(); multipart.addBodyPart(bodyPart); multipart.addBodyPart(attachment1); multipart.addBodyPart(attachment2); message.setContent(multipart); Transport.send(message); System.out.println(\"多附件邮件发送成功!\"); } catch (Exception e) { e.printStackTrace(); } }}
7.3 嵌入图片的 HTML 邮件
可以使用 MimeMultipart
的 related
类型将图片嵌入到 HTML 邮件中。
代码示例:嵌入图片的 HTML 邮件
import javax.mail.*;import javax.mail.internet.*;import java.util.Properties;import java.io.File;public class EmailWithEmbeddedImage { public static void main(String[] args) { final String fromEmail = \"your-email@example.com\"; final String password = \"your-email-password\"; final String toEmail = \"recipient@example.com\"; Properties properties = new Properties(); properties.put(\"mail.smtp.host\", \"smtp.example.com\"); properties.put(\"mail.smtp.port\", \"587\"); properties.put(\"mail.smtp.auth\", \"true\"); properties.put(\"mail.smtp.starttls.enable\", \"true\"); Session session = Session.getInstance(properties, new Authenticator() { @Override protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication(fromEmail, password); } }); try { Message message = new MimeMessage(session); message.setFrom(new InternetAddress(fromEmail)); message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(toEmail)); message.setSubject(\"HTML 邮件测试\"); // 创建 HTML 部分 MimeBodyPart htmlPart = new MimeBodyPart(); String htmlContent = \"测试嵌入图片
\" + \"这是嵌入图片的 HTML 邮件:
\" + \"
\"; htmlPart.setContent(htmlContent, \"text/html; charset=utf-8\"); // 创建图片部分 MimeBodyPart imagePart = new MimeBodyPart(); imagePart.attachFile(new File(\"path/to/image.jpg\")); imagePart.setContentID(\"\"); imagePart.setDisposition(MimeBodyPart.INLINE); // 组合内容 Multipart multipart = new MimeMultipart(\"related\"); multipart.addBodyPart(htmlPart); multipart.addBodyPart(imagePart); message.setContent(multipart); Transport.send(message); System.out.println(\"嵌入图片的 HTML 邮件发送成功!\"); } catch (Exception e) { e.printStackTrace(); } }}
7.4 多线程发送邮件
在需要发送大量邮件时,可以使用多线程来提高效率。
代码示例:多线程发送邮件
import javax.mail.*;import javax.mail.internet.*;import java.util.Properties;public class MultiThreadedEmailSender { public static void main(String[] args) { final String fromEmail = \"your-email@example.com\"; final String password = \"your-email-password\"; String[] recipients = {\"recipient1@example.com\", \"recipient2@example.com\", \"recipient3@example.com\"}; for (String recipient : recipients) { new Thread(() -> sendEmail(fromEmail, password, recipient)).start(); } } public static void sendEmail(String fromEmail, String password, String toEmail) { Properties properties = new Properties(); properties.put(\"mail.smtp.host\", \"smtp.example.com\"); properties.put(\"mail.smtp.port\", \"587\"); properties.put(\"mail.smtp.auth\", \"true\"); properties.put(\"mail.smtp.starttls.enable\", \"true\"); Session session = Session.getInstance(properties, new Authenticator() { @Override protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication(fromEmail, password); } }); try { Message message = new MimeMessage(session); message.setFrom(new InternetAddress(fromEmail)); message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(toEmail)); message.setSubject(\"多线程邮件测试\"); message.setText(\"这是通过多线程发送的测试邮件。\"); Transport.send(message); System.out.println(\"邮件发送成功!收件人: \" + toEmail); } catch (MessagingException e) { e.printStackTrace(); } }}
8. 邮件发送的注意事项
-
授权码:
- 部分邮箱(如 QQ 邮箱、Gmail)需要启用 SMTP 并生成授权码,代替密码使用。
-
邮件服务限制:
- 一些免费邮箱(如 Gmail)对每日发送的邮件数量有上限,可考虑使用企业邮箱或专用邮件服务。
-
垃圾邮件防护:
- 添加合适的邮件标题和内容,避免触发垃圾邮件过滤机制。
- 配置 SPF、DKIM 和 DMARC 等邮件认证机制。
-
错误处理:
- 对
MessagingException
进行详细分类和处理,例如网络超时、身份验证失败等。
- 对
9. 总结
通过 JavaMail API,可以轻松实现以下功能:
- 发送纯文本、HTML 格式的邮件;
- 添加附件、多附件;
- 群发邮件(TO、CC、BCC);
- 嵌入图片的邮件;
- 使用多线程提高邮件发送效率。
在实际项目中,建议将邮件发送功能封装为工具类,并结合队列或异步任务处理邮件发送,以提高系统的并发能力和可靠性。