| 1 | XMR1 ;ISC-SF/GMB-SMTP Receiver HELO/MAIL/RCPT (RFC 821) ;02/10/2004  06:31
 | 
|---|
| 2 |  ;;8.0;MailMan;**6,24**;Jun 28, 2002
 | 
|---|
| 3 | HELO ; Recv: "HELO REMOTE.MED.VA.GOV <security num>"
 | 
|---|
| 4 |  ; Send: "250 OK LOCAL.MED.VA.GOV <security num> [8.0,DUP,SER,FTP]"
 | 
|---|
| 5 |  N X,Y,XMDOMREC
 | 
|---|
| 6 |  I XMP="" S XMSG="501 Missing domain specification" X XMSEN Q
 | 
|---|
| 7 |  I '$D(^XMB("NETNAME")) S XMSG="550 Unchristened local domain" X XMSEN Q
 | 
|---|
| 8 |  S X=$P(XMP,"<")
 | 
|---|
| 9 |  I $E(X,$L(X))="." S XMSG="501 Invalid Domain Name" X XMSEN Q
 | 
|---|
| 10 |  S XMSTATE="^HELO^QUIT^"
 | 
|---|
| 11 |  S X=$$UP^XLFSTR(X)
 | 
|---|
| 12 |  S Y=$$FACILITY(X)
 | 
|---|
| 13 |  I Y>0 D
 | 
|---|
| 14 |  . S XMINST=+Y
 | 
|---|
| 15 |  . S (XMSITE,XMC("HELO RECV"))=$P(Y,U,2)
 | 
|---|
| 16 |  E  I $$REJECT(X) D  Q
 | 
|---|
| 17 |  . S XMSG="421 Service not available, closing transmission channel" X XMSEN
 | 
|---|
| 18 |  . S XMC("QUIT")=1
 | 
|---|
| 19 |  E  D
 | 
|---|
| 20 |  . S XMC("HELO RECV")=X
 | 
|---|
| 21 |  . S Y=$$DOMAIN(X)
 | 
|---|
| 22 |  . S XMINST=+Y
 | 
|---|
| 23 |  . S XMSITE=$P(Y,U,2)
 | 
|---|
| 24 |  I +$G(^XMB(1,1,4)) D
 | 
|---|
| 25 |  . D NORELAY
 | 
|---|
| 26 |  E  S XMC("RELAY OK")=1
 | 
|---|
| 27 |  I XMC("BATCH") S XMSTATE="^MAIL^",XMCONT=XMCONT_"TURN^MESS^" Q
 | 
|---|
| 28 |  S XMDOMREC=^DIC(4.2,XMINST,0)
 | 
|---|
| 29 |  I $P(XMDOMREC,U,15) D VALPROC(XMINST,XMDOMREC,XMP,.XMRVAL) Q:'$D(XMRVAL)
 | 
|---|
| 30 |  S XMSG="250 OK "_^XMB("NETNAME")_$S($D(XMRVAL):" <"_XMRVAL_">",1:"")_" ["_$P($T(XMR1+1),";",3)_",DUP,SER,FTP]" X XMSEN
 | 
|---|
| 31 |  S XMSTATE="^MAIL^",XMCONT=XMCONT_"TURN^MESS^"
 | 
|---|
| 32 |  Q
 | 
|---|
| 33 | NORELAY ; We want to prevent this site from unwittingly acting as a relay
 | 
|---|
| 34 |  ; domain for spammers or viruses.  Such nefarious ne'erdowells
 | 
|---|
| 35 |  ; typically route their mail through unsuspecting sites to "launder"
 | 
|---|
| 36 |  ; it.  The unsuspecting sites forward it onward.
 | 
|---|
| 37 |  ; XMC("HELO RECV") contains the sending site's name.  If we
 | 
|---|
| 38 |  ; were to be truly vigorous about this, we would find out the IP
 | 
|---|
| 39 |  ; address of the site and do a reverse DNS lookup to verify the site's
 | 
|---|
| 40 |  ; name.  We don't yet have that capability, so we'll have to make do
 | 
|---|
| 41 |  ; with XMC("HELO RECV") and trust that the site is who it says it is.
 | 
|---|
| 42 |  N XMOKDOM
 | 
|---|
| 43 |  S XMOKDOM="" ; Get list of acceptable sites
 | 
|---|
| 44 |  F  S XMOKDOM=$O(^XMB(1,1,4.1,"B",XMOKDOM)) Q:XMOKDOM=""  D
 | 
|---|
| 45 |  . S XMC("MY DOMAIN",$$UP^XLFSTR(XMOKDOM))=""
 | 
|---|
| 46 |  I $F(^XMB("NETNAME"),".VA.GOV")=($L(^XMB("NETNAME"))+1) D
 | 
|---|
| 47 |  . ; This is a VA site.  Make sure mail from other VA sites is relayed.
 | 
|---|
| 48 |  . I '$D(XMC("MY DOMAIN",".VA.GOV")) S XMC("MY DOMAIN",^XMB("NETNAME"))=""
 | 
|---|
| 49 |  S XMOKDOM="" ; Make sure this site is an acceptable site!
 | 
|---|
| 50 |  F  S XMOKDOM=$O(XMC("MY DOMAIN",XMOKDOM)) Q:XMOKDOM=""  Q:$F(^XMB("NETNAME"),XMOKDOM)=($L(^XMB("NETNAME"))+1)
 | 
|---|
| 51 |  I XMOKDOM="" S XMC("MY DOMAIN",^XMB("NETNAME"))="" ; Default
 | 
|---|
| 52 |  ; Set XMC("RELAY OK")=1 if the sending site is acceptable.
 | 
|---|
| 53 |  S XMOKDOM=""
 | 
|---|
| 54 |  F  S XMOKDOM=$O(XMC("MY DOMAIN",XMOKDOM)) Q:XMOKDOM=""  Q:$F(XMC("HELO RECV"),XMOKDOM)=($L(XMC("HELO RECV"))+1)
 | 
|---|
| 55 |  S XMC("RELAY OK")=XMOKDOM'=""
 | 
|---|
| 56 |  Q
 | 
|---|
| 57 | FACILITY(X) ; If full domain name is found in domain file, either as main
 | 
|---|
| 58 |  ; entry or as synonym, return main entry.  "Domain IEN^Domain name"
 | 
|---|
| 59 |  N DIC,Y,D
 | 
|---|
| 60 |  S DIC="^DIC(4.2,",DIC(0)="FMOZ",D="B^C"
 | 
|---|
| 61 |  D MIX^DIC1
 | 
|---|
| 62 |  Q $S(Y>0:+Y_U_Y(0,0),1:Y)
 | 
|---|
| 63 | DOMAIN(XMDOMAIN) ; Try to find the domain.
 | 
|---|
| 64 |  N DIC,X,Y,D
 | 
|---|
| 65 |  S (X,XMDOMAIN)=$$UP^XLFSTR(XMDOMAIN)
 | 
|---|
| 66 |  S DIC="^DIC(4.2,",DIC(0)="FMXZ",D="B^C"
 | 
|---|
| 67 |  F  D MIX^DIC1 Q:Y>0!(X'[".")  S X=$P(X,".",2,99)
 | 
|---|
| 68 |  Q:Y>0 +Y_U_Y(0,0)
 | 
|---|
| 69 |  N XMTOP
 | 
|---|
| 70 |  S XMTOP=X
 | 
|---|
| 71 |  ; If the top-level domain is found in the Internet Suffix file, then
 | 
|---|
| 72 |  ; just pretend that we're talking to this site's parent.
 | 
|---|
| 73 |  ; (TURN command will be disabled.)
 | 
|---|
| 74 |  I $$FIND1^DIC(4.2996,"","QX",XMTOP) Q ^XMB("PARENT")_U_$P(^DIC(4.2,^XMB("PARENT"),0),U,1)
 | 
|---|
| 75 |  ; Add the top-level domain to the DOMAIN file.
 | 
|---|
| 76 |  N XMFDA,XMIENS,XMIEN
 | 
|---|
| 77 |  S XMIENS="?+1,"
 | 
|---|
| 78 |  S XMFDA(4.2,XMIENS,.01)=XMTOP        ; Top-level domain name
 | 
|---|
| 79 |  S XMFDA(4.2,XMIENS,1)="C"            ; Closed
 | 
|---|
| 80 |  S XMFDA(4.2,XMIENS,1.7)="y"          ; Disable TURN command
 | 
|---|
| 81 |  S XMFDA(4.2,XMIENS,2)=^XMB("PARENT") ; Relay domain
 | 
|---|
| 82 |  D UPDATE^DIE("","XMFDA","XMIEN")
 | 
|---|
| 83 |  ; If there's a problem with adding the top-level domain to the DOMAIN
 | 
|---|
| 84 |  ; file, just pretend that we're talking to this site's parent.
 | 
|---|
| 85 |  ; (TURN command will be disabled.)
 | 
|---|
| 86 |  I $D(DIERR) Q ^XMB("PARENT")_U_$P(^DIC(4.2,^XMB("PARENT"),0),U,1)
 | 
|---|
| 87 |  ; Notify someone that we've added a new domain to the DOMAIN file.
 | 
|---|
| 88 |  N XMINSTR,XMPARM
 | 
|---|
| 89 |  S XMPARM(1)=XMTOP
 | 
|---|
| 90 |  S XMPARM(2)=XMDOMAIN
 | 
|---|
| 91 |  S XMINSTR("FROM")="POSTMASTER"
 | 
|---|
| 92 |  D TASKBULL^XMXBULL(.5,"XM DOMAIN ADDED",.XMPARM,,,.XMINSTR)
 | 
|---|
| 93 |  Q XMIEN(1)_U_XMTOP
 | 
|---|
| 94 | VALPROC(XMINST,XMDOMREC,XMP,XMRVAL) ; Check validation number
 | 
|---|
| 95 |  L +^DIC(4.2,XMINST,0):0 E  S XMSG="550 Domain file locked, try later" X XMSEN Q
 | 
|---|
| 96 |  S XMRVAL=$P($P(XMP,"<",2),">")
 | 
|---|
| 97 |  D VALCHK(.XMDOMREC,XMRVAL)
 | 
|---|
| 98 |  I '$D(XMRVAL) L -^DIC(4.2,XMINST,0) Q
 | 
|---|
| 99 |  S XMRVAL=$R(8000000)+1000000 ; generate new validation number
 | 
|---|
| 100 |  ;set val. num in return message, set new Val. num field
 | 
|---|
| 101 |  S $P(XMDOMREC,U,18)=XMRVAL
 | 
|---|
| 102 |  S ^DIC(4.2,XMINST,0)=XMDOMREC
 | 
|---|
| 103 |  Q
 | 
|---|
| 104 | VALCHK(XMDOMREC,XMRVAL) ; Check the validation number
 | 
|---|
| 105 |  Q:XMRVAL=$P(XMDOMREC,U,15)  ; 15=current number; 18=new number
 | 
|---|
| 106 |  I XMRVAL=$P(XMDOMREC,U,18) S $P(XMDOMREC,U,15)=$P(XMDOMREC,U,18) Q
 | 
|---|
| 107 |  K XMRVAL
 | 
|---|
| 108 |  N XMPARM,XMINSTR
 | 
|---|
| 109 |  S XMINSTR("FROM")="POSTMASTER"
 | 
|---|
| 110 |  S XMPARM(1)=XMC("HELO RECV")
 | 
|---|
| 111 |  D TASKBULL^XMXBULL(.5,"XMVALBAD",.XMPARM,"","",.XMINSTR)
 | 
|---|
| 112 |  S XMSG="550 Bad validation number" X XMSEN
 | 
|---|
| 113 |  Q
 | 
|---|
| 114 | VALSET(XMINST,XMRVAL) ;check validation number
 | 
|---|
| 115 |  ;if new val. num. exist, then set val. num. to it and set to null
 | 
|---|
| 116 |  Q:'$G(XMRVAL)
 | 
|---|
| 117 |  N XMDOMREC
 | 
|---|
| 118 |  S XMDOMREC=$G(^DIC(4.2,XMINST,0))
 | 
|---|
| 119 |  S $P(XMDOMREC,U,15)=XMRVAL
 | 
|---|
| 120 |  S $P(XMDOMREC,U,18)=""
 | 
|---|
| 121 |  S ^DIC(4.2,XMINST,0)=XMDOMREC
 | 
|---|
| 122 |  L -^DIC(4.2,XMINST,0)
 | 
|---|
| 123 |  K XMRVAL
 | 
|---|
| 124 |  Q
 | 
|---|
| 125 | MAIL ; Recv: "MAIL FROM:<USER.JOE@REMOTE.MED.VA.GOV>"
 | 
|---|
| 126 |  ; Send: "250 OK Message-ID:12345@LOCAL.MED.VA.GOV"
 | 
|---|
| 127 |  N XMD
 | 
|---|
| 128 |  S XMP=$P(XMP,":",2,999)
 | 
|---|
| 129 |  S XMP=$$SCRUB^XMR3(XMP)
 | 
|---|
| 130 |  I XMP'?1"<>",(XMP'?1"<"1.E1"@"1.E1">") S XMSG="501 Invalid reverse-path specification" X XMSEN Q
 | 
|---|
| 131 |  I $$REJECT(XMP) S XMSG="502 No message receipt authorization." X XMSEN Q
 | 
|---|
| 132 |  K XMINSTR,XMNVFROM,XMREMID,XMRXMZ,XM2LONG,XMZ,XMZFDA,XMZIENS,^TMP("XMY",$J),^TMP("XMY0",$J)
 | 
|---|
| 133 |  S XMINSTR("FWD BY")="" ; We're not sure who sent/forwarded it
 | 
|---|
| 134 |  S XMINSTR("ADDR FLAGS")="R"
 | 
|---|
| 135 |  K:$D(XMERR) XMERR K:$D(^TMP("XMERR",$J)) ^TMP("XMERR",$J)
 | 
|---|
| 136 |  D CRE8XMZ^XMXSEND($$EZBLD^DIALOG(34012),.XMZ) ; * No Subject *
 | 
|---|
| 137 |  I $D(XMERR) D  Q
 | 
|---|
| 138 |  . S XMSG="555 "_^TMP("XMERR",$J,1,"TEXT",1)
 | 
|---|
| 139 |  . K XMERR,^TMP("XMERR",$J)
 | 
|---|
| 140 |  . X XMSEN
 | 
|---|
| 141 |  S XMZIENS=XMZ_","
 | 
|---|
| 142 |  S (XMNVFROM,XMZFDA(3.9,XMZIENS,1),XMZFDA(3.9,XMZIENS,41))=XMP ; mail from
 | 
|---|
| 143 |  S XMSTATE="^RCPT^DATA"
 | 
|---|
| 144 |  S (XMD,XMZFDA(3.9,XMZIENS,1.4))=$$NOW^XLFDT() ; Message date default
 | 
|---|
| 145 |  S $P(^XMB(3.9,XMZ,0),U,3)=XMD
 | 
|---|
| 146 |  D PUTMSG^XMXMSGS2(.5,.95,"ARRIVING",XMZ)
 | 
|---|
| 147 |  S XMSG="250 OK Message-ID:"_XMZ_"@"_^XMB("NETNAME") X XMSEN Q:ER
 | 
|---|
| 148 |  S XMD=$$INDT^XMXUTIL1(XMD)
 | 
|---|
| 149 |  ;DON'T CHANGE ORDER OF .001 & .002 LINES !
 | 
|---|
| 150 |  S ^XMB(3.9,XMZ,2,.001,0)="Received: "_$S($L($G(XMC("HELO RECV"))):"from "_XMC("HELO RECV")_" by "_^XMB("NETNAME")_" (MailMan/"_$P($T(XMR1+1),";",3)_" "_XMPROT_")",1:"(BATCH)")_" id "_XMZ_" ; "_XMD
 | 
|---|
| 151 |  N XMFDA,XMIENS
 | 
|---|
| 152 |  S XMIENS=XMINST_","
 | 
|---|
| 153 |  S XMFDA(4.2999,XMIENS,1)=$H
 | 
|---|
| 154 |  S XMFDA(4.2999,XMIENS,2)=XMZ   ; Message in transit
 | 
|---|
| 155 |  ;S XMFDA(4.2999,XMIENS,3)="@"   ; Last line xmit'd
 | 
|---|
| 156 |  D FILE^DIE("","XMFDA")
 | 
|---|
| 157 |  Q
 | 
|---|
| 158 | REJECT(XMNVFROM) ; Check Senders rejected list
 | 
|---|
| 159 |  Q:'$O(^XMBX(4.501,0)) 0
 | 
|---|
| 160 |  N XMNO,XMREJECT,XMIEN,XMREC
 | 
|---|
| 161 |  S XMNVFROM=$$UP^XLFSTR(XMNVFROM)
 | 
|---|
| 162 |  S XMNO="",XMREJECT=0
 | 
|---|
| 163 |  F  S XMNO=$O(^XMBX(4.501,"B",XMNO)) Q:XMNO=""  D  Q:XMREJECT
 | 
|---|
| 164 |  . Q:XMNVFROM'[$$UP^XLFSTR(XMNO)
 | 
|---|
| 165 |  . S XMIEN=$O(^XMBX(4.501,"B",XMNO,0)) Q:'XMIEN
 | 
|---|
| 166 |  . S XMREC=$G(^XMBX(4.501,XMIEN,0)) Q:XMREC=""
 | 
|---|
| 167 |  . I XMNVFROM[$$UP^XLFSTR($P(XMREC,U,1)),'$P(XMREC,U,2) S XMREJECT=1
 | 
|---|
| 168 |  Q XMREJECT
 | 
|---|
| 169 | RCPT ; Specify recipients
 | 
|---|
| 170 |  S XMP=$P(XMP,":",2,999) I XMP="" S XMSG="501 Invalid forward path specification" X XMSEN Q
 | 
|---|
| 171 |  I XMP["> FWD BY:" S XMINSTR("NET FWD BY")=$P(XMP,"> FWD BY:",2)
 | 
|---|
| 172 |  E  K XMINSTR("NET FWD BY")
 | 
|---|
| 173 |  Q:$$LOOKUP(XMP,.XMINSTR)=0
 | 
|---|
| 174 |  S XMSG="250 'RCPT' accepted" X XMSEN
 | 
|---|
| 175 |  S XMSTATE="^DATA^RCPT"
 | 
|---|
| 176 |  Q
 | 
|---|
| 177 | LOOKUP(XMTO,XMINSTR) ;
 | 
|---|
| 178 |  N XMFULL,XMRESTR
 | 
|---|
| 179 |  S XMRESTR("NET RECEIVE")=$G(XMNVFROM)
 | 
|---|
| 180 |  S XMTO=$TR($P($P(XMTO,">",1),"<",2,99),"<")  ; I've seen <<user@site> and <<user@site>>
 | 
|---|
| 181 |  I XMTO="" S XMSG="550 Malformed address" X XMSEN Q 0
 | 
|---|
| 182 |  I $E(XMTO,1)'="""",XMTO?1"@"1.E1":"1.E1"@"1.E S XMTO=$P(XMTO,":",2)
 | 
|---|
| 183 |  D CHKADDR^XMXADDR(.5,XMTO,.XMINSTR,.XMRESTR,.XMFULL)
 | 
|---|
| 184 |  I $D(XMERR) D  Q 0
 | 
|---|
| 185 |  . S XMSG="550 "_^TMP("XMERR",$J,XMERR,"TEXT",1)
 | 
|---|
| 186 |  . X XMSEN
 | 
|---|
| 187 |  . K XMERR,^TMP("XMERR",$J)
 | 
|---|
| 188 |  I $G(XMFULL)="SHARED,MAIL" D  Q 0
 | 
|---|
| 189 |  . S XMSG="550 'Shared,Mail' user may not receive network mail."
 | 
|---|
| 190 |  . X XMSEN
 | 
|---|
| 191 |  . K ^TMP("XMY",$J,.6),^TMP("XMY0",$J,"SHARED,MAIL")
 | 
|---|
| 192 |  ; Don't act as a relay domain for unauthorized sites.
 | 
|---|
| 193 |  I XMFULL'["@" Q XMFULL  ; Local address OK
 | 
|---|
| 194 |  I XMC("RELAY OK") Q XMFULL  ; Relay from accepted site
 | 
|---|
| 195 |  N XMOKDOM,XMTRELAY
 | 
|---|
| 196 |  S XMTRELAY=$P(XMFULL,"@",2)
 | 
|---|
| 197 |  S XMOKDOM=""
 | 
|---|
| 198 |  F  S XMOKDOM=$O(XMC("MY DOMAIN",XMOKDOM)) Q:XMOKDOM=""  Q:$F(XMTRELAY,XMOKDOM)=($L(XMTRELAY)+1)
 | 
|---|
| 199 |  I XMOKDOM'="" Q XMFULL  ; Relay from an outside site to an inside site.
 | 
|---|
| 200 |  ; Relay from an outside site to an outside site.
 | 
|---|
| 201 |  S XMSG="550 Relaying denied."
 | 
|---|
| 202 |  X XMSEN
 | 
|---|
| 203 |  K ^TMP("XMY",$J,XMFULL),^TMP("XMY0",$J,XMFULL)
 | 
|---|
| 204 |  ; Notify someone that a relay attempt was denied.
 | 
|---|
| 205 |  N XMINSTR,XMPARM,XMTO
 | 
|---|
| 206 |  S XMPARM(1)=XMC("HELO RECV")
 | 
|---|
| 207 |  S XMPARM(2)=XMFULL
 | 
|---|
| 208 |  S XMPARM(3)=XMNVFROM
 | 
|---|
| 209 |  S XMINSTR("FROM")="POSTMASTER"
 | 
|---|
| 210 |  S XMTO(.5)=""
 | 
|---|
| 211 |  D TASKBULL^XMXBULL(.5,"XM RELAY ATTEMPTED",.XMPARM,,.XMTO,.XMINSTR)
 | 
|---|
| 212 |  Q 0
 | 
|---|