]> Pileus Git - ~andy/fetchmail/blob - etrn.c
69175149ab9cbea1f32637c06ae4ce6c5da2494b
[~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, 
32                          int *countp, int *newp, int *bytes)
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     /* make sure we don't enter the fetch loop */
53     *bytes = *countp = *newp = -1;
54
55     /*
56      * By default, the hostlist has a single entry, the fetchmail host's
57      * canonical DNS name.
58      */
59     for (qnp = ctl->smtphunt; qnp; qnp = qnp->next)
60     {
61         /* ship the actual poll and get the response */
62         gen_send(sock, "ETRN %s", qnp->id);
63         if ((ok = gen_recv(sock, buf, sizeof(buf))))
64             return(ok);
65
66         /* this switch includes all response codes described in RFC1985 */
67         switch(atoi(buf))
68         {
69         case 250:       /* OK, queuing for node <x> started */
70             error(0, 0, "Queuing for %s started", qnp->id);
71             break;
72
73         case 251:       /* OK, no messages waiting for node <x> */
74             error(0, 0, "No messages waiting for %s", qnp->id);
75             return(PS_NOMAIL);
76
77         case 252:       /* OK, pending messages for node <x> started */
78         case 253:       /* OK, <n> pending messages for node <x> started */
79             error(0, 0, "Pending messages for %s started", qnp->id);
80             break;
81
82         case 458:       /* Unable to queue messages for node <x> */
83             error(0, -1, "Unable to queue messages for node %s",qnp->id);
84             return(PS_PROTOCOL);
85
86         case 459:       /* Node <x> not allowed: <reason> */
87             error(0, -1, "Node %s not allowed: %s", qnp->id, buf);
88             return(PS_AUTHFAIL);
89
90         case 500:       /* Syntax Error */
91             error(0, -1, "ETRN syntax error");
92             return(PS_PROTOCOL);
93
94         case 501:       /* Syntax Error in Parameters */
95             error(0, -1, "ETRN syntax error in parameters");
96             return(PS_PROTOCOL);
97
98         default:
99             error(0, -1, "Unknown ETRN error %d", atoi(buf));
100             return(PS_PROTOCOL);
101         }
102     }
103
104     return(0);
105 }
106
107 static int etrn_logout(int sock, struct query *ctl)
108 /* send logout command */
109 {
110     return(gen_transact(sock, "QUIT"));
111 }
112
113 const static struct method etrn =
114 {
115     "ETRN",             /* ESMTP ETRN extension */
116 #if INET6
117     "smtp",             /* standard SMTP port */
118 #else /* INET6 */
119     25,                 /* standard SMTP port */
120 #endif /* INET6 */
121     FALSE,              /* this is not a tagged protocol */
122     FALSE,              /* this does not use a message delimiter */
123     etrn_ok,            /* parse command response */
124     NULL,               /* no password canonicalization */
125     NULL,               /* no need to get authentication */
126     etrn_getrange,      /* initialize message sending */
127     NULL,               /* we cannot get a list of sizes */
128     NULL,               /* how do we tell a message is old? */
129     NULL,               /* no way to fetch headers */
130     NULL,               /* no way to fetch body */
131     NULL,               /* no message trailer */
132     NULL,               /* how to delete a message */
133     etrn_logout,        /* log out, we're done */
134     FALSE,              /* no, we can't re-poll */
135 };
136
137 int doETRN (struct query *ctl)
138 /* retrieve messages using ETRN */
139 {
140     int status;
141
142     if (ctl->keep) {
143         fprintf(stderr, "Option --keep is not supported with ETRN\n");
144         return(PS_SYNTAX);
145     }
146     if (ctl->flush) {
147         fprintf(stderr, "Option --flush is not supported with ETRN\n");
148         return(PS_SYNTAX);
149     }
150     if (ctl->mailboxes->id) {
151         fprintf(stderr, "Option --remote is not supported with ETRN\n");
152         return(PS_SYNTAX);
153     }
154     if (check_only) {
155         fprintf(stderr, "Option --check is not supported with ETRN\n");
156         return(PS_SYNTAX);
157     }
158     peek_capable = FALSE;
159
160     status = do_protocol(ctl, &etrn);
161     if (status == PS_NOMAIL)
162         status = PS_SUCCESS;
163     return(status);
164 }
165 #endif /* ETRN_ENABLE */
166
167 /* etrn.c ends here */