2 * odmr.c -- ODMR protocol methods (see RFC 2645)
4 * For license terms, see the file COPYING in this directory.
12 #ifdef HAVE_STRING_H /* strcat() */
15 #ifdef HAVE_NET_SOCKET_H /* BeOS needs this */
16 #include <net/socket.h>
18 #include <sys/types.h>
20 #ifdef HAVE_NET_SELECT_H /* AIX needs this */
21 #include <net/select.h>
23 #ifdef HAVE_SYS_SELECT_H /* AIX 4.1, at least, needs this */
24 #include <sys/select.h>
30 #include "fetchmail.h"
34 static int odmr_ok (int sock, char *argbuf)
35 /* parse command response */
40 if (ok == SM_UNRECOVERABLE)
46 static int odmr_getrange(int sock, struct query *ctl, const char *id,
47 int *countp, int *newp, int *bytes)
48 /* send ODMR and then run a reverse SMTP session */
50 int ok, opts, smtp_sock;
51 char buf [MSGBUFSIZE+1];
52 struct idlist *qnp; /* pointer to Q names */
54 if ((ok = SMTP_ehlo(sock, fetchmailhost,
55 ctl->server.esmtp_name, ctl->server.esmtp_password,
58 report(stderr, GT_("%s's SMTP listener does not support ESMTP\n"),
59 ctl->server.pollname);
62 else if (!(opts & ESMTP_ATRN))
64 report(stderr, GT_("%s's SMTP listener does not support ATRN\n"),
65 ctl->server.pollname);
69 /* make sure we don't enter the fetch loop */
70 *bytes = *countp = *newp = -1;
72 /* authenticate via CRAM-MD5 */
73 ok = do_cram_md5(sock, "AUTH", ctl, "334 ");
78 * By default, the hostlist has a single entry, the fetchmail host's
82 for (qnp = ctl->domainlist; qnp; qnp = qnp->next)
83 if (strlen(buf) + strlen(qnp->id) + 1 >= sizeof(buf))
90 buf[strlen(buf) - 1] = '\0'; /* nuke final comma */
92 /* ship the domain list and get turnaround */
93 gen_send(sock, "ATRN %s", buf);
94 if ((ok = gen_recv(sock, buf, sizeof(buf))))
97 /* this switch includes all response codes described in RFC2645 */
100 case 250: /* OK, turnaround is about to happe */
101 if (outlevel > O_SILENT)
102 report(stdout, GT_("Turnaround now...\n"));
105 case 450: /* ATRN request refused */
106 if (outlevel > O_SILENT)
107 report(stdout, GT_("ATRN request refused.\n"));
110 case 451: /* Unable to process ATRN request now */
111 report(stderr, GT_("Unable to process ATRN request now\n"));
114 case 453: /* You have no mail */
115 if (outlevel > O_SILENT)
116 report(stderr, GT_("You have no mail.\n"));
119 case 502: /* Command not implemented */
120 report(stderr, GT_("Command not implemented\n"));
123 case 530: /* Authentication required */
124 report(stderr, GT_("Authentication required.\n"));
128 report(stderr, GT_("Unknown ODMR error %d\n"), atoi(buf));
133 * OK, if we got here it's time to become a pipe between the ODMR
134 * remote server (sending) and the SMTP listener we've designated
135 * (receiving). We're not going to try to be a protocol machine;
136 * instead, we'll use select(2) to watch the read sides of both
137 * sockets and just throw their data at each other.
139 if ((smtp_sock = smtp_open(ctl)) == -1)
143 int maxfd = (sock > smtp_sock) ? sock : smtp_sock;
148 struct timeval timeout;
149 char buf[MSGBUFSIZE];
152 FD_SET(sock, &readfds);
153 FD_SET(smtp_sock, &readfds);
155 timeout.tv_sec = ctl->server.timeout;
158 if (select(maxfd+1, &readfds, NULL, NULL, &timeout) == -1)
159 return(PS_PROTOCOL); /* timeout */
161 if (FD_ISSET(sock, &readfds))
163 int n = SockRead(sock, buf, sizeof(buf));
167 SockWrite(smtp_sock, buf, n);
168 if (outlevel >= O_MONITOR)
169 report(stdout, "ODMR< %s", buf);
171 if (FD_ISSET(smtp_sock, &readfds))
173 int n = SockRead(smtp_sock, buf, sizeof(buf));
177 SockWrite(sock, buf, n);
178 if (outlevel >= O_MONITOR)
179 report(stdout, "ODMR> %s", buf);
182 SockClose(smtp_sock);
188 static int odmr_logout(int sock, struct query *ctl)
189 /* send logout command */
191 /* if we have a smtp_socket, then we've turned around and the
192 local smtp server is in control of the connection (so we don't
194 if (ctl->smtp_socket == -1)
195 return(gen_transact(sock, "QUIT"));
200 const static struct method odmr =
202 "ODMR", /* ODMR protocol */
204 "odmr", /* standard SMTP port */
205 "odmrs", /* ssl SMTP port */
206 #else /* INET6_ENABLE */
207 366, /* standard SMTP port */
208 2366, /* ssl SMTP port (BOGUS! RANDOM VALUE) */
209 #endif /* INET6_ENABLE */
210 FALSE, /* this is not a tagged protocol */
211 FALSE, /* this does not use a message delimiter */
212 odmr_ok, /* parse command response */
213 NULL, /* no need to get authentication */
214 odmr_getrange, /* initialize message sending */
215 NULL, /* we cannot get a list of sizes */
216 NULL, /* how do we tell a message is old? */
217 NULL, /* no way to fetch headers */
218 NULL, /* no way to fetch body */
219 NULL, /* no message trailer */
220 NULL, /* how to delete a message */
221 odmr_logout, /* log out, we're done */
222 FALSE, /* no, we can't re-poll */
225 int doODMR (struct query *ctl)
226 /* retrieve messages using ODMR */
231 fprintf(stderr, GT_("Option --keep is not supported with ODMR\n"));
235 fprintf(stderr, GT_("Option --flush is not supported with ODMR\n"));
238 if (ctl->mailboxes->id) {
239 fprintf(stderr, GT_("Option --remote is not supported with ODMR\n"));
243 fprintf(stderr, GT_("Option --check is not supported with ODMR\n"));
246 peek_capable = FALSE;
248 status = do_protocol(ctl, &odmr);
249 if (status == PS_NOMAIL)
253 #endif /* ODMR_ENABLE */
255 /* odmr.c ends here */