]> Pileus Git - ~andy/fetchmail/blob - imap.c
87dfe19989d19a95c8d290bce75babb67d0ed503
[~andy/fetchmail] / imap.c
1 /* Copyright 1996 by Eric S. Raymond
2  * All rights reserved.
3  * For license terms, see the file COPYING in this directory.
4  */
5
6 /***********************************************************************
7   module:       imap.c
8   project:      fetchmail
9   programmer:   Eric S. Raymond
10   description:  IMAP client code
11
12  ***********************************************************************/
13
14 #include  <config.h>
15 #include  <varargs.h>
16
17 #include  <stdio.h>
18 #if defined(STDC_HEADERS)
19 #include  <string.h>
20 #endif
21 #if defined(HAVE_UNISTD_H)
22 #include  <unistd.h>
23 #endif
24 #include  <errno.h>
25
26 #include  "socket.h"
27 #include  "fetchmail.h"
28
29 static int count, first;
30
31 /*********************************************************************
32
33  Method declarations for IMAP 
34
35  *********************************************************************/
36
37 static int exists, unseen, recent;
38
39 int imap_ok (argbuf,socket)
40 /* parse command response */
41 char *argbuf;
42 int socket;
43 {
44   int ok;
45   char buf [POPBUFSIZE+1];
46   char *bufp;
47   int n;
48
49   do {
50     if (SockGets(socket, buf, sizeof(buf)) < 0)
51       return(PS_SOCKET);
52
53     if (outlevel == O_VERBOSE)
54       fprintf(stderr,"%s\n",buf);
55
56     /* interpret untagged status responses */
57     if (strstr(buf, "EXISTS"))
58         exists = atoi(buf+2);
59     if (strstr(buf, "RECENT"))
60         recent = atoi(buf+2);
61     if (sscanf(buf + 2, "OK [UNSEEN %d]", &n) == 1)
62         unseen = n;
63
64   } while
65       (tag[0] != '\0' && strncmp(buf, tag, strlen(tag)));
66
67   if (tag[0] == '\0') {
68     strcpy(argbuf, buf);
69     return(0); 
70   }
71   else {
72     if (strncmp(buf + TAGLEN + 1, "OK", 2) == 0) {
73       strcpy(argbuf, buf + TAGLEN);
74       return(0);
75     }
76     else if (strncmp(buf + TAGLEN + 1, "BAD", 2) == 0)
77       return(PS_ERROR);
78     else
79       return(PS_PROTOCOL);
80   }
81 }
82
83 int imap_getauth(socket, queryctl, buf)
84 /* apply for connection authorization */
85 int socket;
86 struct hostrec *queryctl;
87 char *buf;
88 {
89     /* try to get authorized */
90     return(gen_transact(socket,
91                   "LOGIN %s %s",
92                   queryctl->remotename, queryctl->password));
93 }
94
95 static imap_getrange(socket, queryctl, countp, firstp)
96 /* get range of messages to be fetched */
97 int socket;
98 struct hostrec *queryctl;
99 int *countp;
100 int *firstp;
101 {
102     int ok;
103
104     /* find out how many messages are waiting */
105     exists = unseen = recent = -1;
106     ok = gen_transact(socket,
107                   "SELECT %s",
108                   queryctl->remotefolder[0] ? queryctl->remotefolder : "INBOX");
109     if (ok != 0)
110         return(ok);
111
112     /* compute size of message run */
113     *countp = exists;
114     if (queryctl->fetchall)
115         *firstp = 1;
116     else {
117         if (exists > 0 && unseen == -1) {
118             fprintf(stderr,
119                     "no UNSEEN response; assuming all %d RECENT messages are unseen\n",
120                     recent);
121             *firstp = exists - recent + 1;
122         } else {
123             *firstp = unseen;
124         }
125     }
126
127     return(0);
128 }
129
130 static int imap_fetch(socket, number, limit, lenp)
131 /* request nth message */
132 int socket;
133 int number;
134 int limit;
135 int *lenp; 
136 {
137     char buf [POPBUFSIZE+1];
138     int num;
139
140     if (limit) 
141         gen_send(socket,
142                      "PARTIAL %d RFC822 0 %d",
143                      number, limit);
144     else 
145         gen_send(socket,
146                      "FETCH %d RFC822",
147                      number);
148
149     /* looking for FETCH response */
150     do {
151         if (SockGets(socket, buf,sizeof(buf)) < 0)
152             return(PS_SOCKET);
153     } while
154             (sscanf(buf+2, "%d FETCH (RFC822 {%d}", &num, lenp) != 2);
155
156     if (num != number)
157         return(PS_ERROR);
158     else
159         return(0);
160 }
161
162 static imap_trail(socket, queryctl, number)
163 /* discard tail of FETCH response */
164 int socket;
165 struct hostrec *queryctl;
166 int number;
167 {
168     char buf [POPBUFSIZE+1];
169
170     if (SockGets(socket, buf,sizeof(buf)) < 0)
171         return(PS_SOCKET);
172     else
173         return(0);
174 }
175
176 static struct method imap =
177 {
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 */
190 };
191
192 int doIMAP (queryctl)
193 /* retrieve messages using IMAP Version 2bis or Version 4 */
194 struct hostrec *queryctl;
195 {
196     return(do_protocol(queryctl, &imap));
197 }
198