]> Pileus Git - ~andy/fetchmail/blob - smtp.c
Special socket I/O almost gone!
[~andy/fetchmail] / smtp.c
1 /*
2  * smtp.c -- code for speaking SMTP to a listener port
3  *
4  * Concept due to Harry Hochheiser.  Implementation by ESR.  Cleanup and
5  * strict RFC821 compliance by Cameron MacPherson.
6  *
7  * Copyright 1996 Eric S. Raymond
8  * All rights reserved.
9  * For license terms, see the file COPYING in this directory.
10  */
11
12 #include <config.h>
13 #include <stdio.h>
14 #include <unistd.h>
15 #include <string.h>
16 #include "socket.h"
17 #include "fetchmail.h"
18 #include "smtp.h"
19
20 int SMTP_helo(FILE *sockfp,char *host)
21 /* send a "HELO" message to the SMTP listener */
22 {
23   int ok;
24
25   fprintf(sockfp,"HELO %s\r\n", host);
26   if (outlevel == O_VERBOSE)
27       fprintf(stderr, "SMTP> HELO %s\n", host);
28   ok = SMTP_ok(sockfp,NULL);
29   return ok;
30 }
31
32 int SMTP_from(FILE *sockfp, char *from)
33 /* send a "MAIL FROM:" message to the SMTP listener */
34 {
35   int ok;
36
37   fprintf(sockfp,"MAIL FROM:<%s>\r\n", from);
38   if (outlevel == O_VERBOSE)
39       fprintf(stderr, "SMTP> MAIL FROM:<%s>\n", from);
40   ok = SMTP_ok(sockfp,NULL);
41   return ok;
42 }
43
44 int SMTP_rcpt(FILE *sockfp, char *to)
45 /* send a "RCPT TO:" message to the SMTP listener */
46 {
47   int ok;
48
49   fprintf(sockfp,"RCPT TO:<%s>\r\n", to);
50   if (outlevel == O_VERBOSE)
51       fprintf(stderr, "SMTP> RCPT TO:<%s>\n", to);
52   ok = SMTP_ok(sockfp,NULL);
53   return ok;
54 }
55
56 int SMTP_data(FILE *sockfp)
57 /* send a "DATA" message to the SMTP listener */
58 {
59   int ok;
60
61   fprintf(sockfp,"DATA\r\n");
62   if (outlevel == O_VERBOSE)
63       fprintf(stderr, "SMTP> DATA\n");
64   ok = SMTP_ok(sockfp,NULL);
65   return ok;
66 }
67
68 int SMTP_quit(FILE *sockfp)
69 /* send a "QUIT" message to the SMTP listener */
70 {
71   int ok;
72
73   fprintf(sockfp,"QUIT\r\n");
74   if (outlevel == O_VERBOSE)
75       fprintf(stderr, "SMTP> QUIT\n");
76   ok = SMTP_ok(sockfp,NULL);
77   return ok;
78 }
79
80 int SMTP_eom(FILE *sockfp)
81 /* send a message data terminator to the SMTP listener */
82 {
83   int ok;
84
85   fprintf(sockfp,".\r\n");
86   if (outlevel == O_VERBOSE)
87       fprintf(stderr, "SMTP>. (EOM)\n");
88   ok = SMTP_ok(sockfp,NULL);
89   return ok;
90 }
91
92 void SMTP_rset(FILE *sockfp)
93 /* send a "RSET" message to the SMTP listener */
94 {
95   fprintf(sockfp,"RSET\r\n");
96   if (outlevel == O_VERBOSE)
97       fprintf(stderr, "SMTP> RSET\n");
98 }
99
100 static int SMTP_check(FILE *sockfp,char *argbuf)
101 /* returns status of SMTP connection */
102 {
103   int  ok;  
104   char buf[SMTPBUFSIZE];
105   
106   if (fgets(buf, sizeof(buf)-1, sockfp) != (char *)NULL) {
107     if (outlevel == O_VERBOSE)
108     {
109         char    *sp, *tp;
110
111         for (tp = sp = buf; *sp; sp++)
112             if (*sp != '\r')
113                 *tp++ = *sp;
114         *tp++ = '\0';
115         fprintf(stderr, "SMTP< %s", buf);
116     }
117     if (argbuf)
118       strcpy(argbuf,buf);
119     if (buf[0] == '1' || buf[0] == '2' || buf[0] == '3')
120       ok = SM_OK;
121     else 
122       ok = SM_ERROR;
123   }
124   else
125     ok = SM_UNRECOVERABLE;
126   return (ok);
127 }
128
129 int SMTP_ok(FILE *sockfp,char *argbuf)
130 /* accepts SMTP response, returns status of SMTP connection */
131 {
132   int  ok;  
133
134   /* I can tell that the SMTP server connection is ok if I can read a
135      status message that starts with "1xx" ,"2xx" or "3xx".
136      Therefore, it can't be ok if there's no data waiting to be read
137      
138      Tried to deal with this with a call to SockDataWaiting, but 
139      it failed badly.
140
141     */
142
143   ok = SMTP_check(sockfp,argbuf);
144   if (ok == SM_ERROR) /* if we got an error, */
145     {
146       SMTP_rset(sockfp);
147       ok = SMTP_check(sockfp,argbuf);  /* how does it look now ? */
148       if (ok == SM_OK)  
149         ok = SM_ERROR;                /* It's just a simple error, for*/
150                                       /*         the current message  */
151       else
152         ok = SM_UNRECOVERABLE;       /* if it still says error, we're */
153                                      /* in bad shape                  */ 
154     }
155   return ok;
156 }
157
158 /* smtp.c ends here */