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.