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.truename, &opts)))
42 error(0, 0, "%s's SMTP listener does not support ESMTP",
43 ctl->server.pollname);
46 else if (!(opts & ESMTP_ETRN))
48 error(0, 0, "%s's SMTP listener does not support ETRN",
49 ctl->server.pollname);
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(0, errno, "gethostname failed: ");
90 /* in case we got a host basename (as we do in Linux),
92 hp = gethostbyname(hname);
93 if (hp == (struct hostent *) NULL)
95 /* exit with error message */
96 error(0, 0, "gethostbyname failed for %s", hname);
104 /* ship the actual poll and get the response */
105 gen_send(sock, "ETRN %s", qname);
106 if ((ok = gen_recv(sock, buf, sizeof(buf))))
109 /* this switch includes all the response codes described in RFC1985 */
112 case 250: /* OK, queuing for node <x> started */
113 error(0, 0, "Queuing for %s started", qname);
116 case 251: /* OK, no messages waiting for node <x> */
117 error(0, 0, "No messages waiting for %s", qname);
120 case 252: /* OK, pending messages for node <x> started */
121 case 253: /* OK, <n> pending messages for node <x> started */
122 error(0, 0, "Pending messages for %s started", qname);
125 case 458: /* Unable to queue messages for node <x> */
126 error(0, -1, "Unable to queue messages for node %s", qname);
129 case 459: /* Node <x> not allowed: <reason> */
130 error(0, -1, "Node %s not allowed: %s", qname, buf);
133 case 500: /* Syntax Error */
134 error(0, -1, "ETRN syntax error");
137 case 501: /* Syntax Error in Parameters */
138 error(0, -1, "ETRN syntax error in parameters");
142 error(0, -1, "Unknown ETRN error %d", atoi(buf));
150 const static struct method etrn =
152 "ETRN", /* ESMTP ETRN extension */
153 25, /* standard SMTP port */
154 FALSE, /* this is not a tagged protocol */
155 FALSE, /* this does not use a message delimiter */
156 FALSE, /* no getsizes method */
157 etrn_ok, /* parse command response */
158 NULL, /* no need to get authentication */
159 etrn_getrange, /* initialize message sending */
160 NULL, /* we cannot get a list of sizes */
161 NULL, /* how do we tell a message is old? */
162 NULL, /* no way to fetch headers */
163 NULL, /* no way to fetch body */
164 NULL, /* no message trailer */
165 NULL, /* how to delete a message */
166 "QUIT", /* the ETRN exit command */
169 int doETRN (struct query *ctl)
170 /* retrieve messages using ETRN */
173 fprintf(stderr, "Option --keep is not supported with ETRN\n");
177 fprintf(stderr, "Option --flush is not supported with ETRN\n");
180 if (ctl->mailboxes->id) {
181 fprintf(stderr, "Option --remote is not supported with ETRN\n");
185 fprintf(stderr, "Option --check is not supported with ETRN\n");
188 peek_capable = FALSE;
189 return(do_protocol(ctl, &etrn));
192 /* etrn.c ends here */