Я пытаюсь реализовать довольно специализированный почтовый клиент, использующий libcurl (7.66) для отправки электронной почты.
К сожалению, всегда происходит сбой при вызове curl_easy_perform (curl), независимо от того, что я пытаюсь вообще.
В настоящее время в обратном вызове process_mail я все закомментировал;просто возвращаю 0. Я довольно уверен, этого должно быть достаточно, чтобы, по крайней мере, не сломать приложение ...
Реальная цель - это получить почту в виде строки в памяти и просто скопировать ее вstream.
Я действительно ценю любую помощь ... У меня довольно большая задержка из-за этой проблемы.
Вот файл заголовка:
#ifndef MAILMESSAGE_H
#define MAILMESSAGE_H
#include <QObject>
#include <QDebug>
#include <QFile>
#include <QIODevice>
#include <QByteArray>
#include <curl/curl.h>
#include <stdio.h>
class MailMessage : public QObject
{
Q_OBJECT
public:
explicit MailMessage(QObject *parent = nullptr);
void setSMTPPort(QString smtp_port);
void setSMTPAddress(QString smtp_address);
void setSMTPUser(QString smtp_user);
void setSMTPPassword(QString smtp_password);
void addTo(QString address_to);
void setFrom(QString address_from);
void setSubject(QString subject);
void setAlternativeText(QString text);
void setHTML(QString html);
void addAttachment(QString attachment_path, QString filename);
void generateMessage();
// return POSIX-style: 0: ok; 1: error
int sendMail();
QString message;
int message_size;
const char* message_char;
QString smtp_port;
QString smtp_address;
QString smtp_user;
QString smtp_password;
//QStringList addresses_to;
QString address_to;
QString address_from;
QString subject;
QString payload_text;
QString payload_html;
QStringList attachments_base64;
double upload_speed;
double upload_time;
protected:
static size_t process_mail(void *ptr, size_t size, size_t nmemb, void *userp);
signals:
public slots:
};
#endif // MAILMESSAGE_H
И соответствующие части реализации:
void MailMessage::generateMessage()
{
this->message = //"To: "+ this->address_to +"\r\n"
"From: "+ this->address_from +"\r\n"
"Subject: "+ this->subject +"\r\n"
"Content-Type: multipart/mixed; boundary=MixedBoundary"
"\r\n"
"--MixedBoundary"
"Content-Type: multipart/alternative; boundary=AlternativeBoundary"
"\r\n"
"--AlternativeBoundary"
"Content-Type: text/plain; charset=\"utf-8\""
"\r\n"+ this->payload_text +"\r\n"
"--AlternativeBoundary"
"Content-Type: text/html; charset=\"utf-8\""
"\r\n"+ this->payload_html +"\r\n"
"--AlternativeBoundary--"
"\r\n"
"--MixedBoundary";
/*
"Content-Type: application/pdf; name=\"HelloWorld.pdf\""
"Content-Transfer-Encoding: base64"
"Content-Disposition: attachment; filename=\"HelloWorld.pdf\"";
*/
this->message.append("\r\n"
"--MixedBoundary--");
QByteArray array = this->message.toLocal8Bit();
this->message_char = array.data();
this->message_size = sizeof(this->message_char);
}
size_t MailMessage::process_mail(void *ptr, size_t size, size_t nmemb, void *userprocess)
{
size_t retcode = 0;
/*
MailMessage *self = reinterpret_cast<MailMessage*>(userprocess);
if (sizeof(self->message_char) == 0)
return retcode;
retcode = (size * nmemb >= sizeof(self->message_char)) ? sizeof(self->message_char) : size * nmemb;
self->message_size -= retcode;
memcpy(ptr, self->message_char, retcode);
self->message_char += retcode;
*/
return retcode;
}
int MailMessage::sendMail()
{
//qDebug() << this->message;
CURLcode res = CURLE_OK;
CURL *curl = curl_easy_init();
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
// CURLUSESSL_ALL, CURLUSESSL_NONE, CURLUSESSL_TRY, CURLUSESSL_CONTROL
curl_easy_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_ALL);
curl_easy_setopt(curl, CURLOPT_URL, this->smtp_address.toStdString().c_str());
curl_easy_setopt(curl, CURLOPT_USERNAME, this->smtp_user.toStdString().c_str());
curl_easy_setopt(curl, CURLOPT_PASSWORD, this->smtp_password.toStdString().c_str());
curl_easy_setopt(curl, CURLOPT_MAIL_FROM, this->address_from.toStdString().c_str());
curl_easy_setopt(curl, CURLOPT_MAIL_RCPT, this->address_to.toStdString().c_str());
curl_easy_setopt(curl, CURLOPT_READFUNCTION, &MailMessage::process_mail);
curl_easy_setopt(curl, CURLOPT_READDATA, this);
/* 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));
}
else
{
curl_easy_getinfo(curl, CURLINFO_SPEED_UPLOAD, &upload_speed);
curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME, &upload_time);
qDebug() << "Speed: "+QString::number(upload_speed) + " Time: "+QString::number(upload_time);
}
//curl_slist_free_all(this->address_to.toStdString().c_str());
curl_easy_cleanup(curl);
return 0;
}
И, наконец, некоторые выдержки из консольного вывода:
* start date: May 8 08:01:21 2019 GMT
* expire date: May 13 23:59:59 2021 GMT
* subjectAltName: host "mail.gmx.net" matched cert's "mail.gmx.net"
* issuer: C=DE; O=T-Systems International GmbH; OU=T-Systems Trust Center; ST=Nordrhein Westfalen; postalCode=57250; L=Netphen; street=Untere Industriestr. 20; CN=TeleSec ServerPass Extended Validation Class 3 CA
* SSL certificate verify ok.
> EHLO cf-19
* SMTP 0x5572580cd700 state change from UPGRADETLS to EHLO
< 250-gmx.com Hello cf-19 [2.202.204.204]
* Curl_pp_readresp_ 55 bytes of trailing server response left
< 250-8BITMIME* Curl_pp_readresp_ 41 bytes of trailing server response left
< 250-AUTH LOGIN PLAIN
* Curl_pp_readresp_ 19 bytes of trailing server response left
< 250 SIZE 69920427
> AUTH PLAIN
* SASL 0x5572580cd780 state change from STOP to PLAIN
* SMTP 0x5572580cd700 state change from EHLO to AUTH
< 334
> AHNhbXVlbF9iZWNrZXJAZ214LmRlADI4OTZhY2Q2
* SASL 0x5572580cd780 state change from PLAIN to FINAL
< 235 Authentication succeeded
* SASL 0x5572580cd780 state change from FINAL to STOP
* SMTP 0x5572580cd700 state change from AUTH to STOP
* STATE: PROTOCONNECT => DO handle 0x5572580d0678; line 1701 (connection #0)
* DO phase starts
> MAIL FROM:<xxxxxxx@xxx.xx>
* SMTP 0x5572580cd700 state change from STOP to MAIL
* STATE: DO => DOING handle 0x5572580d0678; line 1743 (connection #0)
< 250 Requested mail action okay, completed
03:37:55: The program has unexpectedly finished.
03:37:55: The process was ended forcefully.