122712Sdist /* 234921Sbostic * Copyright (c) 1983 Eric P. Allman 333731Sbostic * Copyright (c) 1988 Regents of the University of California. 433731Sbostic * All rights reserved. 533731Sbostic * 642829Sbostic * %sccs.include.redist.c% 733731Sbostic */ 822712Sdist 933731Sbostic # include "sendmail.h" 1022712Sdist 1133731Sbostic #ifndef lint 1233731Sbostic #ifdef SMTP 13*57389Seric static char sccsid[] = "@(#)srvrsmtp.c 6.2 (Berkeley) 01/01/93 (with SMTP)"; 1433731Sbostic #else 15*57389Seric static char sccsid[] = "@(#)srvrsmtp.c 6.2 (Berkeley) 01/01/93 (without SMTP)"; 1633731Sbostic #endif 1733731Sbostic #endif /* not lint */ 1833731Sbostic 199339Seric # include <errno.h> 2011728Seric # include <signal.h> 214549Seric 2233731Sbostic # ifdef SMTP 234556Seric 244549Seric /* 254549Seric ** SMTP -- run the SMTP protocol. 264549Seric ** 274549Seric ** Parameters: 284549Seric ** none. 294549Seric ** 304549Seric ** Returns: 314549Seric ** never. 324549Seric ** 334549Seric ** Side Effects: 344549Seric ** Reads commands from the input channel and processes 354549Seric ** them. 364549Seric */ 374549Seric 384549Seric struct cmd 394549Seric { 404549Seric char *cmdname; /* command name */ 414549Seric int cmdcode; /* internal code, see below */ 424549Seric }; 434549Seric 444549Seric /* values for cmdcode */ 454549Seric # define CMDERROR 0 /* bad command */ 464549Seric # define CMDMAIL 1 /* mail -- designate sender */ 474976Seric # define CMDRCPT 2 /* rcpt -- designate recipient */ 484549Seric # define CMDDATA 3 /* data -- send message text */ 499339Seric # define CMDRSET 4 /* rset -- reset state */ 509339Seric # define CMDVRFY 5 /* vrfy -- verify address */ 519339Seric # define CMDHELP 6 /* help -- give usage info */ 529339Seric # define CMDNOOP 7 /* noop -- do nothing */ 539339Seric # define CMDQUIT 8 /* quit -- close connection and die */ 549339Seric # define CMDHELO 9 /* helo -- be polite */ 5536230Skarels # define CMDONEX 10 /* onex -- sending one transaction only */ 5636230Skarels # define CMDVERB 11 /* verb -- go into verbose mode */ 5736230Skarels /* debugging-only commands, only enabled if SMTPDEBUG is defined */ 5836230Skarels # define CMDDBGQSHOW 12 /* showq -- show send queue */ 5936230Skarels # define CMDDBGDEBUG 13 /* debug -- set debug mode */ 604549Seric 614549Seric static struct cmd CmdTab[] = 624549Seric { 634549Seric "mail", CMDMAIL, 644976Seric "rcpt", CMDRCPT, 654549Seric "data", CMDDATA, 664549Seric "rset", CMDRSET, 674549Seric "vrfy", CMDVRFY, 687762Seric "expn", CMDVRFY, 694549Seric "help", CMDHELP, 704549Seric "noop", CMDNOOP, 714549Seric "quit", CMDQUIT, 724976Seric "helo", CMDHELO, 738544Seric "verb", CMDVERB, 749314Seric "onex", CMDONEX, 7536230Skarels /* 7636230Skarels * remaining commands are here only 7736230Skarels * to trap and log attempts to use them 7836230Skarels */ 799339Seric "showq", CMDDBGQSHOW, 808544Seric "debug", CMDDBGDEBUG, 814549Seric NULL, CMDERROR, 824549Seric }; 834549Seric 849339Seric bool InChild = FALSE; /* true if running in a subprocess */ 859378Seric bool OneXact = FALSE; /* one xaction only this run */ 8611146Seric 879339Seric #define EX_QUIT 22 /* special code for QUIT command */ 888544Seric 8955012Seric smtp(e) 9055012Seric register ENVELOPE *e; 914549Seric { 924549Seric register char *p; 938544Seric register struct cmd *c; 944549Seric char *cmd; 9546928Sbostic static char *skipword(); 964549Seric bool hasmail; /* mail command received */ 975003Seric auto ADDRESS *vrfyqueue; 9812612Seric ADDRESS *a; 9930448Seric char *sendinghost; 1008544Seric char inp[MAXLINE]; 10157232Seric char cmdbuf[MAXLINE]; 1027124Seric extern char Version[]; 10311151Seric extern char *macvalue(); 10412612Seric extern ADDRESS *recipient(); 10524943Seric extern ENVELOPE BlankEnvelope; 10624943Seric extern ENVELOPE *newenvelope(); 1074549Seric 1085003Seric hasmail = FALSE; 1097363Seric if (OutChannel != stdout) 1107363Seric { 1117363Seric /* arrange for debugging output to go to remote host */ 1127363Seric (void) close(1); 1137363Seric (void) dup(fileno(OutChannel)); 1147363Seric } 11555012Seric settime(e); 11624971Seric if (RealHostName != NULL) 11725050Seric { 11825050Seric CurHostName = RealHostName; 11925050Seric setproctitle("srvrsmtp %s", CurHostName); 12025050Seric } 12125050Seric else 12225050Seric { 12325050Seric /* this must be us!! */ 12425050Seric CurHostName = MyHostName; 12525050Seric } 12655012Seric expand("\001e", inp, &inp[sizeof inp], e); 12755360Seric message("220", "%s", inp); 12824943Seric SmtpPhase = "startup"; 12930448Seric sendinghost = NULL; 1304549Seric for (;;) 1314549Seric { 13212612Seric /* arrange for backout */ 13312612Seric if (setjmp(TopFrame) > 0 && InChild) 13412612Seric finis(); 13512612Seric QuickAbort = FALSE; 13612612Seric HoldErrs = FALSE; 13751951Seric LogUsrErrs = FALSE; 13812612Seric 1397356Seric /* setup for the read */ 14055012Seric e->e_to = NULL; 1414577Seric Errors = 0; 1427275Seric (void) fflush(stdout); 1437356Seric 1447356Seric /* read the input line */ 145*57389Seric p = sfgets(inp, sizeof inp, InChannel, ReadTimeout); 1467356Seric 1477685Seric /* handle errors */ 1487356Seric if (p == NULL) 1497356Seric { 1504549Seric /* end of file, just die */ 15136230Skarels message("421", "%s Lost input channel from %s", 15225050Seric MyHostName, CurHostName); 15355464Seric #ifdef LOG 15455464Seric if (LogLevel >= 4) 15555464Seric syslog(LOG_NOTICE, "lost input channel from %s", 15655464Seric CurHostName); 15755464Seric #endif 1584549Seric finis(); 1594549Seric } 1604549Seric 1614549Seric /* clean up end of line */ 1624558Seric fixcrlf(inp, TRUE); 1634549Seric 1644713Seric /* echo command to transcript */ 16555012Seric if (e->e_xfp != NULL) 16655012Seric fprintf(e->e_xfp, "<<< %s\n", inp); 1674713Seric 1684549Seric /* break off command */ 1694549Seric for (p = inp; isspace(*p); p++) 1704549Seric continue; 17157232Seric cmd = cmdbuf; 17257232Seric while (*p != '\0' && !isspace(*p) && cmd < &cmdbuf[sizeof cmdbuf - 2]) 17324981Seric *cmd++ = *p++; 17424981Seric *cmd = '\0'; 1754549Seric 17625691Seric /* throw away leading whitespace */ 17725691Seric while (isspace(*p)) 17825691Seric p++; 17925691Seric 1804549Seric /* decode command */ 1814549Seric for (c = CmdTab; c->cmdname != NULL; c++) 1824549Seric { 18333725Sbostic if (!strcasecmp(c->cmdname, cmdbuf)) 1844549Seric break; 1854549Seric } 1864549Seric 18751954Seric /* reset errors */ 18851954Seric errno = 0; 18951954Seric 1904549Seric /* process command */ 1914549Seric switch (c->cmdcode) 1924549Seric { 1934976Seric case CMDHELO: /* hello -- introduce yourself */ 19424943Seric SmtpPhase = "HELO"; 19525050Seric setproctitle("%s: %s", CurHostName, inp); 19633725Sbostic if (!strcasecmp(p, MyHostName)) 19714877Seric { 19836230Skarels /* 19936230Skarels * didn't know about alias, 20036230Skarels * or connected to an echo server 20136230Skarels */ 20247570Seric message("553", "%s config error: mail loops back to myself", 20347570Seric MyHostName); 20414877Seric break; 20514877Seric } 20633725Sbostic if (RealHostName != NULL && strcasecmp(p, RealHostName)) 20711146Seric { 20824981Seric char hostbuf[MAXNAME]; 20911146Seric 21024981Seric (void) sprintf(hostbuf, "%s (%s)", p, RealHostName); 21130448Seric sendinghost = newstr(hostbuf); 21211146Seric } 21311146Seric else 21430448Seric sendinghost = newstr(p); 2154997Seric message("250", "%s Hello %s, pleased to meet you", 21636230Skarels MyHostName, sendinghost); 2174976Seric break; 2184976Seric 2194549Seric case CMDMAIL: /* mail -- designate sender */ 22024943Seric SmtpPhase = "MAIL"; 22124943Seric 22211151Seric /* force a sending host even if no HELO given */ 22355012Seric if (RealHostName != NULL && macvalue('s', e) == NULL) 22430448Seric sendinghost = RealHostName; 22511151Seric 2269314Seric /* check for validity of this command */ 2274558Seric if (hasmail) 2284558Seric { 2294558Seric message("503", "Sender already specified"); 2304558Seric break; 2314558Seric } 2329339Seric if (InChild) 2339339Seric { 23436230Skarels errno = 0; 2359339Seric syserr("Nested MAIL command"); 2369339Seric exit(0); 2379339Seric } 2389339Seric 2399339Seric /* fork a subprocess to process this command */ 24055012Seric if (runinchild("SMTP-MAIL", e) > 0) 2419339Seric break; 24255012Seric define('s', sendinghost, e); 24355012Seric define('r', "SMTP", e); 24455012Seric initsys(e); 245*57389Seric setproctitle("%s %s: %s", e->e_id, CurHostName, inp); 2469339Seric 2479339Seric /* child -- go do the processing */ 2484549Seric p = skipword(p, "from"); 2494549Seric if (p == NULL) 2504549Seric break; 25155012Seric setsender(p, e); 2524577Seric if (Errors == 0) 2534549Seric { 2544549Seric message("250", "Sender ok"); 2554549Seric hasmail = TRUE; 2564549Seric } 2579339Seric else if (InChild) 2589339Seric finis(); 2594549Seric break; 2604549Seric 2614976Seric case CMDRCPT: /* rcpt -- designate recipient */ 26224943Seric SmtpPhase = "RCPT"; 263*57389Seric setproctitle("%s %s: %s", e->e_id, CurHostName, inp); 26412612Seric if (setjmp(TopFrame) > 0) 26514785Seric { 26655012Seric e->e_flags &= ~EF_FATALERRS; 26712612Seric break; 26814785Seric } 26912612Seric QuickAbort = TRUE; 27051951Seric LogUsrErrs = TRUE; 2714549Seric p = skipword(p, "to"); 2724549Seric if (p == NULL) 2734549Seric break; 27455012Seric a = parseaddr(p, (ADDRESS *) NULL, 1, '\0', e); 27512612Seric if (a == NULL) 27612612Seric break; 27716886Seric a->q_flags |= QPRIMARY; 27855012Seric a = recipient(a, &e->e_sendqueue, e); 27912612Seric if (Errors != 0) 28012612Seric break; 28112612Seric 28212612Seric /* no errors during parsing, but might be a duplicate */ 28355012Seric e->e_to = p; 28412612Seric if (!bitset(QBADADDR, a->q_flags)) 28512612Seric message("250", "Recipient ok"); 28612612Seric else 2874549Seric { 28812612Seric /* punt -- should keep message in ADDRESS.... */ 28912612Seric message("550", "Addressee unknown"); 2904549Seric } 29155012Seric e->e_to = NULL; 2924549Seric break; 2934549Seric 2944549Seric case CMDDATA: /* data -- text of mail */ 29524943Seric SmtpPhase = "DATA"; 2964976Seric if (!hasmail) 2974549Seric { 2984976Seric message("503", "Need MAIL command"); 2994976Seric break; 3004549Seric } 30155012Seric else if (e->e_nrcpts <= 0) 3024549Seric { 3034976Seric message("503", "Need RCPT (recipient)"); 3044976Seric break; 3054549Seric } 3064976Seric 3074976Seric /* collect the text of the message */ 30824943Seric SmtpPhase = "collect"; 309*57389Seric setproctitle("%s %s: %s", e->e_id, CurHostName, inp); 31055012Seric collect(TRUE, e); 3114976Seric if (Errors != 0) 3124976Seric break; 3134976Seric 3148238Seric /* 3158238Seric ** Arrange to send to everyone. 3168238Seric ** If sending to multiple people, mail back 3178238Seric ** errors rather than reporting directly. 3188238Seric ** In any case, don't mail back errors for 3198238Seric ** anything that has happened up to 3208238Seric ** now (the other end will do this). 32110197Seric ** Truncate our transcript -- the mail has gotten 32210197Seric ** to us successfully, and if we have 32310197Seric ** to mail this back, it will be easier 32410197Seric ** on the reader. 3258238Seric ** Then send to everyone. 3268238Seric ** Finally give a reply code. If an error has 3278238Seric ** already been given, don't mail a 3288238Seric ** message back. 3299339Seric ** We goose error returns by clearing error bit. 3308238Seric */ 3318238Seric 33224943Seric SmtpPhase = "delivery"; 33355012Seric if (e->e_nrcpts != 1) 3349378Seric { 3359378Seric HoldErrs = TRUE; 33616886Seric ErrorMode = EM_MAIL; 3379378Seric } 33855012Seric e->e_flags &= ~EF_FATALERRS; 33955012Seric e->e_xfp = freopen(queuename(e, 'x'), "w", e->e_xfp); 3404976Seric 3414976Seric /* send to all recipients */ 34255012Seric sendall(e, SM_DEFAULT); 34355012Seric e->e_to = NULL; 3444976Seric 34523516Seric /* save statistics */ 34655012Seric markstats(e, (ADDRESS *) NULL); 34723516Seric 3488238Seric /* issue success if appropriate and reset */ 3498238Seric if (Errors == 0 || HoldErrs) 3509283Seric message("250", "Ok"); 3518238Seric else 35255012Seric e->e_flags &= ~EF_FATALERRS; 3539339Seric 3549339Seric /* if in a child, pop back to our parent */ 3559339Seric if (InChild) 3569339Seric finis(); 35724943Seric 35824943Seric /* clean up a bit */ 35924943Seric hasmail = 0; 36055012Seric dropenvelope(e); 36155012Seric CurEnv = e = newenvelope(e); 36255012Seric e->e_flags = BlankEnvelope.e_flags; 3634549Seric break; 3644549Seric 3654549Seric case CMDRSET: /* rset -- reset state */ 3664549Seric message("250", "Reset state"); 3679339Seric if (InChild) 3689339Seric finis(); 3699339Seric break; 3704549Seric 3714549Seric case CMDVRFY: /* vrfy -- verify address */ 37255012Seric if (runinchild("SMTP-VRFY", e) > 0) 3739339Seric break; 37425050Seric setproctitle("%s: %s", CurHostName, inp); 37555173Seric #ifdef LOG 37655173Seric if (LogLevel >= 9) 37755173Seric syslog(LOG_INFO, "%s: %s", CurHostName, inp); 37855173Seric #endif 3795003Seric vrfyqueue = NULL; 3807762Seric QuickAbort = TRUE; 38155012Seric sendtolist(p, (ADDRESS *) NULL, &vrfyqueue, e); 3827762Seric if (Errors != 0) 3839339Seric { 3849339Seric if (InChild) 3859339Seric finis(); 3867762Seric break; 3879339Seric } 3885003Seric while (vrfyqueue != NULL) 3895003Seric { 3905003Seric register ADDRESS *a = vrfyqueue->q_next; 3915003Seric char *code; 3925003Seric 3937685Seric while (a != NULL && bitset(QDONTSEND|QBADADDR, a->q_flags)) 3945003Seric a = a->q_next; 3955003Seric 3967685Seric if (!bitset(QDONTSEND|QBADADDR, vrfyqueue->q_flags)) 3975003Seric { 3985003Seric if (a != NULL) 3995003Seric code = "250-"; 4005003Seric else 4015003Seric code = "250"; 4025003Seric if (vrfyqueue->q_fullname == NULL) 4035003Seric message(code, "<%s>", vrfyqueue->q_paddr); 4045003Seric else 4055003Seric message(code, "%s <%s>", 4065003Seric vrfyqueue->q_fullname, vrfyqueue->q_paddr); 4075003Seric } 4085003Seric else if (a == NULL) 4095003Seric message("554", "Self destructive alias loop"); 4105003Seric vrfyqueue = a; 4115003Seric } 4129339Seric if (InChild) 4139339Seric finis(); 4144549Seric break; 4154549Seric 4164549Seric case CMDHELP: /* help -- give user info */ 4174577Seric help(p); 4184549Seric break; 4194549Seric 4204549Seric case CMDNOOP: /* noop -- do nothing */ 4214549Seric message("200", "OK"); 4224549Seric break; 4234549Seric 4244549Seric case CMDQUIT: /* quit -- leave mail */ 42525050Seric message("221", "%s closing connection", MyHostName); 4269339Seric if (InChild) 4279339Seric ExitStat = EX_QUIT; 4284549Seric finis(); 4294549Seric 4308544Seric case CMDVERB: /* set verbose mode */ 4318544Seric Verbose = TRUE; 43225025Seric SendMode = SM_DELIVER; 4338544Seric message("200", "Verbose mode"); 4348544Seric break; 4358544Seric 4369314Seric case CMDONEX: /* doing one transaction only */ 4379378Seric OneXact = TRUE; 4389314Seric message("200", "Only one transaction"); 4399314Seric break; 4409314Seric 44136230Skarels # ifdef SMTPDEBUG 4429339Seric case CMDDBGQSHOW: /* show queues */ 4436907Seric printf("Send Queue="); 44455012Seric printaddr(e->e_sendqueue, TRUE); 4455003Seric break; 4467275Seric 4477275Seric case CMDDBGDEBUG: /* set debug mode */ 4487676Seric tTsetup(tTdvect, sizeof tTdvect, "0-99.1"); 4497676Seric tTflag(p); 4507676Seric message("200", "Debug set"); 4517275Seric break; 4527275Seric 45336230Skarels # else /* not SMTPDEBUG */ 45424945Seric 45536230Skarels case CMDDBGQSHOW: /* show queues */ 45636230Skarels case CMDDBGDEBUG: /* set debug mode */ 45736233Skarels # ifdef LOG 45836233Skarels if (RealHostName != NULL && LogLevel > 0) 45936230Skarels syslog(LOG_NOTICE, 46036230Skarels "\"%s\" command from %s (%s)\n", 46136230Skarels c->cmdname, RealHostName, 46236230Skarels inet_ntoa(RealHostAddr.sin_addr)); 46336233Skarels # endif 46436230Skarels /* FALL THROUGH */ 46536230Skarels # endif /* SMTPDEBUG */ 46636230Skarels 4674549Seric case CMDERROR: /* unknown command */ 4684549Seric message("500", "Command unrecognized"); 4694549Seric break; 4704549Seric 4714549Seric default: 47236230Skarels errno = 0; 4734549Seric syserr("smtp: unknown code %d", c->cmdcode); 4744549Seric break; 4754549Seric } 4764549Seric } 4774549Seric } 4784549Seric /* 4794549Seric ** SKIPWORD -- skip a fixed word. 4804549Seric ** 4814549Seric ** Parameters: 4824549Seric ** p -- place to start looking. 4834549Seric ** w -- word to skip. 4844549Seric ** 4854549Seric ** Returns: 4864549Seric ** p following w. 4874549Seric ** NULL on error. 4884549Seric ** 4894549Seric ** Side Effects: 4904549Seric ** clobbers the p data area. 4914549Seric */ 4924549Seric 4934549Seric static char * 4944549Seric skipword(p, w) 4954549Seric register char *p; 4964549Seric char *w; 4974549Seric { 4984549Seric register char *q; 4994549Seric 5004549Seric /* find beginning of word */ 5014549Seric while (isspace(*p)) 5024549Seric p++; 5034549Seric q = p; 5044549Seric 5054549Seric /* find end of word */ 5064549Seric while (*p != '\0' && *p != ':' && !isspace(*p)) 5074549Seric p++; 5084549Seric while (isspace(*p)) 5094549Seric *p++ = '\0'; 5104549Seric if (*p != ':') 5114549Seric { 5124549Seric syntax: 5134549Seric message("501", "Syntax error"); 5144549Seric Errors++; 5154549Seric return (NULL); 5164549Seric } 5174549Seric *p++ = '\0'; 5184549Seric while (isspace(*p)) 5194549Seric p++; 5204549Seric 5214549Seric /* see if the input word matches desired word */ 52233725Sbostic if (strcasecmp(q, w)) 5234549Seric goto syntax; 5244549Seric 5254549Seric return (p); 5264549Seric } 5274577Seric /* 5284577Seric ** HELP -- implement the HELP command. 5294577Seric ** 5304577Seric ** Parameters: 5314577Seric ** topic -- the topic we want help for. 5324577Seric ** 5334577Seric ** Returns: 5344577Seric ** none. 5354577Seric ** 5364577Seric ** Side Effects: 5374577Seric ** outputs the help file to message output. 5384577Seric */ 5394577Seric 5404577Seric help(topic) 5414577Seric char *topic; 5424577Seric { 5434577Seric register FILE *hf; 5444577Seric int len; 5454577Seric char buf[MAXLINE]; 5464577Seric bool noinfo; 5474577Seric 5488269Seric if (HelpFile == NULL || (hf = fopen(HelpFile, "r")) == NULL) 5494577Seric { 5504577Seric /* no help */ 55111931Seric errno = 0; 5524577Seric message("502", "HELP not implemented"); 5534577Seric return; 5544577Seric } 5554577Seric 55649669Seric if (topic == NULL || *topic == '\0') 55749669Seric topic = "smtp"; 55849669Seric else 55949669Seric makelower(topic); 56049669Seric 5614577Seric len = strlen(topic); 5624577Seric noinfo = TRUE; 5634577Seric 5644577Seric while (fgets(buf, sizeof buf, hf) != NULL) 5654577Seric { 5664577Seric if (strncmp(buf, topic, len) == 0) 5674577Seric { 5684577Seric register char *p; 5694577Seric 57056795Seric p = strchr(buf, '\t'); 5714577Seric if (p == NULL) 5724577Seric p = buf; 5734577Seric else 5744577Seric p++; 5754577Seric fixcrlf(p, TRUE); 5764577Seric message("214-", p); 5774577Seric noinfo = FALSE; 5784577Seric } 5794577Seric } 5804577Seric 5814577Seric if (noinfo) 5824577Seric message("504", "HELP topic unknown"); 5834577Seric else 5844577Seric message("214", "End of HELP info"); 5854628Seric (void) fclose(hf); 5864577Seric } 5878544Seric /* 5889339Seric ** RUNINCHILD -- return twice -- once in the child, then in the parent again 5899339Seric ** 5909339Seric ** Parameters: 5919339Seric ** label -- a string used in error messages 5929339Seric ** 5939339Seric ** Returns: 5949339Seric ** zero in the child 5959339Seric ** one in the parent 5969339Seric ** 5979339Seric ** Side Effects: 5989339Seric ** none. 5999339Seric */ 6008544Seric 60155012Seric runinchild(label, e) 6029339Seric char *label; 60355012Seric register ENVELOPE *e; 6049339Seric { 6059339Seric int childpid; 6069339Seric 60716158Seric if (!OneXact) 6089339Seric { 60916158Seric childpid = dofork(); 61016158Seric if (childpid < 0) 61116158Seric { 61216158Seric syserr("%s: cannot fork", label); 61316158Seric return (1); 61416158Seric } 61516158Seric if (childpid > 0) 61616158Seric { 61716158Seric auto int st; 6189339Seric 61916158Seric /* parent -- wait for child to complete */ 62016158Seric st = waitfor(childpid); 62116158Seric if (st == -1) 62216158Seric syserr("%s: lost child", label); 6239339Seric 62416158Seric /* if we exited on a QUIT command, complete the process */ 62516158Seric if (st == (EX_QUIT << 8)) 62616158Seric finis(); 6279339Seric 62816158Seric return (1); 62916158Seric } 63016158Seric else 63116158Seric { 63216158Seric /* child */ 63316158Seric InChild = TRUE; 63425050Seric QuickAbort = FALSE; 63555012Seric clearenvelope(e, FALSE); 63616158Seric } 6379339Seric } 63815256Seric 63916158Seric /* open alias database */ 64055012Seric initaliases(AliasFile, FALSE, e); 64116158Seric 64216158Seric return (0); 6439339Seric } 6449339Seric 64556795Seric # endif /* SMTP */ 646