{$X+,B-,V-} {essential compiler directives} Unit pmail; {Example unit for the nwMess unit / NwTP 0.6 API. (c) 1993,1995, R.Spronk } INTERFACE uses nwMisc,nwBindry,nwMess,nwServ; {nwserv used for GetFileServerDateAndTime only. } CONST {Mail Options} PM_NO_NOTIFY =$02; PM_DELIVER_IF_AF=$10; PM_NO_CONF_REQ =$08; PM_NO_MAIL =$04; Var result:word; Function PMailInstalled:boolean; { Checks if an object PEGASUS_MAIL of type OT_PEGASUS_MAIL exists in the bindery. If the object exists, pmail is installed.} Function SendMailFile(DestObjectName:string;objType:word; subject,fileName:string):boolean; { PEGASUS MAIL V3.0 Compatible: Sends a messagebody textfile (ASCII) to the mail directory of the destination object. The object can either be a user or a group object. Wildcards are allowed. The destination object will see the calling object as the message originating object. Notes: -Autoforwarding will be ignored. -This is a single server function. -Possible resultcodes: $0 Success; $100 * The given file could not be found. Supply full path and filename. $101 * User and Group objects only; $102 ? Error scanning bindery, see Nwbindry.Result for netware error # ; $110 ? Group has no members / error reading members of a group. $111 * Group or user object doesn't exist $200 * Insufficient privilege to use the mail system. $201 * You are not allowed to send to groups. $202 * The supplied receiver user object has no access to mail / has halted all incoming mail OR the receiving object equals the sending object. -All msgs were sent when the resultcode is $00; -No msgs are send. (resultcodes marked with *) -Some or no msgs may have been sent before this error occured.(marked ?) } IMPLEMENTATION{=============================================================} Function PMailInstalled:boolean; Var lastObj :LongInt; foundObjName:string; rt :word; rid :LongInt; rf,rs :byte; rhp :Boolean; begin { Checks if an object PEGASUS_MAIL of type OT_PEGASUS_MAIL exists in the bindery. If the object exists, pmail is installed.} lastObj:=-1; PmailInstalled:=ScanBinderyObject('PEGASUS_MAIL',OT_PEGASUS_MAIL,lastObj, foundObjName,rt,rid,rf,rs,rhp); end; {------------------Send file as message--------------------------------------} Type TPmailHdr=record from,too,date,subject,xmailer:string; end; var senderObjId:LongInt; warning :byte; time :TnovTime; Procedure getRandomFileName(Var filename:string); { construct a semi-random filename out of the current date & time } Var tim:TnovTime; t :byte; begin nwServ.GetFileServerDateAndTime(tim); fileName[0]:=#8; filename[1]:=chr(tim.month); filename[2]:=chr(tim.day); filename[3]:=chr(tim.hour); filename[4]:=chr(tim.min DIV 2); filename[5]:=chr(tim.sec DIV 2); filename[6]:=chr(random(36)); filename[7]:=chr(random(36)); filename[8]:=chr(random(36)); for t:=1 to 8 do if filename[t]<=#9 then inc(filename[t],ord('0')) else inc(filename[t],ord('A')-10); end; Function IsObjGroupMember(objId:longInt;GroupName:string):boolean; Var objName:string; objType:word; begin IsObjGroupMember:=GetBinderyObjectName(objId,objName,objType) and IsBinderyObjectInSet(GroupName,OT_USER_GROUP,'GROUP_MEMBERS', objName,OT_USER); end; Function PmailNotifyUser(objName:string):boolean; { Read the MAIL_OPTIONS property (created by Pmail) of the destination object. Structure of the property: 01 len Pmail_forwarding_adress_(asciiz) [OPTIONAL] 02 len Internet_forwarding_adress_(asciiz) [OPTIONAL] 03 04 extended_features_byte ???_byte [NOT optional] 04 len Charon 3.5+ sender synonym. [OPTIONAL] Notes: -len= 3+length of the next asciiz string (excluding trailing 0) -the above fields appear within the property in random order. If the PM_NO_NOTIFY or the PM_NO_MAIL flag within the extended features byte is set, then the destination object won't be notified. } Var segNbr :word; propValue:Tproperty; moreSeg :boolean; propFlags:Byte; t :word; fieldFlag:byte; Notify :boolean; begin SegNbr:=1; warning:=$00; IF ReadPropertyValue(objName,OT_USER,'MAIL_OPTIONS',SegNbr, propValue,moreSeg,propFlags) then begin t:=1; REPEAT fieldFlag:=propValue[t]; if fieldFlag<>3 then t:=t+propValue[t+1]; UNTIL (t>127) or (fieldFlag=3); if fieldFlag=3 then begin Notify:=((propValue[t+2] and PM_NO_NOTIFY)=0) and ((propValue[t+2] and PM_NO_MAIL)=0); if (propValue[t+2] and PM_NO_MAIL)>0 then warning:=$02; end; end else if nwBindry.result=$EC { empty property, default: notify. } then Notify:=true else Notify:=false; { when in doubt, don't notify } PmailNotifyUser:=Notify; end; Procedure SendMsgToUser(UserObjID:LongInt;VAR Hdr:TPmailHdr;fileName:string); {copy file as a msg to the users' mail directory.} Var userObjName:string; objType :word; buffer :array[1..4096] of byte; bytesRead,bufOffs:word; MsgFilePath,MailDir,MailFile:string; Fin,Fout :file; sendIt,NotifyReceiver:boolean; MsgFrom :string; begin SendIt:=NOT(UserObjId=SenderObjId); { don't mail yourself } { checking Pmail settings.. } IF IsObjGroupMember(UserObjId,'NOMAILBOX') then SendIt:=false; IsObjGroupMember(UserObjId,'MAILUSERS'); if (nwBindry.result=$EA) { no such member } OR IsObjGroupMember(UserObjId,'NOMAIL') then sendit:=false; GetBinderyObjectName(UserObjID,UserObjName,objType); NotifyReceiver:=PmailNotifyUser(UserObjName); if warning=$02 { receiving user has PM_NO_MAIL flag raised } then sendit:=false; if sendit then begin warning:=$00; if pos('From',hdr.from)=0 then Hdr.from:= 'From: '+Hdr.from; MsgFrom:=Hdr.From; delete(MsgFrom,1,16); Hdr.too := 'To: '+UserObjName; if pos('Date',Hdr.date)=0 then Hdr.date:= 'Date: '+Hdr.date; if pos('Subj',Hdr.subject)=0 then Hdr.subject:='Subject: '+hdr.subject; Hdr.xmailer:='X-mailer: NwTP gateway to Pmail.'; bufOffs:=1; move(hdr.from[1],buffer[bufOffs],ord(hdr.from[0])); inc(bufOffs,2+ord(hdr.from[0])); buffer[bufOffs-2]:=13;buffer[bufOffs-1]:=10; { ret/ lf } move(hdr.too[1],buffer[bufOffs],ord(hdr.too[0])); inc(bufOffs,2+ord(hdr.too[0])); buffer[bufOffs-2]:=13;buffer[bufOffs-1]:=10; { ret/ lf } move(hdr.date[1],buffer[bufOffs],ord(hdr.date[0])); inc(bufOffs,2+ord(hdr.date[0])); buffer[bufOffs-2]:=13;buffer[bufOffs-1]:=10; { ret/ lf } move(hdr.subject[1],buffer[bufOffs],ord(hdr.subject[0])); inc(bufOffs,2+ord(hdr.subject[0])); buffer[bufOffs-2]:=13;buffer[bufOffs-1]:=10; { ret/ lf } move(hdr.xmailer[1],buffer[bufOffs],ord(hdr.xmailer[0])); inc(bufOffs,2+ord(hdr.xmailer[0])); buffer[bufOffs-2]:=13;buffer[bufOffs-1]:=10; { ret/ lf } buffer[bufOffs]:=13;buffer[bufOffs+1]:=10; { empty line } inc(bufOffs,2); MailDir:=HexStr(UserObjId,8); while maildir[1]='0' do delete(Maildir,1,1); GetRandomFileName(MailFile); {$I-} MsgFilePath:='SYS:MAIL\'+MailDir+'\'+MailFile+'.CNM'; assign(Fin,fileName); reset(Fin,1); assign(Fout,MsgFilePath); rewrite(Fout,1); { buffOfs-1 = number of bytes in buffer already filled } BlockRead(Fin,buffer[bufOffs],4096-(bufOffs-1),bytesRead); BlockWrite(Fout,buffer[1],bytesRead+(bufOffs-1)); REPEAT BlockRead(Fin,buffer[1],4096,bytesRead); BlockWrite(Fout,buffer[1],bytesRead); UNTIL bytesRead<4096; close(Fin); close(Fout); {$I+} IF NotifyReceiver then nwMess.SendmessageToUser(UserObjName, '(NwTP/Pmail:) You have mail. (From:'+MsgFrom+')') end else warning:=$01; end; Procedure SendMsgToGroup(GroupObjName:string;Hdr:TPmailHdr;fileName:string); Label abrt; Var NbrOfWrites:word; i :byte; lastObj :LongInt; foundGroupName:string; rt :word; rid :LongInt; rf,rs :byte; rhp :boolean; SegNbr :byte; propValue:Tproperty; moreSeg :boolean; propFlags:byte; objId : LongInt; begin NbrOfWrites:=0; lastObj:=-1; WHILE ScanBinderyObject(GroupObjName,OT_USER_GROUP,lastObj, foundGroupName,rt,rid,rf,rs,rhp) do begin {1} if (GroupObjName<>'NOMAIL') and (GroupObjName<>'NOMAILBOX') then begin {3} SegNbr:=1; While ReadPropertyValue(foundGroupName,OT_USER_GROUP,'GROUP_MEMBERS', SegNbr,propValue,moreSeg,propFlags) do begin {5} i:=1; Repeat objId:=MakeLong((PropValue[i] *256 +PropValue[i+1]), (PropValue[i+2] *256 + PropValue[i+3] ) ); if objId<>0 then begin SendMsgToUser(objId,Hdr,fileName); inc(NbrOfWrites); end; inc(i,4); Until (i>128) or (objId=0); inc(SegNbr); end; {5} If nwBindry.Result<>$EC {no such segment} then begin Result:=$110; goto abrt; end; end; {3} end; {1} if nwBindry.Result<>$FC {no such object} then begin result:=$111; goto abrt; end; if NbrOfWrites=0 {no users found} then result:=$110; abrt: ; end; Function SendMailFile(DestObjectName:string;objType:word; subject,fileName:string):boolean; Var secLevel :byte; senderName:string; SenderObjType:word; Hdr :TPmailHdr; lastObj :longInt; foundUserName:string; rt :word; rf,rs :byte; rhp :boolean; DestObjId :longint; testFile :file; begin Warning:=$00; { check: does filename exist? if not, stop right away. error $100 } {$I-} assign(testFile,filename); reset(testFile); if IOresult<>0 then begin result:=$100; SendmailFile:=False; exit; end else close(testFile); {$I+} GetBinderyAccessLevel(secLevel,senderObjId); GetBinderyObjectName(senderObjId,senderName,SenderObjType); {checking pmail config. groups... } IsObjGroupMember(senderObjId,'MAILUSERS'); if (nwBindry.result=$EA) { mailusers group exists, sender not a member } OR IsObjGroupMember(senderObjId,'NOMAIL') then begin result:=$200; { Insufficient privilege to use the mail system. } SendMailFile:=false; exit; end; Hdr.from:=senderName; Hdr.subject:=subject; GetFileServerDateAndTime(time); NovTime2String(time,Hdr.date); Result:=0; if objType=OT_USER then begin lastObj:=-1; WHILE ScanBinderyObject(DestObjectName,OT_USER,lastObj, foundUserName,rt,DestObjID,rf,rs,rhp) do begin SendMsgToUser(DestObjId,Hdr,fileName); end; IF nwBindry.result<>$FC { no such object } then result:=$102; end else if objType=OT_USER_GROUP then begin IsObjGroupMember(senderObjId,'GROUPMAIL'); if (nwBindry.result=$EA) { group groupmail exists, sender not a member } OR IsObjGroupMember(senderObjId,'NOGROUPMAIL') then result:=$201 { don't send } else SendMsgToGroup(DestObjectName,Hdr,fileName) end else result:=$101; if (warning=$01) and (objType=OT_USER) and (result=$00) and (pos('*',DestObjectName)=0) and (pos('?',DestObjectName)=0) then result:=$202; SendMailFile:=(result=0); { possible resultcodes: $0 Success; $100 * The given file could not be found. Supply full path and filename. $101 * User and Group objects only; $102 ? Error scanning bindery, see Nwbindry.Result for netware error # ; $110 ? Group has no members / error reading members of a group. $111 * Group or user object doesn't exist $200 * Insufficient privilege to use the mail system. $201 * You are not allowed to send to groups. $202 * The supplied receiver user object has no access to mail / has halted all incoming mail OR the receiving object equals the sending object. Note: -All msgs were send when the resultcode is $00; -No msgs are send. (resultcodes marked with *) -Some or no msgs may have been send before this error occured.(marked ?) } end; begin Randomize; end.