14796Seric # include <ctype.h> 24684Seric # include <sysexits.h> 34865Seric # include "sendmail.h" 44684Seric 55182Seric # ifndef SMTP 6*8237Seric SCCSID(@(#)usersmtp.c 3.23 09/21/82 (no SMTP)); 75182Seric # else SMTP 84684Seric 9*8237Seric SCCSID(@(#)usersmtp.c 3.23 09/21/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(); 708005Seric if (r < 0 || 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(); 808005Seric if (r < 0) 818005Seric return (EX_TEMPFAIL); 828005Seric else if (REPLYTYPE(r) == 5) 834976Seric return (EX_UNAVAILABLE); 847963Seric else 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); 938084Seric smtpmessage("MAIL From:<%s>", canonname(buf)); 944865Seric r = reply(); 958005Seric if (r < 0 || REPLYTYPE(r) == 4) 964865Seric return (EX_TEMPFAIL); 977963Seric else if (r == 250) 987963Seric return (EX_OK); 997963Seric else if (r == 552) 1007963Seric return (EX_UNAVAILABLE); 1017964Seric return (EX_PROTOCOL); 1024684Seric } 1034684Seric /* 1044976Seric ** SMTPRCPT -- designate recipient. 1054797Seric ** 1064797Seric ** Parameters: 1074865Seric ** to -- address of recipient. 1084797Seric ** 1094797Seric ** Returns: 1104865Seric ** exit status corresponding to recipient status. 1114797Seric ** 1124797Seric ** Side Effects: 1134865Seric ** Sends the mail via SMTP. 1144797Seric */ 1154797Seric 1164976Seric smtprcpt(to) 1174865Seric ADDRESS *to; 1184797Seric { 1194797Seric register int r; 1207685Seric extern char *canonname(); 1214797Seric 1226051Seric if (SmtpPid < 0) 1236051Seric return (SmtpErrstat); 1246051Seric 1258084Seric smtpmessage("RCPT To:<%s>", canonname(to->q_user)); 1264865Seric 1274797Seric r = reply(); 1288005Seric if (r < 0 || REPLYTYPE(r) == 4) 1294865Seric return (EX_TEMPFAIL); 1307963Seric else if (REPLYTYPE(r) == 2) 1317963Seric return (EX_OK); 1327964Seric else if (r == 550 || r == 551 || r == 553) 1337964Seric return (EX_NOUSER); 1347964Seric else if (r == 552 || r == 554) 1357964Seric return (EX_UNAVAILABLE); 1367964Seric return (EX_PROTOCOL); 1374797Seric } 1384797Seric /* 1394865Seric ** SMTPFINISH -- finish up sending all the SMTP protocol. 1404684Seric ** 1414684Seric ** Parameters: 1424865Seric ** m -- mailer being sent to. 1436980Seric ** e -- the envelope for this message. 1444684Seric ** 1454684Seric ** Returns: 1464976Seric ** exit status corresponding to DATA command. 1474684Seric ** 1484684Seric ** Side Effects: 1494865Seric ** none. 1504684Seric */ 1514684Seric 1526980Seric smtpfinish(m, e) 1534865Seric struct mailer *m; 1546980Seric register ENVELOPE *e; 1554684Seric { 1564684Seric register int r; 1574684Seric 1586051Seric if (SmtpPid < 0) 1596051Seric return (SmtpErrstat); 1606051Seric 1614797Seric /* 1624797Seric ** Send the data. 1634797Seric ** Dot hiding is done here. 1644797Seric */ 1654797Seric 1664865Seric smtpmessage("DATA"); 1674796Seric r = reply(); 1688005Seric if (r < 0 || REPLYTYPE(r) == 4) 1694797Seric return (EX_TEMPFAIL); 1707963Seric else if (r == 554) 1717963Seric return (EX_UNAVAILABLE); 1727963Seric else if (r != 354) 1737964Seric return (EX_PROTOCOL); 1746980Seric (*e->e_puthdr)(SmtpOut, m, CurEnv); 1756980Seric fprintf(SmtpOut, "\n"); 1766980Seric (*e->e_putbody)(SmtpOut, m, TRUE); 1774865Seric smtpmessage("."); 1784796Seric r = reply(); 1798005Seric if (r < 0 || REPLYTYPE(r) == 4) 1804797Seric return (EX_TEMPFAIL); 1817963Seric else if (r == 250) 1827963Seric return (EX_OK); 1837963Seric else if (r == 552 || r == 554) 1847963Seric return (EX_UNAVAILABLE); 1857964Seric return (EX_PROTOCOL); 1864684Seric } 1874684Seric /* 1884865Seric ** SMTPQUIT -- close the SMTP connection. 1894865Seric ** 1904865Seric ** Parameters: 1914865Seric ** name -- name of mailer we are quitting. 1927229Seric ** showresp -- if set, give a response message. 1934865Seric ** 1944865Seric ** Returns: 1954865Seric ** none. 1964865Seric ** 1974865Seric ** Side Effects: 1984865Seric ** sends the final protocol and closes the connection. 1994865Seric */ 2004865Seric 2017229Seric smtpquit(name, showresp) 2024865Seric char *name; 2037229Seric bool showresp; 2044865Seric { 2054865Seric register int i; 2064865Seric 2076051Seric if (SmtpPid < 0) 2087229Seric return; 2097229Seric smtpmessage("QUIT"); 2107229Seric (void) reply(); 2117229Seric (void) fclose(SmtpIn); 2127229Seric (void) fclose(SmtpOut); 2137229Seric i = endmailer(SmtpPid, name); 2147229Seric if (showresp) 2157229Seric giveresponse(i, TRUE, LocalMailer); 2164865Seric } 2174865Seric /* 2184684Seric ** REPLY -- read arpanet reply 2194684Seric ** 2204684Seric ** Parameters: 2214796Seric ** none. 2224684Seric ** 2234684Seric ** Returns: 2244684Seric ** reply code it reads. 2254684Seric ** 2264684Seric ** Side Effects: 2274684Seric ** flushes the mail file. 2284684Seric */ 2294684Seric 2304796Seric reply() 2314684Seric { 2324865Seric (void) fflush(SmtpOut); 2334684Seric 2347677Seric if (tTd(18, 1)) 2354796Seric printf("reply\n"); 2364796Seric 2377356Seric /* 2387356Seric ** Read the input line, being careful not to hang. 2397356Seric */ 2407356Seric 2414684Seric for (;;) 2424684Seric { 2434684Seric char buf[MAXLINE]; 2444684Seric register int r; 2457356Seric register char *p; 2464684Seric 2477685Seric /* actually do the read */ 2487677Seric (void) fflush(Xscript); /* for debugging */ 2497685Seric p = sfgets(buf, sizeof buf, SmtpIn); 2507356Seric if (p == NULL) 2517356Seric return (-1); 252*8237Seric fixcrlf(buf, TRUE); 2537356Seric 2547356Seric /* log the input in the transcript for future error returns */ 2557229Seric if (Verbose && !HoldErrs) 256*8237Seric nmessage(Arpa_Info, "%s", buf); 257*8237Seric fprintf(Xscript, "%s\n", buf); 2587356Seric 2597356Seric /* if continuation is required, we can go on */ 2604796Seric if (buf[3] == '-' || !isdigit(buf[0])) 2614684Seric continue; 2627356Seric 2637356Seric /* decode the reply code */ 2644684Seric r = atoi(buf); 2657356Seric 2667356Seric /* extra semantics: 0xx codes are "informational" */ 2674684Seric if (r < 100) 2684684Seric continue; 2697356Seric 2704684Seric return (r); 2714684Seric } 2724684Seric } 2734796Seric /* 2744865Seric ** SMTPMESSAGE -- send message to server 2754796Seric ** 2764796Seric ** Parameters: 2774796Seric ** f -- format 2784796Seric ** a, b, c -- parameters 2794796Seric ** 2804796Seric ** Returns: 2814796Seric ** none. 2824796Seric ** 2834796Seric ** Side Effects: 2844865Seric ** writes message to SmtpOut. 2854796Seric */ 2864796Seric 2874865Seric /*VARARGS1*/ 2884865Seric smtpmessage(f, a, b, c) 2894796Seric char *f; 2904796Seric { 2914796Seric char buf[100]; 2924796Seric 2934865Seric (void) sprintf(buf, f, a, b, c); 2947677Seric if (tTd(18, 1) || (Verbose && !HoldErrs)) 295*8237Seric nmessage(Arpa_Info, ">>> %s", buf); 296*8237Seric fprintf(Xscript, " >>> %s\n", buf); 2977229Seric fprintf(SmtpOut, "%s\r\n", buf); 2984796Seric } 2995182Seric 3005182Seric # endif SMTP 301