]> Pileus Git - ~andy/fetchmail/blob - etrn.c
d8234dca88bd20bee50d5b61e14dcaafa133ed53
[~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 [POPBUFSIZE+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      * 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 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     25,                 /* standard SMTP port */
117     FALSE,              /* this is not a tagged protocol */
118     FALSE,              /* this does not use a message delimiter */
119     etrn_ok,            /* parse command response */
120     NULL,               /* no need to get authentication */
121     etrn_getrange,      /* initialize message sending */
122     NULL,               /* we cannot get a list of sizes */
123     NULL,               /* how do we tell a message is old? */
124     NULL,               /* no way to fetch headers */
125     NULL,               /* no way to fetch body */
126     NULL,               /* no message trailer */
127     NULL,               /* how to delete a message */
128     etrn_logout,        /* log out, we're done */
129     FALSE,              /* no, we can't re-poll */
130 };
131
132 int doETRN (struct query *ctl)
133 /* retrieve messages using ETRN */
134 {
135     int status;
136
137     if (ctl->keep) {
138         fprintf(stderr, "Option --keep is not supported with ETRN\n");
139         return(PS_SYNTAX);
140     }
141     if (ctl->flush) {
142         fprintf(stderr, "Option --flush is not supported with ETRN\n");
143         return(PS_SYNTAX);
144     }
145     if (ctl->mailboxes->id) {
146         fprintf(stderr, "Option --remote is not supported with ETRN\n");
147         return(PS_SYNTAX);
148     }
149     if (check_only) {
150         fprintf(stderr, "Option --check is not supported with ETRN\n");
151         return(PS_SYNTAX);
152     }
153     peek_capable = FALSE;
154
155     status = do_protocol(ctl, &etrn);
156     if (status == PS_NOMAIL)
157         status = PS_SUCCESS;
158     return(status);
159 }
160 #endif /* ETRN_ENABLE */
161
162 /* etrn.c ends here */