1 # include <ctype.h> 2 # include <sysexits.h> 3 # include "sendmail.h" 4 5 # ifndef SMTP 6 SCCSID(@(#)usersmtp.c 3.19 08/29/82 (no SMTP)); 7 # else SMTP 8 9 SCCSID(@(#)usersmtp.c 3.19 08/29/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 (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 (REPLYTYPE(r) == 5) 81 return (EX_UNAVAILABLE); 82 else if (REPLYTYPE(r) != 2) 83 return (EX_TEMPFAIL); 84 85 /* 86 ** Send the MAIL command. 87 ** Designates the sender. 88 */ 89 90 expand("$g", buf, &buf[sizeof buf - 1], CurEnv); 91 smtpmessage("MAIL From: %s", canonname(buf)); 92 r = reply(); 93 if (REPLYTYPE(r) == 4) 94 return (EX_TEMPFAIL); 95 else if (r == 250) 96 return (EX_OK); 97 else if (r == 552) 98 return (EX_UNAVAILABLE); 99 return (EX_PROTOCOL); 100 } 101 /* 102 ** SMTPRCPT -- designate recipient. 103 ** 104 ** Parameters: 105 ** to -- address of recipient. 106 ** 107 ** Returns: 108 ** exit status corresponding to recipient status. 109 ** 110 ** Side Effects: 111 ** Sends the mail via SMTP. 112 */ 113 114 smtprcpt(to) 115 ADDRESS *to; 116 { 117 register int r; 118 extern char *canonname(); 119 120 if (SmtpPid < 0) 121 return (SmtpErrstat); 122 123 smtpmessage("RCPT To: %s", canonname(to->q_user)); 124 125 r = reply(); 126 if (REPLYTYPE(r) == 4) 127 return (EX_TEMPFAIL); 128 else if (REPLYTYPE(r) == 2) 129 return (EX_OK); 130 else if (r == 550 || r == 551 || r == 553) 131 return (EX_NOUSER); 132 else if (r == 552 || r == 554) 133 return (EX_UNAVAILABLE); 134 return (EX_PROTOCOL); 135 } 136 /* 137 ** SMTPFINISH -- finish up sending all the SMTP protocol. 138 ** 139 ** Parameters: 140 ** m -- mailer being sent to. 141 ** e -- the envelope for this message. 142 ** 143 ** Returns: 144 ** exit status corresponding to DATA command. 145 ** 146 ** Side Effects: 147 ** none. 148 */ 149 150 smtpfinish(m, e) 151 struct mailer *m; 152 register ENVELOPE *e; 153 { 154 register int r; 155 156 if (SmtpPid < 0) 157 return (SmtpErrstat); 158 159 /* 160 ** Send the data. 161 ** Dot hiding is done here. 162 */ 163 164 smtpmessage("DATA"); 165 r = reply(); 166 if (REPLYTYPE(r) == 4) 167 return (EX_TEMPFAIL); 168 else if (r == 554) 169 return (EX_UNAVAILABLE); 170 else if (r != 354) 171 return (EX_PROTOCOL); 172 (*e->e_puthdr)(SmtpOut, m, CurEnv); 173 fprintf(SmtpOut, "\n"); 174 (*e->e_putbody)(SmtpOut, m, TRUE); 175 smtpmessage("."); 176 r = reply(); 177 if (REPLYTYPE(r) == 4) 178 return (EX_TEMPFAIL); 179 else if (r == 250) 180 return (EX_OK); 181 else if (r == 552 || r == 554) 182 return (EX_UNAVAILABLE); 183 return (EX_PROTOCOL); 184 } 185 /* 186 ** SMTPQUIT -- close the SMTP connection. 187 ** 188 ** Parameters: 189 ** name -- name of mailer we are quitting. 190 ** showresp -- if set, give a response message. 191 ** 192 ** Returns: 193 ** none. 194 ** 195 ** Side Effects: 196 ** sends the final protocol and closes the connection. 197 */ 198 199 smtpquit(name, showresp) 200 char *name; 201 bool showresp; 202 { 203 register int i; 204 205 if (SmtpPid < 0) 206 return; 207 smtpmessage("QUIT"); 208 (void) reply(); 209 (void) fclose(SmtpIn); 210 (void) fclose(SmtpOut); 211 i = endmailer(SmtpPid, name); 212 if (showresp) 213 giveresponse(i, TRUE, LocalMailer); 214 } 215 /* 216 ** REPLY -- read arpanet reply 217 ** 218 ** Parameters: 219 ** none. 220 ** 221 ** Returns: 222 ** reply code it reads. 223 ** 224 ** Side Effects: 225 ** flushes the mail file. 226 */ 227 228 reply() 229 { 230 (void) fflush(SmtpOut); 231 232 if (tTd(18, 1)) 233 printf("reply\n"); 234 235 /* 236 ** Read the input line, being careful not to hang. 237 */ 238 239 for (;;) 240 { 241 char buf[MAXLINE]; 242 register int r; 243 register char *p; 244 245 /* actually do the read */ 246 (void) fflush(Xscript); /* for debugging */ 247 p = sfgets(buf, sizeof buf, SmtpIn); 248 249 if (p == NULL) 250 return (-1); 251 252 /* log the input in the transcript for future error returns */ 253 if (Verbose && !HoldErrs) 254 fputs(buf, stdout); 255 fputs(buf, Xscript); 256 257 /* if continuation is required, we can go on */ 258 if (buf[3] == '-' || !isdigit(buf[0])) 259 continue; 260 261 /* decode the reply code */ 262 r = atoi(buf); 263 264 /* extra semantics: 0xx codes are "informational" */ 265 if (r < 100) 266 continue; 267 268 return (r); 269 } 270 } 271 /* 272 ** SMTPMESSAGE -- send message to server 273 ** 274 ** Parameters: 275 ** f -- format 276 ** a, b, c -- parameters 277 ** 278 ** Returns: 279 ** none. 280 ** 281 ** Side Effects: 282 ** writes message to SmtpOut. 283 */ 284 285 /*VARARGS1*/ 286 smtpmessage(f, a, b, c) 287 char *f; 288 { 289 char buf[100]; 290 291 (void) sprintf(buf, f, a, b, c); 292 if (tTd(18, 1) || (Verbose && !HoldErrs)) 293 printf(">>> %s\n", buf); 294 fprintf(Xscript, ">>> %s\n", buf); 295 fprintf(SmtpOut, "%s\r\n", buf); 296 } 297 298 # endif SMTP 299