c++调smtp发邮件必须依赖libcurl或poco::net等第三方库,因标准库无网络协议支持;libcurl更稳,需正确配置url、auth、tls和readfunction四参数,并构造合法mime格式邮件体。

用 C++ 调 SMTP 发邮件,得靠第三方库,标准库不支持
标准 C++ 没有网络协议栈,更没有 sendmail() 或 smtp_send() 这种函数。你写的每行 C++ 代码,如果想发邮件,最终都得调用底层 socket、构造 MIME、处理 AUTH、响应状态码——这些没人手写,也不该手写。
主流选择只有两个:libcurl(最稳)和 Poco::Net(C++ 原生感强)。前者兼容性好、错误提示直白;后者类型安全高,但对初学者来说编译和 SSL 配置容易卡住。
-
libcurl需要链接-lcurl,且必须启用openssl或gnutls后端(Windows 上常用curl-winssl) - 别用
libsmtp或网上搜到的“50 行 SMTP 类”——它们通常不支持 STARTTLS、无 SASL 认证、MIME 编码错乱,发出去的邮件大概率进垃圾箱 - Gmail/Outlook 等现代邮箱强制要求 TLS + 登录认证,明文发信(
telnet smtp.xxx 25那套)基本失效
libcurl 发邮件的关键参数不能漏:URL、AUTH、TLS、MIME
很多人把 curl_easy_setopt() 当成黑盒填参,结果返回 CURLE_COULDNT_CONNECT 或服务器静默丢信。核心是四个参数必须显式设对:
-
CURLOPT_URL:必须是smtps://smtp.gmail.com:465(不是smtp://,不是:587不加STARTTLS配置) -
CURLOPT_USERNAME和CURLOPT_PASSWORD:Gmail 必须用「应用专用密码」,不是账号密码;Outlook 用主密码即可(但需开启两步验证) -
CURLOPT_USE_SSL:设为CURLUSESSL_ALL(465 端口)或配合CURLOPT_MAIL_AUTH手动触发 STARTTLS(587 端口) -
CURLOPT_READFUNCTION:必须提供回调函数来喂 MIME 内容;不能传裸字符串指针,curl不帮你序列化
示例关键片段:
立即学习“C++免费学习笔记(深入)”;
curl_easy_setopt(curl, CURLOPT_URL, "smtps://smtp.gmail.com:465"); curl_easy_setopt(curl, CURLOPT_USERNAME, "me@gmail.com"); curl_easy_setopt(curl, CURLOPT_PASSWORD, "abcd-efgh-ijkl-mnop"); // 应用专用密码 curl_easy_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_ALL); curl_easy_setopt(curl, CURLOPT_READFUNCTION, payload_source);
邮件体必须是合法 MIME,换行和编码错一个就退信
SMTP 协议本身只传字节流,但收件方(如 Gmail)会用 MIME 解析器严格校验结构。常见退信原因不是连不上服务器,而是 550-5.7.1 Message rejected due to: missing or malformed headers。
- 必须有
From:、To:、Subject:、Date:四个头字段,且From和To的邮箱格式要带<xxx></xxx>尖括号 - 正文前必须空一行,且整封邮件以
\r\n.\r\n结尾(注意是 CRLF,不是 LF) - 中文主题或正文必须用
=?UTF-8?B?xxxx?=base64 编码,不能直接写 UTF-8 字节 —— 否则 Outlook 直接拒收 - 附件要用
multipart/mixed+ boundary 分隔,别手写 boundary 字符串,用uuid4()之类生成唯一值
本地调试时,别直接打生产邮箱,先用 MailHog 或 smtp4dev 拦截
每次改一行代码就发一封测试邮件?既慢又容易触发 Gmail 的频率限制(535-5.7.8 Username and Password not accepted 可能是被临时封了登录尝试)。本地用轻量工具模拟 SMTP 服务,能立刻看到原始请求和响应。
-
MailHog:Go 写的,docker run -d -p 1025:1025 -p 8025:8025 mailhog/mailhog,浏览器打开http://localhost:8025查收 -
smtp4dev:Windows 用户友好,GUI 界面,监听127.0.0.1:25,无需认证 - 把 C++ 代码里的
CURLOPT_URL改成smtp://127.0.0.1:25,其他逻辑完全不动,就能验证 MIME 构造和 libcurl 调用是否正确
真正上线前,记得把 CURLOPT_VERBOSE 设为 1L,抓一段真实失败日志——很多问题只在 TLS 握手阶段暴露,比如证书链不全、SNI 未启用、OpenSSL 版本太老。










