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