14796Seric # include <ctype.h> 2*7356Seric # include <signal.h> 34684Seric # include <sysexits.h> 44865Seric # include "sendmail.h" 54684Seric 65182Seric # ifndef SMTP 7*7356Seric SCCSID(@(#)usersmtp.c 3.13 07/05/82 (no SMTP)); 85182Seric # else SMTP 94684Seric 10*7356Seric SCCSID(@(#)usersmtp.c 3.13 07/05/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]; 44*7356Seric extern tick(); 454684Seric 464865Seric /* 474865Seric ** Open the connection to the mailer. 484865Seric */ 494684Seric 506051Seric SmtpIn = SmtpOut = NULL; 514865Seric SmtpPid = openmailer(m, pvp, ctladdr, TRUE, &SmtpOut, &SmtpIn); 526051Seric if (SmtpPid < 0) 536051Seric { 546051Seric SmtpErrstat = ExitStat; 556051Seric # ifdef DEBUG 566051Seric if (Debug > 0) 576051Seric printf("smtpinit: cannot open: Errstat %d errno %d\n", 586051Seric SmtpErrstat, errno); 596051Seric # endif DEBUG 606051Seric return (ExitStat); 616051Seric } 62*7356Seric (void) signal(SIGALRM, tick); 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. 754976Seric ** My mother taught me to always introduce myself, even 764976Seric ** if it is useless. 774976Seric */ 784976Seric 794976Seric smtpmessage("HELO %s", HostName); 804976Seric r = reply(); 814976Seric if (REPLYTYPE(r) == 5) 824976Seric return (EX_UNAVAILABLE); 834976Seric if (REPLYTYPE(r) != 2) 844976Seric return (EX_TEMPFAIL); 854976Seric 864976Seric /* 874865Seric ** Send the MAIL command. 884865Seric ** Designates the sender. 894865Seric */ 904796Seric 916980Seric expand("$g", buf, &buf[sizeof buf - 1], CurEnv); 924865Seric smtpmessage("MAIL From:<%s>", buf); 934865Seric r = reply(); 944865Seric if (REPLYTYPE(r) == 4) 954865Seric return (EX_TEMPFAIL); 964865Seric if (r != 250) 974865Seric return (EX_SOFTWARE); 984865Seric return (EX_OK); 994684Seric } 1004684Seric /* 1014976Seric ** SMTPRCPT -- designate recipient. 1024797Seric ** 1034797Seric ** Parameters: 1044865Seric ** to -- address of recipient. 1054797Seric ** 1064797Seric ** Returns: 1074865Seric ** exit status corresponding to recipient status. 1084797Seric ** 1094797Seric ** Side Effects: 1104865Seric ** Sends the mail via SMTP. 1114797Seric */ 1124797Seric 1134976Seric smtprcpt(to) 1144865Seric ADDRESS *to; 1154797Seric { 1164797Seric register int r; 1174797Seric 1186051Seric if (SmtpPid < 0) 1196051Seric return (SmtpErrstat); 1206051Seric 1214976Seric smtpmessage("RCPT To:<%s>", to->q_user); 1224865Seric 1234797Seric r = reply(); 1244865Seric if (REPLYTYPE(r) == 4) 1254865Seric return (EX_TEMPFAIL); 1264865Seric if (r != 250) 1274865Seric return (EX_NOUSER); 1284797Seric 1294865Seric return (EX_OK); 1304797Seric } 1314797Seric /* 1324865Seric ** SMTPFINISH -- finish up sending all the SMTP protocol. 1334684Seric ** 1344684Seric ** Parameters: 1354865Seric ** m -- mailer being sent to. 1366980Seric ** e -- the envelope for this message. 1374684Seric ** 1384684Seric ** Returns: 1394976Seric ** exit status corresponding to DATA command. 1404684Seric ** 1414684Seric ** Side Effects: 1424865Seric ** none. 1434684Seric */ 1444684Seric 1456980Seric smtpfinish(m, e) 1464865Seric struct mailer *m; 1476980Seric register ENVELOPE *e; 1484684Seric { 1494684Seric register int r; 1504684Seric 1516051Seric if (SmtpPid < 0) 1526051Seric return (SmtpErrstat); 1536051Seric 1544797Seric /* 1554797Seric ** Send the data. 1564797Seric ** Dot hiding is done here. 1574797Seric */ 1584797Seric 1594865Seric smtpmessage("DATA"); 1604796Seric r = reply(); 1614797Seric if (REPLYTYPE(r) == 4) 1624797Seric return (EX_TEMPFAIL); 1634684Seric if (r != 354) 1644684Seric return (EX_SOFTWARE); 1656980Seric (*e->e_puthdr)(SmtpOut, m, CurEnv); 1666980Seric fprintf(SmtpOut, "\n"); 1676980Seric (*e->e_putbody)(SmtpOut, m, TRUE); 1684865Seric smtpmessage("."); 1694796Seric r = reply(); 1704797Seric if (REPLYTYPE(r) == 4) 1714797Seric return (EX_TEMPFAIL); 1724684Seric if (r != 250) 1734684Seric return (EX_SOFTWARE); 1744684Seric return (EX_OK); 1754684Seric } 1764684Seric /* 1774865Seric ** SMTPQUIT -- close the SMTP connection. 1784865Seric ** 1794865Seric ** Parameters: 1804865Seric ** name -- name of mailer we are quitting. 1817229Seric ** showresp -- if set, give a response message. 1824865Seric ** 1834865Seric ** Returns: 1844865Seric ** none. 1854865Seric ** 1864865Seric ** Side Effects: 1874865Seric ** sends the final protocol and closes the connection. 1884865Seric */ 1894865Seric 1907229Seric smtpquit(name, showresp) 1914865Seric char *name; 1927229Seric bool showresp; 1934865Seric { 1944865Seric register int i; 1954865Seric 1966051Seric if (SmtpPid < 0) 1977229Seric return; 1987229Seric smtpmessage("QUIT"); 1997229Seric (void) reply(); 2007229Seric (void) fclose(SmtpIn); 2017229Seric (void) fclose(SmtpOut); 2027229Seric i = endmailer(SmtpPid, name); 2037229Seric if (showresp) 2047229Seric giveresponse(i, TRUE, LocalMailer); 2054865Seric } 2064865Seric /* 2074684Seric ** REPLY -- read arpanet reply 2084684Seric ** 2094684Seric ** Parameters: 2104796Seric ** none. 2114684Seric ** 2124684Seric ** Returns: 2134684Seric ** reply code it reads. 2144684Seric ** 2154684Seric ** Side Effects: 2164684Seric ** flushes the mail file. 2174684Seric */ 2184684Seric 2194796Seric reply() 2204684Seric { 2214865Seric (void) fflush(SmtpOut); 2224684Seric 2234796Seric if (Debug) 2244796Seric printf("reply\n"); 2254796Seric 226*7356Seric /* 227*7356Seric ** Read the input line, being careful not to hang. 228*7356Seric */ 229*7356Seric 2304684Seric for (;;) 2314684Seric { 2324684Seric char buf[MAXLINE]; 2334684Seric register int r; 234*7356Seric register char *p; 2354684Seric 236*7356Seric /* arrange to time out the read */ 237*7356Seric if (setjmp(TickFrame) != 0) 2384684Seric return (-1); 239*7356Seric (void) alarm(ReadTimeout); 240*7356Seric 241*7356Seric /* actually do the read */ 242*7356Seric p = fgets(buf, sizeof buf, SmtpIn); 243*7356Seric 244*7356Seric /* clean up timeout and check for errors */ 245*7356Seric (void) alarm(0); 246*7356Seric if (p == NULL) 247*7356Seric return (-1); 248*7356Seric 249*7356Seric /* log the input in the transcript for future error returns */ 2507229Seric if (Verbose && !HoldErrs) 2514684Seric fputs(buf, stdout); 2527229Seric fputs(buf, Xscript); 253*7356Seric 254*7356Seric /* if continuation is required, we can go on */ 2554796Seric if (buf[3] == '-' || !isdigit(buf[0])) 2564684Seric continue; 257*7356Seric 258*7356Seric /* decode the reply code */ 2594684Seric r = atoi(buf); 260*7356Seric 261*7356Seric /* extra semantics: 0xx codes are "informational" */ 2624684Seric if (r < 100) 2634684Seric continue; 264*7356Seric 2654684Seric return (r); 2664684Seric } 2674684Seric } 2684796Seric /* 2694865Seric ** SMTPMESSAGE -- send message to server 2704796Seric ** 2714796Seric ** Parameters: 2724796Seric ** f -- format 2734796Seric ** a, b, c -- parameters 2744796Seric ** 2754796Seric ** Returns: 2764796Seric ** none. 2774796Seric ** 2784796Seric ** Side Effects: 2794865Seric ** writes message to SmtpOut. 2804796Seric */ 2814796Seric 2824865Seric /*VARARGS1*/ 2834865Seric smtpmessage(f, a, b, c) 2844796Seric char *f; 2854796Seric { 2864796Seric char buf[100]; 2874796Seric 2884865Seric (void) sprintf(buf, f, a, b, c); 2897229Seric if (Debug || (Verbose && !HoldErrs)) 2907229Seric printf(">>> %s\n", buf); 2917229Seric fprintf(Xscript, ">>> %s\n", buf); 2927229Seric fprintf(SmtpOut, "%s\r\n", buf); 2934796Seric } 2945182Seric 2955182Seric # endif SMTP 296