Go to the first, previous, next, last section, table of contents.


15 The appendfile transport

The `appendfile' transport delivers a message by appending it to a file in the local file system, or by creating an entirely new file in a specified directory. In the latter case, `maildir' format can optionally be used to give added protection against failures that happen part-way through the delivery. `Appendfile' can also be used as a pseudo-remote transport for putting messages into files for remote delivery by some means other than Exim.

The `appendfile' transport is typically used for local deliveries to users' mailboxes, and in this case messages are sent to it explicitly by directors (or, exceptionally, routers). It is also normally used for delivering messages to files or directories whose names are obtained directly from alias, forwarding, or filtering operations.

As `appendfile' is a local transport, it is always run in a separate process, under a non-privileged uid and gid, which are set by `setuid()'. In the common local delivery case, these are the uid and gid belonging to the user to whom the mail is being delivered. The current directory is also normally set to the user's home directory. See chapter "Environment for running local transports" for a discussion of the local delivery environment.

If the transport fails for any reason, the message remains on the input queue so that there can be another delivery attempt later. If there is an error while appending to the file (for example, quota exceeded or partition filled), Exim attempts to reset the file's length and last modification time back to what they were before.

Before appending to the file, a number of security checks are made, and the file is locked. A detailed description is given below, after the list of private options.

15.1 Private options for appendfile

allow_symlink (appendfile) option

Option: allow_symlink
Type: boolean
Default: false

By default, `appendfile' will not deliver if the path name for the file is that of a symbolic link. Setting this option relaxes that constraint, but there are security issues involved in the use of symbolic links. Be sure you know what you are doing if you set this. Details of exactly what this option affects are included in the discussion which follows this list of options.

batch (appendfile) option

Option: batch
Type: string
Default: "none"

Normally, each address that is directed or routed to an `appendfile' transport is handled separately. In special cases it may be desirable to handle several addresses at once, for example, when passing a message with several addresses to a different mail regime (for example, UUCP), though this is more often done using the `pipe' transport. If this option is set to the string `domain', then all addresses with the same domain that are directed or routed to the transport are handled in a single delivery. If it is set to `all' then multiple domains are batched. The list of addresses is included in the `Envelope-to:' header if `envelope_to_add' is set (see below). The only difference between this option and `bsmtp' is the inclusion of SMTP command lines in the output for `bsmtp'.

batch_max (appendfile) option

Option: batch_max
Type: integer
Default: 100

This limits the number of addresses that can be handled in a batch, and applies to both the `batch' and the `bsmtp' options.

bsmtp (appendfile) option

Option: bsmtp
Type: string
Default: "none"

This option is used to set up an `appendfile' transport as a pseudo-remote transport for delivering messages into local files in batch SMTP format for onward transmission by some non-Exim means. It is usually necessary to suppress the default settings of the `prefix' and `suffix' options when using batch SMTP. The value of the option must be one of the strings `none', `one', `domain', or `all'. The first of these turns the feature off. A full description of the batch SMTP mechanism is given in section "Outgoing batched SMTP" in chapter "SMTP processing". When `bstmp' is set, the `batch' option automatically takes the same value. See also the `use_crlf' option.

bsmtp_helo (appendfile) option

Option: bsmtp_helo
Type: boolean
Default: false

When this option is set, a HELO line is added to the output at the start of each message written in batch SMTP format. Some software that reads batch SMTP is unhappy without this.

check_group (appendfile) option

Option: check_group
Type: boolean
Default: false

The group owner of the file is checked only when this option is set. The default setting is unset because the default file mode is 0600, which means that the group is irrelevant.

create_directory (appendfile) option

Option: create_directory
Type: boolean
Default: true

See section "Operational details for delivery to a new file" below.

create_file (appendfile) option

Option: create_file
Type: string
Default: "anywhere"

This option constrains the location of files that are created by this transport. It must be set to one of the words `anywhere', `inhome', or `belowhome'. In the second and third cases, a home directory must have been set up for the address by the director that handled it. This option isn't useful when an explicit file name is given for normal mailbox deliveries; it is intended for the case when file names have been generated from user's `.forward' files, which are usually handled by an `appendfile' transport called `address_file'. See also `file_must_exist'.

current_directory (appendfile) option

Option: current_directory
Type: string
Default: unset

If this option is set, it specifies the directory to make current when running the delivery process. The string is expanded at the time the transport is run. See chapter "Environment for running local transports" for details of the local delivery environment.

delivery_date_add (appendfile) option

Option: delivery_date_add
Type: boolean
Default: true

If this option is true, a `Delivery-date:' header is added to the message. This gives the actual time the delivery was made. As this is not a standard header, Exim has a configuration option (`delivery_date_remove') which requests its removal from incoming messages, so that delivered messages can safely be resent to other recipients.

directory (appendfile) option

Option: directory
Type: string
Default: unset

This option is mutually exclusive with the `file' option. If `directory' is set, the string is expanded, and the message is delivered into a new file in the given directory (or if `maildir_format' is set, into a sub-directory thereof), instead of being appended to a single mailbox file. See section "Operational details for delivery to a new file" for details of this form of delivery.

directory_mode (appendfile) option

Option: directory_mode
Type: integer
Default: 0700

See section "Operational details for delivery to a new file" below.

envelope_to_add (appendfile) option

Option: envelope_to_add
Type: boolean
Default: true

If this option is true, an `Envelope-to:' header is added to the message. This gives the original address(es) in the incoming envelope that caused this delivery to happen. More than one address may be present if `batch' or `bsmtp' is set, or if more than one original address was aliased or forwarded to the same final address. As this is not a standard header, Exim has a configuration option (`envelope_to_remove') which requests its removal from incoming messages, so that delivered messages can safely be resent to other recipients.

file (appendfile) option

Option: file
Type: string
Default: unset

This option need not be set when `appendfile' is being used to deliver to files whose names are obtained from forwarding, filtering, or aliasing address expansions (by default under the instance name `address_file'), as in those cases the file name is associated with the address. Otherwise, the `file' option must be set unless the `directory' option is set. Either `use_fcntl_lock' or `use_lockfile' (or both) must be set with `file'. If you are using more than one host to deliver over NFS into the same mailboxes, you should always use lock files.

The string value is expanded for each delivery, and must yield an absolute path. If the expansion contains a reference to the `local_part' variable, this is checked to ensure that it does not contain a forward slash character -- to prevent an unexpected change of directory. The most common settings of this option are variations on one of these examples:


file = /var/spool/mail/${local_part}
file = /home/${local_part}/inbox
file = ${home}/inbox

In the first example, all deliveries are done into the same directory. If Exim is configured to use lock files (see `use_lockfile' below) it must be able to create a file in the directory, so the `sticky' bit must be turned on for deliveries to be possible, or alternatively the `group' option can be used to run the delivery under a group id which has write access to the directory.

If there is no file name, or the expansion fails, or a local part contains a forward slash character, a delivery error occurs.

file_must_exist (appendfile) option

Option: file_must_exist
Type: boolean
Default: false

If this option is true, the file specified by the `file' option must exist, and an error occurs if it does not. Otherwise, it is created if it does not exist.

from_hack (appendfile) option

Option: from_hack
Type: boolean
Default: true

If this option is true, lines in the body of the message that start with the string `From ' are modified by adding a right angle-bracket at their start. This is necessary for traditional BSD-format mailboxes, where such lines might otherwise indicate the start of a new message.

group (appendfile) option

Option: group
Type: string
Default: unset

If this option is set, it specifies the group under whose gid the delivery process is to be run. If it is not set, a value associated with a user may be used (see below); otherwise a value must have been associated with the address by the director which handled it. If the string contains no $ characters, it is resolved when Exim starts up. Otherwise, the string is expanded at the time the transport is run, and must yield either a digit string or a name which can be looked up using `getgrnam()'.

The `group' option is commonly set for local deliveries on systems where the set of user mailboxes is in a single directory owned by a group such as `mail'. Note that it should not be set on the instance of `appendfile' that is called `address_file', because that applies to deliveries directly to files specified by users in their forward files, and such deliveries should take place under the individual users' personal uids and gids.

lock_interval (appendfile) option

Option: lock_interval
Type: time
Default: 3s

This specifies the time to wait between attempts to lock the file. See below for details of locking.

lock_retries (appendfile) option

Option: lock_retries
Type: integer
Default: 10

This specifies the maximum number of attempts to lock the file. A value of zero is treated as 1. See below for details of locking.

lockfile_mode (appendfile) option

Option: lockfile_mode
Type: integer
Default: 0600

This specifies the mode of the created lock file, when a lock file is being used (see `use_lockfile').

lockfile_timeout (appendfile) option

Option: lockfile_timeout
Type: time
Default: 30m

When a lock file is being used (see `use_lockfile'), if a lock file already exists and is older than this value, it is assumed to have been left behind by accident, and Exim attempts to remove it.

maildir_format (appendfile) option

Option: maildir_format
Type: boolean
Default: false

If this option is set with the `directory' option, then the delivery is into a new file in the `maildir' format that is used by some other mail software. See section "Operational details for delivery to a new file" below.

maildir_retries (appendfile) option

Option: maildir_retries
Type: integer
Default: 10

This option specifies the number of times to retry when writing a file in `maildir' format. See section "Operational details for delivery to a new file" below.

mode (appendfile) option

Option: mode
Type: integer
Default: 0600

If the output file is created, it is given this mode. If it already exists and has wider permissions, they are reduced to this mode. If it has narrower permissions, an error occurs unless `mode_fail_narrower' is false. However, if the delivery is the result of a `save' command in a filter file specifing a particular mode, then the mode of the output file is always forced to take that value, and this option is ignored.

mode_fail_narrower (appendfile) option

Option: mode_fail_narrower
Type: boolean
Default: true

This option applies in the case when an existing mailbox file has a narrower mode than that specified by the `mode' option. If `mode_fail_narrower' is true, the delivery is frozen (`mailbox has the wrong mode'); otherwise Exim continues with the delivery attempt, using the existing mode of the file.

notify_comsat (appendfile) option

Option: notify_comsat
Type: boolean
Default: false

If this option is true, the `comsat' daemon is notified after every successful delivery to a user mailbox. This is the daemon that notifies logged on users about incoming mail.

prefix (appendfile) option

Option: prefix
Type: string
Default: "see below"

The string specified here is expanded and output at the start of every message. The default is


prefix = "From ${if def:return_path{$return_path}{MAILER-DAEMON}}\
  ${tod_bsdinbox}\n"

This line can be suppressed by setting


prefix =

and this is usually necessary when doing batch SMTP deliveries.

quota (appendfile) option

Option: quota
Type: string
Default: unset

This option imposes a limit on the size of the file to which Exim is appending. The value is expanded, and must then be a numerical value (decimal point allowed), optionally followed by one of the letters K or M. The expansion happens while Exim is running as root or the Exim user, before `setuid()' is called for the delivery, so files that are inaccessible to the end user can be used to hold quota values that are looked up in the expansion. When delivery fails because this quota is exceeded, the handling of the error is as for system quota failures. The value specified is not accurate to the last byte, owing to separator lines and additional headers that may get added during the delivery.

require_lockfile (appendfile) option

Option: require_lockfile
Type: boolean
Default: true

When a lock file is being used (see `use_lockfile') and `require_lockfile' is true, a lock file must be created before delivery can proceed. If the option is not true, failure to create a lock file is not treated as an error, though failure of the `fcntl()' locking function is. This option should always be set when delivering from more than one host over NFS. It is required to be set if the `file' option is set and `use_fcntl_lock' is not set.

retry_use_local_part (appendfile) option

Option: retry_use_local_part
Type: boolean
Default: true

When a local delivery suffers a temporary failure, both the local part and the domain are normally used to form a key that is used to determine when next to try the address. This handles common cases such as exceeding a quota, where the failure applies to the specific local part. However, when local delivery is being used to collect messages for onward transmission by some other means, a temporary failure may not depend on the local part at all. Setting this option false causes Exim to use only the domain when handling retries for this transport.

return_path_add (appendfile) option

Option: return_path_add
Type: boolean
Default: true

If this option is true, a `Return-path:' header is added to the message. Although the return path is normally available in the prefix line of BSD mailboxes, this is commonly not displayed by MUAs, and so the user does not have easy access to it.

RFC 822 states that the `Return-path:' header is `added by the final transport system that delivers the message to its recipient' (section 4.3.1), which implies that this header should not be present in incoming messages. Exim has a configuration option, `return_path_remove', which requests removal of this header from incoming messages, so that delivered messages can safely be resent to other recipients.

suffix (appendfile) option

Option: suffix
Type: string
Default: "\n"

The string specified here is expanded and output at the end of every message. The default blank line can be suppressed by setting


suffix =

and this is usually necessary when doing batch SMTP deliveries.

use_crlf (appendfile) option

Option: use_crlf
Type: boolean
Default: false

This option causes lines to be terminated with the two-character CRLF sequence (carriage return, linefeed) instead of just a linefeed character. In the case of batched SMTP, the byte sequence written to the file is then an exact image of what would be sent down a real SMTP connection. If the `prefix' or `suffix' options are defined, their contents are written verbatim, so must contain their own carriage return characters if these are needed.

use_fcntl_lock (appendfile) option

Option: use_fcntl_lock
Type: boolean
Default: true

This option controls the use of the `fcntl()' function to lock a file when a message is being appended. It should be turned off only if you know that all your MUAs use lock file locking. When `use_fcntl_lock' is off, `use_lockfile' and `require_lockfile' must both be on.

use_lockfile (appendfile) option

Option: use_lockfile
Type: boolean
Default: true

If this option is turned off, Exim does not attempt to create a lock file when appending to a file. Thus the only locking is by `fcntl()'. It is not possible to turn both `use_lockfile' and `use_fcntl_lock' off. You should only turn `use_lockfile' off if you are absolutely sure that every MUA that is ever going to look at your users' mailboxes uses `fcntl()' rather than a lock file, and even then only when you are not delivering over NFS from more than one host. In order to append to an NFS file safely from more than one host, it is necessary to take out a lock before opening the file, and the lock file achieves this. Otherwise, even with `fcntl()' locking, there is a risk of file corruption. See also the `require_lockfile' option.

user (appendfile) option

Option: user
Type: string
Default: unset

If this option is set, it specifies the user under whose uid the delivery process is to be run. If it is not set, a value must have been associated with the address by the director that handled it. If the string contains no $ characters, it is resolved when Exim starts up. Otherwise, the string is expanded at the time the transport is run, and must yield either a digit string or a name which can be looked up using `getpwnam()'. When `getpwnam()' is used, either at start-up time or later, the group id value associated with the user is taken as the value to be used if the `group' option is not set.

15.2 Operational details for appending

Before appending to a file, Exim proceeds as follows:

At the end of delivery, Exim closes the file (which releases the `fcntl()' lock) and then deletes the lock file if one was created.

15.3 Operational details for delivery to a new file

When the `directory' option is set, each message is delivered into a newly-created file. No locking is performed while writing the message, as each delivery creates a new file, so the various locking options of the transport are ignored. The `From' line that by default separates messages in a single file is not normally needed, nor is the escaping of message lines that start with `From', and there is no need to ensure a newline at the end of each message. Consequently, the default settings in `appendfile' need changing as follows:


  no_from_hack
  prefix=""
  suffix=""

There are two different ways in which delivery to a single file can be done, depending on the setting of the `maildir_format' option.

For non-maildir delivery, new files are created directly in the named directory. For example, when delivering messages into files using the `bsmtp' option (see section "Outgoing batched SMTP" in chapter "SMTP processing") a setting such as


directory = /var/bsmtp/${host}

might be used. A message is written to a file with a temporary name, which is then renamed when the delivery is complete. The final name is constructed from the time and the file's inode number, and starts with the letter `q' for compatibility with `smail'.

If the `create_directory' option is set (the default), an attempt is made to create the directory if it does not exist; if it is created then its mode is given by the `directory_mode' option. If creation fails, or if the `create_directory' option is not set, then the delivery is deferred.

If the `maildir_format' option is true, then Exim

  1. ensures that subdirectories called `tmp', `new', and `cur' exist within the given directory, and
  2. delivers each message by writing it to a file whose name is `tmp/<time>.<pid>.<host>' and then renaming it into the `new' directory if all goes well.

If the subdirectories (and indeed the main directory itself) do not exist, Exim creates them with mode `directory_mode' if the `create_directory' option is true. Otherwise it freezes the delivery.

Before opening the temporary file, Exim calls `stat()' on its name. If any response other than ENOENT (does not exist) is given, it waits 2 seconds and tries again, up to `maildir_retries' times.


Go to the first, previous, next, last section, table of contents.