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