1 # include <ctype.h> 2 # include <sysexits.h> 3 # include "sendmail.h" 4 5 # ifndef SMTP 6 SCCSID(@(#)usersmtp.c 3.9 03/06/82 (no SMTP)); 7 # else SMTP 8 9 SCCSID(@(#)usersmtp.c 3.9 03/06/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 (void) expand("$g", buf, &buf[sizeof buf - 1]); 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 ** editfcn -- a function to call to output the 134 ** text of the message with. 135 ** 136 ** Returns: 137 ** exit status corresponding to DATA command. 138 ** 139 ** Side Effects: 140 ** none. 141 */ 142 143 smtpfinish(m, editfcn) 144 struct mailer *m; 145 int (*editfcn)(); 146 { 147 register int r; 148 149 if (SmtpPid < 0) 150 return (SmtpErrstat); 151 152 /* 153 ** Send the data. 154 ** Dot hiding is done here. 155 */ 156 157 smtpmessage("DATA"); 158 r = reply(); 159 if (REPLYTYPE(r) == 4) 160 return (EX_TEMPFAIL); 161 if (r != 354) 162 return (EX_SOFTWARE); 163 (*editfcn)(SmtpOut, m, TRUE); 164 smtpmessage("."); 165 r = reply(); 166 if (REPLYTYPE(r) == 4) 167 return (EX_TEMPFAIL); 168 if (r != 250) 169 return (EX_SOFTWARE); 170 return (EX_OK); 171 } 172 /* 173 ** SMTPQUIT -- close the SMTP connection. 174 ** 175 ** Parameters: 176 ** name -- name of mailer we are quitting. 177 ** 178 ** Returns: 179 ** none. 180 ** 181 ** Side Effects: 182 ** sends the final protocol and closes the connection. 183 */ 184 185 smtpquit(name) 186 char *name; 187 { 188 register int i; 189 190 if (SmtpPid < 0) 191 { 192 i = SmtpErrstat; 193 } 194 else 195 { 196 smtpmessage("QUIT"); 197 (void) reply(); 198 (void) fclose(SmtpIn); 199 (void) fclose(SmtpOut); 200 i = endmailer(SmtpPid, name); 201 } 202 giveresponse(i, TRUE, LocalMailer); 203 } 204 /* 205 ** REPLY -- read arpanet reply 206 ** 207 ** Parameters: 208 ** none. 209 ** 210 ** Returns: 211 ** reply code it reads. 212 ** 213 ** Side Effects: 214 ** flushes the mail file. 215 */ 216 217 reply() 218 { 219 (void) fflush(SmtpOut); 220 221 if (Debug) 222 printf("reply\n"); 223 224 /* read the input line */ 225 for (;;) 226 { 227 char buf[MAXLINE]; 228 register int r; 229 230 if (fgets(buf, sizeof buf, SmtpIn) == NULL) 231 return (-1); 232 if (Verbose) 233 fputs(buf, stdout); 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 strcat(buf, "\r\n"); 264 if (Debug) 265 fputs(buf, stdout); 266 fputs(buf, SmtpOut); 267 } 268 269 # endif SMTP 270