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