14796Seric # include <ctype.h> 24684Seric # include <sysexits.h> 34865Seric # include "sendmail.h" 44684Seric 55182Seric # ifndef SMTP 6*7964Seric SCCSID(@(#)usersmtp.c 3.19 08/29/82 (no SMTP)); 75182Seric # else SMTP 84684Seric 9*7964Seric SCCSID(@(#)usersmtp.c 3.19 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) 307963Seric # 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. 757963Seric ** 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); 827963Seric 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); 957963Seric else if (r == 250) 967963Seric return (EX_OK); 977963Seric else if (r == 552) 987963Seric return (EX_UNAVAILABLE); 99*7964Seric return (EX_PROTOCOL); 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); 1287963Seric else if (REPLYTYPE(r) == 2) 1297963Seric return (EX_OK); 130*7964Seric else if (r == 550 || r == 551 || r == 553) 131*7964Seric return (EX_NOUSER); 132*7964Seric else if (r == 552 || r == 554) 133*7964Seric return (EX_UNAVAILABLE); 134*7964Seric return (EX_PROTOCOL); 1354797Seric } 1364797Seric /* 1374865Seric ** SMTPFINISH -- finish up sending all the SMTP protocol. 1384684Seric ** 1394684Seric ** Parameters: 1404865Seric ** m -- mailer being sent to. 1416980Seric ** e -- the envelope for this message. 1424684Seric ** 1434684Seric ** Returns: 1444976Seric ** exit status corresponding to DATA command. 1454684Seric ** 1464684Seric ** Side Effects: 1474865Seric ** none. 1484684Seric */ 1494684Seric 1506980Seric smtpfinish(m, e) 1514865Seric struct mailer *m; 1526980Seric register ENVELOPE *e; 1534684Seric { 1544684Seric register int r; 1554684Seric 1566051Seric if (SmtpPid < 0) 1576051Seric return (SmtpErrstat); 1586051Seric 1594797Seric /* 1604797Seric ** Send the data. 1614797Seric ** Dot hiding is done here. 1624797Seric */ 1634797Seric 1644865Seric smtpmessage("DATA"); 1654796Seric r = reply(); 1664797Seric if (REPLYTYPE(r) == 4) 1674797Seric return (EX_TEMPFAIL); 1687963Seric else if (r == 554) 1697963Seric return (EX_UNAVAILABLE); 1707963Seric else if (r != 354) 171*7964Seric return (EX_PROTOCOL); 1726980Seric (*e->e_puthdr)(SmtpOut, m, CurEnv); 1736980Seric fprintf(SmtpOut, "\n"); 1746980Seric (*e->e_putbody)(SmtpOut, m, TRUE); 1754865Seric smtpmessage("."); 1764796Seric r = reply(); 1774797Seric if (REPLYTYPE(r) == 4) 1784797Seric return (EX_TEMPFAIL); 1797963Seric else if (r == 250) 1807963Seric return (EX_OK); 1817963Seric else if (r == 552 || r == 554) 1827963Seric return (EX_UNAVAILABLE); 183*7964Seric return (EX_PROTOCOL); 1844684Seric } 1854684Seric /* 1864865Seric ** SMTPQUIT -- close the SMTP connection. 1874865Seric ** 1884865Seric ** Parameters: 1894865Seric ** name -- name of mailer we are quitting. 1907229Seric ** showresp -- if set, give a response message. 1914865Seric ** 1924865Seric ** Returns: 1934865Seric ** none. 1944865Seric ** 1954865Seric ** Side Effects: 1964865Seric ** sends the final protocol and closes the connection. 1974865Seric */ 1984865Seric 1997229Seric smtpquit(name, showresp) 2004865Seric char *name; 2017229Seric bool showresp; 2024865Seric { 2034865Seric register int i; 2044865Seric 2056051Seric if (SmtpPid < 0) 2067229Seric return; 2077229Seric smtpmessage("QUIT"); 2087229Seric (void) reply(); 2097229Seric (void) fclose(SmtpIn); 2107229Seric (void) fclose(SmtpOut); 2117229Seric i = endmailer(SmtpPid, name); 2127229Seric if (showresp) 2137229Seric giveresponse(i, TRUE, LocalMailer); 2144865Seric } 2154865Seric /* 2164684Seric ** REPLY -- read arpanet reply 2174684Seric ** 2184684Seric ** Parameters: 2194796Seric ** none. 2204684Seric ** 2214684Seric ** Returns: 2224684Seric ** reply code it reads. 2234684Seric ** 2244684Seric ** Side Effects: 2254684Seric ** flushes the mail file. 2264684Seric */ 2274684Seric 2284796Seric reply() 2294684Seric { 2304865Seric (void) fflush(SmtpOut); 2314684Seric 2327677Seric if (tTd(18, 1)) 2334796Seric printf("reply\n"); 2344796Seric 2357356Seric /* 2367356Seric ** Read the input line, being careful not to hang. 2377356Seric */ 2387356Seric 2394684Seric for (;;) 2404684Seric { 2414684Seric char buf[MAXLINE]; 2424684Seric register int r; 2437356Seric register char *p; 2444684Seric 2457685Seric /* actually do the read */ 2467677Seric (void) fflush(Xscript); /* for debugging */ 2477685Seric p = sfgets(buf, sizeof buf, SmtpIn); 2487356Seric 2497356Seric if (p == NULL) 2507356Seric return (-1); 2517356Seric 2527356Seric /* log the input in the transcript for future error returns */ 2537229Seric if (Verbose && !HoldErrs) 2544684Seric fputs(buf, stdout); 2557229Seric fputs(buf, Xscript); 2567356Seric 2577356Seric /* if continuation is required, we can go on */ 2584796Seric if (buf[3] == '-' || !isdigit(buf[0])) 2594684Seric continue; 2607356Seric 2617356Seric /* decode the reply code */ 2624684Seric r = atoi(buf); 2637356Seric 2647356Seric /* extra semantics: 0xx codes are "informational" */ 2654684Seric if (r < 100) 2664684Seric continue; 2677356Seric 2684684Seric return (r); 2694684Seric } 2704684Seric } 2714796Seric /* 2724865Seric ** SMTPMESSAGE -- send message to server 2734796Seric ** 2744796Seric ** Parameters: 2754796Seric ** f -- format 2764796Seric ** a, b, c -- parameters 2774796Seric ** 2784796Seric ** Returns: 2794796Seric ** none. 2804796Seric ** 2814796Seric ** Side Effects: 2824865Seric ** writes message to SmtpOut. 2834796Seric */ 2844796Seric 2854865Seric /*VARARGS1*/ 2864865Seric smtpmessage(f, a, b, c) 2874796Seric char *f; 2884796Seric { 2894796Seric char buf[100]; 2904796Seric 2914865Seric (void) sprintf(buf, f, a, b, c); 2927677Seric if (tTd(18, 1) || (Verbose && !HoldErrs)) 2937229Seric printf(">>> %s\n", buf); 2947229Seric fprintf(Xscript, ">>> %s\n", buf); 2957229Seric fprintf(SmtpOut, "%s\r\n", buf); 2964796Seric } 2975182Seric 2985182Seric # endif SMTP 299