Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

sending an email with libcurl/smtp with gmail: login denied

I know there are hundreds of posts out there but somehow this does not work for me. I am trying to send an email with libcurl. This is my code:

#include <stdio.h>
#include <string.h>
#include <curl/curl.h>

#define FROM    "<[email protected]>"
#define TO      "<[email protected]>"
#define CC      "<[email protected]>"

static const char *payload_text[] = {
  "Date: Mon, 29 Nov 2010 21:54:29 +1100\r\n",
  "To: " TO "\r\n",
  "From: " FROM "(Example User)\r\n",
  "Cc: " CC "(Another example User)\r\n",
  "Message-ID: <dcd7cb36-11db-487a-9f3a-e652a9458efd@"
  "rfcpedant.example.org>\r\n",
  "Subject: SMTP example message\r\n",
  "\r\n", /* empty line to divide headers from body, see RFC5322 */
  "The body of the message starts here.\r\n",
  "\r\n",
  "It could be a lot of lines, could be MIME encoded, whatever.\r\n",
  "Check RFC5322.\r\n",
  NULL
};

struct upload_status {
  int lines_read;
};

static size_t payload_source(void *ptr, size_t size, size_t nmemb, void *userp)
{
  struct upload_status *upload_ctx = (struct upload_status *)userp;
  const char *data;

  if((size == 0) || (nmemb == 0) || ((size*nmemb) < 1)) {
    return 0;
  }

  data = payload_text[upload_ctx->lines_read];

  if(data) {
    size_t len = strlen(data);
    memcpy(ptr, data, len);
    upload_ctx->lines_read++;

    return len;
  }

  return 0;
}

int main(void)
{
  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) {
    curl_easy_setopt(curl, CURLOPT_URL, "smtp://smtp.gmail.com:587");
    curl_easy_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_ALL);
    curl_easy_setopt(curl, CURLOPT_USERNAME, "[email protected]");
    curl_easy_setopt(curl, CURLOPT_PASSWORD, "mypassword");
    curl_easy_setopt(curl, CURLOPT_MAIL_FROM, FROM);

    recipients = curl_slist_append(recipients, TO);
    recipients = curl_slist_append(recipients, CC);
    curl_easy_setopt(curl, CURLOPT_MAIL_RCPT, recipients);

   curl_easy_setopt(curl, CURLOPT_READFUNCTION, payload_source);
curl_easy_setopt(curl, CURLOPT_READDATA, &upload_ctx);
    curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);

    res = curl_easy_perform(curl);

    /* Check for errors */
    if(res != CURLE_OK)
      fprintf(stderr, "curl_easy_perform() failed: %s\n",
              curl_easy_strerror(res));

    curl_slist_free_all(recipients);

    curl_easy_cleanup(curl);
  }

  return (int)res;
}

I also tried this example which is very similar except the text gets piped through a different file.

But I always get

curl_easy_perform() failed: Login denied

and then gmail sends me a message saying that someone tried to hack into my account. (login credentials are correct)

This curl-config --feature

gives me

SSL IPv6 UnixSockets libz NTLM NTLM_WB

Reading a couple of blogposts I also tried with hotmail using smtp://smtp.live.com:465

But here I get

curl_easy_perform() failed: Couldn't connect to server

What am I doing wrong here?

like image 345
Tom Avatar asked May 07 '16 19:05

Tom


People also ask

Why is my SMTP for Gmail not working?

In Google mail, you must allow "less secure" apps access in order for your SMTP settings to work. There are two places this setting must be enabled: Visit: https://myaccount.google.com/ and on the left side, go to Security, then scroll down to Less secure app access: Turn this on, as you must allow it to use SMTP.

Can still connect to Gmail with SMTP server?

Yes! You can use the SMTP server even if you've enabled two-factor authentication on your Google account. However, you will need to generate an app password so that the app can still connect.

What is my Gmail SMTP username and password?

Gmail SMTP username: Your full Gmail address, such as [email protected]. Gmail SMTP password: Your Gmail password. Gmail SMTP port: 465 (SSL)/587 (TLS)


2 Answers

I had to spend a great deal of time to get this to work but I finally got it to work. Here's what I found:

First:

#define FROM    "<[email protected]>"
#define TO      "<[email protected]>"
#define CC      "<[email protected]>"

There should not be any "<" or ">" in the email adress. I did the mistake of reusing the defines and could not for my life understand why the login failed.

Second:

You will most likely need to go here and allow unsecure apps: https://www.google.com/settings/security/lesssecureapps

Third:

If you're using port 587 you will need the following line:

curl_easy_setopt(m_curl, CURLOPT_USE_SSL, CURLUSESSL_ALL);

This does not seem to be needed for 465.

Note:

It's ok to use either port 465 or 587. 465 requires SSL so you will need to use smtps instead of smtp to specify this - smtps://smtp.gmail.com:465. I found some info about it here: https://support.google.com/a/answer/176600?hl=en

like image 163
NiceGuyBob Avatar answered Jan 02 '23 08:01

NiceGuyBob


In 2022, you need to create a App Password on you google account. And then using this password you can send the emails without problem.

Take a look on this link: https://support.google.com/mail/answer/185833?hl=en

like image 30
Helder Ribeiro Avatar answered Jan 02 '23 08:01

Helder Ribeiro