C - Libcurl - How to search for Mails with special chars (ä,ö,ü) - c

i use libcurl to search for mails in my mailbox.
But i cannot search mails with mails that inlcudes special chars (ä,ö,ü) in the subject.
int main(void)
{
CURL *curl;
CURLcode res = CURLE_OK;
curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_USERNAME, "myuser");
curl_easy_setopt(curl, CURLOPT_PASSWORD, "mypassword");
curl_easy_setopt(curl, CURLOPT_URL, "imaps://imap.gmail.com:993/INBOX");
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "SEARCH SUBJECT Spülmaschine");
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);
}
return (int)res;
}
The mail cannot be found.
I searching a while but i cannot find some tipps.
Have someone any ideas ?
EDIT:// No one of the following trys will work:
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "SEARCH CHARSET UTF-8 SUBJECT \x53\x70\xc3\xbc\x6c\x6d\x61\x73\x63\x68\x69\x6e\x65");
//try it with UTF-7
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "SEARCH SUBJECT Sp+APw-lmaschine");
sprintf(strSearchString, "SEARCH CHARSET UTF-8 SUBJECT {%i}\r\n\x53\x70\xc3\xbc\x6c\x6d\x61\x73\x63\x68\x69\x6e\x65", strlen("\x53\x70\xc3\xbc\x6c\x6d\x61\x73\x63\x68\x69\x6e\x65"));
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, strSearchString);

After a long time i found a solution:
int main(void) {
CURL *curl;
CURLcode res = CURLE_OK;
curl = curl_easy_init();
if (curl) {
curl_easy_setopt(curl, CURLOPT_USERNAME, "myuser");
curl_easy_setopt(curl, CURLOPT_PASSWORD, "mypass");
curl_easy_setopt(curl, CURLOPT_URL, "imaps://imap.gmail.com:993");
// see RFC6855 IMAP Support for UTF-8
// imap.gmail.com states UTF8=ACCEPT in CAPABILITY response,
// so enable it to use UTF-8 in quoted strings.
// Must come after AUTHENTICATE and before SELECT.
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "ENABLE UTF8=ACCEPT");
res = curl_easy_perform(curl);
if (res != CURLE_OK)
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
// SELECT INBOX broken out from URL
if (res == CURLE_OK) {
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "SELECT INBOX");
res = curl_easy_perform(curl);
if (res != CURLE_OK)
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
if (res == CURLE_OK) {
// U+00FC LATIN SMALL LETTER U WITH DIAERESIS is \xC3\xBC in UTF-8
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "SEARCH
SUBJECT \"Sp\xC3\xBClmaschine\"");
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);
}
return (int) res;
}

While technically against protocol for including 8-bit characters, try SEARCH CHARSET UTF-8 SUBJECT "spülmaschine", and make sure you really are sending UTF-8 and not some other encoding. This will work on many servers. I do not know if you can make libcurl do it the proper way with an IMAP literal.
Note: some server software just doesn't support search that well. Remember, you can always use a tool like socat or python's imaplib, which give you pretty low level access to the protocol for experimenting.

Related

C libcurl verify if message is sent to webhook

Because of variable my_description changes frequently I get this error:
{"code": 50109, "message": "The request body contains invalid JSON."}
It is possible to modify the code below to verify if libcurl gets an error when sending the message to webhook? I want to print when the message is sent and when exist an error in sending a message.
I tried this:
if(res != CURLE_OK)
fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
but it is not helpful.
Anybody can help me, please? Thanks!
#include <stdio.h>
#include <curl/curl.h>
#define nullptr ((void*)0)
int main() {
char message[65500];
int max_len = sizeof message;
CURL *curl;
CURLcode res;
char webhook[] = "DISCORD_WEBHOOK";
char my_description[] = "Description";
snprintf(message, max_len,"{\"username\": \"Test\",\"embeds\":[{\"description\": \"%s\"}]}", my_description);
curl = curl_easy_init();
if(curl) {
struct curl_slist* headers = nullptr;
headers = curl_slist_append(headers, "Content-Type: application/json");
curl_easy_setopt(curl, CURLOPT_URL, webhook);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, message);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
}
return 0;
}
I tried this:
if(res != CURLE_OK)
fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
You might want to try this:
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
} else {
long response_code = 0;
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code);
if(response_code != 200) {
// Error
}
}
An invalid JSON can be caused by quotes in my_description. Quotes must be replaced with escape sequences \".

steps to setup the ssl connection for the C client developed using libcurl with the local host apache on ubuntu

I have setup the apache on ubuntu local host using the ans no 19 of below link
How do I allow HTTPS for Apache on localhost?
Using all the steps described, I have generated the self signed "mykey.key" and "mycert.pem" and set it to "SSLCertificatefile" and "SSCertificateKeyFile"
now I can connect to "https://localhost:443".
But when I try to run the lipcurl c program, I am getting the error "curl_easy_perform() failed: Problem with the local SSL certificate"
Here I am using the same key & certificate what I have generated in above step :mykey.key & mycert.pem.
int main(void)
{
CURL *curl;
CURLcode res;
FILE *headerfile;
const char *pPassphrase = NULL;
static const char *pCertFile = "mycert.pem";
static const char *pCACertFile = "/usr/local/share/ca-certificates/CACert.crt";
static const char *pHeaderFile = "dumpit";
const char *pKeyName;
const char *pKeyType;
const char *pEngine;
headerfile = fopen(pHeaderFile, "wb");
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl) {
/* what call to write: */
curl_easy_setopt(curl, CURLOPT_URL, "https://localhost:443");
curl_easy_setopt(curl, CURLOPT_HEADERDATA, headerfile);
do { /* dummy loop, just to break out from */
if(pEngine) {
/* use crypto engine */
if(curl_easy_setopt(curl, CURLOPT_SSLENGINE, pEngine) != CURLE_OK) {
/* load the crypto engine */
fprintf(stderr, "cannot set crypto engine\n");
break;
}
if(curl_easy_setopt(curl, CURLOPT_SSLENGINE_DEFAULT, 1L) != CURLE_OK) {
/* set the crypto engine as default */
/* only needed for the first time you load
a engine in a curl object... */
fprintf(stderr, "cannot set crypto engine as default\n");
break;
}
}
curl_easy_setopt(curl, CURLOPT_SSLCERTTYPE, "PEM");
curl_easy_setopt(curl, CURLOPT_SSLCERT, pCertFile);
curl_easy_setopt(curl, CURLOPT_SSLKEYTYPE, pKeyType);
curl_easy_setopt(curl, CURLOPT_SSLKEY, pKeyName);
curl_easy_setopt(curl, CURLOPT_CAINFO, pCACertFile);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
res = curl_easy_perform(curl);
if(res != CURLE_OK)
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
} while(0);
/* always cleanup */
curl_easy_cleanup(curl);
}
curl_global_cleanup();
return 0;
}
here the content of "mycert.pem" & "CACert.crt" are same as I have made the copy.
please suggest, if I am missing any step

Use curl with a webpage with no security protocol

I have a webpage: 10.1.1.165 that I am trying to get the data off of. I have built this program in linux and it works fine, however, when developing for windows systems I am running into an issue.
if (filename.substr(filename.length() - 4, 4) == "html" || filename.substr(filename.length() - 3, 3) == "htm")
{
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
string s;
if (curl)
{
curl_easy_setopt(curl, CURLOPT_URL, filename.c_str());
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &s);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
if (gLogger->isDebug()) curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout/1000);
//curl_easy_setopt (curl, CURLOPT_VERBOSE, 1L); //remove this to disable verbose output
// Perform the request, res will get the return code
res = curl_easy_perform(curl);
// Check for errors
if (res != CURLE_OK)
{
while (res == CURLE_OPERATION_TIMEDOUT)
{
res = curl_easy_perform(curl);
}
if (res != CURLE_OK)
{
gLogger->error("curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
curl_easy_cleanup(curl);
return -1;
}
}
curl_easy_cleanup(curl);
On my linux system, this works perfectly. On my Windows system I get: curl_easy_perform() failed: Unsupported protocol. If I go to my webpage 10.1.1.165 I see that it is being hosted with NO security. I have no way of changing how that webpage is being hosted.
Per this resource: https://curl.haxx.se/libcurl/c/CURLOPT_PROTOCOLS.html
By default libcurl will accept all protocols
Does anyone know why curl doesn't like me grabbing this webpage on windows? And if so, what settings might I have to adjust?
I have solved my issue by switching to curl-7.55.1. Previously I was using curl-7.68.0. I'm not sure if the functionality was removed or if using it is more involved.

keep-alive curl C htttps POST

With this code I am sending strings to a webserver using libcurl and write the data to a MySQL (is done at the webserver).
My Problem is that for every call of this function the program starts a new key exchange with the webserver. I would like to have a persistant connection to the Server.
I searched here and web already and didnt find any satisfying solutions.
Multi-handler and forced keep alive still open a new connection.
Following is my Code to establish an SSL Connection:
CURL *curl;
CURLcode res;
res = curl_global_init(CURL_GLOBAL_DEFAULT); // Check for errors
if(res != CURLE_OK) {
fprintf(stderr, "curl_global_init() failed: %s\n",
curl_easy_strerror(res));
return 1;
}
// curl handler
curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, STRING);
curl_easy_setopt(curl, CURLOPT_URL, "https://IP/something/something.php");
curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1L);
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); //verbose output activated
struct curl_slist *headers=NULL;
headers = curl_slist_append(headers, "Content-Type: application/json"); // type JSON
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
// Perform the request, res will get the return code
res = curl_easy_perform(curl);
// Check for errors
if(res != CURLE_OK)
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
// cleanup
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
is Answered by Daniel Stenberg here, which is a similar/the same question.
Re-use the same curl handle in subsequent requests! Don't call curl_easy_cleanup(curl) and curl_easy_init() again between them.
So the Solution is to call curl_easy_cleanup(curl) and curl_easy_init() only once.

curl wsdl soap error - mismatched Actions between sender and receiver

I am trying to post the curl based soap request to url using c API's. My libcurl version is curl 7.30.0 (i686-pc-linux-gnu) libcurl/7.30.0 OpenSSL/1.0.0 zlib/1.2.5.I am receiving the below error.Also below code i am using to post the request.i am using correct soap action aswell "GetAuthToken", Why this error is happening while posting the request.Thanks in advance.
Error:
The message with Action '' cannot be processed at the receiver, due to a ContractFilter mismatch at the EndpointDispatcher. This may be because of either a contract mismatch (mismatched Actions between sender and receiver) or a binding/security mismatch between the sender and the receiver. Check that sender and receiver have the same contract and the same binding (including security requirements, e.g. Message, Transport, None)
Request:
123456789
url:
http://x.xx.xx.xxx:20003/HIMS/SecurityService/?wsdl
Sample code:
int main()
{
CURL *curl;
CURLcode res;
struct curl_slist *headers = NULL;
FILE *out_fd = (FILE *) 0;
char errorbuf[300]="",filename[32]="Response.txt";
char errmsg[256];
int Timeout=120;
int buffer_size = 0;
char urlbuff[100]="";
char buff[128] = "http://x.xx.xx.xxx:20003/HIMS/SecurityService/?wsdl";
memset(urlbuff,0,sizeof(urlbuff));
curl = curl_easy_init();
buffer_size = strlen(buffer);
if(curl)
{
out_fd = fopen (filename, "w");
curl_easy_setopt(curl, CURLOPT_FILE, out_fd);
headers = curl_slist_append(headers, "Content-type:text/xml;charset=utf-8; SOAPAction=GetAuthToken");
sprintf(urlbuff,"%s",buff);
curl_easy_setopt(curl, CURLOPT_URL, urlbuff);
Timeout=2000;
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, buffer_size);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, buffer);
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, Timeout);
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER,errmsg);
res = curl_easy_perform(curl);
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
fclose(out_fd);
if(CURLE_OK != res)
{
printf("\nerrorbuf:%s:%d\n",errorbuf,res);
return -1;
}
return 0;
}
}
Assuming you have created a valid soap envelope for this request. In your code, you missed to define a POST request with your curl.
curl_easy_setopt(curl, CURLOPT_POST, 1L);

Resources