14796Seric # include <ctype.h> 27356Seric # include <signal.h> 34684Seric # include <sysexits.h> 44865Seric # include "sendmail.h" 54684Seric 65182Seric # ifndef SMTP 7*7685Seric SCCSID(@(#)usersmtp.c 3.16 08/08/82 (no SMTP)); 85182Seric # else SMTP 94684Seric 10*7685Seric SCCSID(@(#)usersmtp.c 3.16 08/08/82); 115182Seric 124684Seric /* 134865Seric ** SMTPINIT -- initialize SMTP. 144684Seric ** 154865Seric ** Opens the connection and sends the initial protocol. 164684Seric ** 174684Seric ** Parameters: 184865Seric ** m -- mailer to create connection to. 194865Seric ** pvp -- pointer to parameter vector to pass to 204865Seric ** the mailer. 214865Seric ** ctladdr -- controlling address for this mailer. 224684Seric ** 234684Seric ** Returns: 244865Seric ** appropriate exit status -- EX_OK on success. 254684Seric ** 264684Seric ** Side Effects: 274865Seric ** creates connection and sends initial protocol. 284684Seric */ 294684Seric 304865Seric # define REPLYTYPE(r) ((r) / 100) 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(); 45*7685Seric 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 } 637356Seric (void) signal(SIGALRM, tick); 644796Seric 654865Seric /* 664865Seric ** Get the greeting message. 674865Seric ** This should appear spontaneously. 684865Seric */ 694797Seric 704865Seric r = reply(); 714865Seric if (REPLYTYPE(r) != 2) 724865Seric return (EX_TEMPFAIL); 734684Seric 744865Seric /* 754976Seric ** Send the HELO command. 764976Seric ** My mother taught me to always introduce myself, even 774976Seric ** if it is useless. 784976Seric */ 794976Seric 804976Seric smtpmessage("HELO %s", HostName); 814976Seric r = reply(); 824976Seric if (REPLYTYPE(r) == 5) 834976Seric return (EX_UNAVAILABLE); 844976Seric if (REPLYTYPE(r) != 2) 854976Seric return (EX_TEMPFAIL); 864976Seric 874976Seric /* 884865Seric ** Send the MAIL command. 894865Seric ** Designates the sender. 904865Seric */ 914796Seric 926980Seric expand("$g", buf, &buf[sizeof buf - 1], CurEnv); 93*7685Seric smtpmessage("MAIL From: %s", canonname(buf)); 944865Seric r = reply(); 954865Seric if (REPLYTYPE(r) == 4) 964865Seric return (EX_TEMPFAIL); 974865Seric if (r != 250) 984865Seric return (EX_SOFTWARE); 994865Seric return (EX_OK); 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; 118*7685Seric extern char *canonname(); 1194797Seric 1206051Seric if (SmtpPid < 0) 1216051Seric return (SmtpErrstat); 1226051Seric 123*7685Seric smtpmessage("RCPT To: %s", canonname(to->q_user)); 1244865Seric 1254797Seric r = reply(); 1264865Seric if (REPLYTYPE(r) == 4) 1274865Seric return (EX_TEMPFAIL); 1284865Seric if (r != 250) 1294865Seric return (EX_NOUSER); 1304797Seric 1314865Seric return (EX_OK); 1324797Seric } 1334797Seric /* 1344865Seric ** SMTPFINISH -- finish up sending all the SMTP protocol. 1354684Seric ** 1364684Seric ** Parameters: 1374865Seric ** m -- mailer being sent to. 1386980Seric ** e -- the envelope for this message. 1394684Seric ** 1404684Seric ** Returns: 1414976Seric ** exit status corresponding to DATA command. 1424684Seric ** 1434684Seric ** Side Effects: 1444865Seric ** none. 1454684Seric */ 1464684Seric 1476980Seric smtpfinish(m, e) 1484865Seric struct mailer *m; 1496980Seric register ENVELOPE *e; 1504684Seric { 1514684Seric register int r; 1524684Seric 1536051Seric if (SmtpPid < 0) 1546051Seric return (SmtpErrstat); 1556051Seric 1564797Seric /* 1574797Seric ** Send the data. 1584797Seric ** Dot hiding is done here. 1594797Seric */ 1604797Seric 1614865Seric smtpmessage("DATA"); 1624796Seric r = reply(); 1634797Seric if (REPLYTYPE(r) == 4) 1644797Seric return (EX_TEMPFAIL); 1654684Seric if (r != 354) 1664684Seric return (EX_SOFTWARE); 1676980Seric (*e->e_puthdr)(SmtpOut, m, CurEnv); 1686980Seric fprintf(SmtpOut, "\n"); 1696980Seric (*e->e_putbody)(SmtpOut, m, TRUE); 1704865Seric smtpmessage("."); 1714796Seric r = reply(); 1724797Seric if (REPLYTYPE(r) == 4) 1734797Seric return (EX_TEMPFAIL); 1744684Seric if (r != 250) 1754684Seric return (EX_SOFTWARE); 1764684Seric return (EX_OK); 1774684Seric } 1784684Seric /* 1794865Seric ** SMTPQUIT -- close the SMTP connection. 1804865Seric ** 1814865Seric ** Parameters: 1824865Seric ** name -- name of mailer we are quitting. 1837229Seric ** showresp -- if set, give a response message. 1844865Seric ** 1854865Seric ** Returns: 1864865Seric ** none. 1874865Seric ** 1884865Seric ** Side Effects: 1894865Seric ** sends the final protocol and closes the connection. 1904865Seric */ 1914865Seric 1927229Seric smtpquit(name, showresp) 1934865Seric char *name; 1947229Seric bool showresp; 1954865Seric { 1964865Seric register int i; 1974865Seric 1986051Seric if (SmtpPid < 0) 1997229Seric return; 2007229Seric smtpmessage("QUIT"); 2017229Seric (void) reply(); 2027229Seric (void) fclose(SmtpIn); 2037229Seric (void) fclose(SmtpOut); 2047229Seric i = endmailer(SmtpPid, name); 2057229Seric if (showresp) 2067229Seric giveresponse(i, TRUE, LocalMailer); 2074865Seric } 2084865Seric /* 2094684Seric ** REPLY -- read arpanet reply 2104684Seric ** 2114684Seric ** Parameters: 2124796Seric ** none. 2134684Seric ** 2144684Seric ** Returns: 2154684Seric ** reply code it reads. 2164684Seric ** 2174684Seric ** Side Effects: 2184684Seric ** flushes the mail file. 2194684Seric */ 2204684Seric 2214796Seric reply() 2224684Seric { 2234865Seric (void) fflush(SmtpOut); 2244684Seric 2257677Seric if (tTd(18, 1)) 2264796Seric printf("reply\n"); 2274796Seric 2287356Seric /* 2297356Seric ** Read the input line, being careful not to hang. 2307356Seric */ 2317356Seric 2324684Seric for (;;) 2334684Seric { 2344684Seric char buf[MAXLINE]; 2354684Seric register int r; 2367356Seric register char *p; 2374684Seric 238*7685Seric /* actually do the read */ 2397677Seric (void) fflush(Xscript); /* for debugging */ 240*7685Seric p = sfgets(buf, sizeof buf, SmtpIn); 2417356Seric 2427356Seric if (p == NULL) 2437356Seric return (-1); 2447356Seric 2457356Seric /* log the input in the transcript for future error returns */ 2467229Seric if (Verbose && !HoldErrs) 2474684Seric fputs(buf, stdout); 2487229Seric fputs(buf, Xscript); 2497356Seric 2507356Seric /* if continuation is required, we can go on */ 2514796Seric if (buf[3] == '-' || !isdigit(buf[0])) 2524684Seric continue; 2537356Seric 2547356Seric /* decode the reply code */ 2554684Seric r = atoi(buf); 2567356Seric 2577356Seric /* extra semantics: 0xx codes are "informational" */ 2584684Seric if (r < 100) 2594684Seric continue; 2607356Seric 2614684Seric return (r); 2624684Seric } 2634684Seric } 2644796Seric /* 2654865Seric ** SMTPMESSAGE -- send message to server 2664796Seric ** 2674796Seric ** Parameters: 2684796Seric ** f -- format 2694796Seric ** a, b, c -- parameters 2704796Seric ** 2714796Seric ** Returns: 2724796Seric ** none. 2734796Seric ** 2744796Seric ** Side Effects: 2754865Seric ** writes message to SmtpOut. 2764796Seric */ 2774796Seric 2784865Seric /*VARARGS1*/ 2794865Seric smtpmessage(f, a, b, c) 2804796Seric char *f; 2814796Seric { 2824796Seric char buf[100]; 2834796Seric 2844865Seric (void) sprintf(buf, f, a, b, c); 2857677Seric if (tTd(18, 1) || (Verbose && !HoldErrs)) 2867229Seric printf(">>> %s\n", buf); 2877229Seric fprintf(Xscript, ">>> %s\n", buf); 2887229Seric fprintf(SmtpOut, "%s\r\n", buf); 2894796Seric } 2905182Seric 2915182Seric # endif SMTP 292