2 * odmr.c -- ODMR protocol methods (see RFC 2645)
4 * For license terms, see the file COPYING in this directory.
13 #include <sys/types.h>
14 #include <sys/select.h>
19 #include "fetchmail.h"
24 static int odmr_ok (int sock, char *argbuf)
25 /* parse command response */
30 ok = SMTP_ok(sock, SMTP_MODE, TIMEOUT_DEFAULT);
31 if (ok == SM_UNRECOVERABLE)
37 static int odmr_getrange(int sock, struct query *ctl, const char *id,
38 int *countp, int *newp, int *bytes)
39 /* send ODMR and then run a reverse SMTP session */
41 int ok, opts, smtp_sock;
42 int doing_smtp_data = 0; /* Are we in SMTP DATA state? */
43 char buf [MSGBUFSIZE+1];
44 struct idlist *qnp; /* pointer to Q names */
47 if ((ok = SMTP_ehlo(sock, SMTP_MODE, fetchmailhost,
48 ctl->server.esmtp_name, ctl->server.esmtp_password,
51 report(stderr, GT_("%s's SMTP listener does not support ESMTP\n"),
52 ctl->server.pollname);
55 else if (!(opts & ESMTP_ATRN))
57 report(stderr, GT_("%s's SMTP listener does not support ATRN\n"),
58 ctl->server.pollname);
62 /* make sure we don't enter the fetch loop */
63 *bytes = *countp = *newp = -1;
65 /* authenticate via CRAM-MD5 */
66 ok = do_cram_md5(sock, "AUTH", ctl, "334 ");
71 * By default, the hostlist has a single entry, the fetchmail host's
75 for (qnp = ctl->domainlist; qnp; qnp = qnp->next)
76 if (strlen(buf) + strlen(qnp->id) + 1 >= sizeof(buf))
83 buf[strlen(buf) - 1] = '\0'; /* nuke final comma */
85 /* ship the domain list and get turnaround */
86 gen_send(sock, "ATRN %s", buf);
87 if ((ok = gen_recv(sock, buf, sizeof(buf))))
90 /* this switch includes all response codes described in RFC2645 */
93 case 250: /* OK, turnaround is about to happe */
94 if (outlevel > O_SILENT)
95 report(stdout, GT_("Turnaround now...\n"));
98 case 450: /* ATRN request refused */
99 if (outlevel > O_SILENT)
100 report(stdout, GT_("ATRN request refused.\n"));
103 case 451: /* Unable to process ATRN request now */
104 report(stderr, GT_("Unable to process ATRN request now\n"));
107 case 453: /* You have no mail */
108 if (outlevel > O_SILENT)
109 report(stderr, GT_("You have no mail.\n"));
112 case 502: /* Command not implemented */
113 report(stderr, GT_("Command not implemented\n"));
116 case 530: /* Authentication required */
117 report(stderr, GT_("Authentication required.\n"));
121 char *t = sdump(buf, strlen(buf));
122 report(stderr, GT_("Unknown ODMR error \"%s\"\n"), t);
129 * OK, if we got here it's time to become a pipe between the ODMR
130 * remote server (sending) and the SMTP listener we've designated
131 * (receiving). We're not going to try to be a protocol machine;
132 * instead, we'll use select(2) to watch the read sides of both
133 * sockets and just throw their data at each other.
135 if ((smtp_sock = smtp_setup(ctl)) == -1)
139 int maxfd = (sock > smtp_sock) ? sock : smtp_sock;
144 struct timeval timeout;
147 FD_SET(sock, &readfds);
148 FD_SET(smtp_sock, &readfds);
150 timeout.tv_sec = ctl->server.timeout;
153 if (select(maxfd+1, &readfds, NULL, NULL, &timeout) == -1)
154 return(PS_PROTOCOL); /* timeout */
156 if (FD_ISSET(sock, &readfds))
158 int n = SockRead(sock, buf, sizeof(buf));
162 SockWrite(smtp_sock, buf, n);
163 if (outlevel >= O_MONITOR && !doing_smtp_data)
164 report(stdout, "ODMR< %s", buf);
166 if (FD_ISSET(smtp_sock, &readfds))
168 int n = SockRead(smtp_sock, buf, sizeof(buf));
172 SockWrite(sock, buf, n);
173 if (outlevel >= O_MONITOR)
174 report(stdout, "ODMR> %s", buf);
176 /* We are about to receive message data if the local MTA
177 * sends 354 (after receiving DATA) */
178 if (!doing_smtp_data && !strncmp(buf, "354", 3))
181 if (outlevel > O_SILENT)
182 report(stdout, GT_("receiving message data\n"));
184 else if (doing_smtp_data)
188 SockClose(smtp_sock);
194 static int odmr_logout(int sock, struct query *ctl)
195 /* send logout command */
197 /* if we have a smtp_socket, then we've turned around and the
198 local smtp server is in control of the connection (so we don't
200 if (ctl->smtp_socket == -1)
201 return(gen_transact(sock, "QUIT"));
206 static const struct method odmr =
208 "ODMR", /* ODMR protocol */
209 "odmr", /* standard ODMR port */
210 "odmrs", /* ssl ODMR port */
211 FALSE, /* this is not a tagged protocol */
212 FALSE, /* this does not use a message delimiter */
213 odmr_ok, /* parse command response */
214 NULL, /* no need to get authentication */
215 odmr_getrange, /* initialize message sending */
216 NULL, /* we cannot get a list of sizes */
217 NULL, /* we cannot get a list of sizes of subsets */
218 NULL, /* how do we tell a message is old? */
219 NULL, /* no way to fetch headers */
220 NULL, /* no way to fetch body */
221 NULL, /* no message trailer */
222 NULL, /* how to delete a message */
223 NULL, /* how to mark a message as seen */
224 NULL, /* no mailbox support */
225 odmr_logout, /* log out, we're done */
226 FALSE, /* no, we can't re-poll */
229 int doODMR (struct query *ctl)
230 /* retrieve messages using ODMR */
235 fprintf(stderr, GT_("Option --keep is not supported with ODMR\n"));
239 fprintf(stderr, GT_("Option --flush is not supported with ODMR\n"));
242 if (ctl->mailboxes->id) {
243 fprintf(stderr, GT_("Option --folder is not supported with ODMR\n"));
247 fprintf(stderr, GT_("Option --check is not supported with ODMR\n"));
250 peek_capable = FALSE;
252 status = do_protocol(ctl, &odmr);
253 if (status == PS_NOMAIL)
257 #endif /* ODMR_ENABLE */
259 /* odmr.c ends here */