企业邮箱 SMTP 发送服务开发实战:Python / Java 双语言示例
在企业信息化系统里,自动发邮件是绕不开的需求:用户注册验证码、订单状态通知、服务器告警、审批待办提醒……这些场景都需要程序代替人工发信。本文以**阿里邮箱(企业邮)**为例,手把手演示如何通过 SMTP 协议在 Python 和 Java 中发送邮件,并总结几个生产环境必踩的坑。
适用读者:开发者、IT 管理员。代码示例均可直接复制运行,只需替换邮箱地址和授权码。
一、阿里邮箱 SMTP 配置要点
在写代码前,先把服务端参数和账号权限搞清楚,否则十有八九卡在"连接失败"或"认证错误"。
1. 服务器地址与端口
| 协议 | 服务器地址 | SSL 加密端口 | 非加密端口 |
|---|---|---|---|
| SMTP(发信) | smtp.qiye.aliyun.com |
465 | 25 |
说明:也可使用
smtp.您的邮箱域名(需自行配置 smtp 的 CNAME 解析)。端口 80 和 587 尚未开放,不要尝试。
2. 两个关键坑(务必先看)
- ECS 默认封禁 25 端口:如果你的发信程序部署在阿里云 ECS 上,25 端口默认不通。请一律使用 465(SSL) 端口,避免无谓排查。
- 密码不是登录密码:阿里邮箱第三方客户端默认使用**授权码(三方客户端安全密码)**作为 SMTP 密码。若管理员开启了"三方客户端安全密码"功能,必须用生成的授权码,而不是网页登录密码。此外,第三方客户端访问默认关闭,需管理员在后台"设置第三方客户端登录权限"中开启。
二、Python 实战(smtplib + SSL)
Python 标准库 smtplib 即可完成,无需额外依赖。以下示例通过 465 端口 + SSL 发送一封纯文本邮件:
import smtplib
import ssl
from email.mime.text import MIMEText
from email.utils import formataddr
# ===== 配置区 =====
SMTP_HOST = "smtp.qiye.aliyun.com"
SMTP_PORT = 465 # SSL 加密端口
SENDER = "noreply@your-domain.com" # 发件人完整邮箱地址
AUTH_CODE = "your_auth_code" # 三方客户端授权码,不是登录密码
RECEIVER = "user@example.com"
# ===== 构建邮件 =====
msg = MIMEText("这是通过阿里邮箱 SMTP 发送的测试邮件", "plain", "utf-8")
msg["From"] = formataddr(("系统通知", SENDER))
msg["To"] = RECEIVER
msg["Subject"] = "SMTP 发信测试"
# ===== 发送 =====
context = ssl.create_default_context()
with smtplib.SMTP_SSL(SMTP_HOST, SMTP_PORT, context=context) as server:
server.login(SENDER, AUTH_CODE)
server.send_message(msg)
print("邮件发送成功")
要点说明:
- 使用
SMTP_SSL直接走 465 端口的 SSL 加密,比SMTP+starttls()更简单可靠。 - 发件人显示名用
formataddr包装,避免中文昵称乱码。 - 生产环境建议把
SENDER / AUTH_CODE放进配置中心或环境变量,不要硬编码。
如需发送 HTML 邮件,把 MIMEText 的 _subtype 改为 "html" 即可;带附件则改用 MIMEMultipart。
三、Java 实战(JavaMail)
Java 侧使用 javax.mail(JavaMail)API。Maven 依赖:
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>javax.mail</artifactId>
<version>1.6.2</version>
</dependency>
发送示例:
import java.util.Properties;
import javax.mail.*;
import javax.mail.internet.*;
public class AliMailSmtp {
public static void main(String[] args) throws Exception {
final String host = "smtp.qiye.aliyun.com";
final int port = 465;
final String sender = "noreply@your-domain.com";
final String authCode = "your_auth_code"; // 授权码
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
Session session = Session.getInstance(props, new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(sender, authCode);
}
});
Message message = new MimeMessage(session);
message.setFrom(new InternetAddress(sender, "系统通知"));
message.setRecipients(Message.RecipientType.TO, InternetAddress.parse("user@example.com"));
message.setSubject("SMTP 发信测试");
message.setText("这是通过阿里邮箱 SMTP 发送的测试邮件");
Transport.send(message);
System.out.println("邮件发送成功");
}
}
要点说明:
mail.smtp.ssl.enable=true对应 465 端口;若用 25 端口明文,则不需要此项(但不推荐)。- 中文发件人昵称通过
new InternetAddress(address, "系统通知")指定编码,避免乱码。
四、生产环境避坑指南
| 现象 | 原因 | 解决 |
|---|---|---|
| 连接超时 / 无法连服务器 | 用了 25 端口且部署在 ECS | 改用 465 + SSL |
| 535 认证失败 | 用了登录密码而非授权码 | 改用三方客户端授权码 |
| 能连但发不出去 | 第三方客户端访问未开启 | 管理员后台开启权限 |
| 部分收件人收不到 | 发信频率过高被限流 | 控制频率,批量邮件走专用通道 |
五、SMTP 还是邮件推送服务(DirectMail)?
一个重要的边界:SMTP 适合"人对人 / 系统对少量人"的触发类邮件(验证码、通知);批量、营销、系统大规模推送类邮件,官方明确建议使用邮件推送产品(DirectMail),以免影响企业邮箱自身信誉,进而影响正常邮件投递。
简单判断:
- 日均发信量小、接收方明确(员工、注册用户)→ 用 SMTP 即可。
- 日均成千上万、接收方为外部大列表、含营销内容 → 用 DirectMail,它有独立的送达率优化、退信处理和信誉隔离。
小结
通过本文你掌握了:阿里邮箱 SMTP 服务器与端口(465/25)、授权码机制、Python 与 Java 两套可运行代码,以及 ECS 封禁 25 端口、批量邮件改用 DirectMail 两个核心避坑点。把示例代码里的邮箱地址和授权码替换为你的实际值,即可接入业务系统。
注:本文 SMTP 参数依据阿里云官方文档《IMAP/POP/SMTP 服务器地址及端口配置》《阿里邮箱如何通过 SMTP 程序发信》(2026-05 更新)整理。
更多推荐
所有评论(0)