1 /* Copyright 1996 by Eric S. Raymond
3 * For license terms, see the file COPYING in this directory.
6 /***********************************************************************
9 programmer: Eric S. Raymond
10 description: IMAP client code
12 ***********************************************************************/
18 #if defined(STDC_HEADERS)
21 #if defined(HAVE_UNISTD_H)
27 #include "fetchmail.h"
29 static int count, first;
31 /*********************************************************************
33 Method declarations for IMAP
35 *********************************************************************/
37 static int exists, unseen, recent;
39 int imap_ok (argbuf,socket)
40 /* parse command response */
45 char buf [POPBUFSIZE+1];
50 if (SockGets(socket, buf, sizeof(buf)) < 0)
53 if (outlevel == O_VERBOSE)
54 fprintf(stderr,"%s\n",buf);
56 /* interpret untagged status responses */
57 if (strstr(buf, "EXISTS"))
59 if (strstr(buf, "RECENT"))
61 if (sscanf(buf + 2, "OK [UNSEEN %d]", &n) == 1)
65 (tag[0] != '\0' && strncmp(buf, tag, strlen(tag)));
72 if (strncmp(buf + TAGLEN + 1, "OK", 2) == 0) {
73 strcpy(argbuf, buf + TAGLEN);
76 else if (strncmp(buf + TAGLEN + 1, "BAD", 2) == 0)
83 int imap_getauth(socket, queryctl, buf)
84 /* apply for connection authorization */
86 struct hostrec *queryctl;
89 /* try to get authorized */
90 return(gen_transact(socket,
92 queryctl->remotename, queryctl->password));
95 static imap_getrange(socket, queryctl, countp, firstp)
96 /* get range of messages to be fetched */
98 struct hostrec *queryctl;
104 /* find out how many messages are waiting */
105 exists = unseen = recent = -1;
106 ok = gen_transact(socket,
108 queryctl->remotefolder[0] ? queryctl->remotefolder : "INBOX");
112 /* compute size of message run */
114 if (queryctl->fetchall)
117 if (exists > 0 && unseen == -1) {
119 "no UNSEEN response; assuming all %d RECENT messages are unseen\n",
121 *firstp = exists - recent + 1;
130 static int imap_fetch(socket, number, limit, lenp)
131 /* request nth message */
137 char buf [POPBUFSIZE+1];
142 "PARTIAL %d RFC822 0 %d",
149 /* looking for FETCH response */
151 if (SockGets(socket, buf,sizeof(buf)) < 0)
154 (sscanf(buf+2, "%d FETCH (RFC822 {%d}", &num, lenp) != 2);
162 static imap_trail(socket, queryctl, number)
163 /* discard tail of FETCH response */
165 struct hostrec *queryctl;
168 char buf [POPBUFSIZE+1];
170 if (SockGets(socket, buf,sizeof(buf)) < 0)
176 static struct method imap =
178 "IMAP", /* Internet Message Access Protocol */
179 143, /* standard IMAP3bis/IMAP4 port */
180 1, /* this is a tagged protocol */
181 0, /* no message delimiter */
182 imap_ok, /* parse command response */
183 imap_getauth, /* get authorization */
184 imap_getrange, /* query range of messages */
185 imap_fetch, /* request given message */
186 imap_trail, /* eat message trailer */
187 "STORE %d +FLAGS (\\Deleted)", /* set IMAP delete flag */
188 "EXPUNGE", /* the IMAP expunge command */
189 "LOGOUT", /* the IMAP exit command */
192 int doIMAP (queryctl)
193 /* retrieve messages using IMAP Version 2bis or Version 4 */
194 struct hostrec *queryctl;
196 return(do_protocol(queryctl, &imap));