]> Pileus Git - ~andy/fetchmail/blob - etrn.c
Make the X-IMAP check independent of protocol.
[~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  <unistd.h>
14 #include  "fetchmail.h"
15 #include  "smtp.h"
16 #include  "socket.h"
17
18 static int etrn_ok (int sock, char *argbuf)
19 /* parse command response */
20 {
21     int ok;
22
23     ok = SMTP_ok(sock);
24     if (ok == SM_UNRECOVERABLE)
25         return(PS_PROTOCOL);
26     else
27         return(ok);
28 }
29
30 static int etrn_getrange(int sock, struct query *ctl, char *id, int *countp,
31                                                                     int *newp)
32 /* send ETRN and interpret the response */
33 {
34     int ok, opts;
35     char buf [POPBUFSIZE+1],
36          hname[256];
37     struct idlist *qnp;         /* pointer to Q names */
38     struct hostent *hp;
39
40     if ((ok = SMTP_ehlo(sock, ctl->server.truename, &opts)))
41     {
42         error(0, 0, "%s's SMTP listener does not support ESMTP",
43               ctl->server.pollname);
44         return(ok);
45     }
46     else if (!(opts & ESMTP_ETRN))
47     {
48         error(0, 0, "%s's SMTP listener does not support ETRN",
49               ctl->server.pollname);
50         return(PS_PROTOCOL);
51     }
52
53     *countp = *newp = -1;       /* make sure we don't enter the fetch loop */
54
55     /*
56      * Do it for all nondefault queues in the smtphunt list.
57      * We can tell the nondefault ones because they have a TRUE num field.
58      */
59     for (qnp = ctl->smtphunt; qnp; qnp = qnp->next)
60         if (qnp->val.num)
61         {
62             /* ship the actual poll and get the response */
63             gen_send(sock, "ETRN %s", qnp->id);
64             if ((ok = gen_recv(sock, buf, sizeof(buf))))
65                 return(ok);
66
67             /* this switch includes all response codes described in RFC1985 */
68             switch(atoi(buf))
69             {
70             case 250:   /* OK, queuing for node <x> started */
71                 error(0, 0, "Queuing for %s started", qnp->id);
72                 break;
73
74             case 251:   /* OK, no messages waiting for node <x> */
75                 error(0, 0, "No messages waiting for %s", qnp->id);
76                 return(PS_NOMAIL);
77
78             case 252:   /* OK, pending messages for node <x> started */
79             case 253:   /* OK, <n> pending messages for node <x> started */
80                 error(0, 0, "Pending messages for %s started", qnp->id);
81                 break;
82
83             case 458:   /* Unable to queue messages for node <x> */
84                 error(0, -1, "Unable to queue messages for node %s",qnp->id);
85                 return(PS_PROTOCOL);
86
87             case 459:   /* Node <x> not allowed: <reason> */
88                 error(0, -1, "Node %s not allowed: %s", qnp->id, buf);
89                 return(PS_AUTHFAIL);
90
91             case 500:   /* Syntax Error */
92                 error(0, -1, "ETRN syntax error");
93                 return(PS_PROTOCOL);
94
95             case 501:   /* Syntax Error in Parameters */
96                 error(0, -1, "ETRN syntax error in parameters");
97                 return(PS_PROTOCOL);
98
99             default:
100                 error(0, -1, "Unknown ETRN error %d", atoi(buf));
101                 return(PS_PROTOCOL);
102             }
103         }
104
105     return(0);
106 }
107
108 const static struct method etrn =
109 {
110     "ETRN",             /* ESMTP ETRN extension */
111     25,                 /* standard SMTP port */
112     FALSE,              /* this is not a tagged protocol */
113     FALSE,              /* this does not use a message delimiter */
114     etrn_ok,            /* parse command response */
115     NULL,               /* no need to get authentication */
116     etrn_getrange,      /* initialize message sending */
117     NULL,               /* we cannot get a list of sizes */
118     NULL,               /* how do we tell a message is old? */
119     NULL,               /* no way to fetch headers */
120     NULL,               /* no way to fetch body */
121     NULL,               /* no message trailer */
122     NULL,               /* how to delete a message */
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 */