]> Pileus Git - ~andy/fetchmail/blob - smtp.c
558c32b59456ea902a902481d32f9865015fa3bd
[~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 ((ok = SockGets(buf, sizeof(buf)-1, sockfp)) > 0) {
107     buf[ok] = '\0';
108     if (outlevel == O_VERBOSE)
109         fprintf(stderr, "SMTP< %s\n", buf);
110     if (argbuf)
111       strcpy(argbuf,buf);
112     if (buf[0] == '1' || buf[0] == '2' || buf[0] == '3')
113       ok = SM_OK;
114     else 
115       ok = SM_ERROR;
116   }
117   else
118     ok = SM_UNRECOVERABLE;
119   return (ok);
120 }
121
122 int SMTP_ok(FILE *sockfp,char *argbuf)
123 /* accepts SMTP response, returns status of SMTP connection */
124 {
125   int  ok;  
126
127   /* I can tell that the SMTP server connection is ok if I can read a
128      status message that starts with "1xx" ,"2xx" or "3xx".
129      Therefore, it can't be ok if there's no data waiting to be read
130      
131      Tried to deal with this with a call to SockDataWaiting, but 
132      it failed badly.
133
134     */
135
136   ok = SMTP_check(sockfp,argbuf);
137   if (ok == SM_ERROR) /* if we got an error, */
138     {
139       SMTP_rset(sockfp);
140       ok = SMTP_check(sockfp,argbuf);  /* how does it look now ? */
141       if (ok == SM_OK)  
142         ok = SM_ERROR;                /* It's just a simple error, for*/
143                                       /*         the current message  */
144       else
145         ok = SM_UNRECOVERABLE;       /* if it still says error, we're */
146                                      /* in bad shape                  */ 
147     }
148   return ok;
149 }
150
151 /* smtp.c ends here */