/* ------------------------------------------------------------------------ :Program. ReplyDaemon.rexx :Contents. send receipt-reply messages depending on folder :Author. hartmut Goebel [hG] :Address. Aufsesßplatz 5, D-90459 Nürnberg :Address. UseNet: hartmut@oberon.nbg.sub.org :History. 1.0 [hG] initial release :History. 1.1 [hG] · output onl if there are messages to process :History. · no longer tests PostPone flag :History. 1.2 [hG] uses hgrexxsupport.library 1.2 :History. 2.0 [hG] added optional check for ToName, adapted to UMS v11 :Version. $VER: ReplyDaemon.rexx 2.0 (25.1.95) [hG] :Copyright. Public Domain :Language. ARexx :Translator. RexxMast ------------------------------------------------------------------------ */ /* NAME ReplyDaemon -- send receipt-reply messages depending on folder TEMPLATE Name,Password,Server/K,UseReplyAccount/S,UseFolderAsReplyName/S FUNCTION ReplyDaemon checks for new messages within some given folders and sends receipt-reply messages to the sender of these messages. The checked messages will be marked as unread, archived and postponed, thus both avoiding re-processing and expiring. This is quite usefull for maintaining e.g. a bugs database where the reporters should be given a receipt. You may use a tool like Reciever2Folder to sort your messages into folders first and then run ReplyDaemon to send the receipt-replies. The folders to be checked have to be listed in a config variable. Also subject and body text for the message to be send can be defined per folder via config vars. The receipt-reply may either be send from the users account or a special ReplyDaemon account. The later is for avoiding garbage messages in the user's mail folders. The Reply-Name put in the send message may get three values: - the folder name (if option UseFolderAsReplyName is set) - a reply name specified by a config var (see below) - not set, thus later replies will get to either the user or the ReplyDaemon, depenting on the option UsereplyAccount OPTIONS Name, Password, Server are the normal UMS parameters UseReplyAccount This option tells ReplyDaemon to send the messages not from the users account but his own one. Thus it's possible to expire the sent replies as soon as they are exported by setting 'expire.mail = 0' the the ReplyDaeomn's account. The ReplyDaeomn's account must have an alias 'ReplyDaemon' and require an empty password. Also WriteAccess must be set correctly. UseFolderAsReplyName This tells ReplyDaemon to set the ReplyName of send messages to the name of the folder. The config-var ReplyDaemon.ReplyName. will not be used then. USED CONFIG-VARS ReplyDaemon.Folderlist (required) List of folders to be checked, form: FolderName [ "," ToName ] When specify an optional 'ToName' (seperated from the folder name by a comma), only messages addressed to this name are replied. Thus you can but all mail about a certain project in one single folder and only the bugs get a automatic reply. ReplyDaemon.Subject. (required) ReplyDaemon.MsgText. (required) Defines the subject and body text for the send-out message. The body text will become preceded by an address ('Hi ') plus one empty line and appended by one emtpy line plus the text 'Of course, this message has been generated automaticly :-)'. ReplyDaemon.ReplyName. (optional) If the option UseFolderAsReplyName is not set, this var determines a ReplyName to be put into the send message. EXAMPLE User Name "Mail-Daemon" Alias "Reply-Daemon" Password NetAccess = "#?" expire.mail = "0" expire.private = "0" .... EndUser User Name "Joe User" Password "noone" Alias "ju" Alias "project" Alias "project-bugs" Alias "info" .... ReplyDaemon.FolderList= "project, project-bugs*ninfo" ReplyDaemon.ReplyName.Bugs = "ju" ReplyDaemon.Subject.Bugs = "Recieved your bug report:" ReplyDaemon.MsgText.Bugs= "Thank you for your bug report.*n Joe User*NBugs Maintainer" .... ReplyDaemon.Subject.Info = "Here's your Info" ReplyDaemon.MsgText.Info= "Thank you for requesting the info*n Joe User" .... EndUser TODO >* Es sollte auch die Möglichkeit geben, statt des Textes direkt (in > ums.config) einen FileNamen für ein Textfile anzugeben (z.B. statt > *.msgtext.* *.msgfile.*). Das bläht die config nicht garso > (unnötig) auf. Die Idee kam mir deshalb, weil man z.B. auf diese > Art ziemlich einfach längere (Info-)Files verschicken könnte, ohne > sie nach jeder Änderung zusätzlich in die ums.config quetschen zu > müssen. Ein schönes Beispiel wäre (dachte ich mir), den PGP public > key automatisiert zu verschicken, wenn jemand an > pgp@irgendwer.nbg.sub.org schreibt. */ /*** Startup ***/ ProgramName = "ReplyDaemon"; ArgsTemplate = "Name,Password,Server/K,UseReplyAccount/S,UseFolderAsReplyName/S" ReplyName = "Reply-Daemon"; ReplyPassword = ""; call addlib("hgrexxsupport.library",0,-30); interpret include("ums:s/UMSInit.rexx") if rc ~= 0 then do say "cannot read UMS include-file!" exit 20 end /*** Login ***/ replyAccount = 0; account = UMSLogin(name, password, server) if (account = 0) then do say "unable to login." exit 10 end if useReplyAccount then do replyAccount = UMSLogin(replyName, ReplyPassword, server) if (replyAccount = 0) then do say "unable to login." halt 10 end end; else replyAccount = account FLAGS_Empty = MakeFlags() FLAG_0 = MakeFlags(0) FLAG_1 = MakeFlags(1) FLAG_2 = MakeFlags(2) FLAGS_012 = MakeFlags(0,1,2) FLAG_Old = MakeFlags(UMSUSTAT_Old) FLAGS_PostArch = MakeFlags(UMSUSTAT_PostPoned,UMSUSTAT_Archive) Match = MakeFlags(UMSUSTAT_ViewAccess) Mask = MakeFlags(UMSUSTAT_ViewAccess,/*UMSUSTAT_PostPoned,*/UMSUSTAT_Archive, UMSUSTAT_Old) call UMSSelectField(account, "L", FLAG_0, FLAGS_Empty,,,UMSCODE_Group, "", TRUE) call UMSSelectFlags(account, "L", FLAG_1, FLAGS_Empty,,,"U", Mask, Match) Folderlist = GetUMSConfigVar("","Folderlist", TRUE) do forever parse var FolderList FolderName '0A'x Folderlist FolderName = strip(FolderName) if FolderName = '' then leave; parse var FolderName FolderName ',' ToName ToName = upper(ToName); call ReplyOnMsgsInFolder; end /*** Final cleanup ***/ BREAK_C: BREAK_D: BREAK_E: BREAK_F: ERROR: HALT: IOERR: SYNTAX: IF RC ~= 0 THEN DO say "Error: " rc errortext(rc) "Line" sigl END /*** Logout ***/ call UMSLogout(account) if useReplyAccount then call UMSLogout(replyAccount) exit ReplyOnMsgsInFolder: MessageText = GetUMSConfigVar(FolderName,"MsgText", TRUE) Subject = GetUMSConfigVar(FolderName,"Subject", TRUE) ReplyName = GetUMSConfigVar(FolderName,"ReplyName", FALSE) call UMSSelectFlags(account, "L", FLAGS_Empty, FLAG_2,,,"U", FLAGS_Empty, FLAGS_Empty) call UMSSelectField(account, "L", FLAG_2, FLAGS_Empty,,,UMSCODE_Folder, FolderName) numTagedMsgs = UMSSelectFlags(account, "L", FLAGS_Empty, FLAGS_Empty,,,"L", FLAGS_012, FLAGS_012) if numTagedMsgs = 0 then return say ProgramName || ":" numTagedMsgs "messages in folder" FolderName "found" i=0;last = 0 do forever last = UMSSearchFlags(account, "L", FLAGS_012, FLAGS_012, last) if last = 0 then leave /* we are done */ drop msg. /* _IMPORTANT_ */ if ~ UMSReadMsgHeader(account, last, msg.,true) then do call CheckErr exit end /* generate reply */ drop newmsg. if symbol("msg.UMSCODE_ReplyName") = "VAR" then do newmsg.UMSCODE_ToName = msg.UMSCODE_ReplyName end; else newmsg.UMSCODE_ToName = msg.UMSCODE_FromName /* test whether we should not reply */ if (find(msg.UMSCODE_Attributes,'receipt') ~= 0), /* genaratec message */ | abbrev(upper(newmsg.UMSCODE_ToName),"MAILINGLIST "), /* no reply to a mailinglist */ | ((ToName ~= '') & (upper(msg.UMSCODE_ToName) ~= ToName)) then iterate if symbol("msg.UMSCODE_ReplyAddr") = "VAR" then do newmsg.UMSCODE_ToAddr = msg.UMSCODE_ReplyAddr end; else if symbol("msg.UMSCODE_FromAddr") = "VAR" then do newmsg.UMSCODE_ToAddr = msg.UMSCODE_FromAddr end if useFolderAsReplyName then do newmsg.UMSCODE_ReplyName = FolderName; end; else if ReplyName ~= "" then do newmsg.UMSCODE_ReplyName = ReplyName; end newmsg.UMSCODE_RefID = msg.UMSCODE_MsgID newmsg.UMSCODE_Attributes = "receipt" newmsg.UMSCODE_Subject = Subject msg.UMSCODE_Subject newmsg.UMSCODE_MsgText = "Hi" msg.UMSCODE_FromName ||"!" || '0A 0A'x || MessageText ||, '0A 0A'x || 'Of course, this message has been generated automaticly :-)' if UMSWriteMsg(replyAccount, newmsg.) = 0 then call CheckErr else do /* mark message as postponed and archived but unread */ call UMSSelectMsg(account,"U", FLAGS_PostArch, FLAG_Old, last) i = i+1; end; end; say i return; GetUMSConfigVar: procedure expose account replyAccount programname useReplyAccount /* search order: * User: ProgName.varname.FolderName * User: ProgName.varname * ReplyDeamon ProgName.varname */ FolderName = arg(1); if FolderName ~= '' then Foldername = '.'FolderName; varname = ProgramName || "."arg(2); var = UMSReadConfig(account,varname || FolderName) if (var = "") & (FolderName ~= "") then var = UMSReadConfig(account,varname) if (var = "") & useReplyAccount & (replyAccount ~= 0) then var = UMSReadConfig(replyAccount,varname) if (arg(3) = TRUE) then do if (var = '') then do say ProgramName || ": Configuration variable '" || varname || "' is missing!" exit end end return var /*** Support ***/ CheckErr: procedure expose account replyAccount useReplyAccount err = UMSErrNum(account) if err ~= 0 then do say "UMS Error #" || err || ": " || UMSErrTxt(account) end; else if useReplyAccount then do err = UMSErrNum(replyAccount) if err ~= 0 then say "UMS Error #" || err || ": " || UMSErrTxt(replyAccount) end return