/*

REXX Script -- Helper handling SMTP server events.
See the HELPERS module configuration.

The helper receives requests for standard input. Each request is  a  separate
line ending with a newline. Each request must be answered on standard  output
as a single line ending with a newline. After that the helper should be ready
to accept the next request. Upon receiving an interrupt  signal,  the  helper
should save the data if necessary and exit.


Input request format:

  sessionId OP DATA

  where sessionId - unique identifier for the session starting with OP "NEW"
                    and ending with OP "DESTROY",
        OP        - request type,
        DATA      - request data dependent on OP.


sessionId NEW Flags

  A new connection has been established. Session started.

  Flags (space separated): RELAY, TRUSTED, SSL, SUBMISSION
    RELAY       - client is relay (configured in module-SMTP/server/relays),
    TRUSTED     - client is trusted (configured in module-mail/trusted),
    SUBMISSION  - client has connected to the port specified in
                  module-SMTP/server/submission.

  Response like "flag1,flag2,..." or "flag1,flag2,...:text", where flags is:
    CONTINUE                    - continue with normal command execution
    REPLY:<SMTP response>       - SMTP response: 220 greeting
    CLOSE                       - disconnect client
    TRUSTED                     - treat the client as trusted
    AUTH                        - treat the client as authorized

  Example ("r5tg" is session ID):

  Request:  r5tg NEW TRUSTED
  Response: REPLY:220 mx.domain ESMTP Welcome, trusted user

sessionId DESTROY

  Connection closed. Session ended.

  Response:
    CONTINUE

sessionId COMMAND SMTP_command_from_client

  An SMTP command was received from the user.

  Response like "flag1,flag2,..." or "flag1,flag2,...:text", where flags is:
    CONTINUE                    - continue with normal command execution
    REPLACE:<new SMTP command>  - replace command with another SMTP command
    REPLY:<SMTP response>       - SMTP response (helper executed the command)
    CLOSE                       - disconnect client
    TRUSTED                     - treat the client as trusted
    AUTH                        - treat the client as authorized

  Examples:

  Request:  r5tg COMMAND RCPT TO:<user@mydomain.local> SIZE=23452
  Response: REPLACE:RCPT TO:<user@subdomain.mydomain.local> SIZE=23452

  Request:  r5tg COMMAND X-MYCMD do something
  Response: REPLY:250 2.0.0 OK

sessionId AUTH Mechanism User Result

  Authorization procedure completed.

  Mechanism: [SSL/](PLAIN|LOGIN|CRAM-MD5),
  User: user name
  Result: (Success|The user is disabled|Error|Incorrect password|
           Unsupported mechanism for this user|Login failed)

  Response like "flag1,flag2,...", where flags is:
    CONTINUE                    - continue with normal command execution
    TRUSTED                     - treat the client as trusted
    AUTH                        - treat the client as authorized

sessionId MAILFROM email@address.dom

  The MAIL FROM command has been parsed, the server is ready to accept the
  reverse path.

  Response like "flag1,flag2,..." or "flag1,flag2,...:text", where flags is:
    CONTINUE                    - continue with normal command execution
    REPLY:<SMTP response>       - SMTP response (do not accept MAIL FROM)
    CLOSE                       - disconnect client
    TRUSTED                     - treat the client as trusted
    AUTH                        - treat the client as authorized

sessionId DATA

  The beginning of the transmission of the message body.

  Response like "flag1,flag2,..." or "flag1,flag2,...:text", where flags is:
    CONTINUE                    - continue with normal command execution
    REPLY:<SMTP response>       - SMTP response (do not accept MAIL FROM)
    CLOSE                       - disconnect client
    TRUSTED                     - treat the client as trusted
    AUTH                        - treat the client as authorized

sessionId DATAEND local_file

  The body of the message is completely received. A helper can make changes to
  the message file.

  Response like "flag1,flag2,...", where flags is:
    CONTINUE                    - continue with normal command execution
    CLOSE                       - disconnect client
    TRUSTED                     - treat the client as trusted
    AUTH                        - treat the client as authorized

sessionId HDRFLD Field: value
sessionId HDRFLD

  The message header field was received, or the header was completely received.

  Request:
    sessionId HDRFLD Field: value
      or
    sessionId HDRFLD
      DATA is empty. End of header, the new field from the REPLACE/INSAFTER/
      INSBEFORE response will be added to the end of header.

  Response: <CONTINUE|REPLACE|INSAFTER|INSBEFORE>[:Field: value]
    CONTINUE                    - continue normal execution
    REPLACE:Field: value        - replace the field with another one
    REPLACE                     - don't add the passed field
    INSAFTER:Field: value       - insert a new field after the one passed
    INSBEFORE:Field: value      - insert a new field before the passed one

  Examples:

  Request:  r5tg HDRFLD User-Agent: Mozilla/5.0 (OS/2; Warp 4.5; rv:45.0) Gecko/20100101
  Response: REPLACE:User-Agent: Mozilla/5.0 (ArcaOS; 5.1; rv:45.0) Gecko/20100101

  Request:  r5tg HDRFLD X-Field: some value
  Response: REPLACE

*/

/* Uncomment the following line to write a debug file. */
/* strDbgFile = "hlpsmtpsrv.dbg" */

/* Install an interrupt signal handler. */
call on halt name InterruptHandler

fStop = 0
call debug "Start"

do while \fStop
  /* Reading a request from standard input */
  input = linein()
  if input = "" then
    iterate

  call debug "Input:" || input

  parse var input sessId " " op " " input

  /* Default reply */
  reply = "CONTINUE"

  select
    when op = "COMMAND" then
    do
      if translate(left(input,7)) = "RCPT TO" then
      do
        /* Here we are replacing the recipient address of the form
           v.USER@frs.snc.ru with v.USER@v.frs.snc.ru. Thus messages for all
           addresses starting with "v." in the frs.snc.ru domain will be sent
           to the v.frs.snc.ru subdomain server. */

        parse var input cmd ":" addr opt

        addr = strip( addr )
        if left(addr,1) = "<" then
          parse var addr "<"addr">"

        parse var addr pref "." user "@" domain

        if ( pref = "V" | pref = "v" ) & translate(domain) = "FRS.SNC.RU" then
        do
          addr = pref"."user"@"pref"."domain
          input = strip( cmd":<"addr"> " || strip( opt, "L" ), "T" )
          reply = "REPLACE:"input
        end
      end
    end  /* when op = "COMMAND" then */

    otherwise
  end  /* select */

  call debug "Reply:" || reply

  /* Send response to standard output */
  say reply
end  /* do while \fStop */

/*
   An interrupt signal has been received.
   Now we can save the data and exit.
*/

call debug "Exit"

/* Close debug file. */
if symbol("strDbgFile") = "VAR" then
  call lineout strDbgFile

EXIT

InterruptHandler:
  call debug "Interrupt signal"
  fStop = 1
  return

Debug:
  if symbol("strDbgFile") = "VAR" then
    call lineout strDbgFile, arg(1)
  return
