curl / Mailing Lists / curl-library / Single Mail
Buy commercial curl support from WolfSSL. We help you work out your issues, debug your libcurl applications, use the API, port to new platforms, add new features and more. With a team lead by the curl founder himself.

Connecting to IMAP server using libcurl

From: Jeffrey McKay via curl-library <curl-library_at_cool.haxx.se>
Date: Tue, 1 Sep 2020 14:39:08 -0700

I maintain an IMAP application (Windows), written in VC 2017, that
uses Winsock2 for the underlying
connection. I am investigating using libcurl instead of Winsock in
order to relieve myself of various
issues such as proxies and SSL/TLS, etc.

I am aware of the high level IMAP functions in libcurl but I don't
want to go there, I need more direct
control of IMAP and I need to re-use my existing code. So I would like
to experiment with curl_easy_send()
and curl_easy_recv().

So far not having much luck. I'm basically running the demo program
sendrecv.c that comes with libcurl
(my slightly modified version shown below).

When you connect to an IMAP server it immediately sends back a
response listing its capabilities. The
client does not need to request it. In my program, I can connect to my
test server (outlook.office365.com),
and if I use port 143, the insecure IMAP port, I can receive the
response. But if I use secure port 993,
the program hangs on the select() command, timing out after 60 seconds.

So presumably I have a problem with SSL. I've tried enabling SSL using
CURLOPT_USE_SSL, but it makes no
difference. What am I missing here?

P.S. possibly an unrelated question, but when I try to connect to
imap.gmail.com, the connection fails
with error 56 (CURLE_RECV_ERROR).

-----------------------------------------------------------------------------------

static int wait_on_socket(curl_socket_t sockfd, int for_recv, long timeout_ms)
{
    struct timeval tv;
    fd_set infd, outfd, errfd;
    int res;

    tv.tv_sec = timeout_ms / 1000;
    tv.tv_usec = (timeout_ms % 1000) * 1000;

    FD_ZERO(&infd);
    FD_ZERO(&outfd);
    FD_ZERO(&errfd);

    FD_SET(sockfd, &errfd); /* always check for error */

    if (for_recv) {
        FD_SET(sockfd, &infd);
    }
    else {
        FD_SET(sockfd, &outfd);
    }

    /* select() returns the number of signalled sockets or -1 */
    printf("starting select\n");
    res = select((int)sockfd + 1, &infd, &outfd, &errfd, &tv);
    printf("finished select, res=%d\n", res);
    return res;
}

int main()
{
    CURL *curl;
    CURLcode res;
    int port = 993;
    curl_socket_t sockfd;
    char imap_host[256] = "";
    char buf[1024];
    size_t nread;

    printf("Starting sendrecv demo\n");

    curl = curl_easy_init();
    if (!curl) {
        printf("Unable to initialize curl\n");
        return(0);
    }

    curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, debug_function);
    curl_easy_setopt(curl, CURLOPT_VERBOSE, true);

    //strcpy_s(imap_host, "imap.gmail.com");
    strcpy_s(imap_host, "outlook.office365.com");
    curl_easy_setopt(curl, CURLOPT_URL, imap_host);
    curl_easy_setopt(curl, CURLOPT_CONNECT_ONLY, 1L);
    curl_easy_setopt(curl, CURLOPT_PORT, port);
    curl_easy_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_TRY);
    res = curl_easy_perform(curl);

    printf("Return from connect: %d\n", res);

    /* Extract the socket from the curl handle - we'll need it for waiting. */
    res = curl_easy_getinfo(curl, CURLINFO_ACTIVESOCKET, &sockfd);
    if (res != CURLE_OK) {
        printf("Error getting socket\n");
        return(0);
    }

    printf("Reading IMAP response\n");

    while (1) {
        /* Warning: This example program may loop indefinitely (see above). */

        do {
            nread = 0;
            res = curl_easy_recv(curl, buf, sizeof(buf), &nread);

            if (res == CURLE_AGAIN && !wait_on_socket(sockfd, 1, 60000L)) {
                printf("Error: timeout.\n");
                return(0);
            }
        } while (res == CURLE_AGAIN);

        if (res != CURLE_OK) {
            printf("Error: %s\n", curl_easy_strerror(res));
            break;
        }

        if (nread == 0) {
            /* end of the response */
            break;
        }

        printf("Received %d bytes\n", nread);
        buf[nread] = 0;
        break;

    }

    printf("response: %s\n", buf);

    /* always cleanup */
    curl_easy_cleanup(curl);

    return(0);

}
-------------------------------------------------------------------
Unsubscribe: https://cool.haxx.se/list/listinfo/curl-library
Etiquette: https://curl.haxx.se/mail/etiquette.html
Received on 2020-09-01