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