使用 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-STARTTLS、250-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:port 或 smtps://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 |
强制使用指定认证方式(如 LOGIN、PLAIN、XOAUTH2) |
十一、常见问题排查
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