Home   Package List   Routine Alphabetical List   Global Alphabetical List   FileMan Files List   FileMan Sub-Files List   Package Component Lists   Package-Namespace Mapping  
Routine: XMRPOP

XMRPOP.m

Go to the documentation of this file.
  1. XMRPOP ;ISC-SF/GMB-POP3 Server (RFC 1939) ;05/20/2002 07:05
  1. ;;8.0;MailMan;;Jun 28, 2002
  1. ; Replaces the class III routines ^XMRPOPA, ^XMRPOPB, ^XMRPOPC,
  1. ; which were written by Chiao-Ming Wu, WASH-ISC.
  1. ;
  1. ; Implements RFC 1939 (replaces RFC 1725)
  1. ; Post Office Protocol - Version 3 (POP3) maildrop service
  1. ;
  1. ; Rather than locking the user's IN basket, which severely disrupts
  1. ; mail delivery, we take a snapshot of it, and keep the snapshot in
  1. ; a temp global. We then use the temp global during the session.
  1. ; Here is the layout of the global:
  1. ;
  1. ; ^TMP("XM",$J,"POP3")=# msgs^# octets ; total msgs in IN basket
  1. ; ; (updated if msgs are deleted)
  1. ; ^TMP("XM",$J,"POP3",1)=XMZ^# octets ; msgs 1 thru n are in
  1. ; ... ; IN basket.
  1. ; ^TMP("XM",$J,"POP3",i)=XMZ^# octets ;
  1. ; ^TMP("XM",$J,"POP3",j)=XMZ^# octets ;
  1. ; ... ;
  1. ; ^TMP("XM",$J,"POP3",n)=XMZ^# octets ;
  1. ; ;
  1. ; ^TMP("XM",$J,"POP3","D",i)=XMZ ; user deleted msg i
  1. ; ^TMP("XM",$J,"POP3","D",j)=XMZ ; user deleted msg j
  1. ENTRY ;
  1. N XMK,XMSTATE,XMCMDS,XMCMD,XMDUZ,XMACCESS,XMVERIFY,XMTRY,XMTMSGS,XMTOCTS,XMV
  1. I '$D(ZTQUEUED) S X=$S($D(^%ZOSF("ERRTN")):^("ERRTN"),1:"ERR^ZU"),@(^%ZOSF("TRAP"))
  1. I '$G(DUZ) S DUZ=.5
  1. I '$D(XMDUZ) S XMDUZ=DUZ
  1. I '$D(XMC("BATCH")) S XMC("BATCH")=0
  1. I $S('$D(XMCHAN):1,XMCHAN="":1,1:0) S XMCHAN="TCP/IP-MAILMAN"
  1. D OPEN^XML
  1. I $G(ER)=1 D ^%ZISC:IO'=$G(IO(0)) W !,"Device open failed !",$C(7) Q
  1. S:'$D(XM) XM=""
  1. I 'XMC("BATCH") X ^%ZOSF("EOFF") S X=255 X ^%ZOSF("RM"),^%ZOSF("TYPE-AHEAD")
  1. S ER=0
  1. S XMK=1
  1. S XMSG="+OK "_^XMB("NETNAME")_" POP3 server ready (Comments to: POSTMASTER@"_^XMB("NETNAME")_")" X XMSEN Q:ER
  1. S XMCMDS("AUTH")="^PASS^QUIT^USER^"
  1. S XMCMDS("TRAN")="^DELE^LIST^NOOP^QUIT^RETR^RSET^STAT^TOP^UIDL^"
  1. S XMSTATE="AUTH"
  1. F X XMREC Q:ER D Q:XMCMD="QUIT"!ER
  1. . I XMRG="" S ER=1,XMCMD="" Q
  1. . S XMCMD=$P(XMRG," ",1)
  1. . I $L(XMCMD)<3!($L(XMCMD)>4)!(XMCMD'?.U) S XMSG="-ERR no such command" X XMSEN Q
  1. . I $T(@XMCMD)'[";;" S XMSG="-ERR no such command" X XMSEN Q
  1. . I XMCMDS(XMSTATE)'[(U_XMCMD_U)="" S XMSG="-ERR no such command in "_XMSTATE_" state" X XMSEN Q
  1. . D @XMCMD
  1. I ER,$G(XMCMD)'="QUIT" D QUIT
  1. Q
  1. DELE ;;
  1. N XMID
  1. S XMID=$P(XMRG," ",2,999)
  1. Q:'$$OKID(XMID)
  1. N XMREC,XMZ,XMOCTS
  1. S XMZ=+^TMP("XM",$J,"POP3",XMID),XMOCTS=$P(^(XMID),U,2)
  1. S ^TMP("XM",$J,"POP3","D",XMID)=XMZ
  1. S XMREC=^TMP("XM",$J,"POP3")
  1. S ^TMP("XM",$J,"POP3")=($P(XMREC,U,1)-1)_U_($P(XMREC,U,2)-XMOCTS)
  1. S XMSG="+OK message "_XMID_" deleted" X XMSEN
  1. Q
  1. OKID(XMID) ;
  1. I XMID="" S XMSG="-ERR message-id required" X XMSEN Q 0
  1. I +XMID'=XMID S XMSG="-ERR improper message-id" X XMSEN Q 0
  1. I '$D(^TMP("XM",$J,"POP3",XMID)) S XMSG="-ERR no such message" X XMSEN Q 0
  1. I $D(^TMP("XM",$J,"POP3","D",XMID)) S XMSG="-ERR message "_XMID_" already deleted" X XMSEN Q 0
  1. Q 1
  1. LIST ;;
  1. N XMID,XMOCTS
  1. S XMID=$P(XMRG," ",2,999)
  1. I XMID="" D Q
  1. . S XMSG="+OK "_$P(^TMP("XM",$J,"POP3"),U,1)_" messages ("_$P(^("POP3"),U,2)_" octets)" X XMSEN Q:ER
  1. . F S XMID=$O(^TMP("XM",$J,"POP3",XMID)) Q:'XMID S XMOCTS=$P(^(XMID),U,2) D Q:ER
  1. . . Q:$D(^TMP("XM",$J,"POP3","D",XMID))
  1. . . S XMSG=XMID_" "_XMOCTS X XMSEN
  1. . S XMSG="." X XMSEN
  1. Q:'$$OKID(XMID)
  1. S XMSG="+OK "_XMID_" "_$P(^TMP("XM",$J,"POP3",XMID),U,2) X XMSEN
  1. Q
  1. NOOP ;;
  1. S XMSG="+OK" X XMSEN
  1. Q
  1. PASS ;;
  1. I '$D(XMACCESS) D LOGINERR("-ERR sorry, USER access code expected") Q
  1. S XMVERIFY=$P(XMRG," ",2,999)
  1. I XMVERIFY'="" D LOGIN Q
  1. D LOGINERR("-ERR sorry, PASS verify code expected")
  1. Q
  1. LOGIN ;
  1. N XMLOGIN
  1. S XMLOGIN=$$LOGINOK
  1. I 'XMLOGIN D LOGINERR("-ERR "_$P(XMLOGIN,U,2)) Q
  1. K XMACCESS,XMVERIFY
  1. S XMSTATE="TRAN"
  1. S XMDUZ=DUZ
  1. D INIT^XMVVITAE
  1. D MAILDROP
  1. D RSET
  1. Q
  1. LOGINOK() ;
  1. I $T(@"USERSET^XUSRA")="" Q $$OLDCHK
  1. Q $$USERSET^XUSRA(XMACCESS_";"_XMVERIFY)
  1. OLDCHK() ;
  1. N XUSER,XUF,%1,XMLOGIN
  1. S XUF=0
  1. S XMLOGIN=$$CHECKAV^XUS(XMACCESS_";"_XMVERIFY)
  1. I XMLOGIN S DUZ=XMLOGIN Q 1
  1. Q "0^Not a valid ACCESS CODE/VERIFY CODE pair"
  1. MAILDROP ;
  1. N XMKZ,XMZ,XMOCTS,XMID
  1. K ^TMP("XM",$J,"POP3")
  1. S (XMID,XMKZ,XMTOCTS)=0
  1. F S XMKZ=$O(^XMB(3.7,XMDUZ,2,XMK,1,"C",XMKZ)) Q:'XMKZ D
  1. . S XMZ=$O(^XMB(3.7,XMDUZ,2,XMK,1,"C",XMKZ,0))
  1. . I '$D(^XMB(3.7,XMDUZ,2,XMK,1,XMZ,0)) D ADDITC^XMUT4A(XMDUZ,XMK,XMZ,XMKZ)
  1. . I '$D(^XMB(3.9,XMZ,0)) D ZAPIT^XMXMSGS2(XMDUZ,XMK,XMZ) Q
  1. . S XMID=XMID+1
  1. . S XMOCTS=$$OCTETS(XMZ)
  1. . S XMTOCTS=XMTOCTS+XMOCTS
  1. . S ^TMP("XM",$J,"POP3",XMID)=XMZ_U_XMOCTS
  1. S XMTMSGS=XMID
  1. Q
  1. OCTETS(XMZ) ; Returns the number of 'octets' in a message.
  1. ; Basically, that's a count of the number of characters.
  1. ; We estimate it by multiplying the number of lines by 50.
  1. Q $P($G(^XMB(3.9,XMZ,2,0)),U,4)*50
  1. LOGINERR(XMSG) ;
  1. K XMACCESS,XMVERIFY
  1. S XMTRY=$G(XMTRY)+1
  1. I XMTRY<3 X XMSEN Q
  1. D SIGNOFF(XMSG_"; 3 tries and you're out!")
  1. S XMCMD="QUIT"
  1. Q
  1. QUIT ;;
  1. I XMSTATE="TRAN",'ER D UPDATE
  1. K ^TMP("XM",$J,"POP3")
  1. D SIGNOFF("")
  1. Q
  1. SIGNOFF(XMSG) ;
  1. S XMSG=$S(XMSG'="":XMSG_"; ",ER:"-ERR ",1:"+OK ")_^XMB("NETNAME")_" POP3 server signing off" X XMSEN
  1. Q
  1. RETR ;;
  1. N XMID
  1. S XMID=$P(XMRG," ",2,999)
  1. Q:'$$OKID(XMID)
  1. S XMSG="+OK "_$P(^TMP("XM",$J,"POP3",XMID),U,2)_" octets" X XMSEN Q:ER
  1. D RETRIEVE(XMID,"*")
  1. Q
  1. RSET ;;
  1. K ^TMP("XM",$J,"POP3","D")
  1. S ^TMP("XM",$J,"POP3")=XMTMSGS_U_XMTOCTS
  1. S XMSG="+OK maildrop has "_XMTMSGS_" messages ("_XMTOCTS_" octets)" X XMSEN
  1. Q
  1. STAT ;;
  1. S XMSG="+OK "_$P(^TMP("XM",$J,"POP3"),U,1)_" "_$P(^("POP3"),U,2) X XMSEN
  1. Q
  1. TOP ;;
  1. N XMID,XMLINES
  1. S XMID=$P(XMRG," ",2)
  1. Q:'$$OKID(XMID)
  1. S XMLINES=$P(XMRG," ",3,999)
  1. I +XMLINES'=XMLINES S XMSG="-ERR improper number of lines" X XMSEN Q
  1. S XMSG="+OK" X XMSEN Q:ER
  1. D RETRIEVE(XMID,XMLINES)
  1. Q
  1. UIDL ;;
  1. N XMID,XMZ
  1. S XMID=$P(XMRG," ",2,999)
  1. I XMID="" D Q
  1. . S XMSG="+OK" X XMSEN Q:ER
  1. . F S XMID=$O(^TMP("XM",$J,"POP3",XMID)) Q:'XMID S XMZ=+^(XMID) D Q:ER
  1. . . Q:$D(^TMP("XM",$J,"POP3","D",XMID))
  1. . . S XMSG=XMID_" "_XMZ X XMSEN
  1. . S XMSG="." X XMSEN
  1. Q:'$$OKID(XMID)
  1. S XMSG="+OK "_XMID_" "_+^TMP("XM",$J,"POP3",XMID) X XMSEN
  1. Q
  1. USER ;;
  1. S XMACCESS=$P(XMRG," ",2,999)
  1. I XMACCESS'="" S XMSG="+OK" X XMSEN Q
  1. D LOGINERR("-ERR sorry, USER access code expected")
  1. Q
  1. UPDATE ;
  1. N XMID,XMZ
  1. S XMID=0
  1. F S XMID=$O(^TMP("XM",$J,"POP3","D",XMID)) Q:'XMID S XMZ=+^(XMID) D DEL^XMXMSGS2(XMDUZ,"",XMZ)
  1. Q
  1. RETRIEVE(XMID,XMLINES) ;
  1. N XMZ,XMRESP,XMIM,XMINSTR,XMIU
  1. S XMZ=+^TMP("XM",$J,"POP3",XMID)
  1. D INMSG^XMXUTIL2(XMDUZ,"",XMZ,"","I",.XMIM,.XMINSTR,.XMIU)
  1. D RETRXMZ(XMZ,XMLINES,.XMIM) Q:ER
  1. I 'XMLINES,XMIM("RESPS") D Q:ER
  1. . F XMRESP=XMIU("RESP")+1:1:XMIM("RESPS") D Q:ER
  1. . . N XMIR
  1. . . D INRESP^XMXUTIL2(XMZ,XMRESP,"I",.XMIR) Q:'$D(XMIR)
  1. . . I XMIR("SUBJ")?1"R".N S XMIR("SUBJ")="Re: "_XMIM("SUBJ")
  1. . . S XMSG="" X XMSEN Q:ER ; just for visual separation
  1. . . D RETRXMZ(XMIR("XMZ"),"*",.XMIR,XMZ) Q:ER
  1. E S XMRESP=0
  1. S XMSG="." X XMSEN Q:ER
  1. D LASTACC^XMXUTIL(XMDUZ,XMK,XMZ,XMRESP,.XMIM,.XMINSTR,.XMIU)
  1. I $D(^XMB(3.7,XMDUZ,"N0",XMK,XMZ)),+XMRESP=+$P($G(^XMB(3.9,XMZ,3,0)),U,4) D NONEW^XMXUTIL(XMDUZ,XMK,XMZ,1)
  1. Q
  1. RETRXMZ(XMZ,XMLINES,XMIM,XMZO) ;
  1. N XMI
  1. I $O(^XMB(3.9,XMZ,2,0))'<1 D CRE8HDR(XMZ,.XMIM,.XMZO) Q:ER
  1. S XMI=0
  1. F S XMI=$O(^XMB(3.9,XMZ,2,XMI)) Q:'XMI S XMSG=^(XMI,0) S:$E(XMSG)="." XMSG="."_XMSG X XMSEN Q:ER I XMLINES,XMI'<XMLINES Q
  1. Q
  1. CRE8HDR(XMZ,XMIM,XMZO) ;
  1. S XMSG="Message-ID: <"_XMZ_"@"_^XMB("NETNAME")_">" X XMSEN Q:ER
  1. S XMSG="From: <"_$$NETNAME^XMXUTIL(XMIM("FROM"))_">" X XMSEN Q:ER
  1. S XMSG="To: <"_XMV("NETNAME")_">" X XMSEN Q:ER
  1. S XMSG="Subject: "_XMIM("SUBJ") X XMSEN Q:ER
  1. S XMSG="Date: "_$$INDT^XMXUTIL1(XMIM("DATE")) X XMSEN Q:ER
  1. S XMSG="" X XMSEN Q:ER
  1. Q