2 * pop3.c -- POP3 protocol methods
4 * For license terms, see the file COPYING in this directory.
12 #include "fetchmail.h"
16 int pop3_ok (socket, argbuf)
17 /* parse command response */
22 char buf [POPBUFSIZE+1];
25 if (SockGets(socket, buf, sizeof(buf)) >= 0) {
26 if (outlevel == O_VERBOSE)
27 fprintf(stderr,"%s\n",buf);
30 if (*bufp == '+' || *bufp == '-')
35 while (isalpha(*bufp))
39 if (strcmp(buf,"+OK") == 0)
41 else if (strcmp(buf,"-ERR") == 0)
55 int pop3_getauth(socket, queryctl, greeting)
56 /* apply for connection authorization */
58 struct hostrec *queryctl;
61 char buf [POPBUFSIZE+1];
63 /* build MD5 digest from greeting timestamp + password */
64 if (queryctl->protocol == P_APOP)
69 /* find start of timestamp */
70 for (start = greeting; *start != 0 && *start != '<'; start++)
73 fprintf(stderr,"Required APOP timestamp not found in greeting\n");
77 /* find end of timestamp */
78 for (end = start; *end != 0 && *end != '>'; end++)
80 if (*end == 0 || (end - start - 1) == 1) {
81 fprintf(stderr,"Timestamp syntax error in greeting\n");
85 /* copy timestamp and password into digestion buffer */
86 msg = (char *)xmalloc((end-start-1) + strlen(queryctl->password) + 1);
89 strcat(msg,queryctl->password);
91 strcpy(queryctl->digest, MD5Digest(msg));
95 switch (queryctl->protocol) {
97 if ((gen_transact(socket,"USER %s", queryctl->remotename)) != 0)
100 if ((gen_transact(socket, "PASS %s", queryctl->password)) != 0)
105 if ((gen_transact(socket, "APOP %s %s",
106 queryctl->remotename, queryctl->digest)) != 0)
111 fprintf(stderr,"Undefined protocol request in POP3_auth\n");
118 static pop3_getrange(socket, queryctl, countp)
119 /* get range of messages to be fetched */
121 struct hostrec *queryctl;
125 char buf [POPBUFSIZE+1];
127 /* Ensure that the new list is properly empty */
128 queryctl->newsaved = (struct idlist *)NULL;
130 /* get the total message count */
131 gen_send(socket, "STAT");
132 ok = pop3_ok(socket, buf);
134 sscanf(buf,"%d %*d", countp);
139 * Newer, RFC-1725-conformant POP servers may not have the LAST command.
142 if (*countp > 0 && !queryctl->fetchall)
146 gen_send(socket,"LAST");
147 ok = pop3_ok(socket, buf);
150 if (sscanf(buf, "%d", &last) == 0)
157 /* grab the mailbox's UID list */
158 gen_send(socket, "UIDL");
159 if ((ok = pop3_ok(socket, buf)) == 0) {
160 while (SockGets(socket, buf, sizeof(buf)) >= 0) {
161 if (outlevel == O_VERBOSE)
162 fprintf(stderr,"%s\n",buf);
163 if (strcmp(buf, ".") == 0) {
166 if (sscanf(buf, "%d %s", &num, id) == 2)
167 save_uid(&queryctl->newsaved, num, id);
176 static int pop3_is_old(socket, queryctl, num)
178 struct hostrec *queryctl;
181 if (!queryctl->oldsaved)
182 return (num <= last);
184 return (uid_in_list(&queryctl->oldsaved,
185 uid_find (&queryctl->newsaved, num)));
188 static int pop3_fetch(socket, number, lenp)
189 /* request nth message */
195 char buf [POPBUFSIZE+1], *cp;
197 gen_send(socket, "RETR %d", number);
198 if ((ok = pop3_ok(socket, buf)) != 0)
200 /* look for "nnn octets" -- there may or may not be preceding cruft */
201 if ((cp = strstr(buf, " octets")) == (char *)NULL)
205 while (isdigit(*--cp))
212 static pop3_delete(socket, queryctl, number)
213 /* delete a given message */
215 struct hostrec *queryctl;
218 return(gen_transact(socket, "DELE %d", number));
221 const static struct method pop3 =
223 "POP3", /* Post Office Protocol v3 */
224 110, /* standard POP3 port */
225 0, /* this is not a tagged protocol */
226 1, /* this uses a message delimiter */
227 pop3_ok, /* parse command response */
228 pop3_getauth, /* get authorization */
229 pop3_getrange, /* query range of messages */
230 pop3_is_old, /* how do we tell a message is old? */
231 pop3_fetch, /* request given message */
232 NULL, /* no message trailer */
233 pop3_delete, /* how to delete a message */
234 NULL, /* no POP3 expunge command */
235 "QUIT", /* the POP3 exit command */
238 int doPOP3 (queryctl)
239 /* retrieve messages using POP3 */
240 struct hostrec *queryctl;
242 if (queryctl->mailbox[0]) {
243 fprintf(stderr,"Option --remote is not supported with POP3\n");
246 return(do_protocol(queryctl, &pop3));
249 /* pop3.c ends here */