Museum

Home

Lab Overview

Retrotechnology Articles

Online Manuals

⇒ mailR(5) — UnixWare 2.01

Media Vault

Software Library

Restoration Projects

Artifacts Sought

Related Articles

mail(1)

mailsurr(4)

rewrite(4)






       mailR(5)                                                    mailR(5)


       NAME
             mailR - language used for mail message header rewriting

       DESCRIPTION
             The mailR language is used by mail for the rewriting of a mail
             message's headers.  mailR is used to provide instructions on
             how to rewrite headers.  It is used in the file
             /etc/mail/rewrite or other files (such as /etc/mail/mailsurr)
             included from that file.

             The mailR language and the file /etc/mail/rewrite are similar
             to awk(1).  A series of function definitions is given in the
             file.  These functions include one named main and another
             named local, which are executed at various stages of mail
             delivery.  The main function is executed after a mail message
             is read in by mail.  The local function is executed before a
             mail message is delivered locally.

             Additional references may be provided within
             /etc/mail/mailsurr file so that further functions (rewrite
             instructions) may be executed later.

          Statements
             A function consists of a sequence of statements.  A statement
             can be one of the following:

             var x         Creates a local variable named x.  Variable
                           names start with a letter and consist of
                           letters, digits or underscores.  There are only
                           local variables, each with a dynamically
                           assigned type of string, double, header, array
                           or reference.  arrays are associative (can have
                           any type of index).  references are variables
                           which refer to other variables.  Multiple names
                           may be given, separated by commas.  (If a non-
                           array variable is used in an array context, it
                           will be converted to an array with the value set
                           as the 0'th element.  If an array is used in a
                           non-array context, the value of the first
                           element added to the array will be used.)

             var x = expression
                           Creates a local variable named ``x'' and
                           initializes it with the value of the expression.




                           Copyright 1994 Novell, Inc.               Page 1













      mailR(5)                                                    mailR(5)


            variable = expression
                          The value of the variable is replaced with the
                          value of the expression.  If variable is a
                          reference, the variable referred to is modified
                          as well.

            if (conditional) statement
                          Tests if the conditional is non-zero or a non-
                          empty string and executes statement if so.  (The
                          statement is shown on the same line as the if,
                          but is not required to be so.  The same is true
                          for the following statements as well.)

            else statement
                          This clause is executed if the preceding if
                          statement is false.  The else clause is
                          optional.

            for (expression; conditional; expression) statement
                          Executes the statement while the conditional is
                          true.

            while (conditional) statement
                          Executes statement as long as the conditional is
                          true.

            until (conditional) statement
                          Executes statement as long as the conditional is
                          false.

            break         Breaks out of the enclosing for, while or until
                          loop.

            continue      Skips the rest of the block in a for, while or
                          until loop.

            123, 12.3, 1.2e3
                          Numeric constants.  The format is defined as an
                          optional sign, then a string of digits
                          optionally containing a single decimal point,
                          then an optional e or E followed by an optional
                          sign, followed by an integer.

            "string"      A string constant.  As in C, backslash sequences
                          (\n, \000, \x00) may be embedded within the
                          string and will be converted to the equivalent


                          Copyright 1994 Novell, Inc.               Page 2













       mailR(5)                                                    mailR(5)


                           character.

             x[y]          A reference to the y'th element of the array x.
                           x is an associative array.  If x[y] does not
                           already exist, the elements will be created as
                           needed as an empty string.

             operators

                           x + y       numeric addition

                           x - y       numeric subtraction

                           x * y       numeric multiplication

                           x / y       numeric division

                           x @ y       string concatenation

                           ( )         grouping

                           x < y       relational operator
                                       (Note: For relational and equality
                                       operators, if both expressions are
                                       numbers, compare them as numbers,
                                       otherwise compare them as strings.
                                       When numbers are converted to
                                       strings, they are converted as if
                                       the %g printf format had been used.)

                           x > y       relational operator

                           x <= y      relational operator

                           x >= y      relational operator

                           x == y      equality operator

                           x != y      equality operator

                           x ~ y       match, the string in y is
                                       interpreted as a regular expression
                                       pattern.  The same regular
                                       expressions permitted in the mail
                                       surrogate file are allowed here.
                                       For example, "xyz" ~ "[ax]" will


                           Copyright 1994 Novell, Inc.               Page 3













      mailR(5)                                                    mailR(5)


                                      evaluate true.

                          x !~ y      doesn't match, the string in y is
                                      interpreted as a regular expression
                                      pattern.  The same regular
                                      expressions permitted in the mail
                                      surrogate file are allowed here.

                          x && y      short circuit logical and

                          x || y      short circuit logical or

            !expression   Negates the following expression.

            #             A comment to the end of the line.

            { }           Compound statements are surrounded with braces
                          and may span multiple lines.

            ;             Statements are terminated by semicolons.

            function x(var a, reference b, var c)compound-statement
                          Declares a function named x with the body
                          compound-statement.  The variable declarations
                          inside of the parentheses declare local
                          variables of the given names.  In this example,
                          the variables a and c are copies of the values
                          passed in, while the variable b is a reference
                          which will modify the original value.

            return val    Returns a value from a function.

            generator x(var a)compound-statement
                          A generator function is a special type of
                          function that has a start block.  The first call
                          to a generator must be of the form x(a,b,c)
                          (with arguments), which will cause the function
                          to be executed with those arguments, and any
                          start block within the function will also be
                          executed.  Subsequent calls must be of the form
                          x() (no arguments) and will skip the start
                          block.  Any local variables declared within the
                          generator function at the outermost scope will
                          retain their values between calls to the
                          generator function.  Only var parameters are
                          permitted; no reference parameters are allowed.


                          Copyright 1994 Novell, Inc.               Page 4













       mailR(5)                                                    mailR(5)


                           For example,
                                 for (x = y(a,b,c); x; x = y()) statement

                           will invoke y() repeatedly until y() returns an
                           empty string or 0, executing the statement each
                           time.

             start statement
                           Executes the statement only if this is an
                           initial invocation of a generator function.

             for (x from y) statement
                           Retrieves all values from the array y, one at a
                           time, setting x as a reference to the array
                           element.

             for (x in y) statement
                           Retrieves all values from the array y, one at a
                           time, setting x each time, as a reference, to
                           the index of the array element.

             include "filename"
                           The contents of the given filename are inserted
                           at this point.  The include statement is only
                           allowed outside of function and generator
                           definitions.

          Predefined Functions
             A number of functions are predefined.  These functions cannot
             be redefined.

             In those functions that refer to message header names, such as
             a To header, the string used to refer to that header may be
             given with or without a trailing colon (:) (that is, To: is
             also accepted).  The search for the header is case
             insensitive.  The names From and >From refer to the UNIX
             Postmark (From_) headers and must not be given with a trailing
             colon or in any other case.  (Note the trailing space as part
             of the name.)

             addrparse(var x)
                        Treats x as a series of RFC-822 addresses separated
                        by commas and optional newlines.  Each RFC-822
                        address is assumed to be in one of the two forms:
                              address (comment)
                              comment <address>


                           Copyright 1994 Novell, Inc.               Page 5













      mailR(5)                                                    mailR(5)


                       Returns an array created from x, split on
                       successive addresses.  Each element of the array
                       comprises another array, whose contents become the
                       parsed address, split into its constituent
                       components.  For each address, there are the
                       components address and comment, which include the
                       corresponding parts of the address.  In addition,
                       there is a component named error, which is set to
                       an error message if there is any problem in parsing
                       the address.  There are also the components route,
                       domain_part, and local_part, which are the
                       corresponding portions of the address when treated
                       as @route:local-part@domain-part.  There is also a
                       component group_phrase, which is set only if there
                       is an RFC-822 group list name.  All addresses which
                       are part of the same list have the same group list
                       name and are found in order.  Note that the address
                       may be empty if there was an error, or if there was
                       a group list name without any names associated with
                       it.

            append_header(var hdrtag, var afterhdr, var val)
                       Creates a new header of type hdrtag after the last
                       header of type afterhdr with value val.  If no
                       header of type afterhdr exists, the header is
                       created at the end of all other headers.  For
                       example,
                             append_header("Received", "Received", "by tom")

                       will create a new Received header after all other
                       Received headers with the value by tom.  The case
                       used by hdrtag is used for creating the header.  A
                       header also gets created by saying:
                             headers("Xyz")[0] = string;

                       If the header Xyz: does not already exist, it will
                       be created.  Otherwise, the first header of that
                       type will be replaced.

            characterset()
                       Returns the current character set, such as ``US-
                       ASCII'' or ``ISO-2022-JP''.

            delete_header(var hdr)
                       Deletes all headers of the given name.  (The first
                       >From header cannot be deleted.)  Returns 1 if any


                          Copyright 1994 Novell, Inc.               Page 6













       mailR(5)                                                    mailR(5)


                        headers were deleted, 0 otherwise.

             domain()   Returns the domain name of the system.

             exists(var hdr)
                        Returns true if a header of the given type exists,
                        and false otherwise.  For example,
                              exists("To")

                        will return true if a To header is in the message.

             filter(var command)
                        If the command is successful, replaces the headers
                        and message body with the output from the command.
                        Returns the exit code.

             filterbody(var command)
                        If the command is successful, replaces the message
                        body with the output from the command.  Returns the
                        exit code.

             filterheaders(var command)
                        If the command is successful, replaces all headers,
                        except the first "From " header, with the output
                        from the command.  Returns the exit code.

             filterstring(var string, var command, reference outstring)
                        Sends the given string to the given command and
                        returns the output in outstring.  Returns the exit
                        code.  If there are problems with temporary files,
                        a -2 is returned.  If there is a problem executing
                        the command, a -1 is returned.

             fromcrack(var x, reference user, reference date, reference system,

                               reference forward)
                        Treats x as a UNIX Postmark header and returns the
                        parts of the header in the reference variables.
                        The three forms of UNIX postmarks recognized are
                              >From user date-string
                              >From user date-string remote from system
                              >From user date-string forwarded by user

                        The system reference is filled in if there is a
                        ``remote from'' system present.  The forward
                        reference is filled in if there is a ``forwarded


                           Copyright 1994 Novell, Inc.               Page 7













      mailR(5)                                                    mailR(5)


                       by'' user present.  If x is not a valid UNIX
                       Postmark header, the results are undefined.

            fromdate(var seconds)
                       Returns the date and time formatted as appropriate
                       for a From UNIX Postmark.  The seconds is the time
                       since January 1, 1970.  If 0 is specified, the
                       current time is used.

            getdate(var string)
                       The string is treated as a date and converted into
                       seconds since January 1, 1970, which is usable by
                       the fromdate() and rfc822date() functions.  This
                       requires the use of the DATEMSK environment
                       variable for the C function getdate(3).  If not
                       set, then the DATEMSK environment variable will
                       default to point to the file /etc/mail/datemask.
                       If the date cannot be parsed, a non-positive value
                       is returned.  A 0 value means that getdate returned
                       a value which could not be converted to a time.  A
                       negative value is the negation of the value
                       returned in getdate_err when getdate fails.  See
                       the manual page for getdate for further details.

            getenv(var x)
                       Returns the value of the environment variable with
                       the name x.

            gsubstitute(var s1, var regex, var repl)
                       Return the string created by using the pattern
                       regex on string s1, making all replacements as
                       controlled by repl.  For example,
                             gsubstitute("system!user", "(.*)!(.*)", "\\2@\\1")

                       would return the string iuser@system and
                             gsubstitute("abcdefg", "[bdf]", "X")

                       would return the string aXcXeXg.

            headers(var string)
                       Returns array of references to all headers named by
                       the string, indexed by numbers (starting at 0) and
                       in the order found in the mail message.  For
                       example,
                             headers("To")



                          Copyright 1994 Novell, Inc.               Page 8













       mailR(5)                                                    mailR(5)


                        would return all To headers.  Multiple line headers
                        are returned as a single string with newlines
                        embedded.  (Leading white space on continuation
                        lines are preserved.)  The reference is live: if
                        you change a value, it changes for real.  If the
                        given header does not exist, a place holder for one
                        will be created.  (The new header will not become
                        real until a value has been assigned.)

             headers_pattern(var pattern)
                        Returns array of references to all headers whose
                        names match the regular expression pattern, indexed
                        by numbers (starting at 0) and in the order found
                        in the mail message.  For example,
                              headers_pattern("To")

                        would return all To headers and
                              headers_pattern(".*")

                        would return all headers.  Multiple line headers
                        are returned as a single string with newlines
                        embedded.  (Leading white space on continuation
                        lines are preserved.)  The reference is live: if
                        you change a value, it changes for real.

             int(var x) return value of x truncated to an integer

             isbinary() Return 0, 1 or 2 if the message body is text,
                        generic-text or binary, respectively.

             length(var x)
                        Returns the number of characters in the string x.

             lines(var x)
                        Equivalent to split(x, "\n").

             localmessage()
                        Returns true if the message was created locally.

             mailsystem(var x)
                        If x == 0, return the name of the system, taken
                        from the cluster name or uname if there is no
                        cluster name.  If x != 0, return the uname of the
                        system.




                           Copyright 1994 Novell, Inc.               Page 9













      mailR(5)                                                    mailR(5)


            match(var str, var pat, reference length)
                       Returns the position in string str where the
                       regular expression pat occurs, 0 if it does not
                       occur at all, and -1 if the regular expression does
                       not compile.  The length variable is set to the
                       length of the matched string.

            messageid()
                       Returns a string suitable for use in a Message-ID
                       or Content-ID header.  Each invocation returns a
                       unique string.

            mgetenv(var x)
                       Returns the value of the mail configuration
                       variable with the name x.

            prepend_header(var x, var beforehdr, var z)
                       Creates a new header of type x before the first
                       header of type beforehdr with value z.  If no
                       header of type beforehdr exists, the header is
                       created before all other headers, but after the
                       >From UNIX Postmark headers.  For example,
                             prepend_header("Date", "To", rfc822date(0))

                       will create a new header named Date before the
                       first To header with the value returned from the
                       rfc822date() function.

            print(var string)
                       Print the string on standard output.

            printheaders()
                       Print the current headers on standard output.

            rand()     Returns a random number between 0 and 1.

            recipients()
                       Return an array containing the recipients the mail
                       message was originally addressed to.

            returnpath()
                       Return a string containing the return path to the
                       originator of the message.





                          Copyright 1994 Novell, Inc.              Page 10













       mailR(5)                                                    mailR(5)


             rfc822date(var seconds)
                        Returns the date and time formatted according to
                        the RFC-822 standard.  The seconds is the time
                        since January 1, 1970.  If 0 is specified, the
                        current time is used.

             split(var x, var y)
                        Returns an array created from x, split on each
                        occurrence of the string y.

             split_pattern(var x, var pat)
                        Returns an array created from x, split on each
                        occurrence of the regular expression pattern pat.

             srand(var seed)
                        If the seed is 0, the current time of day is used.
                        The seed used is returned.

             strrstr(var s1, var s2)
                        Finds the last occurrence of the string s2 in the
                        string s1, and returns its position (1-n), or 0 if
                        s2 not present.

             strstr(var s1, var s2)
                        Finds the first occurrence of the string s2 in the
                        string s1 and returns its position (1-n), or 0 if
                        s2 is not present.

             substitute(var s1, var regex, var repl)
                        Returns the string created by using the pattern
                        regex on string s1, making the first replacement as
                        controlled by repl.  For example,
                              substitute("system!user", "(.*)!(.*)", "\\2@\\1")

                        would return the string user@system, and
                              substitute("abcdefg", "[bdf]", "X")

                        would return the string aXcdefg.

             substr(var s, var m, var n)
                        Returns the n-character substring of s that begins
                        at position m (1-based).

             sysname()  If there is a domain name, then sysname() is
                        equivalent to mailsystem(0).domain().  Otherwise,
                        it is equivalent to mailsystem(0).


                           Copyright 1994 Novell, Inc.              Page 11













      mailR(5)                                                    mailR(5)


            texttype() Returns the strings text, generic-text or binary
                       depending on whether the message contains strictly
                       7-bit text, 8-bit text or binary contents.

            time()     Returns the current time as a number of seconds
                       since Jan. 1, 1970.

            username() Returns the name of the user executing this
                       command.

         Attributes
            Some variable types have attributes.  An attribute is referred
            to using x.attribute.

            header variables: .name
                     Return the name of a header, "" if the variable not a
                     header variable.  For example,
                           headers("To")[0].name

                     will return the string, To:.

            array values: .count
                     Return the number of elements in the array, 0 if
                     there are no elements or the variable is not an
                     array.

      EXAMPLES
            Numerous mailR examples may be found in the file
            /etc/mail/rewrite.samp.
            # this function is performed for all messages
            function main()
            {
                # if we're a message generated locally
                if (localmessage())
                    {
                    # make certain that we have a Date: header
                    if (!exists("Date"))
                        headers("Date")[0] = rfc822date(0);

                    # make certain that the Date: header has the proper format
                    else
                        headers("Date")[0] = rfc822date(getdate(headers("Date")[0]));

                    # if there isn't a From: header, create one
                    if (!exists("From"))
                        headers("From")[0] = username() @ "@" @ sysname();


                          Copyright 1994 Novell, Inc.              Page 12













       mailR(5)                                                    mailR(5)


                     }

                 # collapse multiple >From_ headers into a single >From_ header
                 collapse_from_lines();

                 # convert AT&T Mail MTA messages into MIME format
                 if (exists("message-version") && exists("end-of-protocol"))
                     filter("mtatomime");

                 # if not a MIME message, convert to MIME
                 if (!exists("mime-version"))
                     {
                     headers("Mime-Version")[0] = "1.0";

                     # convert to base64-encoded binary
                     if (texttype() == "binary")
                         {
                         filterbody("mimencode -b -p");
                         headers("Content-Type")[0] = "application/octet-stream";
                         headers("Content-Encoding")[0] = "base-64";
                         }

                     # convert to quoted-printable-encoded 8-bit text
                     else if (texttype() == "generic-text")
                         {
                         filterbody("mimencode -q");
                         headers("Content-Type")[0] = "text/plain; charset=" @
                             characterset();
                         headers("Content-Encoding")[0] = "quoted-printable";
                         }

                     # regular text, mark it as such
                     else
                         headers("Content-Type")[0] = "text/plain";
                     }
             }

             function collapse_from_lines()
             {
                 # loop over existing >From headers, extracting
                 # user and system from each
                 var user, date, system, forward, save_system, save_user,
                             save_date, hdr;
                 for (hdr from headers(">From"))
                     {
                     fromcrack(hdr, user, date, system, forward);


                           Copyright 1994 Novell, Inc.              Page 13













      mailR(5)                                                    mailR(5)


                    if (!forward)
                        {
                        save_user = user;
                        save_date = date;
                        if (save_system)
                            save_system = save_system @ "!" @ system;
                        else
                            save_system = system;
                        }
                    }
                delete_header(">From");
                if (save_system)
                    headers("From")[0] = save_user @ " " @ save_date @
                        " remote from " @ save_system;
                else
                    headers("From")[0] = save_user @ " " @ save_date;
            }

      REFERENCES
            mail(1), mailsurr(4), rewrite(4)




























                          Copyright 1994 Novell, Inc.              Page 14








Typewritten Software • bear@typewritten.org • Edmonds, WA 98026