]> Pileus Git - ~andy/fetchmail/blob - etrn.c
7deb43126dcc749543bb020ef7256870beb2d593
[~andy/fetchmail] / etrn.c
1 /*
2  * etrn.c -- ETRN protocol methods
3  *
4  * For license terms, see the file COPYING in this directory.
5  */
6
7 #include  "config.h"
8 #ifdef ETRN_ENABLE
9 #include  <stdio.h>
10 #include  <stdlib.h>
11 #include  <assert.h>
12 #include  <netdb.h>
13 #include  <errno.h>
14 #include  <unistd.h>
15 #include  "fetchmail.h"
16 #include  "smtp.h"
17 #include  "socket.h"
18
19 static int etrn_ok (int sock, char *argbuf)
20 /* parse command response */
21 {
22     int ok;
23
24     ok = SMTP_ok(sock);
25     if (ok == SM_UNRECOVERABLE)
26         return(PS_PROTOCOL);
27     else
28         return(ok);
29 }
30
31 static int etrn_getrange(int sock, struct query *ctl, char *id, int *countp,
32                                                                     int *newp)
33 /* send ETRN and interpret the response */
34 {
35     int ok, opts;
36     char buf [MSGBUFSIZE+1];
37     struct idlist *qnp;         /* pointer to Q names */
38
39     if ((ok = SMTP_ehlo(sock, ctl->server.truename, &opts)))
40     {
41         error(0, 0, "%s's SMTP listener does not support ESMTP",
42               ctl->server.pollname);
43         return(ok);
44     }
45     else if (!(opts & ESMTP_ETRN))
46     {
47         error(0, 0, "%s's SMTP listener does not support ETRN",
48               ctl->server.pollname);
49         return(PS_PROTOCOL);
50     }
51
52     *countp = *newp = -1;       /* make sure we don't enter the fetch loop */
53
54     /*
55      * By default, the hostlist has a single entry, the fetchmail host's
56      * canonical DNS name.
57      */
58     for (qnp = ctl->smtphunt; qnp; qnp = qnp->next)
59     {
60         /* ship the actual poll and get the response */
61         gen_send(sock, "ETRN %s", qnp->id);
62         if ((ok = gen_recv(sock, buf, sizeof(buf))))
63             return(ok);
64
65         /* this switch includes all response codes described in RFC1985 */
66         switch(atoi(buf))
67         {
68         case 250:       /* OK, queuing for node <x> started */
69             error(0, 0, "Queuing for %s started", qnp->id);
70             break;
71
72         case 251:       /* OK, no messages waiting for node <x> */
73             error(0, 0, "No messages waiting for %s", qnp->id);
74             return(PS_NOMAIL);
75
76         case 252:       /* OK, pending messages for node <x> started */
77         case 253:       /* OK, <n> pending messages for node <x> started */
78             error(0, 0, "Pending messages for %s started", qnp->id);
79             break;
80
81         case 458:       /* Unable to queue messages for node <x> */
82             error(0, -1, "Unable to queue messages for node %s",qnp->id);
83             return(PS_PROTOCOL);
84
85         case 459:       /* Node <x> not allowed: <reason> */
86             error(0, -1, "Node %s not allowed: %s", qnp->id, buf);
87             return(PS_AUTHFAIL);
88
89         case 500:       /* Syntax Error */
90             error(0, -1, "ETRN syntax error");
91             return(PS_PROTOCOL);
92
93         case 501:       /* Syntax Error in Parameters */
94             error(0, -1, "ETRN syntax error in parameters");
95             return(PS_PROTOCOL);
96
97         default:
98             error(0, -1, "Unknown ETRN error %d", atoi(buf));
99             return(PS_PROTOCOL);
100         }
101     }
102
103     return(0);
104 }
105
106 static int etrn_logout(int sock, struct query *ctl)
107 /* send logout command */
108 {
109     return(gen_transact(sock, "QUIT"));
110 }
111
112 const static struct method etrn =
113 {
114     "ETRN",             /* ESMTP ETRN extension */
115 #if INET6
116     "smtp",             /* standard SMTP port */
117 #else /* INET6 */
118     25,                 /* standard SMTP port */
119 #endif /* INET6 */
120     FALSE,              /* this is not a tagged protocol */
121     FALSE,              /* this does not use a message delimiter */
122     etrn_ok,            /* parse command response */
123     NULL,               /* no password canonicalization */
124     NULL,               /* no need to get authentication */
125     etrn_getrange,      /* initialize message sending */
126     NULL,               /* we cannot get a list of sizes */
127     NULL,               /* how do we tell a message is old? */
128     NULL,               /* no way to fetch headers */
129     NULL,               /* no way to fetch body */
130     NULL,               /* no message trailer */
131     NULL,               /* how to delete a message */
132     etrn_logout,        /* log out, we're done */
133     FALSE,              /* no, we can't re-poll */
134 };
135
136 int doETRN (struct query *ctl)
137 /* retrieve messages using ETRN */
138 {
139     int status;
140
141     if (ctl->keep) {
142         fprintf(stderr, "Option --keep is not supported with ETRN\n");
143         return(PS_SYNTAX);
144     }
145     if (ctl->flush) {
146         fprintf(stderr, "Option --flush is not supported with ETRN\n");
147         return(PS_SYNTAX);
148     }
149     if (ctl->mailboxes->id) {
150         fprintf(stderr, "Option --remote is not supported with ETRN\n");
151         return(PS_SYNTAX);
152     }
153     if (check_only) {
154         fprintf(stderr, "Option --check is not supported with ETRN\n");
155         return(PS_SYNTAX);
156     }
157     peek_capable = FALSE;
158
159     status = do_protocol(ctl, &etrn);
160     if (status == PS_NOMAIL)
161         status = PS_SUCCESS;
162     return(status);
163 }
164 #endif /* ETRN_ENABLE */
165
166 /* etrn.c ends here */