curl-library
libcurl >= 7.34.0 break prev working smtp code
Date: Wed, 16 Apr 2014 15:16:23 -0700
Hello,
I just tried upgrading to 7.36.0 from 7.33.0 and previously working smtp
code has stopped working. I tried all version in between and it looks like
it broke in 7.34.0. The actual error from curl_easy_perform is not very
revealing:
E0416 22:00:39.329601 19934 mail.cpp:112] curl_easy_perform: Failure when
receiving data from the peer
Here's the relevant code:
std::string create_to_address()
{
std::ostringstream oss;
oss << "<" << config::get().error_mail_address() << ">";
return oss.str();
}
std::string create_from_address()
{
char host[128];
if (::gethostname(host, sizeof(host)) != 0) {
throw errno_error("gethostname");
}
std::ostringstream oss;
oss << "<live@" << host << ".mixpanel.com>";
return oss.str();
}
struct mail_context
{
std::string message;
size_t written;
};
size_t mail_read(void *ptr, size_t size, size_t nmemb, void *userdata)
{
mail_context& ctx = *reinterpret_cast<mail_context *>(userdata);
size_t n = std::min(ctx.message.length() - ctx.written, size * nmemb);
std::memcpy(ptr, ctx.message.c_str() + ctx.written, n);
ctx.written += n;
return n;
}
void deliver_mail(const std::string& subject, const std::string& message)
{
auto to_address = create_to_address();
auto from_address = create_from_address();
mail_context ctx;
std::ostringstream oss;
oss << "To: " << to_address << "\r\n"
<< "From: " << from_address << "\r\n"
<< "Subject: " << subject << "\r\n"
<< "\r\n"
<< message;
ctx.message = oss.str();
auto cleanup = [](CURL *curl) { if (curl != 0) curl_easy_cleanup(curl);
};
std::unique_ptr<CURL, decltype(cleanup)> curl(curl_easy_init(),
cleanup);
if (!curl) {
throw std::runtime_error("curl_easy_init failed");
}
CURLcode rc;
if ((rc = curl_easy_setopt(curl.get(), CURLOPT_NOSIGNAL, 1)) !=
CURLE_OK) { // necessary in multithreaded code
throw std::runtime_error(curl_easy_strerror(rc));
}
if ((rc = curl_easy_setopt(curl.get(), CURLOPT_MAIL_FROM,
from_address.c_str())) != CURLE_OK) {
throw std::runtime_error(curl_easy_strerror(rc));
}
auto cleanup_recipients = [](struct curl_slist *slist) { if (slist)
curl_slist_free_all(slist); };
std::unique_ptr<struct curl_slist, decltype(cleanup_recipients)>
recipients(
curl_slist_append(0, to_address.c_str()), cleanup_recipients);
if (!recipients) {
throw std::runtime_error("curl_slist_append failed");
}
if ((rc = curl_easy_setopt(curl.get(), CURLOPT_MAIL_RCPT,
recipients.get())) != CURLE_OK) {
throw std::runtime_error(curl_easy_strerror(rc));
}
if ((rc = curl_easy_setopt(curl.get(), CURLOPT_READFUNCTION,
&mail_read)) != CURLE_OK) {
throw std::runtime_error(curl_easy_strerror(rc));
}
if ((rc = curl_easy_setopt(curl.get(), CURLOPT_READDATA, &ctx)) !=
CURLE_OK) {
throw std::runtime_error(curl_easy_strerror(rc));
}
std::vector<std::string> servers;
if (is_live()) {
servers = {"10.4.44.87", "10.61.29.135"};
} else {
servers = {"127.0.0.1"};
}
for (auto& server : servers) {
auto url = "smtp://" + server;
if ((rc = curl_easy_setopt(curl.get(), CURLOPT_URL, url.c_str()))
!= CURLE_OK) {
throw std::runtime_error(curl_easy_strerror(rc));
}
ctx.written = 0;
if ((rc = curl_easy_perform(curl.get())) != CURLE_OK) {
LOG(ERROR) << "curl_easy_perform: " << curl_easy_strerror(rc);
} else {
break;
}
}
}
Avery
-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette: http://curl.haxx.se/mail/etiquette.html
Received on 2014-04-17