1 # include <ctype.h> 2 # include <sysexits.h> 3 # include "sendmail.h" 4 5 # ifndef SMTP 6 SCCSID(@(#)usersmtp.c 3.12.1.1 07/04/82 (no SMTP)); 7 # else SMTP 8 9 SCCSID(@(#)usersmtp.c 3.12.1.1 07/04/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 HOPS command. 85 ** This is non-standard and may give an "unknown command". 86 ** This is not an error. 87 ** It can give a "bad hop count" error if the hop 88 ** count is exceeded. 89 */ 90 91 /* 92 ** Send the MAIL command. 93 ** Designates the sender. 94 */ 95 96 expand("$g", buf, &buf[sizeof buf - 1], CurEnv); 97 smtpmessage("MAIL From:<%s>", buf); 98 r = reply(); 99 if (REPLYTYPE(r) == 4) 100 return (EX_TEMPFAIL); 101 if (r != 250) 102 return (EX_SOFTWARE); 103 return (EX_OK); 104 } 105 /* 106 ** SMTPRCPT -- designate recipient. 107 ** 108 ** Parameters: 109 ** to -- address of recipient. 110 ** 111 ** Returns: 112 ** exit status corresponding to recipient status. 113 ** 114 ** Side Effects: 115 ** Sends the mail via SMTP. 116 */ 117 118 smtprcpt(to) 119 ADDRESS *to; 120 { 121 register int r; 122 123 if (SmtpPid < 0) 124 return (SmtpErrstat); 125 126 smtpmessage("RCPT To:<%s>", to->q_user); 127 128 r = reply(); 129 if (REPLYTYPE(r) == 4) 130 return (EX_TEMPFAIL); 131 if (r != 250) 132 return (EX_NOUSER); 133 134 return (EX_OK); 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 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 if (r != 250) 178 return (EX_SOFTWARE); 179 return (EX_OK); 180 } 181 /* 182 ** SMTPQUIT -- close the SMTP connection. 183 ** 184 ** Parameters: 185 ** name -- name of mailer we are quitting. 186 ** showresp -- if set, give a response message. 187 ** 188 ** Returns: 189 ** none. 190 ** 191 ** Side Effects: 192 ** sends the final protocol and closes the connection. 193 */ 194 195 smtpquit(name, showresp) 196 char *name; 197 bool showresp; 198 { 199 register int i; 200 201 if (SmtpPid < 0) 202 return; 203 smtpmessage("QUIT"); 204 (void) reply(); 205 (void) fclose(SmtpIn); 206 (void) fclose(SmtpOut); 207 i = endmailer(SmtpPid, name); 208 if (showresp) 209 giveresponse(i, TRUE, LocalMailer); 210 } 211 /* 212 ** REPLY -- read arpanet reply 213 ** 214 ** Parameters: 215 ** none. 216 ** 217 ** Returns: 218 ** reply code it reads. 219 ** 220 ** Side Effects: 221 ** flushes the mail file. 222 */ 223 224 reply() 225 { 226 (void) fflush(SmtpOut); 227 228 if (Debug) 229 printf("reply\n"); 230 231 /* read the input line */ 232 for (;;) 233 { 234 char buf[MAXLINE]; 235 register int r; 236 237 if (fgets(buf, sizeof buf, SmtpIn) == NULL) 238 return (-1); 239 if (Verbose && !HoldErrs) 240 fputs(buf, stdout); 241 fputs(buf, Xscript); 242 if (buf[3] == '-' || !isdigit(buf[0])) 243 continue; 244 r = atoi(buf); 245 if (r < 100) 246 continue; 247 return (r); 248 } 249 } 250 /* 251 ** SMTPMESSAGE -- send message to server 252 ** 253 ** Parameters: 254 ** f -- format 255 ** a, b, c -- parameters 256 ** 257 ** Returns: 258 ** none. 259 ** 260 ** Side Effects: 261 ** writes message to SmtpOut. 262 */ 263 264 /*VARARGS1*/ 265 smtpmessage(f, a, b, c) 266 char *f; 267 { 268 char buf[100]; 269 270 (void) sprintf(buf, f, a, b, c); 271 if (Debug || (Verbose && !HoldErrs)) 272 printf(">>> %s\n", buf); 273 fprintf(Xscript, ">>> %s\n", buf); 274 fprintf(SmtpOut, "%s\r\n", buf); 275 } 276 277 # endif SMTP 278