From: Jean-Marc Pigeon (Delson) Date: Sat, 14 Jun 2025 13:56:09 +0000 (-0400) Subject: Starting to implement procedure end_to_mx X-Git-Tag: tag-0.9~181 X-Git-Url: https://jmp-git.ovh.safe.ca/?a=commitdiff_plain;h=9c615eb66837041d08e5b2d7ec998ab8c96fbc0a;p=jmp%2Fmailleur Starting to implement procedure end_to_mx --- diff --git a/lib/lvleml.c b/lib/lvleml.c index ff46ec7..1f960dc 100644 --- a/lib/lvleml.c +++ b/lib/lvleml.c @@ -898,7 +898,7 @@ return done; /* Procedure to connect to the remote SMTP server */ /* */ /********************************************************/ -static _Bool connect_to_mx(RMTTYP *rmt) +static _Bool connect_mx(RMTTYP *rmt) { #define OPEP "lvleml.c:connect_to_mx," @@ -976,6 +976,47 @@ return done; */ /********************************************************/ /* */ +/* Procedure to reset the remote session */ +/* */ +/********************************************************/ +static _Bool reset_mx(RMTTYP *rmt) + +{ +_Bool ok; +int phase; +_Bool proceed; + +ok=false; +phase=0; +proceed=true; +while (proceed==true) { + switch (phase) { + break; + default : //SAFE Guard + proceed=false; + break; + } + phase++; + } +return ok; +} +/* +^L +*/ +/********************************************************/ +/* */ +/* Procedure to close the remote connection with MX*/ +/* */ +/********************************************************/ +static void close_mx(RMTTYP *rmt) + +{ +} +/* +^L +*/ +/********************************************************/ +/* */ /* Procedure to send the data to the remote server */ /* */ /********************************************************/ @@ -1073,6 +1114,40 @@ while (proceed==true) { */ /********************************************************/ /* */ +/* Procedure to send one email session to intended */ +/* recipient. */ +/* */ +/********************************************************/ +static TRATYP **send_to_mx(RMTTYP *rmt,TRATYP **list) + +{ +TRATYP **tosend; +char *sessid; +int phase; +_Bool proceed; + +tosend=(TRATYP **)0; +sessid=(char *)0; +phase=0; +proceed=true; +while (proceed==true) { + switch (phase) { + case 3 : //sending data + (void) senddata(rmt,tosend,sessid); + break; + default : //SAFE Guard + proceed=false; + break; + } + phase++; + } +return list; +} +/* +^L +*/ +/********************************************************/ +/* */ /* Procedure to send the whole email transaction */ /* */ /********************************************************/ @@ -1083,7 +1158,6 @@ static void sending_email(char *orgdomain,char *dstdomain,char *sessid,TRATYP ** time_t isnow; RMTTYP rmt; -int tobesend; TRATYP **tosend; int phase; _Bool proceed; @@ -1094,7 +1168,6 @@ rmt.mxs=dns_getmx(dstdomain); rmt.dstdomain=dstdomain; rmt.orgdomain=orgdomain; tosend=(TRATYP **)0; -tobesend=0; phase=0; proceed=true; while (proceed==true) { @@ -1140,7 +1213,7 @@ while (proceed==true) { break; } case 4 : //Opening connection if not open - if (connect_to_mx(&rmt)==false) { + if (connect_mx(&rmt)==false) { char cmt[100]; (void) snprintf(cmt,sizeof(cmt),"Unable to contact ANY MX for domain <%s>", @@ -1179,47 +1252,28 @@ while (proceed==true) { break; } case 6 : { //sending recipient list - int rspcode; TRATYP **dest; - tobesend=0; dest=tosend; while (*dest!=(TRATYP *)0) { - char ***resp; - - (void) eml_freetra_resp(*dest); - resp=&((*dest)->resp); - rspcode=tcp_smtp_command(&rmt,resp,"RCPT TO: <%s>",(*dest)->rcptto); - switch (rspcode) { - case CMDOK : //originator accepted - tobesend++; - (*dest)->sendcode=rspcode; - break; - case UKNUSER : //recipient is unknown - case NORELAY : //email no relayed - (*dest)->code='W'; //Need to send a Warning - (*dest)->sendcode=rspcode; - break; - default : //Not accepted recipient - (void) rou_alert(0,"%s sessid=<%s>, unknwon code='%d'", - OPEP,sessid,rspcode); - (*dest)->code='C'; //completed (Temporary JMPDBG); - (*dest)->sendcode=BADPAR; - break; - } - dest++; + dest=send_to_mx(&rmt,dest); + if (*dest==(TRATYP *)0) + break; //no more to send; + if (reset_mx(&rmt)==false) { + break; //can not send more + } } - if (tobesend>=0) - (void) senddata(&rmt,tosend,sessid); break; } + case 7 : //closing current connection with MX + (void) close_mx(&rmt); + break; case 8 : //cleaning recipient list (void) free(tosend); tosend=(TRATYP **)0; phase=0; //Lets see if we have other recipient break; default : //SAFE Guard - rmt.logptr=log_closelog(rmt.logptr); proceed=false; break; } diff --git a/lib/xx.c b/lib/xx.c new file mode 100644 index 0000000..ff46ec7 --- /dev/null +++ b/lib/xx.c @@ -0,0 +1,1685 @@ +// vim: smarttab tabstop=8 shiftwidth=2 expandtab +/********************************************************/ +/* */ +/* Implement all routine to manage SMTP low level */ +/* exchange. */ +/* */ +/********************************************************/ +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "subrou.h" +#include "unieml.h" +#include "devlog.h" +#include "gestcp.h" +#include "geseml.h" +#include "lvleml.h" + +/* +^L +*/ +/********************************************************/ +/* */ +/* Procedure to free memory used by contact */ +/* */ +/********************************************************/ +static CONTYP *freecontact(CONTYP *contact) + +{ +#define OPEP "lvleml.c:freecontact" + +if (contact!=(CONTYP *)0) { + contact->sqlptr=sql_closesql(contact->sqlptr); + contact->logptr=log_closelog(contact->logptr); + contact->recipients=(RCPTYP **)rou_freelist((void **)contact->recipients, + (genfree_t)eml_freerecipient); + contact->mailfrom=rou_freestr(contact->mailfrom); + contact->cursesid=rou_freestr(contact->cursesid); + contact->mainsesid=rou_freestr(contact->mainsesid); + contact->fqdn=rou_freestr(contact->fqdn); + contact->peername=rou_freestr(contact->peername); + contact->peerip=rou_freestr(contact->peerip); + contact->locserv=rou_freestr(contact->locserv); + contact->locip=rou_freestr(contact->locip); + contact->locname=rou_freestr(contact->locname); + (void) free(contact); + contact=(CONTYP *)0; + } +return contact; +#undef OPEP +} +/* +^L +*/ +/********************************************************/ +/* */ +/* Procedure to get the domain code */ +/* */ +/********************************************************/ +static _Bool setlocdom(CONTYP *contact,RCPTYP *rcpt) + +{ +#define OPEP "lvleml.c:setlocdom," + +char done; +int phase; +_Bool proceed; + +done=true; +phase=0; +proceed=true; +while (proceed==true) { + //(void) rou_alert(0,"JMPDBG %s phase='%d' parm=<%s>",OPEP,phase,parameter); + switch (phase) { + case 0 : //is RCPT ok; + if ((rcpt==(RCPTYP *)0)||(rcpt->domain==(char *)0)) { + (void) rou_alert(0,"%s Recipient is NULL (Bug!?)",OPEP); + done=false; + phase=999; + } + break; + case 1 : //check about local domain, TEMPORARY code + int status; + + status=dns_is_domain_local(rcpt->domain,tls_get_bind_afn()); + switch (status) { + case dns_nomx : + done=false; + break; + case dns_local : + rcpt->code='L'; //domain is local + break; + case dns_remote : + rcpt->code='R'; //domain is remote + break; + default : + (void) rou_alert(0,"%s Unexpected status='%d' for domain<%s>", + OPEP,status,rcpt->domain); + break; + } + break; + default : //SAFE Guard + proceed=false; + break; + } + phase++; + } +return done; +#undef OPEP +} +/* +^L +*/ +/********************************************************/ +/* */ +/* Procedure to transmit a string to the remot peer*/ +/* */ +/********************************************************/ +static void transmit(CONTYP *contact,const char *fmt,...) + +{ +va_list args; +char *line; + +va_start(args,fmt); +line=(char *)0; +if (rou_vasprintf(&line,fmt,args)>0) { + (void) log_fprintlog(contact->logptr,true,"%s",line); + (void) tcp_write(contact->socptr,line); + (void) free(line); + } +va_end(args); +} +/* +^L +*/ +/********************************************************/ +/* */ +/* Procedure to send the signon once the contact */ +/* with peer is detected. */ +/* */ +/********************************************************/ +static void signon(CONTYP *contact) + +{ +#define FMT "%d %s, ESMTP (%s) %s-%s; %s" + +if (contact!=(CONTYP *)0) { + const char *mode; + char signon[100]; + + mode=soc_getstrmode(contact->socptr); + (void) snprintf(signon,sizeof(signon),FMT, + SIGNON,contact->locname, + mode, + appname, + rou_getversion(), + rou_ascsysstamp(time((time_t *)0))); + (void) transmit(contact,"%s",signon); + } +#undef FMT +} +/* +^L +*/ +/********************************************************/ +/* */ +/* Procedure to send ready link information */ +/* is a correct one */ +/* */ +/********************************************************/ +static void linkready(CONTYP *contact,_Bool suite) + +{ +const char *mode; +char sepa; + +sepa=' '; +if (suite==true) + sepa='-'; +mode=soc_getstrmode(contact->socptr); +(void) transmit(contact,"%d%c%s, link (%s) ready, your IP/FQDN=[%s/%s]", + CMDOK,sepa,contact->locname,mode, + contact->peerip,contact->peername); +} +/* +^L +*/ +/********************************************************/ +/* */ +/* Procedure to add received information to */ +/* the email contents. */ +/* */ +/********************************************************/ +static _Bool addreceived(CONTYP *contact,FILE *data) + +{ +_Bool status; +time_t curtime; +int phase; +_Bool proceed; + +status=true; +curtime=time((time_t *)0); +phase=0; +proceed=true; +while (proceed==true) { + switch (phase) { + case 0 : //Inserting the remote information + (void) fprintf(data,"Received: from %s (IP=[%s], originator=<%s>)\n", + contact->peername,contact->peerip,contact->mailfrom); + break; + case 1 : //Inserting the Receive information + (void) fprintf(data,"\tby %s ([%s:%s]/%s-%s) with ESMTP\n", + contact->locname,contact->locip,contact->locserv, + appname,rou_getversion()); + break; + case 2 : //Inserting TLS information + if (soc_iscrypted(contact->socptr)==true) { + (void) fprintf(data,"\t(%s)\n",soc_getcipherid(contact->socptr)); + } + break; + case 3 : //Inserting ID information + (void) fprintf(data,"\tid <%s@%s>;\n", + contact->cursesid,contact->locname); + break; + case 4 : //date information + (void) fprintf(data,"\t%s\n",rou_ascsysstamp(curtime)); + break; + default : //SAFE Guard + proceed=false; + break; + } + phase++; + } +return status; +} +/* +^L +*/ +/********************************************************/ +/* */ +/* Procedure to check if helo or ehlo paratmeter */ +/* is a correct one */ +/* */ +/********************************************************/ +static _Bool isgoodfqdn(CONTYP *contact,char *parameter) + +{ +#define OPEP "lvleml.c:isgoodfqdn" + +_Bool done; +int phase; +_Bool proceed; + +done=false; +phase=0; +proceed=true; +while (proceed==true) { + //(void) rou_alert(0,"JMPDBG %s phase='%d' parm=<%s>",OPEP,phase,parameter); + switch (phase) { + case 0 : //checking if we have a parameter + if ((parameter==(char *)0)||(strlen(parameter)==0)) + phase=999; //no parameter + break; + case 1 : //seems to be a good fqdn + contact->fqdn=rou_freestr(contact->fqdn); + contact->fqdn=strdup(parameter); + done=true; + break; + default : //SAFE guard + proceed=false; + break; + } + phase++; + } +return done; +#undef OPEP +} +/* + +*/ +/************************************************/ +/* */ +/* Procedure to set create the sessid count*/ +/* file. This file is used to keep track */ +/* of the number of the sessionid|(rcpt) */ +/* used to send email to all recipient. */ +/* */ +/************************************************/ +static _Bool setcountfile(CONTYP *contact) + +{ +#define OPEP "lvleml.c:setcountfile," + +_Bool status; +int num; +FILE *qfile; +int phase; +_Bool proceed; + +status=false; +num=0; +qfile=(FILE *)0; +phase=0; +proceed=true; +while (proceed==true) { + switch (phase) { + case 0 : //is contact good + if (contact==(CONTYP *)0) { + (void) rou_alert(0,"%s contact pointer is NULL (bug?)",OPEP); + phase=999; + } + break; + case 1 : //counting recipient number + if ((num=rou_nbrlist((void **)contact->recipients))==0) + phase=999; //No recipient! + break; + case 2 : //creating the count file + if ((qfile=eml_createqfile(contact->cursesid,EXTCNT))==(FILE *)0) { + (void) rou_alert(0,"%s Unable to open 'count' qfile <%s> (error=<%s>)", + OPEP,contact->cursesid,strerror(errno)); + phase=999; + } + break; + case 3 : //inserting number of receipient + if (fprintf(qfile,"%d\n",num)<1) { + (void) rou_alert(0,"%s Unable to set 'count' in qfile <%s> (error=<%s>)", + OPEP,contact->cursesid,strerror(errno)); + (void) fclose(qfile); + phase=999; //trouble trouble + } + break; + case 4 : //closing count file + if (fclose(qfile)!=0) { + (void) rou_alert(0,"%s Unable to close qfile <%s> (error=<%s>)", + OPEP,contact->cursesid,strerror(errno)); + phase=999; //trouble trouble + } + break; + case 5 : //everything fine + status=true; + break; + default : //SAFE Guard + proceed=false; + break; + } + phase++; + } +return status; + + +#undef OPEP +} +/* + +*/ +/************************************************/ +/* */ +/* Procedure to set RCPT directive to */ +/* forward email to SMTP peers. */ +/* */ +/************************************************/ +static _Bool setdirectives(CONTYP *contact,char *ext) + +{ +#define OPEP "lvleml.c:setdirectives," + +_Bool status; +FILE *trans; +int phase; +_Bool proceed; + +status=false; +trans=(FILE *)0; +phase=0; +proceed=true; +while (proceed==true) { + //(void) rou_alert(0,"JMPDBG %s phase='%d'",OPEP,phase); + switch (phase) { + case 0 : //Creating the file + if ((trans=eml_createqfile(contact->cursesid,ext))==(FILE *)0) + phase=999; //trouble trouble + break; + case 1 : //write data to trans file; + if (eml_mktransfile(contact,trans)==false) { + (void) eml_closeqfile(trans); + phase=999; //Trouble trouble + } + break; + case 2 : //closing transfile + if (eml_closeqfile(trans)<0) + phase=999; //Trouble trouble + break; + case 3 : //everythin fine + status=true; + break; + default : //SAFE guard + proceed=false; + break; + } + phase++; + } +#undef OPEP +return status; +} +/* + +*/ +/************************************************/ +/* */ +/* Procedure to send a simple SMTP ccommand*/ +/* (no need to have the response wording) */ +/* */ +/************************************************/ +static int simple_smtp_command(RMTTYP *rmt,char *fmt,...) + +{ +va_list args; +char strloc[300]; + +va_start(args,fmt); +(void) vsnprintf(strloc,sizeof(strloc),fmt,args); +va_end(args); +return tcp_smtp_command(rmt,(char ***)0,strloc); +} +/* + +*/ +/************************************************/ +/* */ +/* Procedure to accept EMAIL contents from */ +/* SMTP peers. */ +/* Return true, if everything is fine */ +/* */ +/************************************************/ +static _Bool getdata(CONTYP *contact) + +{ +#define OPEP "lvleml.c:getdata," +#define EXTMP "tmp" + +_Bool done; +FILE *queue; +_Bool completed; +int total; +TIMESPEC start; +int phase; +_Bool proceed; + +done=false; +queue=(FILE *)0; +completed=false; +total=0; +phase=0; +proceed=setdirectives(contact,EXTMP); +while (proceed==true) { + //(void) rou_alert(0,"JMPDBG %s phase='%d'",OPEP,phase); + switch (phase) { + case 0 : //checking if we have recipient + if (rou_nbrlist((void **)contact->recipients)==0) { + char *cmt; + + cmt="RCPT first. transaction protocol command out of sequence"; + (void) transmit(contact,"%d 5.5.0 %s",BADSEQ,cmt); + done=true; //lets say DATA will be issued + proceed=false; //No recipients + } + break; + case 1 : //opening the queue email + if ((queue=eml_createqfile(contact->cursesid,""))==(FILE *)0) + phase=999; //trouble trouble + break; + case 2 : //adding received stamp to file + if (addreceived(contact,queue)==false) + phase=999; //trouble trouble + break; + case 3 : //sending 'go ahead' to remote + (void) clock_gettime(CLOCK_REALTIME,&start); + (void) transmit(contact,"%d 3.5.0 %s", + DATAOK,"End data with ."); + break; + case 4 : //get incoming line, detect 'single dot' as end + while (completed==false) { + int got; + char *line; + + completed=false; + got=tcp_getline(contact->socptr,WAITRMT,&line); + if (got<0) { //data timeout + phase=999; //trouble trouble + break; //exiting loop + } + total+=got; + if (strcmp(line,".")==0) { + completed=true; + } + else { + if ((strlen(line)>1)&&(line[0]=='.')) + (void) memmove(line,line+1,strlen(line)); + (void) fprintf(queue,"%s\n",line); + } + line=rou_freestr(line); + } + break; + case 5 : //got all data + if (eml_closeqfile(queue)<0) + phase=999; //Trouble trouble + break; + case 6 : //creating the count file + if (setcountfile(contact)==false) + phase=999; //Unable to create count file??? + break; + case 7 : //renameing directive + if (eml_renameqfile(contact->cursesid,EXTMP,EXTRANS)==false) + phase=999; //Trouble trouble + break; + case 8 : //everything fine + const char *fmt; + unsigned int delta; + + total+=1023; + total/=1024; //KBytes + delta=rou_getdifftime(&start); + fmt="%d 3.5.3 Message accepted for delivery (Session ID=<%s>)"; + (void) transmit(contact,fmt,CMDOK,contact->cursesid); + fmt="(DATA stream received: %d Kbytes within %d.%03d seconds)"; + (void) log_fprintlog(contact->logptr,false,fmt,total,delta/1000,delta%1000); + done=true; + proceed=false; //task done + break; + default : //SAFE guard + (void) transmit(contact,"%d 5.5.4 %s", + DATRJC,"Server does not accept mail"); + proceed=false; + break; + } + phase++; + } +return done; + +#undef EXTMP +#undef OPEP +} +/* + +*/ +/************************************************/ +/* */ +/* Procedure to send an "HELO" message */ +/* if EHLO message is not accepted. */ +/* */ +/************************************************/ +static _Bool dohelo(CONTYP *contact,char *parameter) + +{ +#define OPEP "lvleml.c:dohelo" +#define DETAIL "HELO argument is mandatory, closing connection" + +_Bool done; + +if ((done=isgoodfqdn(contact,parameter))==false) + (void) transmit(contact,"%d 5.5.4 %s.",BADPAR,DETAIL); +else + (void) linkready(contact,false); +return done; +#undef DETAIL +#undef OPEP +} +/* + +*/ +/************************************************/ +/* */ +/* Procedure to send an "HELO" message */ +/* if EHLO message is not accepted. */ +/* */ +/************************************************/ +static _Bool doehlo(CONTYP *contact,char *parameter) + +{ +static char *ehlostr[]= { + "-STARTTLS", + "-8BITMIME", + "-ENHANCEDSTATUSCODES", + "-AUTH PLAIN LOGIN", + " HELP", + (char *)0 + }; + +#define OPEP "lvleml.c:doehlo" +#define DETAIL "syntax error (domain part missing), closing connection" + +_Bool done; +int strstart; +int phase; +_Bool proceed; + +done=false; +strstart=0; +phase=0; +proceed=true; +while (proceed==true) { + //(void) rou_alert(0,"JMPDBG %s phase='%d'",OPEP,phase); + switch (phase) { + case 0 : //Do we have a parameter + if ((done=isgoodfqdn(contact,parameter))==false) { + (void) transmit(contact,"%d 5.5.4 %s.",BADPAR,DETAIL); + phase=999; //Trouble trouble + } + break; + case 1 : //thereis an FQDN + (void) linkready(contact,true); + (void) transmit(contact,"%d-SIZE %ld",CMDOK,MXMSIZE); + if (soc_iscrypted(contact->socptr)==true) + strstart++; + for (int i=strstart;ehlostr[i]!=(char *)0;i++) { + (void) transmit(contact,"%d%s",CMDOK,ehlostr[i]); + } + done=true; + break; + default : //SAFE guard + proceed=false; + break; + } + phase++; + } +return done; +#undef DETAIL +#undef OPEP +} +/* + +*/ +/************************************************/ +/* */ +/* Procedure to manage a "MAIL FROM:" */ +/* ommand from the SMTP client. */ +/* */ +/************************************************/ +static _Bool checkfrom(CONTYP *contact,char *mailfrom) + +{ +_Bool success; +_Bool proceed; +int phase; + +success=false; +proceed=true; +phase=0; +while (proceed==true) { + switch (phase) { + case 0 : //do we have an originator + if ((mailfrom==(char *)0)||(strlen(mailfrom)<3)) { + (void) transmit(contact,"%d 5.5.0 <%s> originator not specified", + BADPAR,mailfrom); + phase=999; //no need to go further + } + break; + case 1 : //do we have already a from + if (contact->mailfrom!=(char *)0) { + (void) transmit(contact,"%d 5.5.1 '%s' %s", + BADPAR,contact->mailfrom, + "was previously defined as originator" + ); + phase=999; //no need to go further + } + break; + case 2 : //check from format + if ((mailfrom[0]!='<')||(mailfrom[strlen(mailfrom)-1]!='>')) { + (void) transmit(contact,"%d 5.5.2 '%s' bad Format error", + BADPAR,mailfrom); + phase=999; //no need to go further + } + mailfrom[strlen(mailfrom)-1]='\000'; + (void) memmove(mailfrom,mailfrom+1,strlen(mailfrom)); + break; + case 3 : //everything ok + contact->mailfrom=strdup(mailfrom); + (void) transmit(contact,"%d 2.1.3 %s.. sender ok", + CMDOK,contact->mailfrom); + break; + default : //SAFE guard + proceed=false; + break; + } + phase++; + } +return success; +} +/* + +*/ +/************************************************/ +/* */ +/* Procedure to manage a "RCPT TO:" */ +/* command from the SMTP client. */ +/* */ +/************************************************/ +static _Bool checkto(CONTYP *contact,char *rcptto) + +{ +#define OPEP "lvleml.c:checkto," +_Bool success; +RCPTYP *neu; +const char *detail; +char *report; +_Bool proceed; +int phase; + +success=false; +neu=(RCPTYP *)0; +detail="Address accepted"; +report=(char *)0; +proceed=true; +phase=0; +while (proceed==true) { + //(void) rou_alert(0,"JMPDBG %s phase='%d' rcptto=<%s>",OPEP,phase,rcptto); + switch (phase) { + case 0 : //do we have an originator + if ((rcptto==(char *)0)||(strlen(rcptto)==0)) { + (void) transmit(contact,"%d 5.6.0 <%s> recipient not specified", + BADPAR,rcptto); + phase=999; //no need to go further + } + break; + case 1 : //check rcpt format + if ((rcptto[0]!='<')||(rcptto[strlen(rcptto)-1]!='>')) { + (void) transmit(contact,"%d 5.6.1 '%s' bad Format error", + BADPAR,rcptto); + phase=999; //no need to go further + } + rcptto[strlen(rcptto)-1]='\000'; + (void) memmove(rcptto,rcptto+1,strlen(rcptto)); + break; + case 2 : //checking rcptto format + neu=eml_isemailok(rcptto,&report); + if (neu==(RCPTYP *)0) { + (void) transmit(contact,"%d 5.6.2 %s",NOTEML,report); + report=rou_freestr(report); + phase=999; //no need to go further + } + break; + case 3 : //Do we have a domain MX + if (setlocdom(contact,neu)==false) { + (void) transmit(contact,"%d 5.6.3 %s (domain=%s)", + MISSMX, + "No valid MX found for recipient domain name", + neu->domain); + neu=eml_freerecipient(neu); //free recipient + phase=999; //no need to go further + } + break; + case 4 : //Storing rcpt to + if (eml_addrecipient(&(contact->recipients),neu)==false) { + detail="duplicate recipients will be consolidated"; + neu=eml_freerecipient(neu); + } + break; + case 5 : //everything ok + (void) transmit(contact,"%d 2.6.4 %s",CMDOK,detail); + success=true; + break; + default : //SAFE guard + proceed=false; + break; + } + phase++; + } +return success; +#undef OPEP +} +/* + +*/ +/************************************************/ +/* */ +/* Procedure to reset the current session */ +/* */ +/************************************************/ +static _Bool doreset(CONTYP *contact,char *parameter) + +{ +#define LOCSEQ "2.1.0" + +(void) transmit(contact,"%d-%s flushed session %s", + CMDOK,LOCSEQ,contact->cursesid); +contact->numreset++; +contact->recipients=(RCPTYP **)rou_freelist((void **)(contact->recipients), + (genfree_t)eml_freerecipient); +contact->mailfrom=rou_freestr(contact->mailfrom); +contact->cursesid=rou_freestr(contact->cursesid); +contact->cursesid=eml_getcursesid(contact->mainsesid,contact->numreset); +(void) transmit(contact,"%d %s opening new session %s", + CMDOK,LOCSEQ,contact->cursesid); +return true; + +#undef LOCSEQ +} +/* +^L +*/ +/********************************************************/ +/* */ +/* Procedure to to send ehlo (or helo) to remote */ +/* MX server. */ +/* Return true if succesfull */ +/* */ +/********************************************************/ +static _Bool greetings_rmt(RMTTYP *rmt) + +{ +#define OPEP "lvleml.c:greetings_rmt," + +_Bool done; +int phase; +_Bool proceed; + +done=false; +phase=0; +proceed=true; +while (proceed==true) { + int rspcode; + + rspcode=ERRPROC; + switch (phase) { + case 0 : //Sending EHLO + rspcode=simple_smtp_command(rmt,"EHLO %s",rmt->orgdomain); + switch (rspcode) { + case CMDOK : //So fare, so good + break; + default : //Trouble + (void) rou_alert(0,"%s EHLO Remote <%s> unexpected answer code '%d'", + OPEP,rmt->curmx,rspcode); + phase++; //No STARTTLS available + break; + } + break; + case 1 : //Stating starttls + phase=999; //No need to go futher + rspcode=simple_smtp_command(rmt,"STARTTLS",rmt->orgdomain); + switch (rspcode) { + case SIGNON : //link is now encrypted + done=soc_starttls(rmt->socptr,false); + switch (done) { + case true : + (void) log_fprintlog(rmt->logptr,false,"crypted link is now set"); + break; + case false : + (void) log_fprintlog(rmt->logptr,false,"Unable to set crypted link"); + break; + } + phase=999; //link is now established + break; + default : //Trouble + (void) rou_alert(0,"%s Unable to establish crypted link with <%s>", + OPEP,rmt->curmx); + break; + } + break; + case 2 : //Sending HELO + rspcode=simple_smtp_command(rmt,"HELO %s",rmt->orgdomain); + switch (rspcode) { + case CMDOK : //So fare, so good + done=true; + phase=999; + break; + default : //Trouble + (void) rou_alert(0,"%s, HELO Remote <%s> unexpected answer code '%d'", + OPEP,rmt->curmx,rspcode); + break; + } + break; + default : //SAFE Guard + proceed=false; + break; + } + phase++; + } +return done; + +#undef OPEP +} +/* +^L +*/ +/********************************************************/ +/* */ +/* Procedure to connect to the remote SMTP server */ +/* */ +/********************************************************/ +static _Bool connect_to_mx(RMTTYP *rmt) + +{ +#define OPEP "lvleml.c:connect_to_mx," + +_Bool done; +int phase; +int proceed; + +done=false; +phase=0; +proceed=true; +while (proceed==true) { + switch (phase) { + case 0 : //do we have MX + if (rmt->mxs==(MXTYP **)0) { + (void) log_fprintlog(rmt->logptr,false,"NO MX found for domain <%s>", + rmt->dstdomain); + phase=999; + } + break; + case 1 : //Trying to connect + MXTYP **mxs; + const char *srcip; + + mxs=rmt->mxs; + srcip=(const char *)0; + while (*mxs!=(MXTYP *)0) { + rmt->curmx=*mxs; + (void) rou_alert(0,"%s JMPDBG trying connect to <%s>", + OPEP,rmt->curmx->mxname); + rmt->socptr=soc_openfeedsock(pro_smtp,srcip,rmt->curmx->mxname,EMLPORT); + if (rmt->socptr!=(SOCPTR *)0) { + char cmt[100]; + + (void) snprintf(cmt,sizeof(cmt),"Now Connected to MX <%s>", + rmt->curmx->mxname); + (void) log_fprintlog(rmt->logptr,false,cmt); + break; + } + mxs++; + } + if (rmt->socptr==(SOCPTR *)0) + phase=999; + break; + case 2 : //waiting for signon + int res; + + res=tcp_get_smtp_reply(rmt,WAITRMT,(char ***)0); + switch (res) { + case SIGNON : //everything fine + break; + default : //not getting the right signon + phase=999; //No need to go further + break; + } + break; + case 3 : //send greetings + if ((done=greetings_rmt(rmt))==false) + phase=999; //greeting not successful! + break; + case 4 : //send greetings + break; + default : //SAFE Guard + proceed=false; + break; + } + phase++; + } +return done; + +#undef OPEP +} +/* +^L +*/ +/********************************************************/ +/* */ +/* Procedure to send the data to the remote server */ +/* */ +/********************************************************/ +static void senddata(RMTTYP *rmt,TRATYP **tosend,const char *sessid) + +{ +#define OPEP "lvleml.c:senddata," + +int rspcode; +int sent; +TIMESPEC start; +int phase; +_Bool proceed; + +rspcode=0; +sent=0; +phase=0; +proceed=true; +(void) clock_gettime(CLOCK_REALTIME,&start); +while (proceed==true) { + switch (phase) { + case 0 : //Sendig data request + rspcode=simple_smtp_command(rmt,"DATA"); + switch (rspcode) { + case DATAOK : //data accepted + break; + default : //Unexpected return code + phase=999; //Not accepting data + break; + } + break; + case 1 : //sending session data + sent=tcp_send_smtp_data(rmt,sessid); + if (sent<0) + phase=999; //No need to wait form response code + break; + case 2 : //send the text termination + (void) tcp_write(rmt->socptr,"."); + rspcode= tcp_get_smtp_reply(rmt,WAITRMT,(char ***)0); + break; + case 3 : //sending session data + const char *fmt; + unsigned int delta; + + sent+=1023; + sent/=1024; //Sent now in KByes + fmt="Data stream Sent: %d Kbytes within %d.%03d seconds"; + delta=rou_getdifftime(&start); + (void) log_fprintlog(rmt->logptr,false,fmt,sent,delta/1000,delta%1000); + switch (rspcode) { + case CMDOK : + const char *cmt; + + cmt="Transmission completed successfully"; + (void) log_fprintlog(rmt->logptr,false,cmt); + break; + case MALABRT : //Data rejected + break; + default : //Unexpected return code + break; + } + break; + case 4 : //Updating sending + TRATYP **dest; + + dest=tosend; + while (*dest!=(TRATYP *)0) { + switch ((*dest)->sendcode) { + case CMDOK : + if (rspcode==CMDOK) { + (*dest)->code='C'; //Data was sent properly + } + break; + case UKNUSER : //NO BREAK + case BADPAR : + break; + default : + (void) rou_alert(0,"%s sessid=<%s>, Unexpected code='%d' (Bug?)", + OPEP,sessid,rspcode); + break; + } + dest++; + } + break; + default : //SAFE Guard + proceed=false; + break; + } + phase++; + } +#undef OPEP +} +/* +^L +*/ +/********************************************************/ +/* */ +/* Procedure to send the whole email transaction */ +/* */ +/********************************************************/ +static void sending_email(char *orgdomain,char *dstdomain,char *sessid,TRATYP **tra) + +{ +#define OPEP "lvleml.c:sending_email," + +time_t isnow; +RMTTYP rmt; +int tobesend; +TRATYP **tosend; +int phase; +_Bool proceed; + +isnow=time((time_t *)0); +(void) memset(&rmt,'\000',sizeof(rmt)); +rmt.mxs=dns_getmx(dstdomain); +rmt.dstdomain=dstdomain; +rmt.orgdomain=orgdomain; +tosend=(TRATYP **)0; +tobesend=0; +phase=0; +proceed=true; +while (proceed==true) { + //(void) rou_alert(0,"%s JMPDBG phase='%d'",OPEP,phase); + switch (phase) { + case 0 : //process completed? + if ((*tra)==(TRATYP *)0) + phase=999; //all scanning done + break; + case 1 : //collecting email to be sent + rmt.logptr=log_closelog(rmt.logptr); + while (*tra!=(TRATYP *)0) { + if (strcmp((*tra)->sessid,sessid)!=0) { + sessid=(*tra)->sessid; + break; + } + if (((*tra)->date+(*tra)->delay)<=isnow) { + switch ((*tra)->code) { + case 'R' : //remote email (MX is remote) + (void) eml_add_delay(isnow,*tra); + tosend=(TRATYP **)rou_addlist((void **)tosend,(void *)(*tra)); + break; + default : //Status is not to be send + (void) rou_alert(0,"%s Directive is not! remote email (Bug?)",OPEP); + break; + } + } + tra++; + } + break; + case 2 : //Checking if we have email to be sent + if (tosend==(TRATYP **)0) + phase=-1; //lets continue to see other email + break; + case 3 : { //checking if connection is open + char cmt[100]; + + (void) snprintf(cmt,sizeof(cmt),"session-id=%s",sessid); + rmt.logptr=log_openlog(sessid,false,cmt); + if (rmt.socptr!=(SOCPTR *)0) { //reset the connection + phase++; //NO need to open connection + } + break; + } + case 4 : //Opening connection if not open + if (connect_to_mx(&rmt)==false) { + char cmt[100]; + + (void) snprintf(cmt,sizeof(cmt),"Unable to contact ANY MX for domain <%s>", + dstdomain); + (void) log_fprintlog(rmt.logptr,false,cmt); + if (tosend!=(TRATYP **)0) { + TRATYP **ptr; + char note[150]; + + (void) snprintf(note,sizeof(note),"%d %s",NOANSWR,cmt); + ptr=tosend; + while (*ptr!=(TRATYP *)0) { + (void) eml_freetra_resp(*ptr); + (*ptr)->resp=(char **)rou_addlist((void **)(*ptr)->resp, + (void *)strdup(note)); + ptr++; + } + (void) free(tosend); + } + phase=999; //No need to go further + } + break; + case 5 : { //sending originator + int rspcode; + + rspcode=simple_smtp_command(&rmt,"MAIL FROM: <%s>",(*tosend)->mailfrom); + switch (rspcode) { + case CMDOK : //originator accepted + break; + default : //unexpected answer + (void) rou_alert(0,"%s JMPDBG unexpected response code='%d'", + OPEP,rspcode); + phase+=2; //not sending data + break; + } + break; + } + case 6 : { //sending recipient list + int rspcode; + TRATYP **dest; + + tobesend=0; + dest=tosend; + while (*dest!=(TRATYP *)0) { + char ***resp; + + (void) eml_freetra_resp(*dest); + resp=&((*dest)->resp); + rspcode=tcp_smtp_command(&rmt,resp,"RCPT TO: <%s>",(*dest)->rcptto); + switch (rspcode) { + case CMDOK : //originator accepted + tobesend++; + (*dest)->sendcode=rspcode; + break; + case UKNUSER : //recipient is unknown + case NORELAY : //email no relayed + (*dest)->code='W'; //Need to send a Warning + (*dest)->sendcode=rspcode; + break; + default : //Not accepted recipient + (void) rou_alert(0,"%s sessid=<%s>, unknwon code='%d'", + OPEP,sessid,rspcode); + (*dest)->code='C'; //completed (Temporary JMPDBG); + (*dest)->sendcode=BADPAR; + break; + } + dest++; + } + if (tobesend>=0) + (void) senddata(&rmt,tosend,sessid); + break; + } + case 8 : //cleaning recipient list + (void) free(tosend); + tosend=(TRATYP **)0; + phase=0; //Lets see if we have other recipient + break; + default : //SAFE Guard + rmt.logptr=log_closelog(rmt.logptr); + proceed=false; + break; + } + phase++; + } +rmt.mxs=dns_freemxlist(rmt.mxs); + +#undef OPEP +} +/* +^L +*/ +/********************************************************/ +/* */ +/* Procedure to proceed with peer exchange */ +/* 5 return values: */ +/* 1 exiting via "quit" */ +/* 0 contact timeout */ +/* -1 signal received */ +/* -2 remote disconnected */ +/* -3 BUG! */ +/* */ +/********************************************************/ +PUBLIC int eml_docontact(CONTYP *contact) + +{ +#define OPEP "lvleml.c:eml_docontact" + +int status; +int got; +int delay; +int penalty; +_Bool proceed; + +status=1; +got=0; +delay=300; //5 minutes standard delay +penalty=1; +if (debug>1) + delay/=10; //30 sec in debug mode +proceed=true; +(void) signon(contact); +while (proceed==true) { + char *line; + CODTYP code; + + line=(char *)0; + got=tcp_getline(contact->socptr,delay,&line); + if (got<=0) { //timeout or trouble? + char str[100]; + + switch (got) { + case 0 : //timeout + (void) snprintf(str,sizeof(str),"No data from remote within %d sec",delay); + break; + case -1 : //signal received + (void) snprintf(str,sizeof(str),"Signal Received"); + break; + case -2 : //contact lost + (void) snprintf(str,sizeof(str),"Lost link with remote"); + break; + default : + (void) snprintf(str,sizeof(str),"Unexpected status='%d' (Bug?)",status); + status=-3; + break; + } + (void) log_fprintlog(contact->logptr,false,"Contact terminated; " + "condition=<%s>",str); + //(void) rou_alert(0,"%s exit status='%d'",OPEP,status); + break; //no need to go further + + } + (void) log_fprintlog(contact->logptr,false,"%s",line); + code=eml_getcode(line); + switch (code) { + case c_data : //Peer request to transfer email corps. + proceed=getdata(contact); + break; + case c_helo : //HELO SMTP protocol + proceed=dohelo(contact,line); + break; + case c_ehlo : //EHLO SMTP protocol + proceed=doehlo(contact,line); + break; + case c_noop : //No Operation + (void) transmit(contact,"%d 2.0.0 OK, %s", + CMDOK,contact->mainsesid); + break; + case c_quit : //QUIT SMTP protocol + (void) transmit(contact,"%d 2.0.0 Bye, closing connection CNT=%s", + QUITOK,contact->mainsesid); + status=1; //every thing fine + proceed=false; + break; + case c_mail : //MAIL FROM: checking originator + (void) checkfrom(contact,line); + break; + case c_rcpt : //Doing rpt scanning + if (checkto(contact,line)==false) { + (void) sleep(penalty); //relaxing bad guys + penalty*=2; + } + break; + case c_rset : //Doing session reset + proceed=doreset(contact,line); + break; + case c_starttls : //EHLO start encrypted link in server mode + switch (soc_starttls(contact->socptr,true)) { + case true : //link now in TLS crypted mode + (void) transmit(contact,"%d Link now encrypted (cipher=<%s>)", + CMDOK,soc_get_cipher_name(contact->socptr)); + break; + case false : //unable to establish link + (void) transmit(contact,"%d 5.3.3 command starttls not successful", + CMDBAD); + status=-1; + proceed=false; + break; + } + break; + case c_unknown : //unknown keyword + (void) rou_alert(0,"SMTP Command <%s> from [%s] is unknown (config?)", + line,contact->peerip); + (void) transmit(contact,"%d-5.5.1 Unrecognized command, see RFC 5321",CMDBAD); + (void) transmit(contact,"%d-5.5.1 https://www.rfc-editor.org",CMDBAD); + (void) transmit(contact,"%d 5.5.1 session %s is still running", + CMDBAD,contact->mainsesid); + break; + default : + (void) rou_alert(0,"%s Unable to find entry for code='%d' (Bug?)",OPEP,code); + (void) transmit(contact,"%d-5.5.1 Unrecognized command, see RFC 5321",CMDBAD); + (void) transmit(contact,"%d 2.0.0 Bug!, closing connection Immediatly (%s)", + QUITOK,contact->mainsesid); + status=-1; //remote is a trouble maker + status=-3; + proceed=false; + break; + } + line=rou_freestr(line); + } +return status; +#undef OPEP +} +/* +^L +*/ +/********************************************************/ +/* */ +/* Procedure to wait for a remote client. */ +/* return all reference to the established contact.*/ +/* */ +/********************************************************/ +PUBLIC CONTYP *eml_getcontact(SOCPTR *socptr,int pos) + +{ +#define OPEP "lvleml.c:eml_getcontact" +#define MXCARIN 200 //maximun number of char + //within carpile + +CONTYP *contact; +int phase; +_Bool proceed; + +contact=(CONTYP *)0; +phase=0; +proceed=true; +while (proceed==true) { + //(void) rou_alert(0,"JMPDBG %s phase='%d'",OPEP,phase); + switch (phase){ + case 0 : //check for binding + if (socptr==(SOCPTR *)0) { + (void) rou_alert(0,"%s socket pointer is NULL (Bug!?)",OPEP); + phase=999; //not going further + } + break; + case 1 : //connecting to database + contact=(CONTYP *)calloc(1,sizeof(CONTYP)); + contact->sqlptr=sql_opensql(); + if (contact->sqlptr==(SQLPTR *)0) { + (void) rou_alert(0,"%s Unable to contact database",OPEP); + (void) sleep(2);//delay to avoid avalanche + (void) free(contact); + contact=(CONTYP *)0; + phase=999; //no contact possible. + } + break; + case 2 : //waiting from contact + if ((contact->socptr=soc_accept(socptr,pos))==(SOCPTR *)0) { + (void) rou_alert(3,"%s Unable to open contact",OPEP); + contact=freecontact(contact); + phase=999; //no contact + } + break; + case 3 : //Preparing contact + contact->mainsesid=eml_getmainsesid(); + contact->cursesid=eml_getcursesid(contact->mainsesid,contact->numreset); + contact->locname=soc_getaddrinfo(contact->socptr,true,true); + contact->locip=soc_getaddrinfo(contact->socptr,true,false); + if (contact->locip!=(char *)0) { + char *ptr; + + //extracting service port number + if ((ptr=strrchr(contact->locip,':'))!=(char *)0) { + *ptr='\000'; + contact->locserv=strdup(ptr+1); + } + } + contact->peername=soc_getaddrinfo(contact->socptr,false,true); + contact->peerip=soc_getaddrinfo(contact->socptr,false,false); + contact->logptr=log_openlog(contact->mainsesid,true,(const char *)0); + (void) rou_alert(0,"Contact from peer <%s> to port <%s> started", + contact->peerip,contact->locserv); + break; + case 4 : //check contact validity + if ((contact->locname==(char *)0)||(contact->peerip==(char *)0)) { + (void) rou_alert(0,"%s Unable to establish contact entities",OPEP); + contact=freecontact(contact); + phase=999; //no identity + } + break; + case 5 : //contact is good, then sending a signon + (void) log_fprintlog(contact->logptr,false,"opening connection CNT=%s", + contact->mainsesid); + break; + default : //SAFE guard + proceed=false; + break; + } + phase++; + } +return contact; +#undef MXCARIN +#undef OPEP +} +/* +^L +*/ +/********************************************************/ +/* */ +/* Procedure to wait for a remote client. */ +/* return the frreed memory contact (NULL pointer) */ +/* */ +/********************************************************/ +PUBLIC CONTYP *eml_dropcontact(CONTYP *contact) + +{ +#define OPEP "lvleml.c:eml_dropcontact" + +int phase; +_Bool proceed; + +phase=0; +proceed=true; +while (proceed==true) { + //(void) rou_alert(0,"JMPDBG %s phase='%d'",OPEP,phase); + switch (phase){ + case 0 : //check for binding + if (contact==(CONTYP *)0) { + (void) rou_alert(0,"%s Contact pointer is NULL (Bug!?)",OPEP); + phase=999; //not going further + } + break; + case 1 : //properly closing remote contact + (void) rou_alert(0,"Contact from peer <%s> to port <%s> terminated", + contact->peerip,contact->locserv); + contact->socptr=soc_release(contact->socptr); + //(void) kill(getppid(),SIGCHLD); + //(void) rou_alert(0,"%s JMPDBG signal SIGCHLD sent to='%d'",OPEP,getppid()); + break; + case 2 : //freeing contact memory + contact=freecontact(contact); + break; + default : //SAFE guard + proceed=false; + break; + } + phase++; + } +return contact; +#undef OPEP +} +/* +^L +*/ +/********************************************************/ +/* */ +/* Procedure to generate transfile contents */ +/* return all reference to contact. */ +/* */ +/********************************************************/ +PUBLIC _Bool eml_mktransfile(CONTYP *contact,FILE *qfile) + +{ +#define OPEP "lvleml.c:eml_mktrans" + +_Bool status; + +status=true; +if ((contact!=(CONTYP *)0)&&(contact->recipients!=(RCPTYP **)0)) { + RCPTYP **ptr; + TRATYP **tralist; + time_t isnow; + + ptr=contact->recipients; + tralist=(TRATYP **)0; + isnow=time((time_t *)0); + while (*ptr!=(RCPTYP *)0) { + TRATYP *tra; + char data[300]; + + + (void) snprintf(data,sizeof(data),"%s@%s",(*ptr)->userid,(*ptr)->domain); + tra=(TRATYP *)calloc(1,sizeof(TRATYP)); + tra->code=(*ptr)->code; + tra->date=isnow; + tra->delay=0; + tra->sessid=strdup(contact->cursesid); + tra->mailfrom=strdup(contact->mailfrom); + tra->rcptto=strdup(data); + tralist=(TRATYP **)rou_addlist((void **)tralist,(void *)tra); + ptr++; + } + (void) eml_dump_list_tra(qfile,tralist); + tralist=(TRATYP **)rou_freelist((void **)tralist,(genfree_t)eml_freetra); + } +return status; +#undef OPEP +} +/* +^L +*/ +/********************************************************/ +/* */ +/* Procedure to store local email (MX local) within*/ +/* the serveur right directory. */ +/* */ +/********************************************************/ +PUBLIC void eml_local_email(TRATYP **tra) + +{ +#define OPEP "lvleml.c:eml_local_email," + +time_t isnow; + +isnow=time((time_t *)0); +while (*tra!=(TRATYP *)0) { + if (((*tra)->date+(*tra)->delay)>isnow) + continue; + (void) eml_add_delay(isnow,*tra); + switch ((*tra)->code) { + case 'L' : //local email (MX is local) + (*tra)->code='C'; + if (eml_store_email(*tra)==false) { + (*tra)->code='L'; //Will try to deliver later one + (void) rou_alert(0,"%s Unable to deliver local email <%s> to <%s>", + OPEP,(*tra)->sessid,(*tra)->rcptto); + } + break; + default : //Unexpected local? email?? + (void) rou_alert(0,"%s Directive is not! local email (Bug?)",OPEP); + (void) rou_alert(0,"%s TRA=<%cs %lu %04u %s %s %s",OPEP, + (*tra)->code, + (*tra)->date, + (*tra)->delay, + (*tra)->sessid, + (*tra)->mailfrom, + (*tra)->rcptto); + break; + } + tra++; + } +#undef OPEP +} +/* +^L +*/ +/********************************************************/ +/* */ +/* Procedure to send email to remote recipient */ +/* */ +/********************************************************/ +PUBLIC void eml_remote_email(TRATYP **tra) + +{ +#define OPEP "lvleml.c:eml_remote_email," + +char *orgdomain; +char *dstdomain; +char *sessid; +int phase; +_Bool proceed; + +orgdomain=(char *)0; +dstdomain=(char *)0; +sessid=(char *)0; +phase=0; +proceed=true; +while (proceed==true) { + switch (phase) { + case 0 : //Check if we have tra + if (tra==(TRATYP **)0) { + (void) rou_alert(0,"%s Transaction pointer is NULL (Bug?)",OPEP); + phase=999; + } + break; + case 1 : //set originator domain + if ((orgdomain=strrchr((*tra)->mailfrom,'@'))!=(char *)0) + orgdomain++; + if (orgdomain==(char *)0) { + (void) rou_alert(0,"%s Originator address <%s> without domain? (Bug?)", + OPEP,(*tra)->mailfrom); + phase=999; + } + break; + case 2 : //detecting remote domain + if ((dstdomain=strrchr((*tra)->rcptto,'@'))!=(char *)0) + dstdomain++; + if (dstdomain==(char *)0) { + (void) rou_alert(0,"%s Recipient address <%s> without domain? (Bug?)", + OPEP,(*tra)->rcptto); + phase=999; + } + break; + case 3 : //checking if we have a session ID + sessid=(*tra)->sessid; + if (sessid==(char *)0) { + (void) rou_alert(0,"%s Session ID is NULL (Bug?)",OPEP); + sessid="0000-0000"; + } + break; + case 4 : //sending the whole transaction to remote server + (void) sending_email(orgdomain,dstdomain,sessid,tra); + break; + default : //SAFE Guard + proceed=false; + break; + } + phase++; + } + +#undef OPEP +} +/* +^L +*/ +/********************************************************/ +/* */ +/* Procedure to rebounce an email which was NOT */ +/* deliverable. */ +/* */ +/********************************************************/ +PUBLIC void eml_rebounce_email(TRATYP *tra) + +{ +char *tmp; + +(void) rou_alert(0,"JMPDG rebounce"); +tmp=tra->mailfrom; +tra->mailfrom=tra->rcptto; +tra->mailfrom=tmp; +tra->code='L'; +} +