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*57232Seric static char sccsid[] = "@(#)srvrsmtp.c 5.40 (Berkeley) 12/20/92 (with SMTP)"; 1433731Sbostic #else 15*57232Seric static char sccsid[] = "@(#)srvrsmtp.c 5.40 (Berkeley) 12/20/92 (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]; 101*57232Seric 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 */ 1457685Seric p = sfgets(inp, sizeof inp, InChannel); 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; 171*57232Seric cmd = cmdbuf; 172*57232Seric 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); 24555012Seric setproctitle("%s %s: %s", e->e_id, 24625050Seric CurHostName, inp); 2479339Seric 2489339Seric /* child -- go do the processing */ 2494549Seric p = skipword(p, "from"); 2504549Seric if (p == NULL) 2514549Seric break; 25255012Seric setsender(p, e); 2534577Seric if (Errors == 0) 2544549Seric { 2554549Seric message("250", "Sender ok"); 2564549Seric hasmail = TRUE; 2574549Seric } 2589339Seric else if (InChild) 2599339Seric finis(); 2604549Seric break; 2614549Seric 2624976Seric case CMDRCPT: /* rcpt -- designate recipient */ 26324943Seric SmtpPhase = "RCPT"; 26455012Seric setproctitle("%s %s: %s", e->e_id, 26525050Seric CurHostName, inp); 26612612Seric if (setjmp(TopFrame) > 0) 26714785Seric { 26855012Seric e->e_flags &= ~EF_FATALERRS; 26912612Seric break; 27014785Seric } 27112612Seric QuickAbort = TRUE; 27251951Seric LogUsrErrs = TRUE; 2734549Seric p = skipword(p, "to"); 2744549Seric if (p == NULL) 2754549Seric break; 27655012Seric a = parseaddr(p, (ADDRESS *) NULL, 1, '\0', e); 27712612Seric if (a == NULL) 27812612Seric break; 27916886Seric a->q_flags |= QPRIMARY; 28055012Seric a = recipient(a, &e->e_sendqueue, e); 28112612Seric if (Errors != 0) 28212612Seric break; 28312612Seric 28412612Seric /* no errors during parsing, but might be a duplicate */ 28555012Seric e->e_to = p; 28612612Seric if (!bitset(QBADADDR, a->q_flags)) 28712612Seric message("250", "Recipient ok"); 28812612Seric else 2894549Seric { 29012612Seric /* punt -- should keep message in ADDRESS.... */ 29112612Seric message("550", "Addressee unknown"); 2924549Seric } 29355012Seric e->e_to = NULL; 2944549Seric break; 2954549Seric 2964549Seric case CMDDATA: /* data -- text of mail */ 29724943Seric SmtpPhase = "DATA"; 2984976Seric if (!hasmail) 2994549Seric { 3004976Seric message("503", "Need MAIL command"); 3014976Seric break; 3024549Seric } 30355012Seric else if (e->e_nrcpts <= 0) 3044549Seric { 3054976Seric message("503", "Need RCPT (recipient)"); 3064976Seric break; 3074549Seric } 3084976Seric 3094976Seric /* collect the text of the message */ 31024943Seric SmtpPhase = "collect"; 31155012Seric setproctitle("%s %s: %s", e->e_id, 31225050Seric CurHostName, inp); 31355012Seric collect(TRUE, e); 3144976Seric if (Errors != 0) 3154976Seric break; 3164976Seric 3178238Seric /* 3188238Seric ** Arrange to send to everyone. 3198238Seric ** If sending to multiple people, mail back 3208238Seric ** errors rather than reporting directly. 3218238Seric ** In any case, don't mail back errors for 3228238Seric ** anything that has happened up to 3238238Seric ** now (the other end will do this). 32410197Seric ** Truncate our transcript -- the mail has gotten 32510197Seric ** to us successfully, and if we have 32610197Seric ** to mail this back, it will be easier 32710197Seric ** on the reader. 3288238Seric ** Then send to everyone. 3298238Seric ** Finally give a reply code. If an error has 3308238Seric ** already been given, don't mail a 3318238Seric ** message back. 3329339Seric ** We goose error returns by clearing error bit. 3338238Seric */ 3348238Seric 33524943Seric SmtpPhase = "delivery"; 33655012Seric if (e->e_nrcpts != 1) 3379378Seric { 3389378Seric HoldErrs = TRUE; 33916886Seric ErrorMode = EM_MAIL; 3409378Seric } 34155012Seric e->e_flags &= ~EF_FATALERRS; 34255012Seric e->e_xfp = freopen(queuename(e, 'x'), "w", e->e_xfp); 3434976Seric 3444976Seric /* send to all recipients */ 34555012Seric sendall(e, SM_DEFAULT); 34655012Seric e->e_to = NULL; 3474976Seric 34823516Seric /* save statistics */ 34955012Seric markstats(e, (ADDRESS *) NULL); 35023516Seric 3518238Seric /* issue success if appropriate and reset */ 3528238Seric if (Errors == 0 || HoldErrs) 3539283Seric message("250", "Ok"); 3548238Seric else 35555012Seric e->e_flags &= ~EF_FATALERRS; 3569339Seric 3579339Seric /* if in a child, pop back to our parent */ 3589339Seric if (InChild) 3599339Seric finis(); 36024943Seric 36124943Seric /* clean up a bit */ 36224943Seric hasmail = 0; 36355012Seric dropenvelope(e); 36455012Seric CurEnv = e = newenvelope(e); 36555012Seric e->e_flags = BlankEnvelope.e_flags; 3664549Seric break; 3674549Seric 3684549Seric case CMDRSET: /* rset -- reset state */ 3694549Seric message("250", "Reset state"); 3709339Seric if (InChild) 3719339Seric finis(); 3729339Seric break; 3734549Seric 3744549Seric case CMDVRFY: /* vrfy -- verify address */ 37555012Seric if (runinchild("SMTP-VRFY", e) > 0) 3769339Seric break; 37725050Seric setproctitle("%s: %s", CurHostName, inp); 37855173Seric #ifdef LOG 37955173Seric if (LogLevel >= 9) 38055173Seric syslog(LOG_INFO, "%s: %s", CurHostName, inp); 38155173Seric #endif 3825003Seric vrfyqueue = NULL; 3837762Seric QuickAbort = TRUE; 38455012Seric sendtolist(p, (ADDRESS *) NULL, &vrfyqueue, e); 3857762Seric if (Errors != 0) 3869339Seric { 3879339Seric if (InChild) 3889339Seric finis(); 3897762Seric break; 3909339Seric } 3915003Seric while (vrfyqueue != NULL) 3925003Seric { 3935003Seric register ADDRESS *a = vrfyqueue->q_next; 3945003Seric char *code; 3955003Seric 3967685Seric while (a != NULL && bitset(QDONTSEND|QBADADDR, a->q_flags)) 3975003Seric a = a->q_next; 3985003Seric 3997685Seric if (!bitset(QDONTSEND|QBADADDR, vrfyqueue->q_flags)) 4005003Seric { 4015003Seric if (a != NULL) 4025003Seric code = "250-"; 4035003Seric else 4045003Seric code = "250"; 4055003Seric if (vrfyqueue->q_fullname == NULL) 4065003Seric message(code, "<%s>", vrfyqueue->q_paddr); 4075003Seric else 4085003Seric message(code, "%s <%s>", 4095003Seric vrfyqueue->q_fullname, vrfyqueue->q_paddr); 4105003Seric } 4115003Seric else if (a == NULL) 4125003Seric message("554", "Self destructive alias loop"); 4135003Seric vrfyqueue = a; 4145003Seric } 4159339Seric if (InChild) 4169339Seric finis(); 4174549Seric break; 4184549Seric 4194549Seric case CMDHELP: /* help -- give user info */ 4204577Seric help(p); 4214549Seric break; 4224549Seric 4234549Seric case CMDNOOP: /* noop -- do nothing */ 4244549Seric message("200", "OK"); 4254549Seric break; 4264549Seric 4274549Seric case CMDQUIT: /* quit -- leave mail */ 42825050Seric message("221", "%s closing connection", MyHostName); 4299339Seric if (InChild) 4309339Seric ExitStat = EX_QUIT; 4314549Seric finis(); 4324549Seric 4338544Seric case CMDVERB: /* set verbose mode */ 4348544Seric Verbose = TRUE; 43525025Seric SendMode = SM_DELIVER; 4368544Seric message("200", "Verbose mode"); 4378544Seric break; 4388544Seric 4399314Seric case CMDONEX: /* doing one transaction only */ 4409378Seric OneXact = TRUE; 4419314Seric message("200", "Only one transaction"); 4429314Seric break; 4439314Seric 44436230Skarels # ifdef SMTPDEBUG 4459339Seric case CMDDBGQSHOW: /* show queues */ 4466907Seric printf("Send Queue="); 44755012Seric printaddr(e->e_sendqueue, TRUE); 4485003Seric break; 4497275Seric 4507275Seric case CMDDBGDEBUG: /* set debug mode */ 4517676Seric tTsetup(tTdvect, sizeof tTdvect, "0-99.1"); 4527676Seric tTflag(p); 4537676Seric message("200", "Debug set"); 4547275Seric break; 4557275Seric 45636230Skarels # else /* not SMTPDEBUG */ 45724945Seric 45836230Skarels case CMDDBGQSHOW: /* show queues */ 45936230Skarels case CMDDBGDEBUG: /* set debug mode */ 46036233Skarels # ifdef LOG 46136233Skarels if (RealHostName != NULL && LogLevel > 0) 46236230Skarels syslog(LOG_NOTICE, 46336230Skarels "\"%s\" command from %s (%s)\n", 46436230Skarels c->cmdname, RealHostName, 46536230Skarels inet_ntoa(RealHostAddr.sin_addr)); 46636233Skarels # endif 46736230Skarels /* FALL THROUGH */ 46836230Skarels # endif /* SMTPDEBUG */ 46936230Skarels 4704549Seric case CMDERROR: /* unknown command */ 4714549Seric message("500", "Command unrecognized"); 4724549Seric break; 4734549Seric 4744549Seric default: 47536230Skarels errno = 0; 4764549Seric syserr("smtp: unknown code %d", c->cmdcode); 4774549Seric break; 4784549Seric } 4794549Seric } 4804549Seric } 4814549Seric /* 4824549Seric ** SKIPWORD -- skip a fixed word. 4834549Seric ** 4844549Seric ** Parameters: 4854549Seric ** p -- place to start looking. 4864549Seric ** w -- word to skip. 4874549Seric ** 4884549Seric ** Returns: 4894549Seric ** p following w. 4904549Seric ** NULL on error. 4914549Seric ** 4924549Seric ** Side Effects: 4934549Seric ** clobbers the p data area. 4944549Seric */ 4954549Seric 4964549Seric static char * 4974549Seric skipword(p, w) 4984549Seric register char *p; 4994549Seric char *w; 5004549Seric { 5014549Seric register char *q; 5024549Seric 5034549Seric /* find beginning of word */ 5044549Seric while (isspace(*p)) 5054549Seric p++; 5064549Seric q = p; 5074549Seric 5084549Seric /* find end of word */ 5094549Seric while (*p != '\0' && *p != ':' && !isspace(*p)) 5104549Seric p++; 5114549Seric while (isspace(*p)) 5124549Seric *p++ = '\0'; 5134549Seric if (*p != ':') 5144549Seric { 5154549Seric syntax: 5164549Seric message("501", "Syntax error"); 5174549Seric Errors++; 5184549Seric return (NULL); 5194549Seric } 5204549Seric *p++ = '\0'; 5214549Seric while (isspace(*p)) 5224549Seric p++; 5234549Seric 5244549Seric /* see if the input word matches desired word */ 52533725Sbostic if (strcasecmp(q, w)) 5264549Seric goto syntax; 5274549Seric 5284549Seric return (p); 5294549Seric } 5304577Seric /* 5314577Seric ** HELP -- implement the HELP command. 5324577Seric ** 5334577Seric ** Parameters: 5344577Seric ** topic -- the topic we want help for. 5354577Seric ** 5364577Seric ** Returns: 5374577Seric ** none. 5384577Seric ** 5394577Seric ** Side Effects: 5404577Seric ** outputs the help file to message output. 5414577Seric */ 5424577Seric 5434577Seric help(topic) 5444577Seric char *topic; 5454577Seric { 5464577Seric register FILE *hf; 5474577Seric int len; 5484577Seric char buf[MAXLINE]; 5494577Seric bool noinfo; 5504577Seric 5518269Seric if (HelpFile == NULL || (hf = fopen(HelpFile, "r")) == NULL) 5524577Seric { 5534577Seric /* no help */ 55411931Seric errno = 0; 5554577Seric message("502", "HELP not implemented"); 5564577Seric return; 5574577Seric } 5584577Seric 55949669Seric if (topic == NULL || *topic == '\0') 56049669Seric topic = "smtp"; 56149669Seric else 56249669Seric makelower(topic); 56349669Seric 5644577Seric len = strlen(topic); 5654577Seric noinfo = TRUE; 5664577Seric 5674577Seric while (fgets(buf, sizeof buf, hf) != NULL) 5684577Seric { 5694577Seric if (strncmp(buf, topic, len) == 0) 5704577Seric { 5714577Seric register char *p; 5724577Seric 57356795Seric p = strchr(buf, '\t'); 5744577Seric if (p == NULL) 5754577Seric p = buf; 5764577Seric else 5774577Seric p++; 5784577Seric fixcrlf(p, TRUE); 5794577Seric message("214-", p); 5804577Seric noinfo = FALSE; 5814577Seric } 5824577Seric } 5834577Seric 5844577Seric if (noinfo) 5854577Seric message("504", "HELP topic unknown"); 5864577Seric else 5874577Seric message("214", "End of HELP info"); 5884628Seric (void) fclose(hf); 5894577Seric } 5908544Seric /* 5919339Seric ** RUNINCHILD -- return twice -- once in the child, then in the parent again 5929339Seric ** 5939339Seric ** Parameters: 5949339Seric ** label -- a string used in error messages 5959339Seric ** 5969339Seric ** Returns: 5979339Seric ** zero in the child 5989339Seric ** one in the parent 5999339Seric ** 6009339Seric ** Side Effects: 6019339Seric ** none. 6029339Seric */ 6038544Seric 60455012Seric runinchild(label, e) 6059339Seric char *label; 60655012Seric register ENVELOPE *e; 6079339Seric { 6089339Seric int childpid; 6099339Seric 61016158Seric if (!OneXact) 6119339Seric { 61216158Seric childpid = dofork(); 61316158Seric if (childpid < 0) 61416158Seric { 61516158Seric syserr("%s: cannot fork", label); 61616158Seric return (1); 61716158Seric } 61816158Seric if (childpid > 0) 61916158Seric { 62016158Seric auto int st; 6219339Seric 62216158Seric /* parent -- wait for child to complete */ 62316158Seric st = waitfor(childpid); 62416158Seric if (st == -1) 62516158Seric syserr("%s: lost child", label); 6269339Seric 62716158Seric /* if we exited on a QUIT command, complete the process */ 62816158Seric if (st == (EX_QUIT << 8)) 62916158Seric finis(); 6309339Seric 63116158Seric return (1); 63216158Seric } 63316158Seric else 63416158Seric { 63516158Seric /* child */ 63616158Seric InChild = TRUE; 63725050Seric QuickAbort = FALSE; 63855012Seric clearenvelope(e, FALSE); 63916158Seric } 6409339Seric } 64115256Seric 64216158Seric /* open alias database */ 64355012Seric initaliases(AliasFile, FALSE, e); 64416158Seric 64516158Seric return (0); 6469339Seric } 6479339Seric 64856795Seric # endif /* SMTP */ 649