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)
19 #include "fetchmail.h"
22 #define PROTOCOL_ERROR {error(0, 0, "protocol error"); return(PS_ERROR);}
24 extern char *strstr(); /* needed on sysV68 R3V7.1. */
28 int pop3_ok (FILE *sockfp, char *argbuf)
29 /* parse command response */
32 char buf [POPBUFSIZE+1];
35 if ((ok = gen_recv(sockfp, buf, sizeof(buf))) == 0)
38 if (*bufp == '+' || *bufp == '-')
43 while (isalpha(*bufp))
47 if (strcmp(buf,"+OK") == 0)
49 else if (strcmp(buf,"-ERR") == 0)
61 int pop3_getauth(FILE *sockfp, struct query *ctl, char *greeting)
62 /* apply for connection authorization */
64 /* build MD5 digest from greeting timestamp + password */
65 if (ctl->server.protocol == P_APOP)
70 /* find start of timestamp */
71 for (start = greeting; *start != 0 && *start != '<'; start++)
74 error(0, 0, "Required APOP timestamp not found in greeting");
78 /* find end of timestamp */
79 for (end = start; *end != 0 && *end != '>'; end++)
81 if (*end == 0 || end == start + 1) {
82 error(0, 0, "Timestamp syntax error in greeting");
88 /* copy timestamp and password into digestion buffer */
89 msg = (char *)xmalloc((end-start+1) + strlen(ctl->password) + 1);
91 strcat(msg,ctl->password);
93 strcpy(ctl->digest, MD5Digest(msg));
97 switch (ctl->server.protocol) {
99 if ((gen_transact(sockfp, "USER %s", ctl->remotename)) != 0)
102 if ((gen_transact(sockfp, "PASS %s", ctl->password)) != 0)
107 if ((gen_transact(sockfp, "APOP %s %s",
108 ctl->remotename, ctl->digest)) != 0)
113 if ((gen_transact(sockfp,"USER %s", ctl->remotename)) != 0)
116 if ((gen_transact(sockfp, "RPOP %s", ctl->password)) != 0)
121 error(0, 0, "Undefined protocol request in POP3_auth");
128 static int pop3_getrange(FILE *sockfp, struct query *ctl, int*countp, int*newp)
129 /* 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(sockfp, "STAT");
139 ok = pop3_ok(sockfp, 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(sockfp,"LAST");
157 ok = pop3_ok(sockfp, buf);
160 if (sscanf(buf, "%d", &last) == 0)
162 *newp = (*countp - last);
166 /* grab the mailbox's UID list */
167 if ((ok = gen_transact(sockfp, "UIDL")) != 0)
174 while ((ok = gen_recv(sockfp, buf, sizeof(buf))) == 0)
178 else if (sscanf(buf, "%d %s", &num, id) == 2)
180 save_str(&ctl->newsaved, num, id);
182 /* note: ID comparison is caseblind */
183 if (!str_in_list(&ctl->oldsaved, id))
194 static int pop3_getsizes(FILE *sockfp, int count, int *sizes)
195 /* capture the sizes of all messages */
199 if ((ok = gen_transact(sockfp, "LIST")) != 0)
203 char buf [POPBUFSIZE+1];
205 while ((ok = gen_recv(sockfp, buf, sizeof(buf))) == 0)
211 else if (sscanf(buf, "%d %d", &num, &size) == 2)
212 sizes[num - 1] = size;
221 static int pop3_is_old(FILE *sockfp, struct query *ctl, int num)
222 /* is the given message old? */
225 return (num <= last);
227 /* note: ID comparison is caseblind */
228 return (str_in_list(&ctl->oldsaved,
229 str_find (&ctl->newsaved, num)));
232 static int pop3_fetch(FILE *sockfp, struct query *ctl, int number, int *lenp)
233 /* request nth message */
236 char buf [POPBUFSIZE+1], *cp;
238 gen_send(sockfp, "RETR %d", number);
239 if ((ok = pop3_ok(sockfp, buf)) != 0)
241 /* look for "nnn octets" -- there may or may not be preceding cruft */
242 if ((cp = strstr(buf, " octets")) == (char *)NULL)
246 while (--cp >= buf && isdigit(*cp))
253 static int pop3_delete(FILE *sockfp, struct query *ctl, int number)
254 /* delete a given message */
256 return(gen_transact(sockfp, "DELE %d", number));
259 const static struct method pop3 =
261 "POP3", /* Post Office Protocol v3 */
262 110, /* standard POP3 port */
263 0, /* this is not a tagged protocol */
264 1, /* this uses a message delimiter */
265 pop3_ok, /* parse command response */
266 pop3_getauth, /* get authorization */
267 pop3_getrange, /* query range of messages */
268 pop3_getsizes, /* we can get a list of sizes */
269 pop3_is_old, /* how do we tell a message is old? */
270 pop3_fetch, /* request given message */
271 NULL, /* no message trailer */
272 pop3_delete, /* how to delete a message */
273 "QUIT", /* the POP3 exit command */
276 int doPOP3 (struct query *ctl)
277 /* retrieve messages using POP3 */
280 fprintf(stderr,"Option --remote is not supported with POP3\n");
283 peek_capable = FALSE;
284 return(do_protocol(ctl, &pop3));
287 /* pop3.c ends here */