C/C++, libCurl

Send email using Gmail, C and libcurl – Part 2

Requirements
* A Gmail account (Use a dedicated account! Do not use your personal one!)
* Turn on “Access for less secure apps” under the security settings of the account. less secure apps
* You may also have to enable IMAP in the account settings.

The following code snippets is from Post-recon project. This project is a work in progress.

Generate Message-ID

HRESULT Common::GenerateMessageID(const char *sender, SIZE_T senderLength, char **messageID)
{
    GUID pGuiId;
    WCHAR sGuiId[64] = { 0 };
    WCHAR sTrimId[64] = { 0 };
 
    /*
        ..
        ..
    */
 
    //get first token
    if (strtok_s(senderCopy, "@", &context) == NULL) {
        hFree(senderCopy);
        return S_FALSE;
    }
 
    //Get email domain
    if ((tmp = strtok_s(NULL, "@", &context)) == NULL) {
        hFree(senderCopy);
        return S_FALSE;
    }
 
    /*
        ..
        ..
    */
 
    //Create a GUID, a unique 128-bit integer.
    if (CoCreateGuid(&pGuiId) != S_OK) {
        return S_FALSE;
    }
 
    //Convert a globally unique identifier (GUID) into a string of printable characters.
    if ((strFromGuiSize = StringFromGUID2(pGuiId, sGuiId, _countof(sGuiId))) == 0) {
        return S_FALSE;
    }
 
    /*
        ..
        ..
    */
 
    return S_OK;
}

Get date, time and timezone offset

char* Common::GetTimezoneOffset(void)
{
    /*
        ..
        ..
    */
 
    if (strftime(dateTime, 50, "%a, %d %b %Y %H:%M:%S %z", &gmt) == 0) {
        return NULL;
    }
 
    return dateTime;
}

Email payload

static const char *_payload_text[] = {
    "Date: %s\r\n",         //e.g. Mon, 29 Nov 2010 21:54:29 +1100
    "To: %s\r\n",           //e.g. admin@example.org
    "From: %s(%s)\r\n",     //e.g. support@example.gr(Joe Doe)
    "Message-ID: <%s>\r\n", //e.g. xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx@example.com
    "Subject: %s\r\n",      //subject
    "\r\n",             //do not remove
    "%s\r\n",           //body
    NULL
};

Send email

HRESULT LibCurl::SendEmail(const char *from, const char *fromName, const char *to, const char *subject, const char *body, const char *password)
{
    CURL *curl;
    CURLcode res = CURLE_OK;
    struct curl_slist *recipients = NULL;
    struct upload_status upload_ctx;
 
    char *messageID = 0;
    char *dateTime = 0;
    int size = 0;
 
    char *MSGID = 0;
    char *DATE = 0;
    char *TO = 0;
    char *FROM = 0;
    char *SUBJECT = 0;
    char *BODY = 0;
 
    upload_ctx.lines_read = 0;
 
    //init common lib
    Common::init();
 
    //build DATE string
    dateTime = Common::GetTimezoneOffset();
 
    /*
        ..
        ..
    */
 
    //build messageid string
    Common::GenerateMessageID(from, strlen(from), &messageID);
 
    /*
        ..
        ..
    */
 
 
    curl = curl_easy_init();
    if (curl)
    {
        curl_easy_setopt(curl, CURLOPT_USERNAME, from);
        curl_easy_setopt(curl, CURLOPT_PASSWORD, password);
        curl_easy_setopt(curl, CURLOPT_URL, "smtp://smtp.gmail.com:587");
        curl_easy_setopt(curl, CURLOPT_USE_SSL, (long)CURLUSESSL_ALL);
        curl_easy_setopt(curl, CURLOPT_MAIL_FROM, from);
        recipients = curl_slist_append(recipients, to);
        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);
        curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); //debug, turn it off on production
        res = curl_easy_perform(curl);
        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 (res == CURLE_OK ? S_OK : S_FALSE);
}

Usage

int main(void)
{
    char from[30] = "xxxx@gmail.com";
    char to[30] = "yyyy@gmail.com";
    char name[30] = "Joe Doe";
    char subject[50] = "Hello there";
    char body[100] = "Test body\r\nNew line\r\nTest test\r\nTest";
    char password[50] = "xxxxxyyyyy";
 
    LibCurl::SendEmail(from, name, to, subject, body, password);
 
    return EXIT_SUCCESS;
}

libcurl SMTP TLS example