尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

10 分钟用 curl 搞定邮件协议:SMTP 发信、POP3 收信与 IMAP 管箱实战

10 分钟用 curl 搞定邮件协议:SMTP 发信、POP3 收信与 IMAP 管箱实战 10 分钟用 curl 搞定邮件协议SMTP 发信、POP3 收信与 IMAP 管箱实战【免费下载链接】curlA command line tool and library for transferring data with URL syntax, supporting DICT, FILE, FTP, FTPS, GOPHER, GOPHERS, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, MQTT, MQTTS, POP3, POP3S, RTSP, SCP, SFTP, SMB, SMBS, SMTP, SMTPS, TELNET, TFTP, WS and WSS. libcurl offers a myriad of powerful features项目地址: https://gitcode.com/GitHub_Trending/cu/curl场景切入给监控系统发一封自动告警邮件需求很具体磁盘使用率超过 90% 时脚本要自动给值班同学发邮件另外还要定期从 POP3 邮箱拉取工单回执、用 IMAP 把处理完的邮件标为已读。curl 邮件协议支持把 SMTP / POP3 / IMAP 三件套都塞进了同一个工具和 libcurl 库里——命令行一条命令能跑通C 程序几十行代码就能嵌进去。第一封邮件跑通3 行 curl 命令裸发这一节能让你立刻拿到一次成功体验。最简单的路径是连本机 SMTP 中继127.0.0.1:25无需认证把正文文件投递出去# 向本地 SMTP 中继投递一封邮件 curl -v smtp://127.0.0.1:25 \ --mail-from opsexample.com \ --mail-rcpt oncallexample.com \ -T mail.txt看到250 2.0.0 Ok: queued即发送成功。-v会打印完整的 SMTP 交互EHLO / MAIL FROM / RCPT TO / DATA第一次接触邮件协议时非常值得看一遍。协议怎么选SMTP、POP3、IMAP 对比表这一节帮你 30 秒定协议。三者方向完全不同选错的代价是功能根本不存在协议默认端口安全端口数据流向典型场景SMTP25587STARTTLS/ 465隐式 TLS客户端 → 服务器发信告警、工单、通知POP3110995服务器 → 客户端拉取后可删收信全量下载到本地归档IMAP143993双向服务器端管理管箱搜索、读头、改标记、多端同步选型建议只发就用 SMTP要把邮件搬走归档到本地用 POP3需要按条件搜索、只读头部、修改已读/旗标状态或多设备共享同一邮箱必须上 IMAP。POP3 拉走后服务器端状态如已读不会变IMAP 的状态变更是持久化在服务器上的。发信从裸发到 curl SMTP TLS 加密发送基础发送命令行 C 库两种写法命令行发信收件人可以用--mail-rcpt追加多个# 带认证 STARTTLS 的 curl 发送邮件 curl smtp://smtp.example.com:587 --ssl \ --user ops:$(SMTP_PASS) \ --mail-from opsexample.com \ --mail-rcpt oncallexample.com \ --mail-rcpt backupexample.com \ -T mail.txtC 库写法要点是CURLOPT_MAIL_FROM/CURLOPT_MAIL_RCPT收件人用curl_slist列表加一个读回调#include stdio.h #include string.h #include curl/curl.h /* 读回调从内存字符串逐块提供邮件正文 */ static size_t read_payload(char *dst, size_t size, size_t nmemb, void *userp) { const char **p userp; size_t len strlen(*p); if (size * nmemb len) len size * nmemb; memcpy(dst, *p, len); *p len; return len; } int main(void) { /* 正文需含完整邮件头From/To/Subject 空行 内容 */ const char *body From: opsexample.com\r\n To: oncallexample.com\r\n Subject: 磁盘告警\r\n\r\n 磁盘 /data 使用率 92%请处理。; CURL *c curl_easy_init(); struct curl_slist *rcpt NULL; curl_easy_setopt(c, CURLOPT_URL, smtp://smtp.example.com:587); curl_easy_setopt(c, CURLOPT_MAIL_FROM, opsexample.com); rcpt curl_slist_append(rcpt, oncallexample.com); curl_easy_setopt(c, CURLOPT_MAIL_RCPT, rcpt); /* 收件人列表 */ curl_easy_setopt(c, CURLOPT_UPLOAD, 1L); curl_easy_setopt(c, CURLOPT_READFUNCTION, read_payload); curl_easy_setopt(c, CURLOPT_READDATA, body); curl_easy_setopt(c, CURLOPT_USERNAME, ops); curl_easy_setopt(c, CURLOPT_PASSWORD, getenv(SMTP_PASS)); /* 勿写死 */ curl_easy_setopt(c, CURLOPT_USE_SSL, CURLUSESSL_TRY); /* 尝试 STARTTLS */ if (curl_easy_perform(c) ! CURLE_OK) fprintf(stderr, 发送失败\n); curl_slist_free_all(rcpt); curl_easy_cleanup(c); return 0; }收件人、发件人各选项的含义可查 CURLOPT_MAIL_FROM 官方文档。三种 TLS 档位写法含义适用smtp://不加 TLS 参数明文 25 端口仅内网中继smtp://...:587 --ssl或CURLUSESSL_TRY先明文再 STARTTLS 升级现代邮件服务商smtps://...:465或--ssl-reqd/CURLUSESSL_ALL握手即加密的隐式 TLS支持 465 的服务商收信curl POP3 下载邮件三连查状态 → 全量下载 → 取指定邮件# 1) 查邮箱状态STAT 结果在响应头里-I 只看头 curl -I pop3s://pop.example.com --user user:$(POP_PASS) # 2) 下载全部邮件按 mbox 格式存到本地 curl pop3s://pop.example.com --user user:$(POP_PASS) -o inbox.mbox # 3) 只取第 3 封邮件 curl pop3s://pop.example.com/3 --user user:$(POP_PASS) -o msg3.emlURL 路径里写序号/3就是 RETR 第 3 封不加路径则依次拉取所有邮件。POP3 下载是破坏性的——服务器配置不同取走后可能删除邮件批量操作前先确认服务器是否启用了KEEP之类策略。C 库一次完成下载 查统计STAT 用CURLOPT_CUSTOMREQUEST发出即可官方示例见 pop3-stat.c#include stdio.h #include curl/curl.h static size_t save(char *p, size_t s, size_t n, void *u) { return fwrite(p, s, n, (FILE *)u); /* 追加写入 mbox 文件 */ } int main(void) { FILE *out fopen(inbox.mbox, wb); CURL *c curl_easy_init(); curl_easy_setopt(c, CURLOPT_URL, pop3s://pop.example.com); curl_easy_setopt(c, CURLOPT_USERNAME, user); curl_easy_setopt(c, CURLOPT_PASSWORD, getenv(POP_PASS)); /* 全量下载到本地 */ curl_easy_setopt(c, CURLOPT_WRITEFUNCTION, save); curl_easy_setopt(c, CURLOPT_WRITEDATA, out); curl_easy_perform(c); /* 复用同一连接查统计STAT 结果在响应中 */ curl_easy_setopt(c, CURLOPT_CUSTOMREQUEST, STAT); curl_easy_setopt(c, CURLOPT_NOBODY, 1L); curl_easy_perform(c); fclose(out); curl_easy_cleanup(c); return 0; }管箱curl IMAP 搜索、读取与标记这一节覆盖 IMAP 最常用的五个动作列邮箱、选 INBOX、SEARCH、FETCH、STORE。# 1) 列出所有邮箱URL 不带邮箱名即触发 LIST curl imaps://imap.example.com --user user:$(IMAP_PASS) # 2) 搜索未读邮件; 后是 SEARCH 查询串 curl imaps://imap.example.com;UNSEEN --user user:$(IMAP_PASS) # 3) 读取 INBOX 第 1 封的邮件头 curl imaps://imap.example.com/INBOX;UID1 BODY[HEADER] \ --user user:$(IMAP_PASS) # 4) 标记第 1 封为已读自定义 STORE 命令 curl imaps://imap.example.com/INBOX --user user:$(IMAP_PASS) \ -X STORE 1 FLAGS (\\Seen)URL 的记忆法imaps://主机/[邮箱名];[SEARCH 条件或 FETCH 取件参数]。选择 INBOX 就是给路径加上/INBOXcurl 会自动发EXAMINE。完整取件参数可参考官方示例 imap-fetch.c。C 库里同一句URL 决定命令的规律完全一致#include stdio.h #include curl/curl.h int main(void) { CURL *c curl_easy_init(); curl_easy_setopt(c, CURLOPT_URL, imaps://imap.example.com); curl_easy_setopt(c, CURLOPT_USERNAME, user); curl_easy_setopt(c, CURLOPT_PASSWORD, getenv(IMAP_PASS)); /* 1) 无路径 列出所有邮箱 */ curl_easy_perform(c); /* 2) 搜索未读邮件; 后是查询串 */ curl_easy_setopt(c, CURLOPT_URL, imaps://imap.example.com;UNSEEN); curl_easy_perform(c); /* 3) 读取第 1 封邮件头 */ curl_easy_setopt(c, CURLOPT_URL, imaps://imap.example.com/INBOX;UID1 BODY[HEADER]); curl_easy_perform(c); /* 4) 标记已读自定义 STORE 命令 */ curl_easy_setopt(c, CURLOPT_URL, imaps://imap.example.com/INBOX); curl_easy_setopt(c, CURLOPT_CUSTOMREQUEST, STORE 1 FLAGS (\\Seen)); curl_easy_perform(c); curl_easy_cleanup(c); return 0; }踩坑清单邮件协议常见报错速查报错排查按这个顺序走能覆盖 90% 的问题现象常见原因解法Could not connect to host端口写错、587 与 465 混用、主机不通对照服务商端口先nc -vz 主机 端口验证可达SSL connect error/ STARTTLS 未提供--ssl-reqd用在明文端口或--ssl用在隐式端口隐式端口换smtps://、pop3s://、imaps://显式端口用--sslLogin deniedCURLE_LOGIN_DENIED密码错、服务器只接受特定 SASL 机制--login-options AUTHCRAM-MD5C 里用CURLOPT_LOGIN_OPTIONS指定 PLAIN / LOGIN / CRAM-MD5操作超时防火墙拦了邮件端口、DNS 解析慢--connect-timeout 10 --max-time 60同时检查出网策略IMAP 命令被拒邮箱名不存在、STORE 语法含转义问题先跑 LIST 确认邮箱名注意 shell 里\\Seen的反斜杠转义调试通用手段命令行加-vC 程序开CURLOPT_VERBOSE, 1L并挂CURLOPT_DEBUGFUNCTION回调按CURLINFO_DATA_IN / DATA_OUT分色打印收发的每一行协议数据。安全要点TLS 取舍、证书校验与凭证管理TLS 三档怎么选隐式 TLS465/995/993smtps://等 scheme最安全握手机密即建立STARTTLS587/110/143 --ssl次之注意它存在被中间人降级为明文的风险明文连接只允许出现在隔离内网。证书校验三件套默认开启永远不要为了先跑通关掉# 使用自定义 CA 包校验服务器证书 curl --cacert /etc/ssl/cacert.pem \ --capath /etc/ssl/certs \ smtps://smtp.example.com:465 ...C 里对应CURLOPT_CAINFO/CURLOPT_CAPATHCURLOPT_SSL_VERIFYPEER和CURLOPT_SSL_VERIFYHOST保持默认值 1 / 2。凭证管理三原则不写死在代码里从环境变量或密钥管理服务读命令行用--user ops:$(SMTP_PASS)而不是明文出现在ps输出里多用户脚本可改用--netrc-file指向权限 600 的文件。效率技巧连接复用、批量与并发连接复用C 程序里同一个CURL *句柄连续curl_easy_performTCP 和 TLS 握手只做一次见上面 POP3 示例一次连接完成下载 STAT。要更高吞吐用 multi 接口把多个句柄挂在一个事件循环里。批量命令行的--parallel-Z让一个进程并发处理多个 URL也可以用管道拆批。并发拉邮件xargs 起多个并行 curl比串行快一个数量级# 8 路并发拉取 UID 1~50 的完整邮件 seq 1 50 | xargs -P 8 -I{} \ curl -s imaps://imap.example.com/INBOX;UID{} BODY[] \ --user user:$(IMAP_PASS) -o msg_{}.emlIMAP 侧还有一个省流量的技巧先SEARCH拿 ID 列表再FETCH ... BODY[HEADER]只取头部做筛选最后才对命中的几封取全文避免全量拉正文。上线前检查清单所有连接走 TLS发信 465/587、收信 993/995禁止明文端口出内网未使用--insecure、未关闭SSL_VERIFYPEER/VERIFYHOST凭证来自环境变量或密钥管理代码与 git 历史中无明文密码设置了--connect-timeout与--max-timeC 程序对应CURLOPT_CONNECTTIMEOUT/CURLOPT_TIMEOUT失败路径有日志curl_easy_strerror/ curl 退出码与重试告警邮件本身也要监控发送结果POP3 拉取的破坏性取走即删已在服务器策略中确认【免费下载链接】curlA command line tool and library for transferring data with URL syntax, supporting DICT, FILE, FTP, FTPS, GOPHER, GOPHERS, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, MQTT, MQTTS, POP3, POP3S, RTSP, SCP, SFTP, SMB, SMBS, SMTP, SMTPS, TELNET, TFTP, WS and WSS. libcurl offers a myriad of powerful features项目地址: https://gitcode.com/GitHub_Trending/cu/curl创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表