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