2 * pop3.c -- POP3 protocol methods
4 * For license terms, see the file COPYING in this directory.
12 #if defined(HAVE_UNISTD_H)
15 #if defined(STDC_HEADERS)
20 #include "fetchmail.h"
22 #define PROTOCOL_ERROR {fputs("fetchmail: protocol error\n", stderr); return(PS_ERROR);}
26 int pop3_ok (FILE *sockfp, char *argbuf)
27 /* parse command response */
30 char buf [POPBUFSIZE+1];
33 if (SockGets(buf, sizeof(buf), sockfp) >= 0) {
34 if (outlevel == O_VERBOSE)
35 fprintf(stderr,"%s\n",buf);
38 if (*bufp == '+' || *bufp == '-')
43 while (isalpha(*bufp))
47 if (strcmp(buf,"+OK") == 0)
49 else if (strcmp(buf,"-ERR") == 0)
63 int pop3_getauth(FILE *sockfp, struct query *ctl, char *greeting)
64 /* apply for connection authorization */
66 /* build MD5 digest from greeting timestamp + password */
67 if (ctl->protocol == P_APOP)
72 /* find start of timestamp */
73 for (start = greeting; *start != 0 && *start != '<'; start++)
76 fprintf(stderr,"Required APOP timestamp not found in greeting\n");
80 /* find end of timestamp */
81 for (end = start; *end != 0 && *end != '>'; end++)
83 if (*end == 0 || end == start + 1) {
84 fprintf(stderr,"Timestamp syntax error in greeting\n");
90 /* copy timestamp and password into digestion buffer */
91 msg = (char *)xmalloc((end-start+1) + strlen(ctl->password) + 1);
93 strcat(msg,ctl->password);
95 strcpy(ctl->digest, MD5Digest(msg));
99 switch (ctl->protocol) {
101 if ((gen_transact(sockfp,"USER %s", ctl->remotename)) != 0)
104 if ((gen_transact(sockfp, "PASS %s", ctl->password)) != 0)
109 if ((gen_transact(sockfp, "APOP %s %s",
110 ctl->remotename, ctl->digest)) != 0)
115 fprintf(stderr,"Undefined protocol request in POP3_auth\n");
122 static int pop3_getrange(FILE *sockfp, struct query *ctl, int*countp, int*newp)
123 /* get range of messages to be fetched */
126 char buf [POPBUFSIZE+1];
128 /* Ensure that the new list is properly empty */
129 ctl->newsaved = (struct idlist *)NULL;
131 /* get the total message count */
132 gen_send(sockfp, "STAT");
133 ok = pop3_ok(sockfp, buf);
135 sscanf(buf,"%d %*d", countp);
140 * Newer, RFC-1725-conformant POP servers may not have the LAST command.
141 * We work as hard as possible to hide this ugliness, but it makes
142 * counting new messages intrinsically quadratic in the worst case.
146 if (*countp > 0 && !ctl->fetchall)
150 gen_send(sockfp,"LAST");
151 ok = pop3_ok(sockfp, buf);
154 if (sscanf(buf, "%d", &last) == 0)
156 *newp = (*countp - last);
160 /* grab the mailbox's UID list */
161 if ((ok = gen_transact(sockfp, "UIDL")) != 0)
168 while (SockGets(buf, sizeof(buf), sockfp) >= 0)
170 if (outlevel == O_VERBOSE)
171 fprintf(stderr,"%s\n",buf);
174 else if (sscanf(buf, "%d %s", &num, id) == 2)
176 save_str(&ctl->newsaved, num, id);
177 if (!str_in_list(&ctl->oldsaved, id))
188 static int pop3_getsizes(FILE *sockfp, int count, int *sizes)
189 /* capture the sizes of all messages */
193 if ((ok = gen_transact(sockfp, "LIST")) != 0)
197 char buf [POPBUFSIZE+1];
199 while (SockGets(buf, sizeof(buf), sockfp) >= 0)
203 if (outlevel == O_VERBOSE)
204 fprintf(stderr,"%s\n",buf);
207 else if (sscanf(buf, "%d %d", &num, &size) == 2)
208 sizes[num - 1] = size;
217 static int pop3_is_old(FILE *sockfp, struct query *ctl, int num)
218 /* is the given message old? */
221 return (num <= last);
223 return (str_in_list(&ctl->oldsaved,
224 str_find (&ctl->newsaved, num)));
227 static int pop3_fetch(FILE *sockfp, int number, int *lenp)
228 /* request nth message */
231 char buf [POPBUFSIZE+1], *cp;
233 gen_send(sockfp, "RETR %d", number);
234 if ((ok = pop3_ok(sockfp, buf)) != 0)
236 /* look for "nnn octets" -- there may or may not be preceding cruft */
237 if ((cp = strstr(buf, " octets")) == (char *)NULL)
241 while (--cp > buf && isdigit(*cp))
248 static int pop3_delete(FILE *sockfp, struct query *ctl, int number)
249 /* delete a given message */
251 return(gen_transact(sockfp, "DELE %d", number));
254 const static struct method pop3 =
256 "POP3", /* Post Office Protocol v3 */
257 110, /* standard POP3 port */
258 0, /* this is not a tagged protocol */
259 1, /* this uses a message delimiter */
260 pop3_ok, /* parse command response */
261 pop3_getauth, /* get authorization */
262 pop3_getrange, /* query range of messages */
263 pop3_getsizes, /* we can get a list of sizes */
264 pop3_is_old, /* how do we tell a message is old? */
265 pop3_fetch, /* request given message */
266 NULL, /* no message trailer */
267 pop3_delete, /* how to delete a message */
268 NULL, /* no POP3 expunge command */
269 "QUIT", /* the POP3 exit command */
272 int doPOP3 (struct query *ctl)
273 /* retrieve messages using POP3 */
275 if (ctl->mailbox[0]) {
276 fprintf(stderr,"Option --remote is not supported with POP3\n");
279 return(do_protocol(ctl, &pop3));
282 /* pop3.c ends here */