2 * etrn.c -- ETRN protocol methods
4 * For license terms, see the file COPYING in this directory.
13 #include "fetchmail.h"
17 #ifdef HAVE_GETHOSTBYNAME
20 static int etrn_ok (int sock, char *argbuf)
21 /* parse command response */
26 if (ok == SM_UNRECOVERABLE)
32 static int etrn_getrange(int sock, struct query *ctl, char *id, int *countp,
34 /* send ETRN and interpret the response */
36 int ok, opts, qdone = 0;
37 char buf [POPBUFSIZE+1],
40 struct idlist *qnp; /* pointer to Q names */
43 if ((ok = SMTP_ehlo(sock, ctl->server.names->id, &opts)))
45 error(0, 0, "%s's SMTP listener does not support ESMTP",
46 ctl->server.names->id);
49 else if (!(opts & ESMTP_ETRN))
51 error(0, 0, "%s's SMTP listener does not support ETRN",
52 ctl->server.names->id);
56 *countp = *newp = -1; /* make sure we don't enter the fetch loop */
58 /*** This is a sort of horrible HACK because the ETRN protocol
59 *** does not fit very well into the mailbox concept used in
60 *** this program (IMHO). The last element of ctl->smtphunt
61 *** turned out to be the host being queried (i.e., the smtp server).
62 *** for that reason the rather "funny" condition in the for loop.
63 *** Isn't it sort of unreasonable to add the server to the ETRN
64 *** hunt list? (Concerning ETRN I'm sure! In case I want a Q-run of
65 *** my SMTP-server I can always specify -Smyserver, and this is only
66 *** resonable if I start sendmail without -qtime and in Q-only mode.)
68 *** -- 1997-06-22 Guenther Leber
70 /* do it for all queues in the smtphunt list except the last one
71 which is the SMTP-server itself */
72 for (qnp = ctl->smtphunt; ( (qnp != (struct idlist *) NULL) &&
73 (qnp->next != (struct idlist *) NULL) ) || (qdone == 0);
74 qnp = qnp->next, qdone++)
77 /* extract name of Q */
78 if ( (qnp != (struct idlist *) NULL) &&
79 (qnp->next != (struct idlist *) NULL) )
81 /* take Q-name given in smtp hunt list */
85 /*** use fully qualified host name as Q name ***/
87 if (gethostname(hname, sizeof hname) != 0)
89 /* exit with error message */
90 error(5, errno, "gethostname");
92 /* in case we got a host basename (as we do in Linux),
94 hp = gethostbyname(hname);
95 if (hp == (struct hostent *) NULL)
97 /* exit with error message */
98 error(5, h_errno, "gethostbyname");
105 /* ship the actual poll and get the response */
106 gen_send(sock, "ETRN %s", qname);
107 if ((ok = gen_recv(sock, buf, sizeof(buf))))
110 /* this switch includes all the response codes described in RFC1985 */
113 case 250: /* OK, queuing for node <x> started */
114 error(0, 0, "Queuing for %s started", qname);
117 case 251: /* OK, no messages waiting for node <x> */
118 error(0, 0, "No messages waiting for %s", qname);
121 case 252: /* OK, pending messages for node <x> started */
122 case 253: /* OK, <n> pending messages for node <x> started */
123 error(0, 0, "Pending messages for %s started", qname);
126 case 458: /* Unable to queue messages for node <x> */
127 error(0, -1, "Unable to queue messages for node %s", qname);
130 case 459: /* Node <x> not allowed: <reason> */
131 error(0, -1, "Node %s not allowed: %s", qname, buf);
134 case 500: /* Syntax Error */
135 error(0, -1, "ETRN syntax error");
138 case 501: /* Syntax Error in Parameters */
139 error(0, -1, "ETRN syntax error in parameters");
143 error(0, -1, "Unknown ETRN error %d", atoi(buf));
151 const static struct method etrn =
153 "ETRN", /* ESMTP ETRN extension */
154 25, /* standard SMTP port */
155 FALSE, /* this is not a tagged protocol */
156 FALSE, /* this does not use a message delimiter */
157 FALSE, /* no getsizes method */
158 etrn_ok, /* parse command response */
159 NULL, /* no need to get authentication */
160 etrn_getrange, /* initialize message sending */
161 NULL, /* we cannot get a list of sizes */
162 NULL, /* how do we tell a message is old? */
163 NULL, /* no way to fetch headers */
164 NULL, /* no way to fetch body */
165 NULL, /* no message trailer */
166 NULL, /* how to delete a message */
167 "QUIT", /* the ETRN exit command */
170 int doETRN (struct query *ctl)
171 /* retrieve messages using ETRN */
174 fprintf(stderr, "Option --keep is not supported with ETRN\n");
178 fprintf(stderr, "Option --flush is not supported with ETRN\n");
181 if (ctl->mailboxes->id) {
182 fprintf(stderr, "Option --remote is not supported with ETRN\n");
186 fprintf(stderr, "Option --check is not supported with ETRN\n");
189 peek_capable = FALSE;
190 return(do_protocol(ctl, &etrn));
193 #endif /* HAVE_GETHOSTBYNAME */
195 /* etrn.c ends here */