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