| 1 |
// smtp.C -*- C++ -*- socket library |
| 2 |
// Copyright (C) 1992,1993,1994 Gnanasekaran Swaminathan <gs4t@virginia.edu> |
| 3 |
// |
| 4 |
// Permission is granted to use at your own risk and distribute this software |
| 5 |
// in source and binary forms provided the above copyright |
| 6 |
// notice and this paragraph are preserved on all copies. |
| 7 |
// This software is provided "as is" with no express or implied warranty. |
| 8 |
// |
| 9 |
// Version: 17Oct95 1.10 |
| 10 |
|
| 11 |
#include <config.h> |
| 12 |
|
| 13 |
#include <smtp.h> |
| 14 |
#include <Fork.h> |
| 15 |
#include <fcntl.h> |
| 16 |
#include <unistd.h> |
| 17 |
#include <stdlib.h> |
| 18 |
#include <string.h> |
| 19 |
|
| 20 |
void smtp::smtpbuf::get_response () |
| 21 |
// get all the response that one can get and send all of them to o |
| 22 |
{ |
| 23 |
// if o is 0, then we trash data. |
| 24 |
while (underflow () != EOF) { |
| 25 |
int n = in_avail (); |
| 26 |
if (n < 5) |
| 27 |
continue; |
| 28 |
|
| 29 |
// data is of this form: 221 repsonse <CRLF> or 221-response <CRLF> |
| 30 |
char* q = gptr (); |
| 31 |
char* p = q; |
| 32 |
|
| 33 |
// zap upto <CRLF> |
| 34 |
for (int i = 2; i <= n; i++, p++) |
| 35 |
if (*p == '\r' && *(p+1) == '\n') { |
| 36 |
if (o) |
| 37 |
o->write (q, i); |
| 38 |
gbump (i); |
| 39 |
break; |
| 40 |
} |
| 41 |
|
| 42 |
if (q [3] != '-') |
| 43 |
break; |
| 44 |
} |
| 45 |
} |
| 46 |
|
| 47 |
void smtp::smtpbuf::send_cmd (const char* cmd, const char* s, const char* p) |
| 48 |
{ |
| 49 |
xsputn (cmd, ::strlen (cmd)); |
| 50 |
if (s) |
| 51 |
xsputn (s, ::strlen (s)); |
| 52 |
if (p) |
| 53 |
xsputn (p, ::strlen (p)); |
| 54 |
xsputn ("\r\n", 2); |
| 55 |
flush_output (); |
| 56 |
|
| 57 |
if (o) |
| 58 |
get_response (); |
| 59 |
} |
| 60 |
|
| 61 |
void smtp::smtpbuf::helo () |
| 62 |
{ |
| 63 |
if (o) |
| 64 |
get_response (); |
| 65 |
send_cmd ("HELO ", localhost ()); |
| 66 |
} |
| 67 |
|
| 68 |
void smtp::smtpbuf::mail (const char* reverse_path) |
| 69 |
{ |
| 70 |
if (reverse_path) |
| 71 |
send_cmd ("MAIL FROM:<", reverse_path, ">"); |
| 72 |
else |
| 73 |
send_cmd ("MAIL FROM:<>"); |
| 74 |
} |
| 75 |
|
| 76 |
void smtp::smtpbuf::rcpt (const char* forward_path) |
| 77 |
{ |
| 78 |
if (forward_path) |
| 79 |
send_cmd ("RCPT TO:<", forward_path, ">"); |
| 80 |
} |
| 81 |
|
| 82 |
void smtp::smtpbuf::help (const char* s) |
| 83 |
{ |
| 84 |
send_cmd ("HELP ", s); |
| 85 |
} |
| 86 |
|
| 87 |
void smtp::smtpbuf::send_buf (const char* buf, int len) |
| 88 |
{ |
| 89 |
if (buf == 0 || len <= 0) |
| 90 |
return; |
| 91 |
|
| 92 |
// send line by line |
| 93 |
const unsigned char* p = (const unsigned char*) buf; |
| 94 |
|
| 95 |
#ifdef buggy |
| 96 |
// this doesn't work correctly for ".\n" on a line by itself |
| 97 |
if (*p == '.') |
| 98 |
sputc ((unsigned int) '.'); |
| 99 |
#endif |
| 100 |
|
| 101 |
for (int i = 0; i < len; i++, p++) { |
| 102 |
if (*p == '\n') { |
| 103 |
sputc ((unsigned int) '\r'); |
| 104 |
sputc (*p); |
| 105 |
#ifdef buggy |
| 106 |
// this doesn't work correctly for "\n.\n" - RGL |
| 107 |
if (*(p+1) == '.') |
| 108 |
sputc ((unsigned int) '.'); |
| 109 |
#endif |
| 110 |
} else |
| 111 |
sputc (*p); |
| 112 |
} |
| 113 |
|
| 114 |
// XXX: Need to flush or \r\n.\r\n may not be sent - RGL |
| 115 |
flush_output(); |
| 116 |
} |
| 117 |
|
| 118 |
void smtp::smtpbuf::data (const char* buf, int len) |
| 119 |
{ |
| 120 |
data (); |
| 121 |
send_buf (buf, len); |
| 122 |
xsputn ("\r\n.\r\n", 5); |
| 123 |
flush_output (); |
| 124 |
|
| 125 |
if (o) |
| 126 |
get_response (); |
| 127 |
} |
| 128 |
|
| 129 |
void smtp::smtpbuf::data (const char* filename) |
| 130 |
{ |
| 131 |
data (); |
| 132 |
|
| 133 |
int fd = 0; |
| 134 |
char buf [1024]; |
| 135 |
int rcnt; |
| 136 |
|
| 137 |
if (filename == 0 || (fd = ::open (filename, O_RDONLY )) == -1) |
| 138 |
fd = 0; |
| 139 |
|
| 140 |
while ((rcnt = ::read (fd, buf, 1024)) > 0) |
| 141 |
send_buf (buf, rcnt); |
| 142 |
|
| 143 |
xsputn ("\r\n.\r\n", 5); |
| 144 |
flush_output (); |
| 145 |
|
| 146 |
if (o) |
| 147 |
get_response (); |
| 148 |
} |
| 149 |
|
| 150 |
int smtp::get_response (char* buf, int len) |
| 151 |
// same as get line except what it returns |
| 152 |
// return 1 if output continues after this line |
| 153 |
// return 0 if output has terminated |
| 154 |
{ |
| 155 |
if (len < 8) { |
| 156 |
this->getline (buf, len); |
| 157 |
return 0; |
| 158 |
} |
| 159 |
|
| 160 |
buf [3] = 0; |
| 161 |
this->getline (buf, len); |
| 162 |
return buf [3] == '-'; |
| 163 |
} |
| 164 |
|
| 165 |
ostream& operator << (ostream& o, smtp& s) |
| 166 |
{ |
| 167 |
char buf [1024]; |
| 168 |
int cont = 1; |
| 169 |
while (cont) { |
| 170 |
cont = s.get_response (buf, 1024); |
| 171 |
o << buf << endl; |
| 172 |
} |
| 173 |
return o; |
| 174 |
} |
| 175 |
|
| 176 |
|
| 177 |
void smtp::smtpbuf::serve_clients (int portno) |
| 178 |
{ |
| 179 |
} |
| 180 |
|