]> Pileus Git - ~andy/fetchmail/blob - smtp.c
Improved RFC822 conformance in SMTP code.
[~andy/fetchmail] / smtp.c
1 /* Copyright 1996 Eric S. Raymond
2  * All rights reserved.
3  * For license terms, see the file COPYING in this directory.
4  */
5
6 /***********************************************************************
7   module:       smtp.c
8   project:      fetchmail
9   programmer:   Harry Hochheiser
10                 cleaned up and made rfc821 compliant by Cameron MacPherson
11   description:  Handling of SMTP connections, and processing of mail 
12                  to be forwarded via SMTP connections.
13
14  ***********************************************************************/
15
16 #include <stdio.h>
17 #include <config.h>
18 #include <sys/types.h>
19 #include <unistd.h>
20 #include <string.h>
21 #include "socket.h"
22 #include "fetchmail.h"
23 #include "smtp.h"
24
25 /*********************************************************************
26   function:      SMTP_helo
27   description:   Send a "HELO" message to the SMTP server.
28
29   arguments:     
30     socket       TCP/IP socket for connection to SMTP
31   return value:  Result of SMTP_OK: based on codes in fetchmail.h.
32                  
33  *********************************************************************/
34
35 int SMTP_helo(int socket,char *host)
36 {
37   int ok;
38
39   SockPrintf(socket,"HELO %s\r\n", host);
40   if (outlevel == O_VERBOSE)
41       fprintf(stderr, "SMTP> HELO %s\n", host);
42   ok = SMTP_ok(socket,NULL);
43   return ok;
44 }
45
46 /*********************************************************************
47   function:      SMTP_from
48   description:   Send a "MAIL FROM:" message to the SMTP server.
49
50   arguments:     
51     socket       TCP/IP socket for connection to SMTP
52     from         user name/host of originator
53
54     Note: these args are likely to change, as we get fancier about
55     handling the names.
56
57   return value:  Result of SMTP_ok: based on codes in fetchmail.h.
58                  
59  *********************************************************************/
60 int SMTP_from(int socket, char *from)
61 {
62   int ok;
63
64   SockPrintf(socket,"MAIL FROM:<%s>\r\n", from);
65   if (outlevel == O_VERBOSE)
66       fprintf(stderr, "SMTP> MAIL FROM:<%s>\n", from);
67   ok = SMTP_ok(socket,NULL);
68   return ok;
69 }
70
71 /*********************************************************************
72   function:      SMTP_rcpt
73   description:   Send a "RCPT TO:" message to the SMTP server.
74
75   arguments:     
76     socket       TCP/IP socket for connection to SMTP
77     touser:      user name of recipient
78     tohost:      host name of recipient
79
80   return value:  Result of SMTP_OK: based on codes in fetchmail.h.
81                  
82  *********************************************************************/
83 int SMTP_rcpt(int socket,char *to)
84 {
85   int ok;
86
87   SockPrintf(socket,"RCPT TO:<%s>\r\n", to);
88   if (outlevel == O_VERBOSE)
89       fprintf(stderr, "SMTP> RCPT TO:<%s>\n", to);
90   ok = SMTP_ok(socket,NULL);
91   return ok;
92 }
93
94 /*********************************************************************
95   function:      SMTP_data
96   description:   Send a "DATA" message to the SMTP server.
97
98   arguments:     
99     socket       TCP/IP socket for connection to SMTP
100
101  *********************************************************************/
102 int SMTP_data(int socket)
103 {
104   int ok;
105
106   SockPrintf(socket,"DATA\r\n");
107   if (outlevel == O_VERBOSE)
108       fprintf(stderr, "SMTP> DATA\n");
109   ok = SMTP_ok(socket,NULL);
110   return ok;
111 }
112
113 /*********************************************************************
114   function:      SMTP_quit
115   description:   Send a "QUIT" message to the SMTP server.
116
117   arguments:     
118     socket       TCP/IP socket for connection to SMTP
119
120   return value:  Result of SMTP_OK: based on codes in fetchmail.h.
121
122  *********************************************************************/
123 int SMTP_quit(int socket)
124 {
125   int ok;
126
127   SockPrintf(socket,"QUIT\r\n");
128   if (outlevel == O_VERBOSE)
129       fprintf(stderr, "SMTP> QUIT\n");
130   ok = SMTP_ok(socket,NULL);
131   return ok;
132 }
133
134 /*********************************************************************
135   function:      SMTP_eom
136   description:   Send a message data termination to the SMTP server.
137
138   arguments:     
139     socket       TCP/IP socket for connection to SMTP
140   return value:  Result of SMTP_OK: based on codes in fetchmail.h.
141                  
142  *********************************************************************/
143
144 int SMTP_eom(int socket)
145 {
146   int ok;
147
148   SockPrintf(socket,".\r\n");
149   if (outlevel == O_VERBOSE)
150       fprintf(stderr, "SMTP> (EOM)\n");
151   ok = SMTP_ok(socket,NULL);
152   return ok;
153 }
154
155 /*********************************************************************
156   function:      SMTP_rset
157   description:   Send a "RSET" message to the SMTP server.
158
159   arguments:     
160     socket       TCP/IP socket for connection to SMTP
161
162  *********************************************************************/
163 void SMTP_rset(int socket)
164 {
165   SockPrintf(socket,"RSET\r\n");
166   if (outlevel == O_VERBOSE)
167       fprintf(stderr, "SMTP> RSET\n");
168 }
169
170 /*********************************************************************
171   function:      SMTP_check
172   description:   Returns the status of the smtp connection
173   arguments:     
174     socket       TCP/IP socket for connection to SMTP
175   return value:  based on codes in fetchmail.h.
176                  Do the dirty work of seeing what the status is..
177  *********************************************************************/
178 static int SMTP_check(int socket,char *argbuf)
179 {
180   int  ok;  
181   char buf[SMTPBUFSIZE];
182   
183   if ((ok = SMTP_Gets(socket, buf, sizeof(buf)-1)) > 0) {
184     buf[ok] = '\0';
185     if (outlevel == O_VERBOSE)
186         fprintf(stderr, "SMTP< %s", buf);
187     if (argbuf)
188       strcpy(argbuf,buf);
189     if (buf[0] == '1' || buf[0] == '2' || buf[0] == '3')
190       ok = SM_OK;
191     else 
192       ok = SM_ERROR;
193   }
194   else
195     ok = SM_UNRECOVERABLE;
196   return (ok);
197 }
198
199 /*********************************************************************
200   function:      SMTP_ok
201   description:   Returns the statsus of the smtp connection
202   arguments:     
203     socket       TCP/IP socket for connection to SMTP
204   return value:  based on codes in fetchmail.h.
205  *********************************************************************/
206 int SMTP_ok(int socket,char *argbuf)
207 {
208   int  ok;  
209
210   /* I can tell that the SMTP server connection is ok if I can read a
211      status message that starts with "1xx" ,"2xx" or "3xx".
212      Therefore, it can't be ok if there's no data waiting to be read
213      
214      Tried to deal with this with a call to SockDataWaiting, but 
215      it failed badly.
216
217     */
218
219   ok = SMTP_check(socket,argbuf);
220   if (ok == SM_ERROR) /* if we got an error, */
221     {
222       SMTP_rset(socket);
223       ok = SMTP_check(socket,argbuf);  /* how does it look now ? */
224       if (ok == SM_OK)  
225         ok = SM_ERROR;                /* It's just a simple error, for*/
226                                       /*         the current message  */
227       else
228         ok = SM_UNRECOVERABLE;       /* if it still says error, we're */
229                                      /* in bad shape                  */ 
230     }
231   return ok;
232 }
233
234 /*********************************************************************
235   function:      SMTP_Gets
236   description:   Gets  a line from the SMTP connection
237   arguments:     
238     socket       TCP/IP socket for connection to SMTP
239   return value:  number of bytes read.
240  *********************************************************************/
241 int SMTP_Gets(int socket,char *buf,int sz)
242 {
243   return read(socket,buf,sz);
244 }