---
name: "mailbox"
section: "8"
platform: "linux"
package: "zmailer"
version: "2.99.55-3"
release: "Debian 3.0 (Woody)"
platforms: ["linux"]
url: "https://new.carta.tech/mailbox"
---

# mailbox(8)

zmailer local delivery transport agent

## NAME

mailbox - zmailer local delivery transport agent

## SYNOPSIS

**mailbox** \[ **-c** *channel* \] \[ **-h** *localpart* \] \[ **-l** *logfile* \] \[ **-8abDCHPrSVX** \]

## DESCRIPTION

*mailbox* is a ZMailer transport agent which is usually only run by the [*scheduler*(8)](/scheduler/8.md) program to deliver mail to local user mailbox files.  The *mailbox* program must be run with root privileges and invoked with the same current directory as the *scheduler*, namely *POSTOFFICE***/transport**.

Recipient addresses are processed as follows:

-

  \- Strip doublequotes around the address, if any.

-

  \- Strip prefixing backslashes, if any.

-

  \- If the address starts with a '\|', the rest of the recipient address string is interpreted as a shell command to be run.

-

  \- If the address starts with a '/', the recipient address is a filename to append the message to.

-

  \- Otherwise the recipient address must be a local user id.

-

  \- If user is not found, and the first character of the address is a capital letter, the entire address is folded to lowercase and the user lookup is retried.

If delivering to a user mailbox (**MAILBOX**/*userid*) which doesn't exist, *mailbox* will try to create it.  If the **MAILBOX** directory is mounted from a remote system this will succeed if the directory is group-writable.

Some sanity checks are done on deliveries to files and mailboxes:

-

  \- The file being delivered to must have 1 link only, and must be either /dev/null or a regular file.

-

  \- The file lock must be held. (See below for a chapter about locks.)

There is a further sanity check on mailbox deliveries, namely if the mailbox is not empty the *mailbox* program will enforce 2 newlines as a separator before the message to be delivered.  This guarantees that User Agents, like [*Mail*(1)](/Mail/1.md), can find the about-to-be delivered message even if the current contents of the mailbox is corrupt.

When delivering to a process (by starting a Bourne shell to execute a specified command line), the environment is set up to contain several variables which are listed below at the \`\`Subprogram Environment Variables'' section. The **SIGINT** and **SIGHUP** signals are ignored, but **SIGTERM** is treated normally. If the process dumps core, it will be retried later. Sub-process exit codes are interpreted according to \<sysexits.h\> codes, and of those EX\_NOPERM, EX\_UNAVAILABLE, EX\_NOHOST, EX\_NOUSER, and EX\_DATAERR are treated as permanent errors, all others are treated as temporary failures.

The actual data delivered to a file, mailbox, or process, is identical. It consists of the concationation of a UUCP style separator line, the message header specified in the message control file, and the message body from the original message file. The separator line starts with "From " and is followed by the sender address and a timestamp.

After all deliveries and just before exiting, the *mailbox* process will poke *comsat*(8C) in case recipients have turned on [*biff*(1)](/biff/1.md). The program may be compiled to look in the rwho files on the system for recipient names logged onto neighbouring hosts, in which case the *comsat* on the remote host will be poked.  Even if this compile-time option is enabled, this will only be done for users that have a **.rbiff** file in their home directory. (Unless an '-DRBIFF\_ALWAYS' compile option is used.)

## OPTIONS

- \-c *channel*

  specifies which channel name should be keyed on.  The default is **local**.

- \-h *"localpart"*

  specifies which of the possible multiple recipients is to be picked this time. Default is "none", which selects all local channel recipients, however when the routing is done with scripts storing some tokens (other than "-") into the "host"-part, it is possible to process "host-wise", i.e. so that each **user** has his/her own lock-state, and not just everybody hang on the same lock(s)..

- \-l *logfile*

  specifies a logfile.  Each entry is a line containing message id, pre-existing mailbox size in bytes, number of bytes appended, and the file name or command line delivered to.

- \-V

  prints a version message and exits.

- \-a

  the access time on mailbox files is, by default, preserved across delivery, so that programs such as [*login*(1)](/login/1.md) can determine if new mail has arrived. This option disables the above action.

- \-b

  disables biff notification.

- \-r

  disables remote biff notification (if supported).

- \-8

  enables MIME-QP-decoder to decode incoming MIME-email with Quoted-Printable encoded characters.

- \-M

  enables the creation of MMDF-style mail-folder in the incoming mail folder. The default is "classic" UNIX-style folder.

- \-C

  Canonify username by using internally version of username received in *pw\_name* field of the *getpwnam()* call result.

- \-D\[D\]

  For a user with is *abcdef*, one *-D* will place the mailbox file into directory *$MAILBOX/a/abcdef*. With *-DD* the mailbox file will be placed into directory: *$MAILBOX/a/b/abcdef*.

- \-P\[P\]

  This uses much of similar method as *-D\[D\]* option, but directory names are derived from much more smoothly distributing hash function over user names, namely: *pjwhash32()*.

  With one *-P*, the calculated hash value is used by formula: *'A'+(hash % 26)* to produce one mid-level directory. With *-PP* the formula is more complex: upper directory uses formula: *'A' + (hash / 26) % 26* and lower uses formula: *'A'+(hash % 26)*

  The result of these *-P\[P\]* derived directory paths is something like: *$MAILBOX/X/username* or *$MAILBOX/Y/X/username*

- \-X\[X\]

  This is similar to *-P\[P\]* option, but used hash function is *crc32()*. Resulting distribution is slightly different, and in fact quite smooth.

- \-S

  This option enables \`\`Return-Receipt-To:'' message header recognition and processing along with sending receipt to given address. *(Newer sendmails don't anymore support this facility per default..)*

## INTERFACE

This program reads in processable file names relative to the current working directory of the scheduler (namely: *$POSTIOFFICE/transport/*). Optionally on the same line the scheduler may tell which host is to be looked for from the recipients of the message.

*relative-spool-path* \[ \<TAB\> *hostname* \]

This program produces diagnostic output on the standard output. Normal diagnostic output is of the form:

*id*/*offset*\<TAB\>*notify-data*\<TAB\>*status* *message*

where  *id* is the inode number of the message file, *offset* is a byte offset within its control file where the address being reported on is kept, *status* is one of **ok**, **error**, or **deferred**, and the *message* is descriptive text associated with the report.  The text is terminated by a linefeed.  Any other format (as might be produced by subprocesses) is passed to standard output for logging in the **scheduler** log.

The exit status is a code from **\<sysexits.h\>**.

## LOCKS

Locking scheme used at the system is configurable at the runtime, and has separate parameters for mailboxes, and files. The data is configurable with zenv variable **MBOXLOCKS** at which following characters have meanins:

- \`:'

  Separates mailbox locks, and file-locks at the string. The left side has mailbox locks, and the right side has locks for other regular files. (Files with explicit paths defined.)

- \`.'

  For mailboxes only: Does \`\`dotlock'' (userid.lock), or (at Sun Solaris) maillock() mechanism.

- \`F'

  If the system has *flock()* system call, uses it to lock the entire file. *(Ignored at systems without flock()!)*

- \`L'

  If the system has *lockf()* system call, uses it to lock the entire file. *(Ignored at systems without lockf()!)*

Locks are acquired in the same order as the key characters are listed.

Default for the lockf() capable systems is:

**MBOXLOCKS=".L:L"**

You can choose insane combinations of lock mechanisms, which at some systems cause locks to fail always, like at Linux-2.0 series where program must not use both lockf() and flock() locks.

*It is extremely important, that selected locking methods are same* *throughout the system at all programs trying to acquire locks on* *mail spools.*

## ENVIRONMENT

The default location for user mailbox files varies per systems, but usually it is one of: **/var/mail**, **/var/spool/mail**, This may be modified by setting the variable **MAILBOX** in **/etc/zmailer.conf** to the directory containing user mailbox files, for example **/usr/spool/mail**. This is best done in the ZMailer SiteConfig file.

Variable **MBOXLOCKS** is used to define locking schemes used for mailbox spool files, and separately for other regular files.

## SECURITY

Like all parts of the *ZMailer*, the *mailbox* chooses to err into overtly cautious side. In case of pipes being run under the *mailbox*, the program in pipe is started thru */bin/sh* with severely sanitized environment variables, and with only file descriptors STDIN, STDOUT, and STDERR. Programs are refused from running, if address analysis has found suspicuous data; external messages can't directly run programs, nor those addresses that have had a security breach detected during *.forward*-, or other aliasing analysis. (Same applies also with writing into explicitly named files.)

The pipe subprogram is run with user-id it gets thru the address privilege analysis during message routing, and it gets the group-id thru lookup of:  getpwuid(uid). That is, if you have multiple usernames with same uid, there are no guarantees as to which of them is used for the gid entry.

The pipe subprogram is started **without** use of */bin/sh* command line interpreter (i.e. "system()" call), when the command line begins with slash, and does not contain characters: \`$' and '\>'. If any of those rules is not fulfilled, the subprogram is started with \`\`/bin/sh -c "$cmdlinestr"'' call.   This allows running pipes with carefully formed parameters, when the *mailbox* program is running inside shell-less chroot environment.

## SUBPROGRAM ENVIRONMENT VARIABLES

The *mailbox* sets following environment variables for the subprograms it runs in the pipes:

- HOME

  The homedirectory path is taken from abovementioned *getpwuid()* lookup.

- USER

  Likewise the textual username.

- SENDER

  is the incoming "MAIL FROM:\<..\>" address without brackets. For an incoming error message, value "\<\>" is used.

- ORCPT

  when present, is the XTEXT encoded ORCPT value received at the message injection into this system. See RFC 1891 for details.

- ENVID

  when present, is the XTEXT encoded ENVID value received at the message injection into this system. See RFC 1891 for details.

- ZCONFIG

  is the location of the ZMailer ZENV file.

- MSGSPOOLID

  Is the message spool-id in the ZMailer; subprograms may use this info in co-operation with ZMailer to e.g. [*syslog*(3)](/syslog/3.md) what they have done to the arrived message.

- MESSAGEID

  Is the RFC 822 "Message-ID:" header data as possibly copied into the control file; another item to support [*syslog*(3)](/syslog/3.md) at programs.

- MAILBIN

  is the value from ZENV.

- MAILSHARE

  is the value from ZENV.

- PATH

  is the value from ZENV, or "/usr/bin:/bin:/usr/ucb" in case no ZENV value is available.

- SHELL

  is constant value: "/bin/sh".

- IFS

  is constant value: " \\t\\n".

- TZ

  is value from scheduler's environment variables via normal environment inheritance rules.  Supposedly that of *systemwide* time-zone setting.  Available to subprogram only if set when the *mailbox* was started.

## FILES

*/etc/zmailer.conf*\
 */var/spool/postoffice (POSTOFFICE)*\
 */var/mail (MAILBOX)*

## SEE ALSO

[scheduler(8)](/scheduler/8.md), comsat(8C), [biff(1)](/biff/1.md), [flock(2)](/flock/2.md), [Mail(1)](/Mail/1.md), [mboxpath(1)](/mboxpath/1.md)

## AUTHOR

This program authored and copyright by:\
 Rayan Zachariassen \<rayan@cs.toronto.edu\>\
 Extensive modifications by:\
 Matti Aarnio \<mea@nic.funet.fi\>
