在企业信息化系统里,自动发邮件是绕不开的需求:用户注册验证码、订单状态通知、服务器告警、审批待办提醒……这些场景都需要程序代替人工发信。本文以**阿里邮箱(企业邮)**为例,手把手演示如何通过 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 更新)整理。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐