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>
27 #include "fetchmail.h"
31 static int odmr_ok (int sock, char *argbuf)
32 /* parse command response */
37 if (ok == SM_UNRECOVERABLE)
43 static int odmr_getrange(int sock, struct query *ctl, const char *id,
44 int *countp, int *newp, int *bytes)
45 /* send ODMR and then run a reverse SMTP session */
47 int ok, opts, smtp_sock;
48 char buf [MSGBUFSIZE+1];
49 struct idlist *qnp; /* pointer to Q names */
51 if ((ok = SMTP_ehlo(sock, fetchmailhost, &opts)))
53 report(stderr, _("%s's SMTP listener does not support ESMTP\n"),
54 ctl->server.pollname);
57 else if (!(opts & ESMTP_ATRN))
59 report(stderr, _("%s's SMTP listener does not support ATRN\n"),
60 ctl->server.pollname);
64 /* make sure we don't enter the fetch loop */
65 *bytes = *countp = *newp = -1;
67 /* authenticate via CRAM-MD5 */
68 ok = do_cram_md5(sock, "AUTH", ctl, "334 ");
73 * By default, the hostlist has a single entry, the fetchmail host's
77 for (qnp = ctl->smtphunt; qnp; qnp = qnp->next)
78 if (strlen(buf) + strlen(qnp->id) + 1 >= sizeof(buf))
85 buf[strlen(buf) - 1] = '\0'; /* nuke final comma */
87 /* ship the domain list and get turnaround */
88 gen_send(sock, "ATRN %s", buf);
89 if ((ok = gen_recv(sock, buf, sizeof(buf))))
92 /* this switch includes all response codes described in RFC2645 */
95 case 250: /* OK, turnaround is about to happe */
96 if (outlevel >= O_SILENT)
97 report(stdout, _("Turnaround now...\n"));
100 case 450: /* ATRN request refused */
101 if (outlevel >= O_SILENT)
102 report(stdout, _("ATRN request refused.\n"));
105 case 451: /* Unable to process ATRN request now */
106 report(stderr, _("Unable to process ATRN request now\n"));
109 case 453: /* You have no mail */
110 report(stderr, _("You have no mail.\n"));
113 case 502: /* Command not implemented */
114 report(stderr, _("Command not implemented\n"));
117 case 530: /* Authentication required */
118 report(stderr, _("Authentication required.\n"));
122 report(stderr, _("Unknown ODMR error %d\n"), atoi(buf));
127 * OK, if we got here it's time to become a pipe between the ODMR
128 * remote server (sending) and the local SMTP daemon (receiving).
129 * We're npt going to try to be a protocol machine; instead, we'll
130 * use select(2) to watch the read sides of both sockets and just
131 * throw their data at each other.
134 * FIXME: we hardcode "localhost" here because ODMR is fighting
135 * over the ETRN meaning of smtphost and the POP/IMAP meaning.
136 * ODMR needs both meanings, but there is only one config var. So
137 * for now ODMR always uses the "localhost" SMTP server to connect
140 smtp_sock = SockOpen("localhost", SMTP_PORT, NULL, NULL);
145 int maxfd = (sock > smtp_sock) ? sock : smtp_sock;
150 struct timeval timeout;
151 char buf[MSGBUFSIZE];
154 FD_SET(sock, &readfds);
155 FD_SET(smtp_sock, &readfds);
157 timeout.tv_sec = ctl->server.timeout;
160 if (select(maxfd+1, &readfds, NULL, NULL, &timeout) == -1)
161 return(PS_PROTOCOL); /* timeout */
163 if (FD_ISSET(sock, &readfds))
165 int n = SockRead(sock, buf, sizeof(buf));
169 SockWrite(smtp_sock, buf, n);
170 if (outlevel >= O_MONITOR)
171 report(stdout, "ODMR< %s\n", buf);
173 if (FD_ISSET(smtp_sock, &readfds))
175 int n = SockRead(smtp_sock, buf, sizeof(buf));
179 SockWrite(sock, buf, n);
180 if (outlevel >= O_MONITOR)
181 report(stdout, "ODMR> %s\n", buf);
184 SockClose(smtp_sock);
190 static int odmr_logout(int sock, struct query *ctl)
191 /* send logout command */
193 return(gen_transact(sock, "QUIT"));
196 const static struct method odmr =
198 "ODMR", /* ODMR protocol */
200 "odmr", /* standard SMTP port */
201 "odmrs", /* ssl SMTP port */
202 #else /* INET6_ENABLE */
203 366, /* standard SMTP port */
204 2366, /* ssl SMTP port (BOGUS! RANDOM VALUE) */
205 #endif /* INET6_ENABLE */
206 FALSE, /* this is not a tagged protocol */
207 FALSE, /* this does not use a message delimiter */
208 odmr_ok, /* parse command response */
209 NULL, /* no need to get authentication */
210 odmr_getrange, /* initialize message sending */
211 NULL, /* we cannot get a list of sizes */
212 NULL, /* how do we tell a message is old? */
213 NULL, /* no way to fetch headers */
214 NULL, /* no way to fetch body */
215 NULL, /* no message trailer */
216 NULL, /* how to delete a message */
217 odmr_logout, /* log out, we're done */
218 FALSE, /* no, we can't re-poll */
221 int doODMR (struct query *ctl)
222 /* retrieve messages using ODMR */
227 fprintf(stderr, _("Option --keep is not supported with ODMR\n"));
231 fprintf(stderr, _("Option --flush is not supported with ODMR\n"));
234 if (ctl->mailboxes->id) {
235 fprintf(stderr, _("Option --remote is not supported with ODMR\n"));
239 fprintf(stderr, _("Option --check is not supported with ODMR\n"));
242 peek_capable = FALSE;
244 status = do_protocol(ctl, &odmr);
245 if (status == PS_NOMAIL)
249 #endif /* ODMR_ENABLE */
251 /* odmr.c ends here */