home *** CD-ROM | disk | FTP | other *** search
/ Meeting Pearls 3 / Meeting_Pearls_III.iso / Pearls / comm / Mail+News / UMS11 / rexx / ReplyDaemon.rexx < prev    next >
OS/2 REXX Batch file  |  1995-09-11  |  11KB  |  349 lines

  1. /* ------------------------------------------------------------------------
  2. :Program.    ReplyDaemon.rexx
  3. :Contents.   send receipt-reply messages depending on folder
  4. :Author.     hartmut Goebel [hG]
  5. :Address.    Aufsesßplatz 5, D-90459 Nürnberg
  6. :Address.    UseNet: hartmut@oberon.nbg.sub.org
  7. :History.    1.0  [hG]  initial release
  8. :History.    1.1  [hG]  · output onl if there are messages to process
  9. :History.               · no longer tests PostPone flag
  10. :History.    1.2  [hG]  uses hgrexxsupport.library 1.2
  11. :History.    2.0  [hG]  added optional check for ToName, adapted to UMS v11
  12. :History.    2.1  [cab] replaced hgrexxsupport.library/MakeFlags() by
  13. :History.               UMSMakeFlags(), included kaib's UMSInit.rexx
  14. :Version.    $VER: ReplyDaemon.rexx 2.1 (11.09.95)
  15. :Copyright.  Public Domain
  16. :Language.   ARexx
  17. :Translator. RexxMast
  18. ------------------------------------------------------------------------ */
  19. /*
  20.  
  21. NAME
  22.      ReplyDaemon  --  send receipt-reply messages depending on folder
  23.  
  24. TEMPLATE
  25.      Name,Password,Server/K,UseReplyAccount/S,UseFolderAsReplyName/S
  26.  
  27. FUNCTION
  28.      ReplyDaemon checks for new messages within some given folders
  29.      and sends receipt-reply messages to the sender of these
  30.      messages. The checked messages will be marked as unread,
  31.      archived and postponed, thus both avoiding re-processing and
  32.      expiring.
  33.  
  34.      This is quite usefull for maintaining e.g. a bugs database where
  35.      the reporters should be given a receipt. You may use a tool like
  36.      Reciever2Folder to sort your messages into folders first and
  37.      then run ReplyDaemon to send the receipt-replies.
  38.  
  39.      The folders to be checked have to be listed in a config
  40.      variable. Also subject and body text for the message to be send
  41.      can be defined per folder via config vars.
  42.  
  43.      The receipt-reply may either be send from the users account or a
  44.      special ReplyDaemon account. The later is for avoiding garbage
  45.      messages in the user's mail folders.
  46.  
  47.      The Reply-Name put in the send message may get three values:
  48.      - the folder name (if option UseFolderAsReplyName is set)
  49.      - a reply name specified by a config var (see below)
  50.      - not set, thus later replies will get to either the user or the
  51.        ReplyDaemon, depenting on the option UsereplyAccount
  52.  
  53. OPTIONS
  54.      Name, Password, Server
  55.         are the normal UMS parameters
  56.  
  57.      UseReplyAccount
  58.         This option tells ReplyDaemon to send the messages not from
  59.         the users account but his own one. Thus it's possible to
  60.         expire the sent replies as soon as they are exported by
  61.         setting 'expire.mail = 0' the the ReplyDaeomn's account.
  62.  
  63.         The ReplyDaeomn's account must have an alias 'ReplyDaemon'
  64.         and require an empty password. Also WriteAccess must be set
  65.         correctly.
  66.  
  67.      UseFolderAsReplyName
  68.          This tells ReplyDaemon to set the ReplyName of send messages
  69.          to the name of the folder. The config-var
  70.          ReplyDaemon.ReplyName.<folder> will not be used then.
  71.  
  72. USED CONFIG-VARS
  73.  
  74.      ReplyDaemon.Folderlist          (required)
  75.           List of folders to be checked, form: FolderName [ "," ToName ]
  76.  
  77.           When specify an optional 'ToName' (seperated from the
  78.           folder name by a comma), only messages addressed to this
  79.           name are replied. Thus you can but all mail about a certain
  80.           project in one single folder and only the bugs get a
  81.           automatic reply.
  82.  
  83.      ReplyDaemon.Subject.<folder>    (required)
  84.      ReplyDaemon.MsgText.<folder>    (required)
  85.           Defines the subject and body text for the send-out message.
  86.           The body text will become preceded by an address ('Hi
  87.           <FromName>') plus one empty line and appended by one emtpy
  88.           line plus the text 'Of course, this message has been
  89.           generated automaticly :-)'.
  90.  
  91.      ReplyDaemon.ReplyName.<folder>  (optional)
  92.           If the option UseFolderAsReplyName is not set, this var
  93.           determines a ReplyName to be put into the send message.
  94.  
  95. EXAMPLE
  96.  
  97.      User
  98.         Name  "Mail-Daemon"
  99.        Alias "Reply-Daemon"
  100.        Password
  101.        NetAccess       = "#?"
  102.        expire.mail     = "0"
  103.        expire.private  = "0"
  104.        .... EndUser
  105.  
  106.      User
  107.        Name  "Joe User"
  108.        Password "noone"
  109.        Alias "ju"
  110.        Alias "project"
  111.        Alias "project-bugs"
  112.        Alias "info"
  113.        ....
  114.        ReplyDaemon.FolderList= "project, project-bugs*ninfo"
  115.        ReplyDaemon.ReplyName.Bugs = "ju"
  116.        ReplyDaemon.Subject.Bugs = "Recieved your bug report:"
  117.        ReplyDaemon.MsgText.Bugs= "Thank you for your bug report.*n
  118.                                   Joe User*NBugs Maintainer" ....
  119.        ReplyDaemon.Subject.Info = "Here's your Info"
  120.        ReplyDaemon.MsgText.Info= "Thank you for requesting the info*n
  121.                                   Joe User" ....
  122.      EndUser
  123.  
  124. TODO
  125.  
  126.  >* Es sollte auch die Möglichkeit geben, statt des Textes direkt (in
  127.  >  ums.config) einen FileNamen für ein Textfile anzugeben (z.B. statt
  128.  >  *.msgtext.* *.msgfile.*). Das bläht die config nicht garso
  129.  >  (unnötig) auf. Die Idee kam mir deshalb, weil man z.B. auf diese
  130.  >  Art ziemlich einfach längere (Info-)Files verschicken könnte, ohne
  131.  >  sie nach jeder Änderung zusätzlich in die ums.config quetschen zu
  132.  >  müssen. Ein schönes Beispiel wäre (dachte ich mir), den PGP public
  133.  >  key automatisiert zu verschicken, wenn jemand an
  134.  >  pgp@irgendwer.nbg.sub.org schreibt.
  135.  
  136. */
  137.  
  138. options results
  139. options failat 20
  140.  
  141.  
  142. /*** Startup ***/
  143.  
  144. signal on BREAK_C
  145. signal on BREAK_D
  146. signal on BREAK_E
  147. signal on BREAK_F
  148. signal on ERROR
  149. signal on HALT
  150. signal on IOERR
  151. signal on SYNTAX
  152.  
  153. call addlib('ums.library', 0, -210, 11)
  154. call addlib('rexxdossupport.library', 0, -30, 1)
  155.  
  156. call UMSInitConsts()
  157.  
  158. ProgramName = "ReplyDaemon"
  159. ReplyName = "Reply-Daemon"; ReplyPassword = "";
  160.  
  161. parse arg arguments
  162. ArgsTemplate = "NAME,PASSWORD,SERVER/K,USEREPLYACCOUNT/S,USEFOLDERASREPLYNAME/S"
  163. args.name = ""
  164. args.password = ""
  165. args.server = ""
  166. args.usereplyaccount = 0
  167. args.usefolderasreplyname = 0
  168.  
  169. if strip(arguments) = '?' then do
  170.   call writech(STDOUT, ArgsTemplate': ')
  171.   arguments = readln(STDIN)
  172. end; else nop
  173. if ~ReadArgs(arguments,ArgsTemplate,"args.") then do
  174.   say Fault(RC,ProgramName)
  175.   exit 10
  176. end; else nop
  177.  
  178. drop arguments
  179.  
  180.  
  181. /*** Login ***/
  182.  
  183. account = UMSLogin(args.name, args.password, args.server)
  184. if account = 0 then do
  185.   say "unable to login."
  186.   exit 20
  187. end
  188.  
  189. replyAccount = 0;
  190.  
  191. if args.usereplyaccount then do
  192.   replyAccount = UMSLogin(replyName, ReplyPassword, args.server)
  193.   if (replyAccount = 0) then do
  194.     say "unable to login."
  195.     halt 10
  196.   end
  197. end; else
  198.   replyAccount = account
  199.  
  200. FLAGS_Empty = UMSMakeFlags()
  201. FLAG_0 = UMSMakeFlags(0)
  202. FLAG_1 = UMSMakeFlags(1)
  203. FLAG_2 = UMSMakeFlags(2)
  204. FLAGS_012 = UMSMakeFlags(0,1,2)
  205. FLAG_Old = UMSMakeFlags(UMSUSTAT_Old)
  206. FLAGS_PostArch = UMSMakeFlags(UMSUSTAT_PostPoned,UMSUSTAT_Archive)
  207. Match = UMSMakeFlags(UMSUSTAT_ViewAccess)
  208. Mask  = UMSMakeFlags(UMSUSTAT_ViewAccess, /*UMSUSTAT_PostPoned,*/ UMSUSTAT_Archive, UMSUSTAT_Old)
  209.  
  210. call UMSSelectField(account, "L", FLAG_0, FLAGS_Empty,,,UMSCODE_Group, "", TRUE)
  211. call UMSSelectFlags(account, "L", FLAG_1, FLAGS_Empty,,,"U", Mask, Match)
  212.  
  213. Folderlist = GetUMSConfigVar("","Folderlist", TRUE)
  214. do forever
  215.   parse var FolderList FolderName '0A'x Folderlist
  216.   FolderName = strip(FolderName)
  217.   if FolderName = '' then leave;
  218.   parse var FolderName FolderName ',' ToName
  219.   ToName = upper(ToName);
  220.   call ReplyOnMsgsInFolder;
  221. end
  222.  
  223. /*** Final cleanup ***/
  224.  
  225. BREAK_C:
  226. BREAK_D:
  227. BREAK_E:
  228. BREAK_F:
  229. HALT:
  230.  
  231. RC = 0
  232.  
  233. ERROR:
  234. IOERR:
  235. SYNTAX:
  236.  
  237. IF RC ~= 0 THEN DO
  238.   say "Error: " rc errortext(rc) "Line" sigl
  239. END
  240.  
  241. /*** Logout ***/
  242.  
  243. call UMSLogout(account)
  244. if args.usereplyaccount then
  245.   call UMSLogout(replyAccount)
  246. exit
  247.  
  248. ReplyOnMsgsInFolder:
  249.   MessageText = GetUMSConfigVar(FolderName,"MsgText", TRUE)
  250.   Subject     = GetUMSConfigVar(FolderName,"Subject", TRUE)
  251.   ReplyName   = GetUMSConfigVar(FolderName,"ReplyName", FALSE)
  252.  
  253.   call UMSSelectFlags(account, "L", FLAGS_Empty, FLAG_2,,,"U", FLAGS_Empty, FLAGS_Empty)
  254.   call UMSSelectField(account, "L", FLAG_2, FLAGS_Empty,,,UMSCODE_Folder, FolderName)
  255.  
  256.   numTagedMsgs = UMSSelectFlags(account, "L", FLAGS_Empty, FLAGS_Empty,,,"L", FLAGS_012, FLAGS_012)
  257.  
  258.   if numTagedMsgs = 0 then return
  259.  
  260.   say ProgramName || ":" numTagedMsgs "messages in folder" FolderName "found"
  261.   i=0;last = 0
  262.   do forever
  263.     last = UMSSearchFlags(account, "L", FLAGS_012, FLAGS_012, last)
  264.     if last = 0 then leave /* we are done */
  265.  
  266.     drop msg. /* _IMPORTANT_ */
  267.     if ~ UMSReadMsgHeader(account, last, msg.,true) then do
  268.       call CheckErr
  269.       exit
  270.     end
  271.  
  272.     /* generate reply */
  273.     drop newmsg.
  274.     if symbol("msg.UMSCODE_ReplyName") = "VAR" then do
  275.       newmsg.UMSCODE_ToName = msg.UMSCODE_ReplyName
  276.     end; else
  277.       newmsg.UMSCODE_ToName = msg.UMSCODE_FromName
  278.  
  279.     /* test whether we should not reply */
  280.     if (find(msg.UMSCODE_Attributes,'receipt') ~= 0),  /* genaratec message */
  281.     | abbrev(upper(newmsg.UMSCODE_ToName),"MAILINGLIST "),  /* no reply to a mailinglist */
  282.     | ((ToName ~= '') & (upper(msg.UMSCODE_ToName) ~= ToName))
  283.     then
  284.       iterate
  285.  
  286.     if symbol("msg.UMSCODE_ReplyAddr") = "VAR" then do
  287.       newmsg.UMSCODE_ToAddr = msg.UMSCODE_ReplyAddr
  288.     end; else if symbol("msg.UMSCODE_FromAddr") = "VAR" then do
  289.       newmsg.UMSCODE_ToAddr = msg.UMSCODE_FromAddr
  290.     end
  291.     if args.usefolderasreplyname then do
  292.       newmsg.UMSCODE_ReplyName = FolderName;
  293.     end; else if ReplyName ~= "" then do
  294.       newmsg.UMSCODE_ReplyName = ReplyName;
  295.     end
  296.     newmsg.UMSCODE_RefID   = msg.UMSCODE_MsgID
  297.     newmsg.UMSCODE_Attributes = "receipt"
  298.     newmsg.UMSCODE_Subject = Subject msg.UMSCODE_Subject
  299.     newmsg.UMSCODE_MsgText = "Hi" msg.UMSCODE_FromName ||"!" || '0A 0A'x || MessageText ||,
  300.     '0A 0A'x || 'Of course, this message has been generated automaticly :-)'
  301.  
  302.     if UMSWriteMsg(replyAccount, newmsg.) = 0 then
  303.       call CheckErr
  304.     else do
  305.       /* mark message as postponed and archived but unread */
  306.       call UMSSelectMsg(account,"U", FLAGS_PostArch, FLAG_Old, last)
  307.       i = i+1;
  308.     end;
  309.   end;
  310.   say i
  311.   return;
  312.  
  313. GetUMSConfigVar: procedure expose account replyAccount programname args.
  314.   /* search order:
  315.    * User:  ProgName.varname.FolderName
  316.    * User:  ProgName.varname
  317.    * ReplyDeamon ProgName.varname
  318.    */
  319.   FolderName = arg(1);
  320.   if FolderName ~= '' then
  321.     Foldername = '.'FolderName;
  322.   varname = ProgramName || "."arg(2);
  323.   var = UMSReadConfig(account,varname || FolderName)
  324.   if (var = "") & (FolderName ~= "") then
  325.     var = UMSReadConfig(account,varname)
  326.   if (var = "") & args.usereplyaccount & (replyAccount ~= 0) then
  327.     var = UMSReadConfig(replyAccount,varname)
  328.   if (arg(3) = TRUE) then do
  329.     if (var = '') then do
  330.       say ProgramName || ": Configuration variable '" || varname || "' is missing!"
  331.       exit
  332.     end
  333.   end
  334.   return var
  335.  
  336. /*** Support ***/
  337.  
  338. CheckErr: procedure expose account replyAccount args.
  339.   err = UMSErrNum(account)
  340.   if err ~= 0 then do
  341.     say "UMS Error #" || err || ": " || UMSErrTxt(account)
  342.   end; else if args.usereplyaccount then do
  343.     err = UMSErrNum(replyAccount)
  344.     if err ~= 0 then
  345.     say "UMS Error #" || err || ": " || UMSErrTxt(replyAccount)
  346.   end
  347. return
  348.  
  349.