Museum

Home

Lab Overview

Retrotechnology Articles

Online Manuals

⇒ mailR(5) — DG/UX R4.11

Media Vault

Software Library

Restoration Projects

Artifacts Sought

Related Articles

mail(1)

mailsurr(4)

mime(5)

rewrite(4)



mailR(5)                         DG/UX R4.11                        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.

       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 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 (less than)
                                 (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 (greater than)

                     x <= y      relational operator (less than or equal)

                     x >= y      relational operator (greater than or equal)

                     x == y      equality operator (equal)

                     x != y      equality operator (not equal)

                     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.

                     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.  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 to the index of the array element.

   Predefined Functions
       A number of functions are predefined.

       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 RFC822 addresses separated by
                  commas and optional newlines.  Each RFC822 address is
                  assumed to be in one of the two forms:
                       address (comment)
                       comment <address>

                  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, domainpart, and localpart,
                  which are the corresponding portions of the address when
                  treated as @route:local-part@domain-part.  There is also a
                  component groupphrase, which is set only if there is an
                  RFC822 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.

       appendheader(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,
                       appendheader("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:
                       header(Xyz) = string

                  If the header Xyz does not already exist, it is created.
                  Otherwise, all existing headers of that type are replaced.

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

       deleteheader(var hdr)
                  Deletes all headers of the given name.  (The first >From
                  header cannot be deleted.)

       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)
                  Replaces the headers and message body with the output from
                  the command.  Returns the exit code.

       filterbody(var command)
                  Replaces the message body with the output from the
                  command.  Returns the exit code.

       filterheaders(var command)
                  Replaces headers 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 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 by'' user present.

       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
                  getdateerr 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.

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

                  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.

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

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

                  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.

       index(var s1, var s2)
                  Finds s2 in s1 and returns its position (1-n), 0 if s2 not
                  present.

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

       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.

       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.

       prependheader(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,
                       prependheader("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.

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

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

       rindex(var s1, var s2)
                  Finds s2 in s1 starting from end and returns its position
                  (1-n), 0 if s2 not present.

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

       splitpattern(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.

       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).

       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 variables types have attributes.  An attribute is referred to
       using x.attribute.

       header variables: .name
                name of a header, "" if not a header variable.  For example,
                     header("To").name

                returns the string, to:

       array values: .count
                number of elements in the array, 0 if no elements or not an
                array.

EXAMPLES
       # 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"))
                   header("Date") = rfc822date(0);

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

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

           # collapse multiple >From headers into a single >From header
           collapsefromlines();

           # 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"))
               {
               header("Mime-Version") = "1.0";

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

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

               # regular text, mark it as such
               else
                   header("Content-Type") = "text/plain"
               }
       }

       function collapsefromlines()
       {
           # loop over existing >From headers, extracting
           # user and system from each
           var user, date, system, forward, savesystem, saveuser,
                       savedate, hdr;
           for (hdr in header(">From"))
               {
               fromcrack(hdr, user, date, system, forward);
               if (!forward)
                   {
                   saveuser = user;
                   savedate = date;
                   if (savesystem)
                       savesystem = savesystem @ "!" @ system;
                   else
                       savesystem = system;
                   }
               }
           header(">From") = saveuser @ " " @ savedate @
                       " remote from " @ savesystem;
       }

SEE ALSO
       mail(1), mailsurr(4), mime(5), rewrite(4)


Licensed material--property of copyright holder(s)

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