cURL / Mailing Lists / curl-library / Single Mail

curl-library

Re: libcurl >= 7.34.0 break prev working smtp code

From: Avery Fay <avery_at_mixpanel.com>
Date: Thu, 17 Apr 2014 20:14:54 -0700

Thanks, adding CURLOPT_UPLOAD did the trick.

Avery

On Thu, Apr 17, 2014 at 12:56 AM, Steve Holme <steve_holme_at_hotmail.com>wrote:

> Hi Avery,
>
> Apologies for a) the top posting but I'm using my mobile and b) I may have
> missed it in you code sample but I believe you are missing a
> curl_easy_setopt() to specify the CURLOPT_UPLOAD flag.
>
> Technically this should have been set when using older versions but the
> flag was never checked the the smtp code :-(
>
> King regards
>
> Steve
> ------------------------------
> From: Avery Fay <avery_at_mixpanel.com>
> Sent: ‎17/‎04/‎2014 08:40
> To: curl-library_at_cool.haxx.se
> Subject: libcurl >= 7.34.0 break prev working smtp code
>
> 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
>

-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette: http://curl.haxx.se/mail/etiquette.html
Received on 2014-04-18