c++ - 使用 libcurl 在 smtp 服务器上进行身份验证失败
问题描述
我尝试使用以下代码发送电子邮件:
#include "optimnet_mail.h"
#include <cstring>
struct upload_status {
int lines_read;
};
static size_t payload_source(char *ptr, size_t size, size_t nmemb, void *userp){
char *data = static_cast<char*>(userp);
if((size == 0) || (nmemb == 0) || ((size*nmemb) < 1)) {
return 0;
}
size_t len = strlen(data);
memcpy(ptr, data, len);
return len;
}
std::string mailText(const std::string destination, const std::string content){
const std::string stringResult =
"To: " + destination +
"\r\nFrom: " + FROM +
"\r\nSubject: Solver has finished\r\n" +
"\r\n" + content + "\r\n";
return stringResult;
}
int sendMail(const std::string destination, const std::string content){
const std::string text = mailText(destination, content);
char *data = new char [text.length()+1];
std::strcpy (data,text.c_str());
CURL *curl;
CURLcode res = CURLE_OK;
struct curl_slist *recipients = NULL;
struct upload_status upload_ctx;
upload_ctx.lines_read = 0;
curl = curl_easy_init();
if(curl) {
/* Set username and password */
curl_easy_setopt(curl, CURLOPT_USERNAME, FROM);
curl_easy_setopt(curl, CURLOPT_PASSWORD, PASS);
//using smtps fails instantly
curl_easy_setopt(curl, CURLOPT_URL, "smtps://" HOST ":" PORT);
curl_easy_setopt(curl, CURLOPT_USE_SSL, (long)CURLUSESSL_ALL);
/* If your server doesn't have a valid certificate, then you can disable
* part of the Transport Layer Security protection by setting the
* CURLOPT_SSL_VERIFYPEER and CURLOPT_SSL_VERIFYHOST options to 0 (false).
*/
//curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
//curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
//curl_easy_setopt(curl, CURLOPT_CAINFO, "~/.ssh/known_hosts");
curl_easy_setopt(curl, CURLOPT_MAIL_FROM, FROM);
// Add two recipients
recipients = curl_slist_append(recipients, destination.c_str());
curl_easy_setopt(curl, CURLOPT_MAIL_RCPT, recipients);
//upload data
curl_easy_setopt(curl, CURLOPT_READFUNCTION, payload_source);
curl_easy_setopt(curl, CURLOPT_READDATA, data);
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
/* Send the message */
res = curl_easy_perform(curl);
/* Check for errors */
if(res != CURLE_OK)
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
/* Free the list of recipients */
curl_slist_free_all(recipients);
/* Always cleanup */
curl_easy_cleanup(curl);
}
delete data;
return (int)res;
}
int main(){
return sendMail(std::string("myemail@mycompany.com"),std::string("Test2"));
}
不幸的是,执行此代码会给我以下日志:
* Trying 83.166.143.44:465...
* TCP_NODELAY set
* Connected to mail.infomaniak.ch (83.166.143.44) port 465 (#0)
* successfully set certificate verify locations:
* CAfile: /etc/ssl/certs/ca-certificates.crt
CApath: /etc/ssl/certs
* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384
* Server certificate:
* subject: CN=mail.infomaniak.ch
* start date: Feb 17 22:44:47 2021 GMT
* expire date: May 18 22:44:47 2021 GMT
* subjectAltName: host "mail.infomaniak.ch" matched cert's "mail.infomaniak.ch"
* issuer: C=US; O=Let's Encrypt; CN=R3
* SSL certificate verify ok.
< 220 mail.infomaniak.com ESMTP ready
> EHLO conway
< 250-mail.infomaniak.com
< 250-PIPELINING
< 250-SIZE
< 250-ETRN
< 250-ENHANCEDSTATUSCODES
< 250-8BITMIME
< 250-DSN
< 250 AUTH PLAIN LOGIN
> AUTH PLAIN
< 334
> Some hash
< 535 5.7.0 Invalid login or password
* Closing connection 0
curl_easy_perform() failed: Login denied
另一方面,当使用这个 curl 命令 :
curl --ssl-reqd --url 'smtps://mail.infomaniak.ch' --user 'user@example.com:password' --mail-from 'user@example.com' --mail-rcpt 'myemail@mycompany.com' --upload-file mail.txt
时,确实发送了电子邮件。
我的代码中有什么遗漏吗?我不明白为什么使用完全相同的登录名和密码会使身份验证失败。
编辑:感谢 rustyx 和 Sam Varshavchik,我纠正了端口问题和内存泄漏问题。
解决方案
<myemail@mycompany.com>
问题在于,看起来像的主机和看起来像的用户之间存在差异myemail@mycompany.com
。这就是导致身份验证失败的原因。
推荐阅读
- javascript - 如何在打字稿中显示具有多维数组的json
- git - 如何修复会破坏现有标签的问题
- c# - EF Core 一对多映射到没有键的表
- rust - 使用 rust 将文件名收集到向量中时,借用值的寿命不够长
- sql - 使用相同的主键将值从一行添加到另一行 - Oracle SQL
- wpf - 当 TabControl.TabItem 具有固定值时,如何删除 Header 和 ContentPresenter 之间的线?
- c# - .Net Core 自定义属性中的依赖注入
- ruby-on-rails - 捆绑安装后 Rails 为每个页面返回 HTTP 500,没有错误日志
- java - Wifi P2P 应用程序:BroadcastReceiver STATE_CHANGED_ACTION 被连续触发
- ruby-on-rails - class_name 不能通过 Rails 中的 has_many 关联工作