简体   繁体   中英

C++ libcurl IMAP fetch header fields

I am using libcurl with IMAP to fetch messages from an email inbox. I can fetch messages completely, but I am unable to fetch a header field; my writefunction for curl only returns the first line.

Here is my code:

std::string fetchdata;

size_t write_data(char* buf, size_t size, size_t nmemb, void* up) {
    fetchdata.append((char*)buf, size*nmemb);
    return size*nmemb;
}

int fetchmail() {
    CURL *curl;
    CURLcode res = CURLE_OK;

    curl = curl_easy_init();
    if(curl) {
        curl_easy_setopt(curl, CURLOPT_USERNAME, "myemail@gmail.com");
        curl_easy_setopt(curl, CURLOPT_PASSWORD, "mypassword");
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
        curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);

        curl_easy_setopt(curl, CURLOPT_URL, "imaps://imap.gmail.com:993/INBOX");
        curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "UID FETCH 10 BODY[HEADER.FIELDS (To)]");

        res = curl_easy_perform(curl);

        if(res != CURLE_OK)
            fprintf(stderr, "curl_easy_perform() failed: %s\n",

        curl_easy_strerror(res));        
        curl_easy_cleanup(curl);
    }

    std::ofstream outfile("C:\\Path\\fetched.txt", std::ios_base::app);
    outfile << fetchdata;
    outfile.close();

    return (int)res;
}

Running fetchmail outputs

* 3 FETCH (UID 10 BODY[HEADER.FIELDS (To)] {29}

in fetched.txt. However, this is only the first line; the console outputs

* 3 FETCH (UID 10 BODY[HEADER.FIELDS (To)] {29}
To: laboutpost3@gmail.com

)
A004 OK Success

If I modify write_data() to

size_t write_data(char* buf, size_t size, size_t nmemb, void* up) {
    fetchdata.append((char*)buf, size*nmemb);
    std::cout << buf;
    return size*nmemb;
}

it outputs

* 3 FETCH (UID 10 BODY[HEADER.FIELDS (To)] {29
To: laboutpost3@gmail.com

)
A004 OK Success
ted. (Success)
 (Success)
 (Success)
WRITE] INBOX selected. (Success)
[UIDNEXT 12] Predicted next UID.
* OK [HIGHESTMODSEQ 1759]
A003 OK [READ-WRITE] INBOX selected. (Success)
* OK [HIGHESTMODSEQ 1759]
A003 OK [READ-WRITE] INBOX selected. (Success)

Is this a problem with my write_data() ? buf seems to have all the information.

The buf parameter in the write_data() function is not null-terminated, but calling cout << buf requires a null terminator since buf is a char* pointer. As such, you are printing the content of surrounding memory. The buf data is just raw bytes, that is why you are given the buffer size as another parameter. When printing buf , you have to take that size into account, eg:

std::cout << std::string(buf, size*nmemb);

Alternatively:

std::cout.write(buf, size*nmemb);

Since you are using CURLOPT_CUSTOMREQUEST , curl sends the request as-is and gives you back the server's reply as-is. In that situation, curl has no context to know what the request is or how to process the reply for you. You will have to parse the reply yourself if you want to extract smaller portions of it.

You might want to look at curl's documentation and examples, in particular use the UID and SECTION parameters of an IMAP url (Read RFC 5092 for the full syntax), eg:

curl_easy_setopt(curl, CURLOPT_URL, "imaps://imap.gmail.com:993/INBOX/;uid=10/;section=HEADER.FIELDS%20(To)");

That will allow curl to generate its own FETCH request without you having to resort to using CURLOPT_CUSTOMREQUEST manually. Since curl is creating the FETCH request, it is more likely to parse the response for you, giving just the requested header data to your write_data() function so it has less to parse/strip manually.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM