home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Spezial / SPEZIAL2_97.zip / SPEZIAL2_97.iso / ANWEND / ONLINE / SREFV12J / POSTMAIL.80 < prev    next >
Text File  |  1997-06-30  |  23KB  |  716 lines

  1. /* a sample of a SRE-FILTER "post-filter" -- 13 May 1997
  2. This will mail a message to selected users, depending on the value
  3. of the request selector, or the client's IP address.
  4. For general notes on how  POSTFILT is called, see the bottom of this file.
  5.  
  6.     ----------------------- A Mail Notification Facility ----------------
  7.  
  8. This will automatically send "e-mail alerts" to specified recipients given specified events.
  9. It calls a local version of the SREF_MAILIT procedure.
  10.  
  11. It requires that a valid SMTP Gateway be available (the SMTP Gateway
  12. is set by running SRE-FILTER's configurator and modifying the SMTP_GATEWAY variable)
  13. Note that if you may be able to use OS/2's SENDMAIL program to use the server as
  14. an SMTP gateway (see the TCP/IP command reference documentation).
  15.  
  16. To use this routine, you will need to set up an "event" list.  The event list
  17. should contain the following information:
  18.  a)   What type of event to examine (client or request selector)
  19.  b)   The value that triggers a "match" (i.e.; a client's address, or a request for a particular file)
  20.  c)   The list of e-mail addresses to send "e-mail alerts" to
  21.  d)   An optional message to include in these alerts.
  22.  e)   An optional subject line
  23.  
  24. This routine uses the EVENTS.field.n  stem variable to store this event list.
  25.  
  26.   field should take one of 4 values
  27.      a)TYPE   : Either CLIENT or REQUEST (REQUEST is the "request selector")
  28.      b)VALUE : An IP (name or numeric) address, or a target request selector.  
  29.               Either may contain * characters;
  30.               (either as domain wildcards or as a wildcard)
  31.      c)RECIPIENTS: A space delimited list of e-mail  addresses
  32.      d)MESSAGE : An optional message.  It may contain CRLFs, and be quite long.
  33.      e)SUBJECT: An optional 1 line message to use as the SUBJECT.
  34.  
  35.    n is an integer value (that should run from 1.. "# of events")
  36.  
  37. You also must set EVENTS.0 equal to the "# of  events"
  38.  
  39. The algorithim works by:
  40.   From m=1.. to EVENTS.0
  41.       If EVENTS.TYPE.m=CLIENT, then see if client's numeric IP address
  42.           matches EVENTS.VALUE.m (with * acceptable as a wildcard)
  43.       If EVENTS.TYPE.m=REQUEST, see if the client's request selector matches EVENTS.VALUE.m,
  44.           (with * signalling that abbreviation matching should be used).
  45.           NOTE: The SEL variable contains the original request selector, before modifications
  46.                 by SRE-FILTER.  The match is against the entire request selector,
  47.                 not just the Action!  Thus, a SEL of FOO.HTM?this_one
  48.                 will NOT match a target of FOO.HTM (but will match FOO.HTM*)
  49.                 In comparision, exact matches (say,
  50.                 in the access_file) compare the action to the target -- so
  51.                 any ?xxx is ignored.
  52.  
  53.  
  54.   If either occurs
  55.       Create a note containing time,date, server name, client's name, SRE-FILTER status
  56.       message, and  EVENTS.MESSAGE.m
  57.            Note that EVENTS.MESSAGE.m is optional.
  58.       If EVENTS.SUBJECT.j is missing, a generic subject line is used.
  59.       Sent this note to each e-mail addresss listed in EVENT.RECIPIENTS.m
  60.  
  61. If there is not SMTP_GATEWAY specified, or EVENTS.0=0, then nothing 
  62. is done.
  63.  
  64. Note that there may be multiple matches; so that several different e-mail alerts (to
  65. different sets of e-mail addresses, some of which may contain common 
  66. addresses) may be generated by each call to this routine.
  67.  
  68. Example  -- note that the numbering goes from 1 (first event) to 3 (third event):
  69.  
  70. EVENTS.0=3
  71.  
  72. EVENTS.TYPE.1="CLIENT"
  73. EVENTS.VALUE.1="*.*.*.*"
  74. EVENTS.RECIPIENTS.1="bob@hisorg.net  jill@staff.agency.gov "
  75.      Note that EVENTS.MESSAGE.1 is not set
  76.  
  77. EVENTS.TYPE.2="REQUEST"
  78. EVENTS.VALUE.2="PROJECTS/PROJ1.HTM"
  79. EVENTS.RECIPIENTS.2="ANDREW@myorg.org"
  80. EVENTS.MESSAGE.2="A request for PROJ1 was recieved "
  81. events.subject.2=' PROJ1 Request '
  82.  
  83. EVENTS.TYPE.3="REQUEST"
  84. EVENTS.VALUE.2="\PUT_FILE*"
  85. EVENTS.RECIPIENTS.3="WEBMASTER@MYORG.ORG"
  86. EVENTS.MESSAGE.3="A file upload has been recieved! "||crlf||" You may want to check it?"
  87.   Note the use of CRLF to add a line feed to the message.
  88.  
  89. Note when EVENTS.TYPE.m=REQUEST:
  90.   all / are converted to \ (in both the SEL and EV*ENTS.VALUE.n), and
  91.   leading and trailing \ are stripped
  92.  
  93.             --------------------------------------------------
  94. */
  95.  
  96.  
  97.  
  98.   
  99. postmail:
  100. CRLF = '0d0a'x
  101. signal on syntax name error2
  102. signal on error name error2
  103.  
  104. /*  ==============  INSERT  EVENTS list here   ================  */
  105.  
  106. EVENTS.0=0
  107.  
  108. /* optional: set verbose=1 to echo status stuff, 2 more stuff, 0 for quiet operation */
  109. verbose=1
  110.  
  111. /* optional: name of sender. If left blank, or =0, a generic name is used */
  112. sender_name=' '
  113.  
  114.  
  115. /* ============ DO NOT CHANGE BELOW HERE  ===================== */
  116. /* args sent here:
  117. post_filter_message,source0,request0,seloriginal,tempfile,
  118. servername,HOST_NICKNAME,used_file,thereferer,tcache
  119. */
  120.  
  121.  
  122. parse arg amessage,source,request,sel,tempfile,servername,host_nickname,used_file,thereferer
  123. parse var source serveraddr serverport transaction_number clientaddr clientport
  124.  
  125. GATEWAY=' '
  126. AFF='SREF_'||SERVERPORT||'_SMTP_GATEWAY'
  127. IF HOST_NICKNAME<>' ' THEN do
  128.    AFF2=AFF2||'.'||HOST_NICKNAME
  129.    GATEWAY=VALUE(AFF2,,'OS2ENVIRONMENT')
  130. end
  131. IF GATEWAY=' ' THEN
  132.   GATEWAY=VALUE(AFF,,'OS2ENVIRONMENT')
  133.  
  134. if symbol('VERBOSE')<>'VAR' then verbose=0
  135.  
  136. if symbol('sender_name')<>'VAR' then sender_name=' '
  137. if sender_name=0 then sender_name=' '
  138.  
  139. if gateway=0 then do                    /* if no gateway specified, do nothing */
  140. /*  call say_stuff*/     /* enable this to get simple pmprintf output */
  141.   call pmprintf_sref(' POSTMAIL: No gateway specified ')
  142.   signal off error ; signal off syntax
  143.   return ' '
  144. end
  145. if events.0=0 then do
  146. /*  call say_stuff*/     /* enable this to get simple pmprintf output */
  147. end
  148.  
  149. sname=servername
  150. cname=clientaddr
  151. alphapos=verify(cNAME,'1234567890.')
  152. if alphapos=0 then  do        /* is numeric ip */
  153.           astat=sockgethostbyaddr(clientaddr,'stuff.!')
  154.           cname=upper(stuff.!name)
  155.           if abbrev(cname,'STUFF.!')=1 then cname=clientaddr
  156. end
  157.  
  158. atime=time()
  159. adate=date()
  160. CRLF = '0d0a'x
  161.  
  162. /* loop through events list .. */
  163. didit=0
  164. do jj=1 to events.0
  165.     if symbol('EVENTS.TYPE.'||jj)<>'VAR' then do
  166.         if verbose>0 then call pmprintf_sref(" POSTMAIL warning: EVENTS.TYPE."jj" not specified. ")
  167.         iterate
  168.     end
  169.     if symbol('EVENTS.VALUE.'||jj)<>'VAR' then do
  170.         if verbose>0 then call pmprintf_sref(" POSTMAIL warning: EVENTS.VALUE."jj" not specified. ")
  171.         iterate
  172.     end
  173.     ok=0
  174.     if events.TYPE.jj="CLIENT" then do 
  175.         ool=verify(events.value.jj,'1234567890*.')
  176.         if ool=0 then
  177.               ok=goodip(events.VALUE.jj,clientaddr)
  178.          else
  179.              ok=goodip(events.VALUE.jj,cname)
  180.    end
  181.    if events.type.jj='REQUEST' then do
  182.        if events.type.jj='REQUEST' then do
  183.           ok=goodsel(upper(events.value.jj),upper(sel))
  184.        end
  185.     end
  186.     if ok=0 then iterate
  187.  
  188.     if didit=0 & verbose>0 then  call pmprintf_sref(" Using gateway at " gateway)
  189.     didit=1
  190.  
  191.  
  192. /* if here, a match occurred */
  193.    address_list=events.recipients.jj
  194.  
  195.    if symbol('events.subject.jj')='VAR' then  
  196.           asubject='Subject: '||events.subject.jj
  197.    else
  198.           asubject='Subject: Notification of WEB transaction  '
  199.  
  200.    themessage="Date: " || adate || ' ' ||atime
  201.    if sender_name=' ' then
  202.       themessage=themessage||crlf||'From: WebServer@'||sname
  203.    else
  204.       themessage=themessage||crlf||'From: 'sender_name
  205.  
  206.    themessage=themessage||crlf||asubject
  207.    themessage=themessage||crlf||'To: '||address_list||crlf
  208.  
  209.    themessage=themessage||crlf||'An e-mail alert from the Web Server at '||sname
  210.    themessage=themessage||crlf||"    Date of occurrence: " || adate || ' ' ||atime
  211.    themessage=themessage||crlf||'     Request by client: '|| cname
  212.    themessage=themessage||crlf||'      Request selector: '|| sel
  213.    themessage=themessage||crlf||' Server status message: '|| amessage
  214.  
  215.    if symbol('events.message.jj')='VAR' then  /* check for a mess up */
  216.       themessage=themessage||crlf||"Notes:"||crlf||events.message.jj||crlf
  217.    else
  218.       themessage=themessage||crlf
  219.    foo=a_mailit(address_list,themessage, gateway,sender_name,verbose)
  220.    if verbose>0 then call pmprintf_sref(" Event " jj ", MAILIT status: "foo)
  221.  
  222. end                     /* try next event */
  223.  
  224. signal off error ; signal off syntax
  225. return ' '
  226.  
  227. /* -----------------------------------------------------------------------*/
  228. /* see if match (or abbreviation match) the sel                          */
  229. /* -----------------------------------------------------------------------*/
  230. goodsel: procedure
  231. parse  arg asel,thesel
  232. asel=translate(asel) ; thesel=translate(thesel)
  233. asel=translate(asel,'\','/') ; asel=strip(asel,,'\')
  234. thesel=translate(thesel,'\','/') ; thesel=strip(thesel,,'\')
  235.  
  236. if asel=thesel then return 1   /* exact match */
  237. return a_wildcard(thesel,asel)
  238.  
  239.  
  240.  
  241. /* -----------------------------------------------------------------------*/
  242. /* see if matches one of a set of good ips (1 if yes)*/
  243. /* -----------------------------------------------------------------------*/
  244. goodip: procedure 
  245.  
  246. parse upper arg anips,cip0
  247. parse var anips ip.1 '.' ip.2 '.' ip.3 '.' ip.4
  248. parse var cip0 cip.1 '.' cip.2 '.' cip.3 '.' cip.4
  249. match=1
  250. do mm2=1 to 4
  251.       if ip.mm2="*" then iterate
  252.       if ip.mm2=cip.mm2 then iterate
  253.       match=0       /*if here, not a match */
  254.       leave
  255. end
  256.  
  257. return match
  258.  
  259.  
  260. /* A simple transaction recorder (used if no SMTP_GATEWAY specified */
  261. say_stuff:
  262. call pmprintf_sref("  - - - - - ")
  263. call pmprintf_sref(time() ' ' date())
  264. call pmprintf_sref("  Message= "  amessage)
  265. call pmprintf_sref(" Source=  " source)
  266. call pmprintf_sref( " Request= "  request)
  267. call pmprintf_sref( " Sel = "  sel)
  268. return 
  269.  
  270.  
  271.  
  272. /********************************/
  273. /* see if needle matches haystack (* wildcards permitted) */
  274. a_wildcard:procedure  /* needle,haystack */
  275. parse arg tn ,tc 
  276. tn=strip(tn); tc=strip(tc)
  277. if tn=tc then   return 1              /* exact match */
  278. /* check for wildcard */
  279. astc=pos('*',tc)
  280. if astc=0 then  return 0          /* not a wildcard candidate */
  281.  
  282. if astc=1 then do
  283.    tc1=""
  284.    tn1=tc1
  285.    len1=0
  286. end
  287. else do
  288.    tc1=substr(tc,1,astc-1)
  289.    len1=length(tc1)
  290.    tn1=left(tn,len1)
  291. end
  292. if astc=length(tc) then do
  293.    tn2=""
  294.    tc2=""
  295.    len2=0
  296. end
  297. else do
  298.    tc2=substr(tc,astc+1)
  299.    len2=length(tc2)
  300.    tn2=right(tn,len2)
  301. end
  302. if tn1<>tc1 | tn2<>tc2 then     /* not a wildcard match */
  303.   return  0 
  304.  
  305. return 1                /* have a wildcard match */
  306.  
  307.  
  308. /******/
  309. /* here on error */
  310. error2:
  311. signal off syntax ; signal off error
  312. call pmprintf_sref(' Error in POSTMAIL at line ' sigl)
  313. return 0
  314.  
  315.  
  316. /*******************************************************************
  317.  *******************************************************************
  318.   *******************************************************************/
  319.  
  320. /*
  321.          ---------------- General notes  ------------------------
  322.  
  323. SRE-FILTER  call this procedure when the POST_FILTER variable is set to YES.
  324.  
  325. 6 arguments are passed here:
  326.     amessage
  327.     source
  328.     request
  329.     sel0
  330.     tempfile
  331.     params
  332.  
  333. Amessage 
  334.     is generated by SRE-FILTER, and indicates what SRE-FILTER did with this request.
  335.  
  336. Source,request,and sel0 are generated by GoServe, and contain:
  337.  
  338.   Source 
  339.        serveraddr serverport transaction_number clientaddr clientport
  340.   Request
  341.     verb uri protocol 
  342.   Sel0
  343.     action '?' awords  (?awords may not be present
  344.  
  345. Tempfile is set in SRE-FILTER
  346.   Tempfile
  347.     A temporary file name. It may have been used to construct the response, so you probably should
  348.     delete it first (use SYSFILEDELETE(TEMPFILE) ).
  349.  
  350. Params
  351.    Are optional parameters sent by SRE-FILTER.  Currently, it contains the name of the
  352.    SMTP gateway (set in the SMTP_GATEWAY variable of SRE-FILTER).
  353.  
  354. Example:
  355.      message               HTML File sent:/INDEX.HTM
  356.      Source                151.121.65.143 80 3 219.134.78.12 1026
  357.      request                GET /sampask2.htm HTTP/1.0
  358.      sel0                   sampask2.htm
  359.      tempfile               D:/GOHTTP/$10.80
  360.      params                mail.myprovider.net
  361.  
  362.  
  363. Note on Amessage:
  364.   The folllowing lists the "messages" that SRE-FILTER may send.  Note that the ||varname
  365.   means the value of Varname is appended to the message.  Also note that when varname=SEL,
  366.   the SEL may be different then SEL0 (say, if a ~ replacement occurred).
  367.  
  368.     Pre-filter used
  369.     Cached file sent: ||sel0
  370.     Bad HTTP Protocol
  371.     Unauthorized access
  372.     No client name found, access denied
  373.     Logon denied to non-inhouse user
  374.     Pre-filter used
  375.     Alias invoked permanent redirect
  376.     Alias invoked temporary redirect
  377.     Transfered non-data directory file
  378.     Access to file denied:  ||sel
  379.     Ping request
  380.     CONTROL Statistics request
  381.     Host request
  382.     Control Moveaudit
  383.     Control Reset all
  384.     Variable display
  385.     !Special request denied: ||sel
  386.     Message box access
  387.     Message box access denied
  388.     Message box viewing
  389.     Special request processing unknown:||sel
  390.     HEAD request: Document not found:  ||sel0
  391.     Head request
  392.     Document not found
  393.     Server is busy
  394.     Non-HTML File sent:||file
  395.     HTML File sent:||file
  396.     HTML File sent (with ssi):||file
  397.     Mappable image request:'||foo
  398.     GET request:||action
  399.     Server busy
  400.     POST error: too much data
  401.     POST error: could not read data
  402.     POST request:||sel
  403.     POST problem:||sel
  404.     CGI-BIN access||sel
  405.  
  406. **************************************************************************/
  407.  
  408. /* This is MAILIT: an SRE-FILTER procedure */
  409. /* ============================================================================ 
  410. MAILIT: A  REXX procedure to mail a note to several recipients.
  411. .
  412. .  Called as:  status=mailit(address_list,message_string,smtp_gateway,optional_sender_address)
  413. .
  414. . address_list: A space delimited list of addresses
  415. . message_string: A message string, that may contain CRLFs (and may be rather long)
  416. . smtp_gateway: The address of your SMTP server 
  417. . optional_senders_address: The sender's address (optional)
  418. .        If sender's address is not given, it will be generated using the servername() function.
  419. .
  420. . Example:
  421. . status=mailit("BOB@HIS.NET" , "This is my message ", "MAIL.MY.ORG" )
  422. .    or
  423. . status= mailit("BOB@HIS.NET JILL@HER.COM " , "This is my message ", ,
  424. .             "MAIL.MY.ORG", "HARRY@MY.ORG")
  425. .
  426. .NOTES:
  427. . SMTP gateway addresses.
  428. .   If you are using an INTERNET provider, use the POP or SMTP gateway address.
  429. .
  430. .   If no such address is available, you can try running the OS/2 SENDMAIL program, and
  431. .   use your hostname as the SMTP gateway address.
  432. .   For example, assuming that SENDMAIL.UML is in c:\mptn\etc,
  433. .   before starting GoServe you should   start sendmail with:
  434. .       [C:]START SENDMAIL -bd -q30m -Cc:\mptn\etc\sendmail.uml
  435. .   Alternatively, you can use AUTOSTART sendmail using the TCPCFG program.
  436. .
  437. . Note on recipient addresses:
  438. .    The message will be sent to each address.  Since the addresses are
  439. .    sent and then the message, this allows for fairly rapid mailing to multiple
  440. .    individuals.
  441. .
  442. . Acknowledgment:
  443. .     This is a modification of a routine written by Dave Briccetti (see acknowledgment at
  444. .     bottom of file)
  445. .     It was modified by Daniel Hellerstein for use in SRE-FILTER. 4/96
  446. .
  447. .
  448. ============================================================================ */
  449.  
  450. a_mailit:
  451. parse arg whotos , themessage  , smtpaddress , sender_address,verbose
  452.  
  453. smtpaddress=strip(smtpaddress)
  454. sender_address=strip(sender_address)
  455.  
  456. /* set some constants */
  457. CRLF                    = '0d0a'x
  458. TRUE                    = 1
  459. FALSE                   = 0
  460. REPLYTYPE_OK            = '2'   /* SMTP reply code first byte */
  461. REPLY_START_MAIL_INPUT  = '354' /* SMTP reply code */
  462.  
  463. if sender_address="" then do
  464.    sendinghost=servername()
  465.    sendinguser="WebServer"
  466.    sender_address=sendinguser||'@'||sendinghost
  467. end
  468.  
  469. MailServer  = smtpaddress  /* Mail server, leave blank if you are connected through a LAN */
  470.  
  471. if \RxFuncQuery("SockLoadFuncs") then nop
  472. else do
  473.        call RxFuncAdd "SockLoadFuncs","rxSock","SockLoadFuncs"
  474.        call SockLoadFuncs
  475. end
  476.  
  477.  
  478. if EstablishProtocol() = FALSE then
  479.     return 0
  480.  
  481. /* The protocol initiated, we'll now send the message to each
  482.    recipient */
  483.  
  484. call SendMsgToEachRecipient
  485.  
  486.  
  487. /* QUIT ends the protocol */
  488.     
  489. CmdReply = TransactSmtpCommand(socket, 'QUIT', 1)
  490.  
  491.  
  492. /* Close the socket */
  493.     
  494. call SockSoClose socket
  495.  
  496. return isgood
  497.  
  498.  
  499. /* ========================================================================= */
  500. SetConstants:
  501. /* ========================================================================= */
  502.  
  503. return
  504.  
  505.  
  506. /* ========================================================================= */
  507. EstablishProtocol:
  508. /* ========================================================================= */
  509.  
  510. socket = ConnectToMailServer(MailServer)    
  511. if socket <= 0 then 
  512. do
  513.     if verbose>0 then 
  514.           call pmprintf_sref( 'Could not connect to mail server')
  515.     return FALSE
  516. end
  517.  
  518. CmdReply = GetCmdReply(socket)
  519.  
  520. if left(CmdReply, 1) \= REPLYTYPE_OK then 
  521. do
  522.     if verbose>0 then 
  523.           call pmprintf_sref( 'Could not establish protocol')
  524.     return FALSE
  525. end
  526.  
  527. /* Send the extended hello, in case this SMTP server supports
  528.    SMTP extensions */
  529.         
  530. CmdReply = TransactSmtpCommand(socket, 'EHLO', 1)
  531. SizeExtensionSupported = 0
  532.         
  533. if left(CmdReply, 1) = REPLYTYPE_OK then do
  534.     /* That worked, so enable extended SMTP processing.  If
  535.        the response to the EHLO indicates support for SIZE,
  536.        enable our use of that feature */
  537.               
  538.     SmtpExtensionsSupported = TRUE
  539.     if pos('250 SIZE', CmdReply) > 0 | pos('250-SIZE', CmdReply) > 0 then
  540.         SizeExtensionSupported = 1
  541. end
  542. else do
  543.     /* The server didn't recognize the EHLO so we'll go with
  544.        the regular HELO */
  545.               
  546.     SmtpExtensionsSupported = FALSE
  547.     SizeExtensionSupported  = FALSE
  548.     CmdReply = TransactSmtpCommand(socket, 'HELO', 1)
  549. end
  550.  
  551. if left(CmdReply, 1) = REPLYTYPE_OK then 
  552.     return TRUE
  553. else
  554.     return FALSE
  555.  
  556.  
  557. /* ========================================================================= */
  558. SendMsgBody: 
  559. /* ========================================================================= */
  560.  
  561. /* DATA tells the server that the body of the message is coming.  It
  562.    should reply with a code meaning "go ahead." */
  563.  
  564. CmdReply = TransactSmtpCommand(socket, 'DATA', 1)
  565. if substr(CmdReply, 1, 3) = REPLY_START_MAIL_INPUT then 
  566. do
  567.     /* Send the data, followed by a '.' on a line by itself to 
  568.        indicate the end of the message */
  569.     CmdReply = TransactSmtpCommand(socket, MsgFileContents || CRLF || '.', 0)
  570. end
  571.  
  572. return
  573.  
  574.  
  575. /* ========================================================================= */
  576. SendMsgToEachRecipient:
  577. /* ========================================================================= */
  578.  
  579. /*
  580. MsgFileContents = charin(MessageFile, 1, chars(MessageFile))
  581. call stream MessageFile, 'c', 'close'
  582. */
  583.  
  584. msgfilecontents=themessage
  585. MsgFileContents = strip(MsgFileContents, 't', '1a'x) 
  586.   /* Strip EOF */
  587.  
  588.         
  589. /* MAIL FROM identifies the sender.  The SIZE= extension
  590.    provides the size of the message, to allow the 
  591.    server to quickly refuse messages bigger than it wants. */
  592.            
  593. MailFromCmd = 'MAIL FROM:' ||sender_address
  594. isgood=1
  595.  
  596. if SizeExtensionSupported then
  597.     MailFromCmd = MailFromCmd ' SIZE=' || length(MsgFileContents)
  598.     
  599. CmdReply = TransactSmtpCommand(socket, MailFromCmd, 1)
  600.  
  601. if left(CmdReply, 1) = REPLYTYPE_OK then do
  602.   whotos=translate(whotos,' ','000d0a1a09'x)
  603.   do while whotos<> ""
  604.      parse var whotos whoto whotos
  605.  
  606.      RecipientEmailAddress = strip(whoto)
  607.      if RecipientEmailAddress \= '' then    /* RCPT identifies the intended recipient of the message */
  608.          CmdReply = TransactSmtpCommand(socket,,
  609.                          "RCPT TO:" || RecipientEmailAddress, 1)
  610. /*say " cmdreply " cmdreply*/
  611.   end /* do */
  612.  
  613.   call SendMsgBody
  614. end
  615. else do
  616.   isgood=0
  617. end
  618. return
  619.  
  620.  
  621. /* ========================================================================= */
  622. ConnectToMailServer: procedure
  623. /* ========================================================================= */
  624.  
  625. parse arg MailServer
  626. socket = 0
  627.  
  628. /* Open a socket to the mail server.  (The Sock* functions are
  629.    documented in the REXX Socket book in the Information folder
  630.    in the OS/2 System folder */
  631.  
  632. call SockInit
  633. if SockGetHostByName(MailServer, 'host.!') = 0 then do
  634.     if verbose>0 then 
  635.          call pmprintf_sref( 'Could not get host by name' errno' ' h_errno)
  636. end
  637. else do
  638.     socket = SockSocket('AF_INET','SOCK_STREAM',0)
  639.     address.!family = 'AF_INET'
  640.     address.!port = 25          /* the standard SMTP port */
  641.     address.!addr = host.!addr
  642.     if SockConnect(socket, 'address.!') = -1 then  do
  643.       if verbose>0 then
  644.             call pmprintf_sref( 'Could not connect socket' errno' ' h_errno)
  645.     end
  646. end
  647. return socket
  648.  
  649.  
  650. /* ========================================================================= */
  651. GetCmdReply: procedure
  652. /* ========================================================================= */
  653.  
  654. parse arg socket
  655.  
  656. CRLF = '0d0a'x
  657.  
  658. /* Receive the response to the SMTP command into a variable.  Use
  659.    more than one socket read if necessary to collect the whole 
  660.    response. */
  661.    
  662. if SockRecv(socket, 'CmdReply', 200) < 0 then do
  663.     if verbose>0 then 
  664.           call pmprintf_sref('Error reading from socket' errno' ' h_errno)
  665.     exit 0
  666. end
  667.  
  668. ReadCount = 1
  669. MaxParts = 10
  670.  
  671. do while ReadCount < MaxParts & right(CmdReply, 2) \= CRLF  
  672.     if SockRecv(socket, 'CmdReplyExtra', 200) < 0 then do
  673.         if verbose>0 then 
  674.            call pmprintf_sref('Error reading from socket')
  675.         exit 0
  676.     end
  677.     CmdReply = CmdReply || CmdReplyExtra
  678.     ReadCount = ReadCount + 1
  679. end
  680.  
  681. return CmdReply
  682.  
  683.  
  684. /* ========================================================================= */
  685. TransactSmtpCommand: 
  686. /* ========================================================================= */
  687.  
  688. parse arg socket, Cmd, SayCmd
  689.  
  690. /* Send a command to the SMTP server, echoing it to the display
  691.    if requested */
  692.  
  693. if SayCmd then 
  694.     if verbose>0 then 
  695.            call pmprintf_sref(" Command is "  Cmd)
  696. rc = SockSend(socket, Cmd || CRLF)
  697. op=GetCmdReply(socket)
  698. return op
  699.  
  700.  
  701. /* ------------- Acknowledgement  ------------------------------
  702. Most of this e-mail routine was obtained from:
  703.  
  704. Send Email Message to a Mailing List Via SMTP, Using the REXX Socket Interface
  705. Written by a novice REXX programmer
  706.      Dave Briccetti, November 1995
  707.      daveb@davebsoft.com, http://www.davebsoft.com
  708.  
  709.   May be used for any purpose
  710.   Thanks to REXX expert <a href=http://www.quercus-sys.com>Charles Daney</a>
  711.   and internet expert David Singer for looking over the code
  712. ----------------------------------------------------------    */
  713.  
  714.  
  715.  
  716.