]> Pileus Git - ~andy/fetchmail/blob - etrn.c
d65e1b03d9c3acb22e17ba3a7e4bab4c551bfcb6
[~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 #include  <stdio.h>
9 #include  <stdlib.h>
10 #include  <assert.h>
11 #include  <netdb.h>
12 #include  <errno.h>
13 #include  "fetchmail.h"
14 #include  "smtp.h"
15 #include  "socket.h"
16
17 static int etrn_ok (int sock, char *argbuf)
18 /* parse command response */
19 {
20     int ok;
21
22     ok = SMTP_ok(sock);
23     if (ok == SM_UNRECOVERABLE)
24         return(PS_PROTOCOL);
25     else
26         return(ok);
27 }
28
29 static int etrn_getrange(int sock, struct query *ctl, char *id, int *countp,
30                                                                     int *newp)
31 /* send ETRN and interpret the response */
32 {
33     int ok, opts;
34     char buf [POPBUFSIZE+1],
35          hname[256];
36     struct idlist *qnp;         /* pointer to Q names */
37     struct hostent *hp;
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      * Do it for all nondefault queues in the smtphunt list.
56      * We can tell the nondefault ones because they have a TRUE num field.
57      */
58     for (qnp = ctl->smtphunt; qnp; qnp = qnp->next)
59         if (qnp->val.num)
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 const static struct method etrn =
108 {
109     "ETRN",             /* ESMTP ETRN extension */
110     25,                 /* standard SMTP port */
111     FALSE,              /* this is not a tagged protocol */
112     FALSE,              /* this does not use a message delimiter */
113     etrn_ok,            /* parse command response */
114     NULL,               /* no need to get authentication */
115     etrn_getrange,      /* initialize message sending */
116     NULL,               /* we cannot get a list of sizes */
117     NULL,               /* how do we tell a message is old? */
118     NULL,               /* no way to fetch headers */
119     NULL,               /* no way to fetch body */
120     NULL,               /* no message trailer */
121     NULL,               /* how to delete a message */
122     NULL,               /* no retained-header check */
123     "QUIT",             /* the ETRN exit command */
124 };
125
126 int doETRN (struct query *ctl)
127 /* retrieve messages using ETRN */
128 {
129     int status;
130
131     if (ctl->keep) {
132         fprintf(stderr, "Option --keep is not supported with ETRN\n");
133         return(PS_SYNTAX);
134     }
135     if (ctl->flush) {
136         fprintf(stderr, "Option --flush is not supported with ETRN\n");
137         return(PS_SYNTAX);
138     }
139     if (ctl->mailboxes->id) {
140         fprintf(stderr, "Option --remote is not supported with ETRN\n");
141         return(PS_SYNTAX);
142     }
143     if (check_only) {
144         fprintf(stderr, "Option --check is not supported with ETRN\n");
145         return(PS_SYNTAX);
146     }
147     peek_capable = FALSE;
148
149     status = do_protocol(ctl, &etrn);
150     if (status == PS_NOMAIL)
151         status = PS_SUCCESS;
152     return(status);
153 }
154
155 /* etrn.c ends here */