1 # include <ctype.h> 2 # include <sysexits.h> 3 # include "sendmail.h" 4 5 # ifndef SMTP 6 SCCSID(@(#)usersmtp.c 3.24 10/07/82 (no SMTP)); 7 # else SMTP 8 9 SCCSID(@(#)usersmtp.c 3.24 10/07/82); 10 11 /* 12 ** SMTPINIT -- initialize SMTP. 13 ** 14 ** Opens the connection and sends the initial protocol. 15 ** 16 ** Parameters: 17 ** m -- mailer to create connection to. 18 ** pvp -- pointer to parameter vector to pass to 19 ** the mailer. 20 ** ctladdr -- controlling address for this mailer. 21 ** 22 ** Returns: 23 ** appropriate exit status -- EX_OK on success. 24 ** 25 ** Side Effects: 26 ** creates connection and sends initial protocol. 27 */ 28 29 # define REPLYTYPE(r) ((r) / 100) 30 # define REPLYCLASS(r) (((r) / 10) % 10) 31 32 static FILE *SmtpOut; /* output file */ 33 static FILE *SmtpIn; /* input file */ 34 static int SmtpPid; /* pid of mailer */ 35 static int SmtpErrstat; /* error status if open fails */ 36 37 smtpinit(m, pvp, ctladdr) 38 struct mailer *m; 39 char **pvp; 40 ADDRESS *ctladdr; 41 { 42 register int r; 43 char buf[MAXNAME]; 44 extern tick(); 45 extern char *canonname(); 46 47 /* 48 ** Open the connection to the mailer. 49 */ 50 51 SmtpIn = SmtpOut = NULL; 52 SmtpPid = openmailer(m, pvp, ctladdr, TRUE, &SmtpOut, &SmtpIn); 53 if (SmtpPid < 0) 54 { 55 SmtpErrstat = ExitStat; 56 # ifdef DEBUG 57 if (tTd(18, 1)) 58 printf("smtpinit: cannot open: Errstat %d errno %d\n", 59 SmtpErrstat, errno); 60 # endif DEBUG 61 return (ExitStat); 62 } 63 64 /* 65 ** Get the greeting message. 66 ** This should appear spontaneously. 67 */ 68 69 r = reply(); 70 if (r < 0 || REPLYTYPE(r) != 2) 71 return (EX_TEMPFAIL); 72 73 /* 74 ** Send the HELO command. 75 ** My mother taught me to always introduce myself. 76 */ 77 78 smtpmessage("HELO %s", HostName); 79 r = reply(); 80 if (r < 0) 81 return (EX_TEMPFAIL); 82 else if (REPLYTYPE(r) == 5) 83 return (EX_UNAVAILABLE); 84 else if (REPLYTYPE(r) != 2) 85 return (EX_TEMPFAIL); 86 87 /* 88 ** Send the MAIL command. 89 ** Designates the sender. 90 */ 91 92 expand("$g", buf, &buf[sizeof buf - 1], CurEnv); 93 smtpmessage("MAIL From:<%s>", canonname(buf, 1)); 94 r = reply(); 95 if (r < 0 || REPLYTYPE(r) == 4) 96 return (EX_TEMPFAIL); 97 else if (r == 250) 98 return (EX_OK); 99 else if (r == 552) 100 return (EX_UNAVAILABLE); 101 return (EX_PROTOCOL); 102 } 103 /* 104 ** SMTPRCPT -- designate recipient. 105 ** 106 ** Parameters: 107 ** to -- address of recipient. 108 ** 109 ** Returns: 110 ** exit status corresponding to recipient status. 111 ** 112 ** Side Effects: 113 ** Sends the mail via SMTP. 114 */ 115 116 smtprcpt(to) 117 ADDRESS *to; 118 { 119 register int r; 120 extern char *canonname(); 121 122 if (SmtpPid < 0) 123 return (SmtpErrstat); 124 125 smtpmessage("RCPT To:<%s>", canonname(to->q_user, 2)); 126 127 r = reply(); 128 if (r < 0 || REPLYTYPE(r) == 4) 129 return (EX_TEMPFAIL); 130 else if (REPLYTYPE(r) == 2) 131 return (EX_OK); 132 else if (r == 550 || r == 551 || r == 553) 133 return (EX_NOUSER); 134 else if (r == 552 || r == 554) 135 return (EX_UNAVAILABLE); 136 return (EX_PROTOCOL); 137 } 138 /* 139 ** SMTPFINISH -- finish up sending all the SMTP protocol. 140 ** 141 ** Parameters: 142 ** m -- mailer being sent to. 143 ** e -- the envelope for this message. 144 ** 145 ** Returns: 146 ** exit status corresponding to DATA command. 147 ** 148 ** Side Effects: 149 ** none. 150 */ 151 152 smtpfinish(m, e) 153 struct mailer *m; 154 register ENVELOPE *e; 155 { 156 register int r; 157 158 if (SmtpPid < 0) 159 return (SmtpErrstat); 160 161 /* 162 ** Send the data. 163 ** Dot hiding is done here. 164 */ 165 166 smtpmessage("DATA"); 167 r = reply(); 168 if (r < 0 || REPLYTYPE(r) == 4) 169 return (EX_TEMPFAIL); 170 else if (r == 554) 171 return (EX_UNAVAILABLE); 172 else if (r != 354) 173 return (EX_PROTOCOL); 174 (*e->e_puthdr)(SmtpOut, m, CurEnv); 175 fprintf(SmtpOut, "\n"); 176 (*e->e_putbody)(SmtpOut, m, TRUE); 177 smtpmessage("."); 178 r = reply(); 179 if (r < 0 || REPLYTYPE(r) == 4) 180 return (EX_TEMPFAIL); 181 else if (r == 250) 182 return (EX_OK); 183 else if (r == 552 || r == 554) 184 return (EX_UNAVAILABLE); 185 return (EX_PROTOCOL); 186 } 187 /* 188 ** SMTPQUIT -- close the SMTP connection. 189 ** 190 ** Parameters: 191 ** name -- name of mailer we are quitting. 192 ** showresp -- if set, give a response message. 193 ** 194 ** Returns: 195 ** none. 196 ** 197 ** Side Effects: 198 ** sends the final protocol and closes the connection. 199 */ 200 201 smtpquit(name, showresp) 202 char *name; 203 bool showresp; 204 { 205 register int i; 206 207 if (SmtpPid < 0) 208 return; 209 smtpmessage("QUIT"); 210 (void) reply(); 211 (void) fclose(SmtpIn); 212 (void) fclose(SmtpOut); 213 i = endmailer(SmtpPid, name); 214 if (showresp) 215 giveresponse(i, TRUE, LocalMailer); 216 } 217 /* 218 ** REPLY -- read arpanet reply 219 ** 220 ** Parameters: 221 ** none. 222 ** 223 ** Returns: 224 ** reply code it reads. 225 ** 226 ** Side Effects: 227 ** flushes the mail file. 228 */ 229 230 reply() 231 { 232 (void) fflush(SmtpOut); 233 234 if (tTd(18, 1)) 235 printf("reply\n"); 236 237 /* 238 ** Read the input line, being careful not to hang. 239 */ 240 241 for (;;) 242 { 243 char buf[MAXLINE]; 244 register int r; 245 register char *p; 246 247 /* actually do the read */ 248 (void) fflush(Xscript); /* for debugging */ 249 p = sfgets(buf, sizeof buf, SmtpIn); 250 if (p == NULL) 251 return (-1); 252 fixcrlf(buf, TRUE); 253 254 /* log the input in the transcript for future error returns */ 255 if (Verbose && !HoldErrs) 256 nmessage(Arpa_Info, "%s", buf); 257 fprintf(Xscript, "%s\n", buf); 258 259 /* if continuation is required, we can go on */ 260 if (buf[3] == '-' || !isdigit(buf[0])) 261 continue; 262 263 /* decode the reply code */ 264 r = atoi(buf); 265 266 /* extra semantics: 0xx codes are "informational" */ 267 if (r < 100) 268 continue; 269 270 return (r); 271 } 272 } 273 /* 274 ** SMTPMESSAGE -- send message to server 275 ** 276 ** Parameters: 277 ** f -- format 278 ** a, b, c -- parameters 279 ** 280 ** Returns: 281 ** none. 282 ** 283 ** Side Effects: 284 ** writes message to SmtpOut. 285 */ 286 287 /*VARARGS1*/ 288 smtpmessage(f, a, b, c) 289 char *f; 290 { 291 char buf[100]; 292 293 (void) sprintf(buf, f, a, b, c); 294 if (tTd(18, 1) || (Verbose && !HoldErrs)) 295 nmessage(Arpa_Info, ">>> %s", buf); 296 fprintf(Xscript, " >>> %s\n", buf); 297 fprintf(SmtpOut, "%s\r\n", buf); 298 } 299 300 # endif SMTP 301