14796Seric # include <ctype.h> 24684Seric # include <sysexits.h> 34865Seric # include "sendmail.h" 44684Seric 55182Seric # ifndef SMTP 6*7963Seric SCCSID(@(#)usersmtp.c 3.18 08/29/82 (no SMTP)); 75182Seric # else SMTP 84684Seric 9*7963Seric SCCSID(@(#)usersmtp.c 3.18 08/29/82); 105182Seric 114684Seric /* 124865Seric ** SMTPINIT -- initialize SMTP. 134684Seric ** 144865Seric ** Opens the connection and sends the initial protocol. 154684Seric ** 164684Seric ** Parameters: 174865Seric ** m -- mailer to create connection to. 184865Seric ** pvp -- pointer to parameter vector to pass to 194865Seric ** the mailer. 204865Seric ** ctladdr -- controlling address for this mailer. 214684Seric ** 224684Seric ** Returns: 234865Seric ** appropriate exit status -- EX_OK on success. 244684Seric ** 254684Seric ** Side Effects: 264865Seric ** creates connection and sends initial protocol. 274684Seric */ 284684Seric 294865Seric # define REPLYTYPE(r) ((r) / 100) 30*7963Seric # define REPLYCLASS(r) (((r) / 10) % 10) 314865Seric 324865Seric static FILE *SmtpOut; /* output file */ 334865Seric static FILE *SmtpIn; /* input file */ 344865Seric static int SmtpPid; /* pid of mailer */ 356051Seric static int SmtpErrstat; /* error status if open fails */ 364865Seric 374865Seric smtpinit(m, pvp, ctladdr) 384865Seric struct mailer *m; 394865Seric char **pvp; 404865Seric ADDRESS *ctladdr; 414684Seric { 424865Seric register int r; 434865Seric char buf[MAXNAME]; 447356Seric extern tick(); 457685Seric extern char *canonname(); 464684Seric 474865Seric /* 484865Seric ** Open the connection to the mailer. 494865Seric */ 504684Seric 516051Seric SmtpIn = SmtpOut = NULL; 524865Seric SmtpPid = openmailer(m, pvp, ctladdr, TRUE, &SmtpOut, &SmtpIn); 536051Seric if (SmtpPid < 0) 546051Seric { 556051Seric SmtpErrstat = ExitStat; 566051Seric # ifdef DEBUG 577677Seric if (tTd(18, 1)) 586051Seric printf("smtpinit: cannot open: Errstat %d errno %d\n", 596051Seric SmtpErrstat, errno); 606051Seric # endif DEBUG 616051Seric return (ExitStat); 626051Seric } 634796Seric 644865Seric /* 654865Seric ** Get the greeting message. 664865Seric ** This should appear spontaneously. 674865Seric */ 684797Seric 694865Seric r = reply(); 704865Seric if (REPLYTYPE(r) != 2) 714865Seric return (EX_TEMPFAIL); 724684Seric 734865Seric /* 744976Seric ** Send the HELO command. 75*7963Seric ** My mother taught me to always introduce myself. 764976Seric */ 774976Seric 784976Seric smtpmessage("HELO %s", HostName); 794976Seric r = reply(); 804976Seric if (REPLYTYPE(r) == 5) 814976Seric return (EX_UNAVAILABLE); 82*7963Seric else if (REPLYTYPE(r) != 2) 834976Seric return (EX_TEMPFAIL); 844976Seric 854976Seric /* 864865Seric ** Send the MAIL command. 874865Seric ** Designates the sender. 884865Seric */ 894796Seric 906980Seric expand("$g", buf, &buf[sizeof buf - 1], CurEnv); 917685Seric smtpmessage("MAIL From: %s", canonname(buf)); 924865Seric r = reply(); 934865Seric if (REPLYTYPE(r) == 4) 944865Seric return (EX_TEMPFAIL); 95*7963Seric else if (r == 250) 96*7963Seric return (EX_OK); 97*7963Seric else if (r == 552) 98*7963Seric return (EX_UNAVAILABLE); 99*7963Seric return (EX_SOFTWARE); 1004684Seric } 1014684Seric /* 1024976Seric ** SMTPRCPT -- designate recipient. 1034797Seric ** 1044797Seric ** Parameters: 1054865Seric ** to -- address of recipient. 1064797Seric ** 1074797Seric ** Returns: 1084865Seric ** exit status corresponding to recipient status. 1094797Seric ** 1104797Seric ** Side Effects: 1114865Seric ** Sends the mail via SMTP. 1124797Seric */ 1134797Seric 1144976Seric smtprcpt(to) 1154865Seric ADDRESS *to; 1164797Seric { 1174797Seric register int r; 1187685Seric extern char *canonname(); 1194797Seric 1206051Seric if (SmtpPid < 0) 1216051Seric return (SmtpErrstat); 1226051Seric 1237685Seric smtpmessage("RCPT To: %s", canonname(to->q_user)); 1244865Seric 1254797Seric r = reply(); 1264865Seric if (REPLYTYPE(r) == 4) 1274865Seric return (EX_TEMPFAIL); 128*7963Seric else if (REPLYCLASS(r) == 5) 1294865Seric return (EX_NOUSER); 130*7963Seric else if (REPLYTYPE(r) == 2) 131*7963Seric return (EX_OK); 132*7963Seric return (EX_SOFTWARE); 1334797Seric } 1344797Seric /* 1354865Seric ** SMTPFINISH -- finish up sending all the SMTP protocol. 1364684Seric ** 1374684Seric ** Parameters: 1384865Seric ** m -- mailer being sent to. 1396980Seric ** e -- the envelope for this message. 1404684Seric ** 1414684Seric ** Returns: 1424976Seric ** exit status corresponding to DATA command. 1434684Seric ** 1444684Seric ** Side Effects: 1454865Seric ** none. 1464684Seric */ 1474684Seric 1486980Seric smtpfinish(m, e) 1494865Seric struct mailer *m; 1506980Seric register ENVELOPE *e; 1514684Seric { 1524684Seric register int r; 1534684Seric 1546051Seric if (SmtpPid < 0) 1556051Seric return (SmtpErrstat); 1566051Seric 1574797Seric /* 1584797Seric ** Send the data. 1594797Seric ** Dot hiding is done here. 1604797Seric */ 1614797Seric 1624865Seric smtpmessage("DATA"); 1634796Seric r = reply(); 1644797Seric if (REPLYTYPE(r) == 4) 1654797Seric return (EX_TEMPFAIL); 166*7963Seric else if (r == 554) 167*7963Seric return (EX_UNAVAILABLE); 168*7963Seric else if (r != 354) 1694684Seric return (EX_SOFTWARE); 1706980Seric (*e->e_puthdr)(SmtpOut, m, CurEnv); 1716980Seric fprintf(SmtpOut, "\n"); 1726980Seric (*e->e_putbody)(SmtpOut, m, TRUE); 1734865Seric smtpmessage("."); 1744796Seric r = reply(); 1754797Seric if (REPLYTYPE(r) == 4) 1764797Seric return (EX_TEMPFAIL); 177*7963Seric else if (r == 250) 178*7963Seric return (EX_OK); 179*7963Seric else if (r == 552 || r == 554) 180*7963Seric return (EX_UNAVAILABLE); 181*7963Seric return (EX_SOFTWARE); 1824684Seric } 1834684Seric /* 1844865Seric ** SMTPQUIT -- close the SMTP connection. 1854865Seric ** 1864865Seric ** Parameters: 1874865Seric ** name -- name of mailer we are quitting. 1887229Seric ** showresp -- if set, give a response message. 1894865Seric ** 1904865Seric ** Returns: 1914865Seric ** none. 1924865Seric ** 1934865Seric ** Side Effects: 1944865Seric ** sends the final protocol and closes the connection. 1954865Seric */ 1964865Seric 1977229Seric smtpquit(name, showresp) 1984865Seric char *name; 1997229Seric bool showresp; 2004865Seric { 2014865Seric register int i; 2024865Seric 2036051Seric if (SmtpPid < 0) 2047229Seric return; 2057229Seric smtpmessage("QUIT"); 2067229Seric (void) reply(); 2077229Seric (void) fclose(SmtpIn); 2087229Seric (void) fclose(SmtpOut); 2097229Seric i = endmailer(SmtpPid, name); 2107229Seric if (showresp) 2117229Seric giveresponse(i, TRUE, LocalMailer); 2124865Seric } 2134865Seric /* 2144684Seric ** REPLY -- read arpanet reply 2154684Seric ** 2164684Seric ** Parameters: 2174796Seric ** none. 2184684Seric ** 2194684Seric ** Returns: 2204684Seric ** reply code it reads. 2214684Seric ** 2224684Seric ** Side Effects: 2234684Seric ** flushes the mail file. 2244684Seric */ 2254684Seric 2264796Seric reply() 2274684Seric { 2284865Seric (void) fflush(SmtpOut); 2294684Seric 2307677Seric if (tTd(18, 1)) 2314796Seric printf("reply\n"); 2324796Seric 2337356Seric /* 2347356Seric ** Read the input line, being careful not to hang. 2357356Seric */ 2367356Seric 2374684Seric for (;;) 2384684Seric { 2394684Seric char buf[MAXLINE]; 2404684Seric register int r; 2417356Seric register char *p; 2424684Seric 2437685Seric /* actually do the read */ 2447677Seric (void) fflush(Xscript); /* for debugging */ 2457685Seric p = sfgets(buf, sizeof buf, SmtpIn); 2467356Seric 2477356Seric if (p == NULL) 2487356Seric return (-1); 2497356Seric 2507356Seric /* log the input in the transcript for future error returns */ 2517229Seric if (Verbose && !HoldErrs) 2524684Seric fputs(buf, stdout); 2537229Seric fputs(buf, Xscript); 2547356Seric 2557356Seric /* if continuation is required, we can go on */ 2564796Seric if (buf[3] == '-' || !isdigit(buf[0])) 2574684Seric continue; 2587356Seric 2597356Seric /* decode the reply code */ 2604684Seric r = atoi(buf); 2617356Seric 2627356Seric /* extra semantics: 0xx codes are "informational" */ 2634684Seric if (r < 100) 2644684Seric continue; 2657356Seric 2664684Seric return (r); 2674684Seric } 2684684Seric } 2694796Seric /* 2704865Seric ** SMTPMESSAGE -- send message to server 2714796Seric ** 2724796Seric ** Parameters: 2734796Seric ** f -- format 2744796Seric ** a, b, c -- parameters 2754796Seric ** 2764796Seric ** Returns: 2774796Seric ** none. 2784796Seric ** 2794796Seric ** Side Effects: 2804865Seric ** writes message to SmtpOut. 2814796Seric */ 2824796Seric 2834865Seric /*VARARGS1*/ 2844865Seric smtpmessage(f, a, b, c) 2854796Seric char *f; 2864796Seric { 2874796Seric char buf[100]; 2884796Seric 2894865Seric (void) sprintf(buf, f, a, b, c); 2907677Seric if (tTd(18, 1) || (Verbose && !HoldErrs)) 2917229Seric printf(">>> %s\n", buf); 2927229Seric fprintf(Xscript, ">>> %s\n", buf); 2937229Seric fprintf(SmtpOut, "%s\r\n", buf); 2944796Seric } 2955182Seric 2965182Seric # endif SMTP 297