2 * pop3.c -- POP3 protocol methods
4 * For license terms, see the file COPYING in this directory.
11 #if defined(HAVE_UNISTD_H)
14 #if defined(STDC_HEADERS)
19 #include "fetchmail.h"
21 #define PROTOCOL_ERROR {fputs("fetchmail: protocol error\n", stderr); return(PS_ERROR);}
25 int pop3_ok (socket, argbuf)
26 /* parse command response */
31 char buf [POPBUFSIZE+1];
34 if (SockGets(socket, buf, sizeof(buf)) >= 0) {
35 if (outlevel == O_VERBOSE)
36 fprintf(stderr,"%s\n",buf);
39 if (*bufp == '+' || *bufp == '-')
44 while (isalpha(*bufp))
48 if (strcmp(buf,"+OK") == 0)
50 else if (strcmp(buf,"-ERR") == 0)
64 int pop3_getauth(socket, ctl, greeting)
65 /* apply for connection authorization */
70 /* build MD5 digest from greeting timestamp + password */
71 if (ctl->protocol == P_APOP)
76 /* find start of timestamp */
77 for (start = greeting; *start != 0 && *start != '<'; start++)
80 fprintf(stderr,"Required APOP timestamp not found in greeting\n");
84 /* find end of timestamp */
85 for (end = start; *end != 0 && *end != '>'; end++)
87 if (*end == 0 || (end - start - 1) == 1) {
88 fprintf(stderr,"Timestamp syntax error in greeting\n");
92 /* copy timestamp and password into digestion buffer */
93 msg = (char *)xmalloc((end-start-1) + strlen(ctl->password) + 1);
96 strcat(msg,ctl->password);
98 strcpy(ctl->digest, MD5Digest(msg));
102 switch (ctl->protocol) {
104 if ((gen_transact(socket,"USER %s", ctl->remotename)) != 0)
107 if ((gen_transact(socket, "PASS %s", ctl->password)) != 0)
112 if ((gen_transact(socket, "APOP %s %s",
113 ctl->remotename, ctl->digest)) != 0)
118 fprintf(stderr,"Undefined protocol request in POP3_auth\n");
125 static int pop3_getrange(socket, ctl, countp, newp)
126 /* get range of messages to be fetched */
132 char buf [POPBUFSIZE+1];
134 /* Ensure that the new list is properly empty */
135 ctl->newsaved = (struct idlist *)NULL;
137 /* get the total message count */
138 gen_send(socket, "STAT");
139 ok = pop3_ok(socket, buf);
141 sscanf(buf,"%d %*d", countp);
146 * Newer, RFC-1725-conformant POP servers may not have the LAST command.
147 * We work as hard as possible to hide this ugliness, but it makes
148 * counting new messages intrinsically quadratic in the worst case.
152 if (*countp > 0 && !ctl->fetchall)
156 gen_send(socket,"LAST");
157 ok = pop3_ok(socket, buf);
160 if (sscanf(buf, "%d", &last) == 0)
162 *newp = (*countp - last);
166 /* grab the mailbox's UID list */
167 if ((ok = gen_transact(socket, "UIDL")) != 0)
174 while (SockGets(socket, buf, sizeof(buf)) >= 0)
176 if (outlevel == O_VERBOSE)
177 fprintf(stderr,"%s\n",buf);
180 else if (sscanf(buf, "%d %s", &num, id) == 2)
182 save_uid(&ctl->newsaved, num, id);
183 if (!uid_in_list(&ctl->oldsaved, id))
194 static int pop3_getsizes(socket, count, sizes)
195 /* capture the sizes of all messages */
202 if ((ok = gen_transact(socket, "LIST")) != 0)
206 char buf [POPBUFSIZE+1];
208 while (SockGets(socket, buf, sizeof(buf)) >= 0)
212 if (outlevel == O_VERBOSE)
213 fprintf(stderr,"%s\n",buf);
216 else if (sscanf(buf, "%d %d", &num, &size) == 2)
217 sizes[num - 1] = size;
226 static int pop3_is_old(socket, ctl, num)
227 /* is the given message old? */
233 return (num <= last);
235 return (uid_in_list(&ctl->oldsaved,
236 uid_find (&ctl->newsaved, num)));
239 static int pop3_fetch(socket, number, lenp)
240 /* request nth message */
246 char buf [POPBUFSIZE+1], *cp;
248 gen_send(socket, "RETR %d", number);
249 if ((ok = pop3_ok(socket, buf)) != 0)
251 /* look for "nnn octets" -- there may or may not be preceding cruft */
252 if ((cp = strstr(buf, " octets")) == (char *)NULL)
256 while (isdigit(*--cp))
263 static int pop3_delete(socket, ctl, number)
264 /* delete a given message */
269 return(gen_transact(socket, "DELE %d", number));
272 const static struct method pop3 =
274 "POP3", /* Post Office Protocol v3 */
275 110, /* standard POP3 port */
276 0, /* this is not a tagged protocol */
277 1, /* this uses a message delimiter */
278 pop3_ok, /* parse command response */
279 pop3_getauth, /* get authorization */
280 pop3_getrange, /* query range of messages */
281 pop3_getsizes, /* we can get a list of sizes */
282 pop3_is_old, /* how do we tell a message is old? */
283 pop3_fetch, /* request given message */
284 NULL, /* no message trailer */
285 pop3_delete, /* how to delete a message */
286 NULL, /* no POP3 expunge command */
287 "QUIT", /* the POP3 exit command */
291 /* retrieve messages using POP3 */
294 if (ctl->mailbox[0]) {
295 fprintf(stderr,"Option --remote is not supported with POP3\n");
298 return(do_protocol(ctl, &pop3));
301 /* pop3.c ends here */