通过C libcurl访问gmail imaps服务器失败

时间:2017-03-27 19:52:15

标签: c linux libcurl gmail-imap

我使用libcurl C库来访问(获取,搜索)gmail imaps服务器,我使用libcurl示例中的代码,即" imap-ssl.c"作为一个测试的例子。第一次执行时的示例代码工作正常并从我的gmail帐户中获取所需的电子邮件,但是当您再次尝试执行该程序时,当想要再次获取不同的电子邮件或同一个电子邮件时,它会失败, 但如果我在大约20分钟后重新运行该程序,它就可以运行并获取所需的邮件。

似乎gmail要求我们立即从服务器获取整个收件箱,即本地(已提取)电子邮件与在线gmail服务器的同步只允许在20分钟内完成一次或者什么。如果一个人一次只想访问一封电子邮件或者只是逐个浏览他的整个Gmail邮件收件箱邮件怎么办?

此外,我尝试使用openssl命令行工具在imap.gmail.com:993(启用ssl)上获取或执行imaps命令,它就像一个魅力,无论我多少次尝试访问gmail它永远不会说一句麻烦,但libcurl确实如此。

以下是示例C代码:

#include<stdio.h>
#include<string.h>
#include <curl/curl.h>

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

curl = curl_easy_init();
if(curl) {
/* Set username and password */
curl_easy_setopt(curl, CURLOPT_USERNAME, "example@gmail.com");
curl_easy_setopt(curl, CURLOPT_PASSWORD, "examplepassword");

/* This will fetch message 1 from the user's inbox. Note the use of
* imaps:// rather than imap:// to request a SSL based connection. */
curl_easy_setopt(curl, CURLOPT_URL,"imaps://imap.gmail.com:993/INBOX/;UID=5");
/* Note: CA cert is already in the right place (checked) */

#ifdef SKIP_PEER_VERIFICATION
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
#endif

/* If the site you're connecting to uses a different host name that what
* they have mentioned in their server certificate's commonName (or
* subjectAltName) fields, libcurl will refuse to connect. You can skip
* this check, but this will make the connection less secure. */
#ifdef SKIP_HOSTNAME_VERIFICATION
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
#endif

curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
/* Perform the fetch */
res = curl_easy_perform(curl);
/* Check for errors */
if(res != CURLE_OK)
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));  
curl_easy_cleanup(curl);
}
return (int)res;
}

以下是它给我的错误/日志:

第一次运行程序时(或20分钟后):

> * Hostname was NOT found in DNS cache
> *   Trying 74.125.206.109...
> * Connected to imap.gmail.com (74.125.206.109) port 993 (#0)
> * successfully set certificate verify locations:
> *   CAfile: none
> >  CApath: /etc/ssl/certs
> * SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
> * Server certificate:
> *      subject: C=US; ST=California; L=Mountain View; O=Google Inc; CN=imap.gmail.com
> *      start date: 2017-03-22 16:46:00 GMT
> *      expire date: 2017-06-14 16:17:00 GMT
> *      subjectAltName: imap.gmail.com matched
> *      issuer: C=US; O=Google Inc; CN=Google Internet Authority G2
> *      SSL certificate verify ok.
> * OK Gimap ready for requests from 182.180.90.60 
> * A001 CAPABILITY
> >      CAPABILITY IMAP4rev1 UNSELECT IDLE NAMESPACE QUOTA ID XLIST CHILDREN X-GM-EXT-1 XYZZY SASL-IR AUTH=XOAUTH2 AUTH=PLAIN
> AUTH=PLAIN-CLIENTTOKEN AUTH=OAUTHBEARER AUTH=XOAUTH A001 OK Thats all
> she wrote! 9
> * A002 AUTHENTICATE PLAIN 
> * CAPABILITY IMAP4rev1 UNSELECT IDLE NAMESPACE QUOTA ID XLIST CHILDREN X-GM-EXT-1 UIDPLUS COMPRESS=DEFLATE ENABLE MOVE CONDSTORE ESEARCH
> UTF8=ACCEPT LIST-EXTENDED LIST-STATUS LITERAL- SPECIAL-USE
> APPENDLIMIT=35651584
> * A002 OK example@gmail.com authenticated (Success)
> * A003 SELECT INBOX
> * FLAGS (\Answered \Flagged \Draft \Deleted \Seen $NotPhishing $Phishing)
> * OK [PERMANENTFLAGS (\Answered \Flagged \Draft \Deleted \Seen $NotPhishing $Phishing \*)] Flags permitted.
> * OK [UIDVALIDITY 1] UIDs valid.
> * 32 EXISTS
> * 0 RECENT
> * OK [UIDNEXT 46] Predicted next UID.
> * OK [HIGHESTMODSEQ 4777]
> * A003 OK [READ-WRITE] INBOX selected. (Success)
> * A004 FETCH 5 BODY[]
> * 5 FETCH (BODY[] {628}
> *Found 628 bytes to download
> >   Bcc: example@gmail.com
> >   Return-Path: <example@gmail.com>
> >   Received: from localhost (["MY IP Address])
> >   by smtp.gmail.com with ESMTPSA id 
> >   for <example@gmail.com>
> >   (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128);
> >   Wed, 15 Mar 2017 03:13:29 -0700 (PDT)
> * Message-ID: <"msg id"@mx.google.com>
> * Date: Wed, 15 Mar 2017 03:13:29 -0700 (PDT)
> * From: example@gmail.com
> >     Written 489 bytes, 139 bytes are left for transfer
> >     Hi, i'm using openssl to send this message, i hope you are doing great man
> >     Thank you so much
> >     I just wanted to tell you that this is also possible
> *  A004 OK Success
> * Connection #0 to host imap.gmail.com left intact

尝试在成功获取后立即重新运行程序:

> * Hostname was NOT found in DNS cache
> *   Trying 74.125.133.108...
> *   Trying 2a00:1450:400c:c07::6d...
> * connect to 2a00:1450:400c:c07::6d port 993 failed: Network is unreachable
>* Failed to connect to imap.gmail.com port 993: Network is unreachable
>* Closing connection 0
>>curl_easy_perform() failed: Couldn't connect to server

任何代码示例都会非常感激。

P.S:已添加代码

1 个答案:

答案 0 :(得分:0)

在第二次尝试时,它无法连接到imap服务器,但这与libcurl无关。

您可以添加以下代码以确保它仅通过IPv4连接,然后调试输出中的错误消息将是从连接尝试到与您更相关的IPv4地址(因为您很可能不会#39) ;有IPv6支持):

curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);

此处有关该选项的更多信息: https://curl.haxx.se/libcurl/c/CURLOPT_IPRESOLVE.html

尝试使用完全相同的IP连接到端口993,因为libcurl程序在libcurl程序不起作用时尝试通过telnet连接。我确定它也会失败。

前进的方法可能会调查你是否有某种可能导致问题的防火墙。尝试运行tcpdump(或者如果你想要一个GUI,则运行wireshark)来查看TCP级别上发生的事情。