使用 curl 进行邮件发送操作汇总

curl 不仅是强大的 HTTP 客户端,同样支持 SMTP / SMTPS 协议,可以直接在命令行发送邮件。

本文汇总常见用法,涵盖连通性测试、STARTTLS、SMTPS、认证、HTML 正文、附件等场景。

协议说明

协议 默认端口 加密方式 说明
smtp:// 25 / 587 无加密或 STARTTLS 明文连接,可通过 --ssl-reqd 升级为 STARTTLS
smtps:// 465 SSL / TLS(隐式) 连接建立时立即协商 TLS,端口通常为 465
STARTTLS 587 显式 TLS 升级 先以明文握手,再通过 STARTTLS 命令升级加密

注意--ssl-reqd 配合 smtp:// 使用时触发 STARTTLS;配合 smtps:// 时则使用隐式 TLS(SSL Wrapping)。


一、连通性测试

1.1 测试 SMTP 端口是否可达(25 端口)

curl -v smtp://smtp.example.com:25

1.2 测试 SMTP 587 端口(STARTTLS)

curl -v smtp://smtp.example.com:587

1.3 测试 SMTPS 465 端口(隐式 TLS)

curl -v smtps://smtp.example.com:465

1.4 测试带认证的连通性(不发邮件,只做 EHLO)

curl -v smtp://smtp.example.com:587 \
  --user "user@example.com:your_password"

输出中可以看到 250-STARTTLS250-AUTH LOGIN PLAIN 等服务器能力列表,用于判断服务器是否正常响应。


二、STARTTLS 发送邮件(587 端口)

STARTTLS 是最常见的企业邮件场景,使用 smtp:// 协议 + --ssl-reqd 强制升级加密。

2.1 发送空邮件(仅测试认证和连接)

curl -v --ssl-reqd \
  --url "smtp://smtp.example.com:587" \
  --user "user@example.com:your_password" \
  --mail-from "user@example.com" \
  --mail-rcpt "recipient@example.com" \
  -T /dev/null

-T /dev/null 表示发送空正文,适合快速验证认证和路由是否通畅。

2.2 发送纯文本邮件(正文来自文件)

准备邮件文件 mail.txt

From: Sender Name <user@example.com>
To: Recipient Name <recipient@example.com>
Subject: Hello from curl

This is a plain text email sent by curl.

发送命令:

curl -v --ssl-reqd \
  --url "smtp://smtp.example.com:587" \
  --user "user@example.com:your_password" \
  --mail-from "user@example.com" \
  --mail-rcpt "recipient@example.com" \
  -T mail.txt

2.3 使用 Office365 / Microsoft 365 发送(STARTTLS)

Office365 的 SMTP 端口为 587,使用 STARTTLS:

curl -v --ssl-reqd \
  --url "smtp://smtp.office365.com:587" \
  --user "user@yourdomain.onmicrosoft.com:your_password" \
  --mail-from "user@yourdomain.onmicrosoft.com" \
  --mail-rcpt "recipient@example.com" \
  -T mail.txt

2.4 使用 Gmail 发送(STARTTLS,587 端口)

curl -v --ssl-reqd \
  --url "smtp://smtp.gmail.com:587" \
  --user "user@gmail.com:your_app_password" \
  --mail-from "user@gmail.com" \
  --mail-rcpt "recipient@example.com" \
  -T mail.txt

Gmail 需要开启「两步验证」并使用「应用专用密码」,不能直接使用账户密码。


三、SMTPS 发送邮件(465 端口,隐式 TLS)

smtps:// 在连接建立时立即进行 TLS 握手,适合支持 465 端口的邮件服务器。

3.1 发送空邮件(测试认证)

curl -v \
  --url "smtps://smtp.example.com:465" \
  --user "user@example.com:your_password" \
  --mail-from "user@example.com" \
  --mail-rcpt "recipient@example.com" \
  -T /dev/null

3.2 发送纯文本邮件

curl -v \
  --url "smtps://smtp.example.com:465" \
  --user "user@example.com:your_password" \
  --mail-from "user@example.com" \
  --mail-rcpt "recipient@example.com" \
  -T mail.txt

3.3 使用 163 邮箱发送(SMTPS,465 端口)

curl -v \
  --url "smtps://smtp.163.com:465" \
  --user "user@163.com:your_auth_code" \
  --mail-from "user@163.com" \
  --mail-rcpt "recipient@example.com" \
  -T mail.txt

163 邮箱需要在设置中开启 SMTP 服务并获取「授权码」,授权码即为密码字段的值。

3.4 使用 QQ 邮箱发送(SMTPS,465 端口)

curl -v \
  --url "smtps://smtp.qq.com:465" \
  --user "user@qq.com:your_auth_code" \
  --mail-from "user@qq.com" \
  --mail-rcpt "recipient@example.com" \
  -T mail.txt

四、SMTP 明文发送(25 端口,无加密)

警告:明文 SMTP 仅适用于内网测试环境,生产环境请勿使用。

4.1 内网 SMTP 中继发送

curl -v \
  --url "smtp://internal-smtp.example.com:25" \
  --mail-from "sender@example.com" \
  --mail-rcpt "recipient@example.com" \
  -T mail.txt

不指定 --user 时,curl 不发送 AUTH 命令,适合无需认证的内网中继。


五、发送 HTML 邮件

准备 HTML 邮件文件 mail_html.txt

From: Sender <user@example.com>
To: Recipient <recipient@example.com>
Subject: HTML Email from curl
MIME-Version: 1.0
Content-Type: text/html; charset=UTF-8

<html>
<body>
  <h1>Hello!</h1>
  <p>This is an <b>HTML</b> email sent by <a href="https://curl.se">curl</a>.</p>
</body>
</html>

发送命令(以 STARTTLS 为例):

curl -v --ssl-reqd \
  --url "smtp://smtp.example.com:587" \
  --user "user@example.com:your_password" \
  --mail-from "user@example.com" \
  --mail-rcpt "recipient@example.com" \
  -T mail_html.txt

六、发送带附件的邮件(MIME multipart)

curl 本身不直接构造 multipart,需要手动拼接 MIME 正文。

准备 mail_attach.txt(将 Base64 编码的文件内嵌):

From: Sender <user@example.com>
To: Recipient <recipient@example.com>
Subject: Email with Attachment
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="BOUNDARY123"

--BOUNDARY123
Content-Type: text/plain; charset=UTF-8

Please find the attachment.

--BOUNDARY123
Content-Type: text/plain; name="hello.txt"
Content-Disposition: attachment; filename="hello.txt"
Content-Transfer-Encoding: base64

SGVsbG8sIFdvcmxkIQo=

--BOUNDARY123--

发送:

curl -v --ssl-reqd \
  --url "smtp://smtp.example.com:587" \
  --user "user@example.com:your_password" \
  --mail-from "user@example.com" \
  --mail-rcpt "recipient@example.com" \
  -T mail_attach.txt

将文件内容进行 Base64 编码:base64 yourfile.txt


七、发送给多个收件人

使用多个 --mail-rcpt 参数:

curl -v --ssl-reqd \
  --url "smtp://smtp.example.com:587" \
  --user "user@example.com:your_password" \
  --mail-from "user@example.com" \
  --mail-rcpt "recipient1@example.com" \
  --mail-rcpt "recipient2@example.com" \
  --mail-rcpt "recipient3@example.com" \
  -T mail.txt

--mail-rcpt 对应 SMTP 的 RCPT TO 命令,邮件正文头部的 To: 字段需要手动在邮件文件中指定以匹配。


八、跳过 SSL 证书验证

在测试环境中,如果服务器使用自签名证书,可以使用 -k 跳过验证:

curl -v -k --ssl-reqd \
  --url "smtp://smtp.example.com:587" \
  --user "user@example.com:your_password" \
  --mail-from "user@example.com" \
  --mail-rcpt "recipient@example.com" \
  -T mail.txt

-k / --insecure 仅用于测试,生产环境禁止使用


九、指定 CA 证书

curl -v --ssl-reqd \
  --cacert /path/to/ca-bundle.crt \
  --url "smtp://smtp.example.com:587" \
  --user "user@example.com:your_password" \
  --mail-from "user@example.com" \
  --mail-rcpt "recipient@example.com" \
  -T mail.txt

十、常用参数速查

参数 说明
--url 指定 SMTP 服务器地址,格式为 smtp://host:portsmtps://host:port
--ssl-reqd 强制要求 SSL/TLS(smtp:// 触发 STARTTLS,smtps:// 触发隐式 TLS)
--user 认证信息,格式为 username:password
--mail-from 发件人地址,对应 SMTP MAIL FROM 命令
--mail-rcpt 收件人地址,对应 SMTP RCPT TO 命令,可多次指定
-T <file> 上传文件作为邮件正文(使用 -T /dev/null 发送空邮件)
-v 详细输出,可查看 SMTP 握手过程
-k 跳过 SSL 证书验证(仅测试用)
--cacert 指定自定义 CA 证书文件
--login-options AUTH=LOGIN 强制使用指定认证方式(如 LOGINPLAINXOAUTH2

十一、常见问题排查

11.1 STARTTLS 握手失败

curl: (35) OpenSSL SSL_connect: Connection reset by peer
  • 检查端口是否正确(STARTTLS 用 587,隐式 TLS 用 465)
  • 确认服务器支持 STARTTLS,可先不加 --ssl-reqd 查看 EHLO 响应

11.2 认证失败(535)

535 5.7.8 Error: authentication failed
  • 检查用户名和密码(部分服务商需要使用「授权码」而非账户密码)
  • 确认账户已开启 SMTP 服务

11.3 连接超时

  • 检查防火墙是否放行对应端口(25/465/587)
  • 企业网络可能封锁对外 SMTP 端口,考虑使用内网中继

11.4 证书错误

curl: (60) SSL certificate problem: unable to get local issuer certificate
  • 使用 --cacert 指定 CA 证书,或临时使用 -k 跳过(仅测试)

参考

  • curl - SMTP
  • curl man page
  • RFC 5321 - SMTP
  • RFC 3207 - STARTTLS