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