diff options
25 files changed, 37786 insertions, 8 deletions
diff --git a/doc/ABOUT b/doc/ABOUT new file mode 100644 index 000000000..4bbaeafe0 --- /dev/null +++ b/doc/ABOUT @@ -0,0 +1,33 @@ +$Cambridge: exim/doc/ABOUT,v 1.1 2005/06/16 10:32:31 ph10 Exp $ + +CVS directory exim/exim-doc +--------------------------- + +This directory contains all the files related to Exim documentation. They are +held in a number of subdirectories. + +doc-docbook This directory contains the AsciiDoc and DocBook sources for + the Exim specification and the filter description. It also + contains a Makefile and all the scripts, stylesheets, etc. + that are used to create the distributed renditions of the + documents. This way of creating the documentation was + introduced for release 4.60. + +doc-misc This directory contains a number of miscellaneous documents + that are relevant to Exim, but not part of its distribution + tarball. + +doc-scripts This directory contains scripts for building exported + documentation from the original SGCAL input source. These were + used up to and including release 4.50. + +doc-src This directory contains the SGCAL source documents that were + used up to and including release 4.50. + +doc-txt This directory contains documentation that is maintained only + as text files. + +Each of these directories contains an ABOUT file that describes its contents in +more detail. + +End diff --git a/doc/doc-docbook/ABOUT b/doc/doc-docbook/ABOUT new file mode 100644 index 000000000..72048b569 --- /dev/null +++ b/doc/doc-docbook/ABOUT @@ -0,0 +1,16 @@ +$Cambridge: exim/doc/doc-docbook/ABOUT,v 1.1 2005/06/16 10:32:31 ph10 Exp $ + +CVS directory exim/exim-doc/doc-docbook +--------------------------------------- + +This directory contains the AsciiDoc and DocBook sources for the Exim +specification and the filter description. It also contains a Makefile and all +the scripts, stylesheets, etc. that are used to create the distributed +renditions of the documents. This way of creating the documentation was +introduced for release 4.60. + +The file HowItWorks.txt explains the processes by which the distributed +renditions are created. It also contains a list of the files in this directory +and what they all contain. + +End diff --git a/doc/doc-docbook/AdMarkup.txt b/doc/doc-docbook/AdMarkup.txt new file mode 100644 index 000000000..40942a629 --- /dev/null +++ b/doc/doc-docbook/AdMarkup.txt @@ -0,0 +1,434 @@ +$Cambridge: exim/doc/doc-docbook/AdMarkup.txt,v 1.1 2005/06/16 10:32:31 ph10 Exp $ + +Asciidoc markup used in the Exim documentation +---------------------------------------------- + +This file contains a summary of the AsciiDoc markup that is used in the source +files of the Exim documentation. The source files are in plain text that can be +edited by any text editor. They are converted by the AsciiDoc application into +DocBook XML for subsequent processing into the various output formats. + +This markup requires AsciiDoc release 6.0.3 or later. + +The advantage of using AsciiDoc format as a "back end" is that is uses +relatively simple markup in the majority of the text, making it easier to read +and edit. The disadvantage is that it is tricky to deal with complicated +formatting - though that is probably true of any markup language - and there +are a few gotchas. + +The Exim documentation uses the default AsciiDoc markup with some additions. I +have created a special AsciiDoc configuration file for use with the Exim +documentation. You must use this configuration if you want to get sensible +results, + + +SPECIAL CHARACTERS + +When typing paragraphs of text, the following character sequences are +recognized as markup if they occur surrounding a "word phrase" within a +paragraph. In the list below, ... represents the text that is enclosed. + + '...' single quotes italic: + used for email addresses, domains, local + parts, header names, user names + + *...* asterisks bold + used for things like "*Note:*" + + `...` backticks monospaced text + used for literal quoting + + $...$ dollar Exim variable + maps to XML <varname> with leading $ + + %...% percent Exim option, command line option + maps to XML <option> + + ^...^ circumflex Exim driver name, Unix command, filter command + maps to XML <command> + + ^^...^^ double circumflex C function: maps to XML <function> + + ^%...%^ circumflex percent parameter: maps to XML <parameter> + Not currently used + + _..._ underscore file name: maps to XML <filename> + + ``...'' backticks & quotes put word in quotation marks + +For example, + + This is an 'italic phrase'. This is a _filename_ and a $variable$. + This ``word'' is in quote marks. + +These quoting characters are recognized only if they are not flanked by +alphanumeric characters. Thus, for instance, an apostrophe within a word can be +represented as a single quote without any problem. Quoting can be nested, but +not overlapped. However, the resulting XML from nested quotes is not always +valid, so nesting is best avoided. (For example, `xxx'yyy'xxx` generates an +<emphasis> item within a <literal> item, and the DocBook DTD doesn't allow +that.) However, one combination that does work is <literal> within an +<emphasis>, so that is what you have to use if you want a boldface monospaced +font. That is, use *`bold mono`* and not `*bold mono*`. Sigh. + +There are also some character sequences that are translated into non-Ascii +characters: + + -- en-dash (–) + --- em-dash (舒) + ~ hard space ( ) + !! dagger (†} + +The two-character sequence ## is turned into nothing. It is useful for +disambiguating markup. For example, something like + + ``quoted ending in 'emphasized''' + +is ambiguous, and as AsciiDoc looks for the longest markup first, it doesn't do +what you want. You have to code this as + + ``quoted ending in 'emphasized'##'' + +The dashes are recognized only when surrounded by white space. The special Exim +AsciiDoc configuration also translates most apostrophes to a typographic +apostrophe (’). There are some cases where this doesn't work, for +example, an apostrophe after a word in another font (because the quote +character gets in the way). For this purpose, there is a named "attribute" that +can be used. Named attributes are substituted inside curly braces. + +For example, in the filter document there is a reference to an imaginary user +called lg303. User names are italicized, so this is always typed as 'lg303' but +if an apostrophe-s is needed after it, you have to type + + 'lg303'{ap}s + +Another named attribute is {tl}, which turns into a tilde character, because a +literal tilde becomes a hard space. + +A third named attribute is {hh}, which turns into two hyphens, because a +literal "--" is converted into an en dash. + +A fourth named attributs is {pc}, which turns into a percent sign. + + +ESCAPING SPECIAL CHARACTERS + +Use backslash if you need to escape a special character. + +***** GOTCHA ***** +Backslash is not special when it precedes any other character. Thus, you need +to know which characters are special, which is a pain. + + +COMMENTS + +You can include comments that will not be copied to the XML document by +creating a comment block that is delimited by at least three slashes. For +example: + + /// + This is an AsciiDoc comment block. + /// + + +URL REFERENCES + +To refer to a URL, just put it in the text, followed by some text in square +brackets to define the displayed text. If that is empty, the URL itself is +displayed. For example, here's a reference to http://www.exim.org/[exim home +page]. In HTML output, all you see is the display text; in printed output you +see something like "exim home page [http://www.exim.org/]". The URL is printed +in whatever is the current font, so it can be made bold by putting it in +asterisks (for example). + + +FORMAL PARAGRAPHS + +A formal paragraph has a title. This is normally typeset in bold at the start +of the paragraph, and is useful as an alternative to a vertical labelled list +(see below). To create such a paragraph, you just put its title first, like +this: + + [title="the title"] + Now give the text of the paragraph as usual. + + +CHAPTERS AND SECTIONS + +AsciiDoc recognizes chapter and sections by looking for underlined lines, with +the underlining character used to determine the type of section. + + This is a chapter title + ----------------------- + + This is a section title + ~~~~~~~~~~~~~~~~~~~~~~~ + +Chapter titles are used for running feet in the PDF form of the manual. +Sometimes they are too long, causing them to be split in an ugly way. The +solution to this is to define a short title for the chapter, like this: + + [titleabbrev="short title"] + This is a rather long chapter title + ----------------------------------- + + +DISPLAYS + +Displayed blocks in a monospaced font can just be indented: + + # Exim filter + deliver baggins@rivendell.middle-earth.example + +However, it seems that if the first line in such a block starts with an +asterisk or if any lines in the block end in a backslash (as is quite often the +case in Exim configuration examples), you have to use a "listing block" or a +"literal block" instead of a "literal paragraph". Otherwise an initial asterisk +makes AsciiDoc think this is a list item, and a terminating backslash causes +lines to be concatenated. + +Another time when you have to use an explicit block is when a display forms +part of a list item. This is because you have to indent such displays more than +usual, because the processors don't appear to do this automatically. + +Listing blocks are delimited by lines of at least three hyphens; literal blocks +are delimited by lines of at least four dots. For example: + +.... +/usr/sbin/sendmail -bf myfilter \ + -f islington@never.where <test-message +.... + +Such blocks are indented by an amount that is specified in the style sheet, but +this amount is always the same, regardless of whether the block is inside a +list item (which is itself indented) or not. So if the block is within a list +item, it must be explicitly indented as well. + +Blocks that are between lines of ampersands (at least 3 in each line) are +displayed (by default) in the normal font, but with the lines unchanged. Quotes +can be used in the block to specify different fonts. For example: + +&&&& +`\n` is replaced by a newline +`\r` is replaced by a carriage return +`\t` is replaced by a tab +&&&& + +When this kind of output is required within a list of any kind (see below), you +must precede it with a line consisting of just a plus sign, because by default +any kind of block terminates the list item. + + +CROSS-REFERENCES + +To set a cross-reference point, enclose the name in double square brackets: + + [[SECTexample]] + +To refer to a cross-reference point, enclose the name in double angle brackets: + + <<SECTexample>> + + +INDEX ENTRIES + +To create an index entry, include a line like one of these: + + cindex:[primary text,secondary text] + oindex:[primary text,secondary text] + +at the appropriate point in the text. The first is for the "concept index" and +the second is for the "options index". Not all forms of output distinguish +between these - sometimes there is just one index. + +The index for the Exim reference manual has a number of "see also" entries. +Rather than invent some fancy AsciiDoc way of doing this, I have just coded +them in XML, using the AsciiDoc escape hatch that is described below under +FUDGES. + + +LISTS + +For a bulleted list, start each item in the list with a hyphen or an asterisk +followed by a space: + + - First item. + - Second item. + +For a numbered list, start each item with a dot followed by a space: + + . First item. + . Second item. + + +VERTICAL LABELLED LISTS + +These are used for Exim command line options and similar things. They map into +XML <variablelist> items. Start the list with the item name, followed by two +colons, on a line by itself. This is followed by the text for the list item. + + +LISTS CONTAINING MORE THAN ONE PARAGRAPH + +If there is more than one paragraph in a list item, the second and subsequent +ones must be preceded by a line containing just a single "+" character, as +otherwise the list is terminated. Literal paragraphs can be included without +any special markup. For example: + + first item:: + This is the pararaph that describes the item. + + We can even have an indented display + within the item + + + but any more paragraphs must be preceded by a plus character + (otherwise they aren't included in the list, and won't be + properly indented). + +The "+" notation can also be used to include other kinds of block within a list +item. It's needed for all block types except nested lists and literal +paragraphs. + +An alternative approach to lists that contain multiple paragraphs or blocks +within each item is to put a line containing just two hyphens immediately +before and immediately after the list. For example: + + -- + . First item + + Second paragraph of first item + + . Second item + + And so on + -- + +This is particularly helpful for nested lists (see below). + + +NESTED LISTS + +You can nest lists of different types. However, if you want to revert to an +outer list item at the end of a nested list, you must use the "--" feature +described above for the inner list, so that its end can be explicitly marked. +For example: + + . Outer list + + + Second paragraph in outer list + + + -- + - Inner list item + - Inner list second item + -- + + + Another paragraph in the outer list first item + + . Next item in the outer list + + +TABLES + +A fixed-width table is started by a line of hyphens that determines the width +of the table, interspersed with the following column stop characters: + + ` backtick align left + ' quote align right + . dot align centre + +The data is then aligned with the stop characters. For example: + + `---`--- + 1 2 + 3 4 + -------- + +Alternatively, if tildes are used instead of hyphens, the data fields are +comma-separated. Columns can also be specified numerically instead of by +pattern. This is usually used with CSV data. For example: + + `10`20`30~ + one, two, three + ~~~~~ + +This format is useful when the data is full of markup so that its final length +bears little relationship to the input (for example, when there are cross +references). + +By default, tables will be rendered with a frame at the top and bottom, and no +separators between rows and columns. You can use AsciiDoc "attributes" to +change this. Attributes are set by a sequence of name=value items in square +brackets, before the thing to which they apply. For example: + + [frame="none"] + `-----`----- + 11 22 + 33 44 + ------------ + +The values for "frame" are "topbot", "sides", "all", or "none". There is also a +"grid" attribute, whose possible values are "none", "cols", "rows", or "all". +For example: + + [frame="sides", grid="cols"] + +The commas between the attribute settings are important; if they are omitted, +AsciiDoc ignores the attribute settings. + + +EXIM CONFIGURATION OPTION HEADINGS + +Each Exim configuration option is formatted with its name, usage, type, and +default value on a single line, spread over the line so as to fill it +completely. The only way I know of aligning text using DocBook is to use a +table. A special table format has been created to handle this special case. For +example: + + `..'= + %keep_malformed%, Use: 'main', Type: 'boolean', Default: 'false' + === + +The first line defines four colums using stop characters, followed by an equals +character that defines the table's "ruler" character. There is no need to +define column widths, because the style forces the columns to fill the page +width. The data is comma-separated. + + +CHANGE BARS + +I haven't yet found a way of doing changebars in the printed versions. However, +it is possible to put a green background behind changed text in the HTML +version, so the appropriate markup should be used. Before a changed paragraph, +insert + + [revisionflag="changed"] + +This should precede any index settings at the start of the paragraph. If you +want to do this for a display, you must use the "&&&" block described above, +because that's the only type that I have set up to support it. + + +FUDGES + +The current release of "fop", a program for producing PostScript from +"formatting objects" (fo) data, which is an intermediate output that can be +generated from DocBook XML, is not very good at page layout. For example, it +can place a section heading as the last line on a page. I have set up a style +that provides a means of forcing a page break in order to get round this. (But +in practice, it happens so often that I have given up trying to use it.) + +At the AsciiDoc level, the markup uses a "backend block", which provides a way +of specifying DocBook output directly. Backend blocks are surrounded by lines +of plusses, and this particular fudge looks like this: + + ++++++++++++ + <?hard-pagebreak?> + ++++++++++++ + +Backend blocks are used to insert XML comments into the output, to mark the +start and end of Exim's command line options. These are used by the x2man +script that creates the man page. + + +Philip Hazel +Last updated: 10 June 2005 diff --git a/doc/doc-docbook/HowItWorks.txt b/doc/doc-docbook/HowItWorks.txt new file mode 100644 index 000000000..9be1466e2 --- /dev/null +++ b/doc/doc-docbook/HowItWorks.txt @@ -0,0 +1,541 @@ +$Cambridge: exim/doc/doc-docbook/HowItWorks.txt,v 1.1 2005/06/16 10:32:31 ph10 Exp $ + +CREATING THE EXIM DOCUMENTATION + +"You are lost in a maze of twisty little scripts." + + +This document describes how the various versions of the Exim documentation, in +different output formats, are created from DocBook XML, and also how the +DocBook XML is itself created. + + +BACKGROUND: THE OLD WAY + +From the start of Exim, in 1995, the specification was written in a local text +formatting system known as SGCAL. This is capable of producing PostScript and +plain text output from the same source file. Later, when the "ps2pdf" command +became available with GhostScript, that was used to create a PDF version from +the PostScript. (A few earlier versions were created by a helpful user who had +bought the Adobe distiller software.) + +A demand for a version in "info" format led me to write a Perl script that +converted the SGCAL input into a Texinfo file. Because of the somewhat +restrictive requirements of Texinfo, this script has always needed a lot of +maintenance, and has never been 100% satisfactory. + +The HTML version of the documentation was originally produced from the Texinfo +version, but later I wrote another Perl script that produced it directly from +the SGCAL input, which made it possible to produce better HTML. + +There were a small number of diagrams in the documentation. For the PostScript +and PDF versions, these were created using Aspic, a local text-driven drawing +program that interfaces directly to SGCAL. For the text and texinfo versions, +alternative ascii-art diagrams were used. For the HTML version, screen shots of +the PostScript output were turned into gifs. + + +A MORE STANDARD APPROACH + +Although in principle SGCAL and Aspic could be generally released, they would +be unlikely to receive much (if any) maintenance, especially after I retire. +Furthermore, the old production method was only semi-automatic; I still did a +certain amount of hand tweaking of spec.txt, for example. As the maintenance of +Exim itself was being opened up to a larger group of people, it seemed sensible +to move to a more standard way of producing the documentation, preferable fully +automated. However, we wanted to use only non-commercial software to do this. + +At the time I was thinking about converting (early 2005), the "obvious" +standard format in which to keep the documentation was DocBook XML. The use of +XML in general, in many different applications, was increasing rapidly, and it +seemed likely to remain a standard for some time to come. DocBook offered a +particular form of XML suited to documents that were effectively "books". + +Maintaining an XML document by hand editing is a tedious, verbose, and +error-prone process. A number of specialized XML text editors were available, +but all the free ones were at a very primitive stage. I therefore decided to +keep the master source in AsciiDoc format (described below), from which a +secondary XML master could be automatically generated. + +All the output formats are generated from the XML file. If, in the future, a +better way of maintaining the XML source becomes available, this can be adopted +without changing any of the processing that produces the output documents. +Equally, if better ways of processing the XML become available, they can be +adopted without affecting the source maintenance. + +A number of issues arose while setting this all up, which are best summed up by +the statement that a lot of the technology is (in 2005) still very immature. It +is probable that trying to do this conversion any earlier would not have been +anywhere near as successful. The main problems that still bother me are +described in the penultimate section of this document. + +The following sections describe the processes by which the AsciiDoc files are +transformed into the final output documents. In practice, the details are coded +into a makefile that specifies the chain of commands for each output format. + + +REQUIRED SOFTWARE + +Installing software to process XML puts lots and lots of stuff on your box. I +run Gentoo Linux, and a lot of things have been installed as dependencies that +I am not fully aware of. This is what I know about (version numbers are current +at the time of writing): + +. AsciiDoc 6.0.3 + + This converts the master source file into a DocBook XML file, using a + customized AsciiDoc configuration file. + +. xmlto 0.0.18 + + This is a shell script that drives various XML processors. It is used to + produce "formatted objects" for PostScript and PDF output, and to produce + HTML output. It uses xsltproc, libxml, libxslt, libexslt, and possibly other + things that I have not figured out, to apply the DocBook XSLT stylesheets. + +. libxml 1.8.17 + libxml2 2.6.17 + libxslt 1.1.12 + + These are all installed on my box; I do not know which of libxml or libxml2 + the various scripts are actually using. + +. xsl-stylesheets-1.66.1 + + These are the standard DocBook XSL stylesheets. + +. fop 0.20.5 + + FOP is a processor for "formatted objects". It is written in Java. The fop + command is a shell script that drives it. + +. w3m 0.5.1 + + This is a text-oriented web brower. It is used to produce the Ascii form of + the Exim documentation from a specially-created HTML format. It seems to do a + better job than lynx. + +. docbook2texi (part of docbook2X 0.8.5) + + This is a wrapper script for a two-stage conversion process from DocBook to a + Texinfo file. It uses db2x_xsltproc and db2x_texixml. Unfortunately, there + are two versions of this command; the old one is based on an earlier fork of + docbook2X and does not work. + +. db2x_xsltproc and db2x_texixml (part of docbook2X 0.8.5) + + More wrapping scripts (see previous item). + +. makeinfo 4.8 + + This is used to make a set of "info" files from a Texinfo file. + +In addition, there are some locally written Perl scripts. These are described +below. + + +ASCIIDOC + +AsciiDoc (http://www.methods.co.nz/asciidoc/) is a Python script that converts +an input document in a more-or-less human-readable format into DocBook XML. +For a document as complex as the Exim specification, the markup is quite +complex - probably no simpler than the original SGCAL markup - but it is +definitely easier to work with than XML itself. + +AsciiDoc is highly configurable. It comes with a default configuration, but I +have extended this with an additional configuration file that must be used when +processing the Exim documents. There is a separate document called AdMarkup.txt +that describes the markup that is used in these documents. This includes the +default AsciiDoc markup and the local additions. + +The author of AsciiDoc uses the extension .txt for input documents. I find +this confusing, especially as some of the output files have .txt extensions. +Therefore, I have used the extension .ascd for the sources. + + +THE MAKEFILE + +The makefile supports a number of targets of the form x.y, where x is one of +"filter", "spec", or "test", and y is one of "xml", "fo", "ps", "pdf", "html", +"txt", or "info". The intermediate targets "x.xml" and "x.fo" are provided for +testing purposes. The other five targets are production targets. For example: + + make spec.pdf + +This runs the necessary tools in order to create the file spec.pdf from the +original source spec.ascd. A number of intermediate files are created during +this process, including the master DocBook source, called spec.xml. Of course, +the usual features of "make" ensure that if this already exists and is +up-to-date, it is not needlessly rebuilt. + +The "test" series of targets were created so that small tests could easily be +run fairly quickly, because processing even the shortish filter document takes +a bit of time, and processing the main specification takes ages. + +Another target is "exim.8". This runs a locally written Perl script called +x2man, which extracts the list of command line options from the spec.xml file, +and creates a man page. There are some XML comments in the spec.xml file to +enable the script to find the start and end of the options list. + +There is also a "clean" target that deletes all the generated files. + + +CREATING DOCBOOK XML FROM ASCIIDOC + +There is a single local AsciiDoc configuration file called MyAsciidoc.conf. +Using this, one run of the asciidoc command creates a .xml file from a .ascd +file. When this succeeds, there is no output. + + +DOCBOOK PROCESSING + +Processing a .xml file into the five different output formats is not entirely +straightforward. For a start, the same XML is not suitable for all the +different output styles. When the final output is in a text format (.txt, +.texinfo) for instance, all non-Ascii characters in the input must be converted +to Ascii transliterations because the current processing tools do not do this +correctly automatically. + +In order to cope with these issues in a flexible way, a Perl script called +Pre-xml was written. This is used to preprocess the .xml files before they are +handed to the main processors. Adding one more tool onto the front of the +processing chain does at least seem to be in the spirit of XML processing. + +The XML processors themselves make use of style files, which can be overridden +by local versions. There is one that applies to all styles, called MyStyle.xsl, +and others for the different output formats. I have included comments in these +style files to explain what changes I have made. Some of the changes are quite +significant. + + +THE PRE-XML SCRIPT + +The Pre-xml script copies a .xml file, making certain changes according to the +options it is given. The currently available options are as follows: + +-abstract + + This option causes the <abstract> element to be removed from the XML. The + source abuses the <abstract> element by using it to contain the author's + address so that it appears on the title page verso in the printed renditions. + This just gets in the way for the non-PostScript/PDF renditions. + +-ascii + + This option is used for Ascii output formats. It makes the following + character replacements: + + &8230; => ... (sic, no #x) + ’ => ' apostrophe + “ => " opening double quote + ” => " closing double quote + – => - en dash + † => * dagger + ‡ => ** double dagger +   => a space hard space + © => (c) copyright + + In addition, this option causes quotes to be put round <literal> text items, + and <quote> and </quote> to be replaced by Ascii quote marks. You would think + the stylesheet would cope with the latter, but it seems to generate non-Ascii + characters that w3m then turns into question marks. + +-bookinfo + + This option causes the <bookinfo> element to be removed from the XML. It is + used for the PostScript/PDF forms of the filter document, in order to avoid + the generation of a full title page. + +-fi + + Replace any occurrence of "fi" by the ligature fi except when it is + inside an XML element, or inside a <literal> part of the text. + + The use of ligatures would be nice for the PostScript and PDF formats. Sadly, + it turns out that fop cannot at present handle the FB01 character correctly. + The only format that does so is the HTML format, but when I used this in the + test version, people complained that it made searching for words difficult. + So at the moment, this option is not used. :-( + +-noindex + + Remove the XML to generate a Concept Index and an Options index. + +-oneindex + + Remove the XML to generate a Concept and an Options Index, and add XML to + generate a single index. + +The source document has two types of index entry, for a concept and an options +index. However, no index is required for the .txt and .texinfo outputs. +Furthermore, the only output processor that supports multiple indexes is the +processor that produces "formatted objects" for PostScript and PDF output. The +HTML processor ignores the XML settings for multiple indexes and just makes one +unified index. Specifying two indexes gets you two copies of the same index, so +this has to be changed. + + +CREATING POSTSCRIPT AND PDF + +These two output formats are created in three stages. First, the XML is +pre-processed. For the filter document, the <bookinfo> element is removed so +that no title page is generated, but for the main specification, no changes are +currently made. + +Second, the xmlto command is used to produce a "formatted objects" (.fo) file. +This process uses the following stylesheets: + + (1) Either MyStyle-filter-fo.xsl or MyStyle-spec-fo.xsl + (2) MyStyle-fo.xsl + (3) MyStyle.xsl + (4) MyTitleStyle.xsl + +The last of these is not used for the filter document, which does not have a +title page. The first three stylesheets were created manually, either by typing +directly, or by coping from the standard style sheet and editing. + +The final stylesheet has to be created from a template document, which is +called MyTitlepage.templates.xml. This was copied from the standard styles and +modified. The template is processed with xsltproc to produce the stylesheet. +All this apparatus is appallingly heavyweight. The processing is also very slow +in the case of the specification document. However, there should be no errors. + +In the third and final part of the processing, the .fo file that is produced by +the xmlto command is processed by the fop command to generate either PostScript +or PDF. This is also very slow, and you get a whole slew of errors, of which +these are a sample: + + [ERROR] property - "background-position-horizontal" is not implemented yet. + + [ERROR] property - "background-position-vertical" is not implemented yet. + + [INFO] JAI support was not installed (read: not present at build time). + Trying to use Jimi instead + Error creating background image: Error creating FopImage object (Error + creating FopImage object + (http://docbook.sourceforge.net/release/images/draft.png) : + org.apache.fop.image.JimiImage + + [WARNING] table-layout=auto is not supported, using fixed! + + [ERROR] Unknown enumerated value for property 'span': inherit + + [ERROR] Error in span property value 'inherit': + org.apache.fop.fo.expr.PropertyException: No conversion defined + + [ERROR] Areas pending, text probably lost in lineinclude parts matched in the + response by response_pattern by means of numeric variables such as + +The last one is particularly meaningless gobbledegook. Some of the errors and +warnings are repeated many times. Nevertheless, it does eventually produce +usable output, though I have a number of issues with it (see a later section of +this document). Maybe one day there will be a new release of fop that does +better. Maybe there will be some other means of producing PostScript and PDF +from DocBook XML. Maybe porcine aeronautics will really happen. + + +CREATING HTML + +Only two stages are needed to produce HTML, but the main specification is +subsequently postprocessed. The Pre-xml script is called with the -abstract and +-oneindex options to preprocess the XML. Then the xmlto command creates the +HTML output directly. For the specification document, a directory of files is +created, whereas the filter document is output as a single HTML page. The +following stylesheets are used: + + (1) Either MyStyle-chunk-html.xsl or MyStyle-nochunk-html.xsl + (2) MyStyle-html.xsl + (3) MyStyle.xsl + +The first stylesheet references the chunking or non-chunking standard +stylesheet, as appropriate. + +The original HTML that I produced from the SGCAL input had hyperlinks back from +chapter and section titles to the table of contents. These links are not +generated by xmlto. One of the testers pointed out that the lack of these +links, or simple self-referencing links for titles, makes it harder to copy a +link name into, for example, a mailing list response. + +I could not find where to fiddle with the stylesheets to make such a change, if +indeed the stylesheets are capable of it. Instead, I wrote a Perl script called +TidyHTML-spec to do the job for the specification document. It updates the +index.html file (which contains the the table of contents) setting up anchors, +and then updates all the chapter files to insert appropriate links. + +The index.html file as built by xmlto contains the whole table of contents in a +single line, which makes is hard to debug by hand. Since I was postprocessing +it anyway, I arranged to insert newlines after every '>' character. + +The TidyHTML-spec script also takes the opportunity to postprocess the +spec.html/ix01.html file, which contains the document index. Again, the index +is generated as one single line, so it splits it up. Then it creates a list of +letters at the top of the index and hyperlinks them both ways from the +different letter portions of the index. + +People wanted similar postprocessing for the filter.html file, so that is now +done using a similar script called TidyHTML-filter. It was easier to use a +separate script because filter.html is a single file rather than a directory, +so the logic is somewhat different. + + +CREATING TEXT FILES + +This happens in four stages. The Pre-xml script is called with the -abstract, +-ascii and -noindex options to remove the <abstract> element, convert the input +to Ascii characters, and to disable the production of an index. Then the xmlto +command converts the XML to a single HTML document, using these stylesheets: + + (1) MyStyle-txt-html.xsl + (2) MyStyle-html.xsl + (3) MyStyle.xsl + +The MyStyle-txt-html.xsl stylesheet is the same as MyStyle-nochunk-html.xsl, +except that it contains an addition item to ensure that a generated "copyright" +symbol is output as "(c)" rather than the Unicode character. This is necessary +because the stylesheet itself generates a copyright symbol as part of the +document title; the character is not in the original input. + +The w3m command is used with the -dump option to turn the HTML file into Ascii +text, but this contains multiple sequences of blank lines that make it look +awkward, so, finally, a local Perl script called Tidytxt is used to convert +sequences of blank lines into a single blank line. + + +CREATING INFO FILES + +This process starts with the same Pre-xml call as for text files. The +<abstract> element is deleted, non-ascii characters in the source are +transliterated, and the <index> elements are removed. The docbook2texi script +is then called to convert the XML file into a Texinfo file. However, this is +not quite enough. The converted file ends up with "conceptindex" and +"optionindex" items, which are not recognized by the makeinfo command. An +in-line call to Perl in the Makefile changes these to "cindex" and "findex" +respectively in the final .texinfo file. Finally, a call of makeinfo creates a +set of .info files. + +There is one apparently unconfigurable feature of docbook2texi: it does not +seem possible to give it a file name for its output. It chooses a name based on +the title of the document. Thus, the main specification ends up in a file +called the_exim_mta.texi and the filter document in exim_filtering.texi. These +files are removed after their contents have been copied and modified by the +inline Perl call, which makes a .texinfo file. + + +CREATING THE MAN PAGE + +I wrote a Perl script called x2man to create the exim.8 man page from the +DocBook XML source. I deliberately did NOT start from the AsciiDoc source, +because it is the DocBook source that is the "standard". This comment line in +the DocBook source marks the start of the command line options: + + <!-- === Start of command line options === --> + +A similar line marks the end. If at some time in the future another way other +than AsciiDoc is used to maintain the DocBook source, it needs to be capable of +maintaining these comments. + + +UNRESOLVED PROBLEMS + +There are a number of unresolved problems with producing the Exim documentation +in the manner described above. I will describe them here in the hope that in +future some way round them can be found. + +(1) Errors in the toolchain + + When a whole chain of tools is processing a file, an error somewhere in + the middle is often very hard to debug. For instance, an error in the + AsciiDoc might not show up until an XML processor throws a wobbly because + the generated XML is bad. You have to be able to read XML and figure out + what generated what. One of the reasons for creating the "test" series of + targets was to help in checking out these kinds of problem. + +(2) There is a mechanism in XML for marking parts of the document as + "revised", and I have arranged for AsciiDoc markup to use it. However, at + the moment, the only output format that pays attention to this is the HTML + output, which sets a green background. There are therefore no revision + marks (change bars) in the PostScript, PDF, or text output formats as + there used to be. (There never were for Texinfo.) + +(3) The index entries in the HTML format take you to the top of the section + that is referenced, instead of to the point in the section where the index + marker was set. + +(4) The HTML output supports only a single index, so the concept and options + index entries have to be merged. + +(5) The index for the PostScript/PDF output does not merge identical page + numbers, which makes some entries look ugly. + +(6) None of the indexes (PostScript/PDF and HTML) make use of textual + markup; the text is all roman, without any italic or boldface. + +(7) I turned off hyphenation in the PostScript/PDF output, because it was + being done so badly. + + (a) It seems to force hyphenation if it is at all possible, without + regard to the "tightness" or "looseness" of the line. Decent + formatting software should attempt hyphenation only if the line is + over some "looseness" threshold; otherwise you get far too many + hyphenations, often for several lines in succession. + + (b) It uses an algorithmic form of hyphenation that doesn't always produce + acceptable word breaks. (I prefer to use a hyphenation dictionary.) + +(8) The PostScript/PDF output is badly paginated: + + (a) There seems to be no attempt to avoid "widow" and "orphan" lines on + pages. A "widow" is the last line of a paragraph at the top of a page, + and an "orphan" is the first line of a paragraph at the bottom of a + page. + + (b) There seems to be no attempt to prevent section headings being placed + last on a page, with no following text on the page. + +(9) The fop processor does not support "fi" ligatures, not even if you put the + appropriate Unicode character into the source by hand. + +(10) There are no diagrams in the new documentation. This is something I could + work on. The previously-used Aspic command for creating line art from a + textual description can output Encapsulated PostScript or Scalar Vector + Graphics, which are two standard diagram representations. Aspic could be + formally released and used to generate output that could be included in at + least some of the output formats. + +The consequence of (7), (8), and (9) is that the PostScript/PDF output looks as +if it comes from some of the very early attempts at text formatting of around +20 years ago. We can only hope that 20 years' progress is not going to get +lost, and that things will improve in this area. + + +LIST OF FILES + +AdMarkup.txt Describes the AsciiDoc markup that is used +HowItWorks.txt This document +Makefile The makefile +MyAsciidoc.conf Localized AsciiDoc configuration +MyStyle-chunk-html.xsl Stylesheet for chunked HTML output +MyStyle-filter-fo.xsl Stylesheet for filter fo output +MyStyle-fo.xsl Stylesheet for any fo output +MyStyle-html.xsl Stylesheet for any HTML output +MyStyle-nochunk-html.xsl Stylesheet for non-chunked HTML output +MyStyle-spec-fo.xsl Stylesheet for spec fo output +MyStyle-txt-html.xsl Stylesheet for HTML=>text output +MyStyle.xsl Stylesheet for all output +MyTitleStyle.xsl Stylesheet for spec title page +MyTitlepage.templates.xml Template for creating MyTitleStyle.xsl +Myhtml.css Experimental css stylesheet for HTML output +Pre-xml Script to preprocess XML +TidyHTML-filter Script to tidy up the filter HTML output +TidyHTML-spec Script to tidy up the spec HTML output +Tidytxt Script to compact multiple blank lines +filter.ascd AsciiDoc source of the filter document +spec.ascd AsciiDoc source of the specification document +x2man Script to make the Exim man page from the XML + +The file Myhtml.css was an experiment that was not followed through. It is +mentioned in a comment in MyStyle-html.xsl, but is not at present in use. + + +Philip Hazel +Last updated: 10 June 2005 diff --git a/doc/doc-docbook/Makefile b/doc/doc-docbook/Makefile new file mode 100644 index 000000000..802f74085 --- /dev/null +++ b/doc/doc-docbook/Makefile @@ -0,0 +1,177 @@ +# $Cambridge: exim/doc/doc-docbook/Makefile,v 1.1 2005/06/16 10:32:31 ph10 Exp $ + +# Make file for Exim documentation from Asciidoc source. + +notarget:; @echo "** You must specify a target, in the form x.y, where x is 'filter', 'spec'," + @echo "** or 'test', and y is 'xml', 'fo', 'ps', 'pdf', 'html', 'txt', or 'info'." + @echo "** One other possible target is 'exim.8'". + exit 1 + + +############################## MAN PAGE ################################ + +exim.8: spec.xml + ./x2man + +######################################################################## + + +############################### FILTER ################################# + +filter.xml: filter.ascd MyAsciidoc.conf + asciidoc -d book -b docbook -f MyAsciidoc.conf filter.ascd + +filter-fo.xml: filter.xml Pre-xml + Pre-xml -bookinfo <filter.xml >filter-fo.xml + +filter-html.xml: filter.xml Pre-xml + Pre-xml <filter.xml >filter-html.xml + +filter-txt.xml: filter.xml Pre-xml + Pre-xml -ascii <filter.xml >filter-txt.xml + +filter.fo: filter-fo.xml MyStyle-filter-fo.xsl MyStyle-fo.xsl MyStyle.xsl + /bin/rm -rf filter.fo filter-fo.fo + xmlto -x MyStyle-filter-fo.xsl fo filter-fo.xml + /bin/mv -f filter-fo.fo filter.fo + +filter.ps: filter.fo + fop filter.fo -ps filter.ps + +filter.pdf: filter.fo + fop filter.fo -pdf filter.pdf + +filter.html: filter-html.xml TidyHTML-filter MyStyle-nochunk-html.xsl MyStyle-html.xsl MyStyle.xsl + /bin/rm -rf filter.html filter-html.html + xmlto -x MyStyle-nochunk-html.xsl html-nochunks filter-html.xml + /bin/mv -f filter-html.html filter.html + ./TidyHTML-filter + +filter.txt: filter-txt.xml Tidytxt MyStyle-txt-html.xsl MyStyle-html.xsl MyStyle.xsl + /bin/rm -rf filter-txt.html + xmlto -x MyStyle-txt-html.xsl html-nochunks filter-txt.xml + w3m -dump filter-txt.html >filter.txt + +# I have not found a way of making docbook2texi write its output anywhere +# other than the file name that it makes up. The --to-stdout option does not +# work. + +filter.info: filter-txt.xml + docbook2texi filter-txt.xml + perl -ne 's/conceptindex/cindex/;s/optionindex/findex/;print;' \ + <exim_filtering.texi | Tidytxt >filter.texinfo + /bin/rm -rf exim_filtering.texi + makeinfo -o filter.info filter.texinfo + +######################################################################## + + +################################ SPEC ################################## + +spec.xml: spec.ascd MyAsciidoc.conf + asciidoc -d book -b docbook -f MyAsciidoc.conf spec.ascd + +spec-fo.xml: spec.xml Pre-xml + Pre-xml <spec.xml >spec-fo.xml + +spec-html.xml: spec.xml Pre-xml + Pre-xml -abstract -oneindex <spec.xml >spec-html.xml + +spec-txt.xml: spec.xml Pre-xml + Pre-xml -abstract -ascii -noindex <spec.xml >spec-txt.xml + +spec.fo: spec-fo.xml MyStyle-spec-fo.xsl MyStyle-fo.xsl MyStyle.xsl MyTitleStyle.xsl + /bin/rm -rf spec.fo spec-fo.fo + xmlto -x MyStyle-spec-fo.xsl fo spec-fo.xml + /bin/mv -f spec-fo.fo spec.fo + +spec.ps: spec.fo + FOP_OPTS=-Xmx512m fop spec.fo -ps spec.ps + +spec.pdf: spec.fo + FOP_OPTS=-Xmx512m fop spec.fo -pdf spec.pdf + +spec.html: spec-html.xml TidyHTML-spec MyStyle-chunk-html.xsl MyStyle-html.xsl MyStyle.xsl + /bin/rm -rf spec.html + xmlto -x MyStyle-chunk-html.xsl -o spec.html html spec-html.xml + ./TidyHTML-spec + +spec.txt: spec-txt.xml Tidytxt MyStyle-txt-html.xsl MyStyle-html.xsl MyStyle.xsl + /bin/rm -rf spec-txt.html + xmlto -x MyStyle-txt-html.xsl html-nochunks spec-txt.xml + w3m -dump spec-txt.html | Tidytxt >spec.txt + +# I have not found a way of making docbook2texi write its output anywhere +# other than the file name that it makes up. The --to-stdout option does not +# work. + +spec.info: spec-txt.xml + docbook2texi spec-txt.xml + perl -ne 's/conceptindex/cindex/;s/optionindex/findex/;print;' \ + <the_exim_mta.texi >spec.texinfo + /bin/rm -rf the_exim_mta.texi + makeinfo -o spec.info spec.texinfo + +######################################################################## + + +################################ TEST ################################## + +# These targets (similar to the above) are for running little tests. + +test.xml: test.ascd MyAsciidoc.conf + asciidoc -d book -b docbook -f MyAsciidoc.conf test.ascd + +test-fo.xml: test.xml Pre-xml + ./Pre-xml <test.xml >test-fo.xml + +test-html.xml: test.xml Pre-xml + ./Pre-xml -abstract -oneindex <test.xml >test-html.xml + +test-txt.xml: test.xml Pre-xml + ./Pre-xml -abstract -ascii -noindex <test.xml >test-txt.xml + +test.fo: test-fo.xml MyStyle-spec-fo.xsl MyStyle-fo.xsl MyStyle.xsl MyTitleStyle.xsl + /bin/rm -rf test.fo test-fo.fo + xmlto -x MyStyle-spec-fo.xsl fo test-fo.xml + /bin/mv -f test-fo.fo test.fo + +test.ps: test.fo + fop test.fo -ps test.ps + +test.pdf: test.fo + fop test.fo -pdf test.pdf + +test.html: test-html.xml MyStyle-nochunk-html.xsl MyStyle-html.xsl MyStyle.xsl + /bin/rm -rf test.html test-html.html + xmlto -x MyStyle-nochunk-html.xsl html-nochunks test-html.xml + /bin/mv -f test-html.html test.html + +test.txt: test-txt.xml Tidytxt MyStyle-txt-html.xsl MyStyle-html.xsl MyStyle.xsl + /bin/rm -rf test-txt.html + xmlto -x MyStyle-txt-html.xsl html-nochunks test-txt.xml + w3m -dump test-txt.html | Tidytxt >test.txt + +# I have not found a way of making docbook2texi write its output anywhere +# other than the file name that it makes up. The --to-stdout option does not +# work. + +test.info: test-txt.xml + docbook2texi test-txt.xml + perl -ne 's/conceptindex/cindex/;s/optionindex/findex/;print;' \ + <short_title.texi >test.texinfo + /bin/rm -rf short_title.texi + makeinfo -o test.info test.texinfo + +######################################################################## + + +################################ CLEAN ################################# + +clean:; /bin/rm -rf exim.8 \ + filter*.xml spec*.xml test*.xml \ + *.fo *.html *.pdf *.ps \ + filter*.txt spec*.txt test*.txt \ + *.info* *.texinfo *.texi + +######################################################################## diff --git a/doc/doc-docbook/MyAsciidoc.conf b/doc/doc-docbook/MyAsciidoc.conf new file mode 100644 index 000000000..4b09e5a6a --- /dev/null +++ b/doc/doc-docbook/MyAsciidoc.conf @@ -0,0 +1,205 @@ +# $Cambridge: exim/doc/doc-docbook/MyAsciidoc.conf,v 1.1 2005/06/16 10:32:31 ph10 Exp $ + +# Asciidoc configuration customization for creating the DocBook XML sources +# of the Exim specification and the filter document. + +[miscellaneous] +newline=\n + +[quotes] +_=filename +$=varname +%=option +^=command +^^=function +^%|%^=parameter +``|''=quoted + +[tags] +strong=<emphasis role="bold">|</emphasis> + +filename=<filename>|</filename> +varname=<varname>$|</varname> +option=<option>|</option> +command=<command>|</command> +function=<function>|</function> +parameter=<parameter>|</parameter> +quoted=<quote>|</quote> + + +[replacements] +# Nothing - this is for disambiguating markup +"##"= + +# -- En dash +(^|[^-])--($|[^-])=\1–\2 + +# --- Em dash +(^|\s+)---($|\s+)=\1舒\2 + +# -- Hard space +~=  + +# ' automatic apostrophe +([A-Za-z0-9])'([A-Za-z\s])=\1’\2 + +# daggers +!!=† +!\?=‡ + +# The default markup recognizes subscripts and superscripts using tilde and +# circumflex. We don't want this. These settings manage to turn off the +# effect, while still allowing tilde to be recognized as a hard space. +\^(.+?)\^=^\1^ +~(.+?)~=~\1~ + + +[attributes] +# Manual apostrophe: needed for an apostrophe after something quoted, because +# I can't get the automatic one to work in that situation +ap=’ + +# Manual tilde: tilde is defined as a hard space, and it doesn't seem possible +# to quote is using a backslash. +tl=~ + +# Two hyphens, to stop them being treated as an en dash +hh=-- + +# Percent: causes confusion with the quote otherwise +pc=% + +# Colon: there's a case where this causes trouble +co=: + +# The sequence "[]" for use in index terms +bk=[] + + +# We need to add extra stuff to the <bookinfo> element + +[header] +<?xml {xmldecl}?> +<!DOCTYPE book {dtddecl}> + +<book lang="en"> +{doctitle#}<bookinfo> + <title>{doctitle}</title> + <titleabbrev>{doctitleabbrev}</titleabbrev> + <date>{date}</date> + {authored#}<author> + <firstname>{firstname}</firstname> + <othername>{middlename}</othername> + <surname>{lastname}</surname> + {authored#}</author> + <authorinitials>{authorinitials}</authorinitials> + {revisionhistory%}<revhistory><revision><revnumber>{revision}</revnumber><date>{date}</date>{authorinitials?<authorinitials>{authorinitials}</authorinitials>}{revremark?<revremark>{revremark}</revremark>}</revision></revhistory> + <corpname>{companyname}</corpname> + <othercredit><contrib>{othercredit},</contrib></othercredit> + {copyright#}<copyright><year>{cpyear}</year><holder>{copyright}</holder></copyright> + <abstract><para>{abstract}</para></abstract> +{doctitle#}</bookinfo> + + +# Define a new kind of block that maps to <literallayout> so as not to +# insist on a monospaced font. Delimiter is &&&. + +[blockdef-literallayout] +delimiter=^&{3,}(\[(?P<args>.*)\])?=*$ +template=literallayoutblock +presubs=specialcharacters,quotes,replacements,macros,callouts + +# The template for my non-monospaced literal layout block + +[literallayoutblock] +<literallayout{revisionflag? revisionflag="{revisionflag}"}> +| +</literallayout> + + +# Paragraph substitution - use <para> rather than <simplepara> + +[paragraph] +{title#}<formalpara{id? id="{id}"{revisionflag? revisionflag="{revisionflag}"}}><title>{title}</title><para> +{title%}<para{id? id="{id}"}{revisionflag? revisionflag="{revisionflag}"}> +| +{title%}</para> +{title#}</para></formalpara> +{empty} + + +# Define a special table for left-centre-right lines, filling the whole page +# width, with a border but no separators, for Exim configuration options. It +# would be nice if this could call the default [table] template, forcing the +# appropriate attributes, but I have not found a way of doing this. + +[tabledef-conf] +fillchar== +format=csv +template=conf-table +colspec=<colspec align="{colalign}"/> +bodyrow=<row>|</row> +bodydata=<entry>|</entry> + +[conf-table] +<{title?table}{title!informaltable}{id? id="{id}"} pgwide="1" frame="all" colsep="0" rowsep="0"> +<title>{title}</title> +<tgroup cols="{cols}"> +<colspec align="left" colwidth="8*"/> +<colspec align="center" colwidth = "5*"/> +<colspec align="center" colwidth = "5*"/> +<colspec align="right" colwidth = "6*"/> +{headrows#}<thead> +{headrows} +{headrows#}</thead> +{footrows#}<tfoot> +{footrows} +{footrows#}</tfoot> +<tbody> +{bodyrows} +</tbody> +</tgroup> +</{title?table}{title!informaltable}> + +# The default indexterm macro generates primary index entries for the +# secondary and tertiary terms as well, which does not make sense +# in the context of the way I write indexes. As well as a replacement +# that does the simple, straightforward thing, we actually want to have +# two different macros: one for concepts and one for options. + +[cindex-inlinemacro] +# Inline index term for concepts. +<indexterm role="concept"> + <primary>{1}</primary> + <secondary>{2}</secondary> + <tertiary>{3}</tertiary> +</indexterm> + +[oindex-inlinemacro] +# Inline index term for options. +<indexterm role="option"> + <primary>{1}</primary> + <secondary>{2}</secondary> + <tertiary>{3}</tertiary> +</indexterm> + +# Allow for the "role" attribute for an index. + +[sect-index] +<index{id? id="{id}"}{role? role="{role}"}> +<title>{title}</title> +| +</index> + + +# Allow for the "titleabbrev" attribute for chapters. + +[sect1] +<chapter{id? id="{id}"}> +<title>{title}</title> +<titleabbrev>{titleabbrev}</titleabbrev> +| +</chapter> + + +#### End #### diff --git a/doc/doc-docbook/MyStyle-chunk-html.xsl b/doc/doc-docbook/MyStyle-chunk-html.xsl new file mode 100644 index 000000000..3a1cb91b2 --- /dev/null +++ b/doc/doc-docbook/MyStyle-chunk-html.xsl @@ -0,0 +1,20 @@ +<!-- $Cambridge: exim/doc/doc-docbook/MyStyle-chunk-html.xsl,v 1.1 2005/06/16 10:32:31 ph10 Exp $ --> + +<!-- This stylesheet driver imports the DocBook XML stylesheet for chunked +HTML output, and then imports my common stylesheet for HTML output. Finally, it +fiddles with the chunking parameters to arrange for chapter chunking only (no +section chunking). --> + +<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version='1.0'> + +<xsl:import href="/usr/share/sgml/docbook/xsl-stylesheets-1.66.1/xhtml/chunk.xsl"/> +<xsl:import href="MyStyle-html.xsl"/> + + +<!-- No section chunking; don't output the list of chunks --> + +<xsl:param name="chunk.section.depth" select="0"></xsl:param> +<xsl:param name="chunk.quietly" select="1"/> + + +</xsl:stylesheet> diff --git a/doc/doc-docbook/MyStyle-filter-fo.xsl b/doc/doc-docbook/MyStyle-filter-fo.xsl new file mode 100644 index 000000000..33a67336b --- /dev/null +++ b/doc/doc-docbook/MyStyle-filter-fo.xsl @@ -0,0 +1,55 @@ +<!-- $Cambridge: exim/doc/doc-docbook/MyStyle-filter-fo.xsl,v 1.1 2005/06/16 10:32:31 ph10 Exp $ --> + +<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version='1.0'> + +<!-- This stylesheet driver imports the DocBook XML stylesheet for FO output, +and then imports my common stylesheet that makes changes that are wanted for +all forms of output. Then it imports my FO stylesheet that contains changes for +all printed output. Finally, there are some changes that apply only when +printing the filter document. --> + +<xsl:import href="/usr/share/sgml/docbook/xsl-stylesheets-1.66.1/fo/docbook.xsl"/> +<xsl:import href="MyStyle.xsl"/> +<xsl:import href="MyStyle-fo.xsl"/> + +<!-- For the filter document, we do not want a title page and verso, as it +isn't really a "book", though we use the book XML style. It turns out that this +can be fiddled simply by changing the text "Table of Contents" to the title of +the document. + +However, it seems that we have to repeat here the language-specific changes +that are also present in MyStyle.xsl, because this overrides rather than adds +to the settings. --> + +<xsl:param name="local.l10n.xml" select="document('')"/> +<l:i18n xmlns:l="http://docbook.sourceforge.net/xmlns/l10n/1.0"> + <l:l10n language="en"> + + <l:gentext key="TableofContents" text="Exim’s interfaces to mail filtering"/> + + <!-- The default (as modified above) gives us "Chapter xxx" or "Section + xxx", with a capital letter at the start. So we have to make an more + complicated explicit change to give just the number. --> + + <l:context name="xref-number"> + <l:template name="chapter" text="%n"/> + <l:template name="sect1" text="%n"/> + <l:template name="sect2" text="%n"/> + <l:template name="section" text="%n"/> + </l:context> + + <!-- I think that having a trailing dot after section numbers looks fussy, + whereas you need it after just the digits of a chapter number. In both + cases we want to get rid of the word "chapter" or "section". --> + + <l:context name="title-numbered"> + <l:template name="chapter" text="%n. %t"/> + <l:template name="sect1" text="%n %t"/> + <l:template name="sect2" text="%n %t"/> + <l:template name="section" text="%n %t"/> + </l:context> + + </l:l10n> +</l:i18n> + +</xsl:stylesheet> diff --git a/doc/doc-docbook/MyStyle-fo.xsl b/doc/doc-docbook/MyStyle-fo.xsl new file mode 100644 index 000000000..bd0dd314c --- /dev/null +++ b/doc/doc-docbook/MyStyle-fo.xsl @@ -0,0 +1,241 @@ +<!-- $Cambridge: exim/doc/doc-docbook/MyStyle-fo.xsl,v 1.1 2005/06/16 10:32:31 ph10 Exp $ --> + +<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns:fo="http://www.w3.org/1999/XSL/Format" + version="1.0"> + +<!-- This stylesheet driver contains changes that I want to apply to the +printed output form of both the filter document and the main Exim +specification. It is imported by MyStyle-filter-fo.xsl and MyStyle-spec-fo.xsl. +--> + +<xsl:import href="MyTitleStyle.xsl"/> + + + +<!-- Set A4 paper, double sided --> + +<xsl:param name="paper.type" select="'A4'"></xsl:param> + +<!-- This currently causes errors +<xsl:param name="double.sided" select="1"></xsl:param> +--> + +<!-- Allow for typed index entries. The "role" setting works with DocBook +version 4.2 or earlier. Later versions (which we are not currently using) +need "type". --> + +<xsl:param name="index.on.type" select="1"></xsl:param> +<xsl:param name="index.on.role" select="1"></xsl:param> + + +<!-- The default uses short chapter titles in the TOC! I want them only for +use in footer lines. So we have to modify this template. I changed +"titleabbrev.markup" to "title.markup". While I'm here, I also made chapter +entries print in bold. --> + +<xsl:template name="toc.line"> + <xsl:variable name="id"> + <xsl:call-template name="object.id"/> + </xsl:variable> + + <xsl:variable name="label"> + <xsl:apply-templates select="." mode="label.markup"/> + </xsl:variable> + + <fo:block text-align-last="justify" + end-indent="{$toc.indent.width}pt" + last-line-end-indent="-{$toc.indent.width}pt"> + <fo:inline keep-with-next.within-line="always"> + <!-- Added lines for bold --> + <xsl:choose> + <xsl:when test="self::chapter"> + <xsl:attribute name="font-weight">bold</xsl:attribute> + </xsl:when> + <xsl:when test="self::index"> + <xsl:attribute name="font-weight">bold</xsl:attribute> + </xsl:when> + </xsl:choose> + <!-- .................. --> + <fo:basic-link internal-destination="{$id}"> + <xsl:if test="$label != ''"> + <xsl:copy-of select="$label"/> + <xsl:value-of select="$autotoc.label.separator"/> + </xsl:if> + <xsl:apply-templates select="." mode="title.markup"/> + </fo:basic-link> + </fo:inline> + <fo:inline keep-together.within-line="always"> + <xsl:text> </xsl:text> + <fo:leader leader-pattern="dots" + leader-pattern-width="3pt" + leader-alignment="reference-area" + keep-with-next.within-line="always"/> + <xsl:text> </xsl:text> + <fo:basic-link internal-destination="{$id}"> + <fo:page-number-citation ref-id="{$id}"/> + </fo:basic-link> + </fo:inline> + </fo:block> +</xsl:template> + + + + + + + +<!-- +Adjust the sizes of the fonts for titles; the defaults are too gross. +--> + +<!-- Level 1 is sect1 level --> + +<xsl:attribute-set name="section.title.level1.properties"> + <xsl:attribute name="font-size"> + <xsl:value-of select="$body.font.master * 1.2"></xsl:value-of> + <xsl:text>pt</xsl:text> + </xsl:attribute> +</xsl:attribute-set> + + +<!-- Fiddling with chapter titles is more messy --> + +<xsl:template match="title" mode="chapter.titlepage.recto.auto.mode"> + <fo:block xmlns:fo="http://www.w3.org/1999/XSL/Format" + xsl:use-attribute-sets="chapter.titlepage.recto.style" + margin-left="{$title.margin.left}" + font-size="17pt" + font-weight="bold" + font-family="{$title.font.family}"> + <xsl:call-template name="component.title"> + <xsl:with-param name="node" select="ancestor-or-self::chapter[1]"/> + </xsl:call-template> + </fo:block> +</xsl:template> + +<xsl:template match="title" mode="chapter.titlepage.verso.auto.mode"> + <fo:block xmlns:fo="http://www.w3.org/1999/XSL/Format" + xsl:use-attribute-sets="chapter.titlepage.recto.style" + margin-left="{$title.margin.left}" + font-size="17pt" + font-weight="bold" + font-family="{$title.font.family}"> + <xsl:call-template name="component.title"> + <xsl:with-param name="node" select="ancestor-or-self::chapter[1]"/> + </xsl:call-template> + </fo:block> +</xsl:template> + + +<!-- This provides a hard pagebreak mechanism as a get-out --> + +<xsl:template match="processing-instruction('hard-pagebreak')"> + <fo:block xmlns:fo="http://www.w3.org/1999/XSL/Format" break-before='page'> + </fo:block> +</xsl:template> + + +<!-- Sort out the footer. Useful information is available at +http://www.sagehill.net/docbookxsl/PrintHeaders.html +--> + + +<xsl:attribute-set name="footer.content.properties"> + <!-- <xsl:attribute name="font-family">serif</xsl:attribute> --> + <!-- <xsl:attribute name="font-size">9pt</xsl:attribute> --> + <xsl:attribute name="font-style">italic</xsl:attribute> +</xsl:attribute-set> + + + + +<!-- Things that can be inserted into the footer are: + +<fo:page-number/> +Inserts the current page number. + +<xsl:apply-templates select="." mode="title.markup"/> +Inserts the title of the current chapter, appendix, or other component. + +<xsl:apply-templates select="." mode="titleabbrev.markup"/> +Inserts the titleabbrev of the current chapter, appendix, or other component, +if it is available. Otherwise it inserts the regular title. + +<xsl:apply-templates select="." mode="object.title.markup"/> +Inserts the chapter title with chapter number label. Likewise for appendices. + +<fo:retrieve-marker ... /> Used to retrieve the current section name. + +<xsl:apply-templates select="//corpauthor[1]"/> +Inserts the value of the first corpauthor element found anywhere in the +document. + +<xsl:call-template name="datetime.format"> + <xsl:with-param ... +Inserts a date timestamp. + +<xsl:call-template name="draft.text"/> +Inserts the Draft message if draft.mode is currently on. + +<fo:external-graphic ... /> +Inserts a graphical image. +See the section Graphic in header or footer for details. +--> + + +<xsl:template name="footer.content"> + <xsl:param name="pageclass" select="''"/> + <xsl:param name="sequence" select="''"/> + <xsl:param name="position" select="''"/> + <xsl:param name="gentext-key" select="''"/> + + <fo:block> + <!-- pageclass can be front, body, back --> + <!-- sequence can be odd, even, first, blank --> + <!-- position can be left, center, right --> + <xsl:choose> + <xsl:when test="$pageclass = 'titlepage'"> + <!-- nop; no footer on title pages --> + </xsl:when> + + <xsl:when test="$double.sided != 0 and $sequence = 'even' + and $position='left'"> + <fo:page-number/> + </xsl:when> + + <xsl:when test="$double.sided != 0 and ($sequence = 'odd' or $sequence = 'first') + and $position='right'"> + <fo:page-number/> + </xsl:when> + + <xsl:when test="$double.sided = 0 and $position='center'"> + <fo:page-number/> + </xsl:when> + + <xsl:when test="$double.sided = 0 and $position='right'"> + <xsl:apply-templates select="." mode="titleabbrev.markup"/> + </xsl:when> + + <xsl:when test="$sequence='blank'"> + <xsl:choose> + <xsl:when test="$double.sided != 0 and $position = 'left'"> + <fo:page-number/> + </xsl:when> + <xsl:when test="$double.sided = 0 and $position = 'center'"> + <fo:page-number/> + </xsl:when> + <xsl:otherwise> + <!-- nop --> + </xsl:otherwise> + </xsl:choose> + </xsl:when> + + <xsl:otherwise> + <!-- nop --> + </xsl:otherwise> + </xsl:choose> + </fo:block> +</xsl:template> + +</xsl:stylesheet> diff --git a/doc/doc-docbook/MyStyle-html.xsl b/doc/doc-docbook/MyStyle-html.xsl new file mode 100644 index 000000000..e0b7537f3 --- /dev/null +++ b/doc/doc-docbook/MyStyle-html.xsl @@ -0,0 +1,171 @@ +<!-- $Cambridge: exim/doc/doc-docbook/MyStyle-html.xsl,v 1.1 2005/06/16 10:32:31 ph10 Exp $ --> + +<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version='1.0'> + +<!-- This stylesheet driver imports my common stylesheet that makes some +changes that are wanted for all forms of output. Then it makes changes that are +specific to HTML output. --> + +<xsl:import href="MyStyle.xsl"/> + +<xsl:param name="shade.verbatim" select="1"></xsl:param> + +<xsl:attribute-set name="shade.verbatim.style"> + <xsl:attribute name="bgcolor">#F0F0E0</xsl:attribute> + <xsl:attribute name="width">100%</xsl:attribute> + <xsl:attribute name="cellpadding">2</xsl:attribute> + <xsl:attribute name="border">0</xsl:attribute> +</xsl:attribute-set> + +<!-- This is how you can make use of a CSS stylesheet, but at present I'm +not doing so. --> + +<!-- +<xsl:param name="html.stylesheet" select="'Myhtml.css'"/> +--> + + +<!-- This removes the title of the current page from the top of the page - +redundant because each page is a chapter, whose title shows just below. It also +removes the titles of the next/prev at the bottom of the page, but I don't +think that matters too much. --> + +<xsl:param name="navig.showtitles" select="'0'"/> + + +<!-- This allows for the setting of RevisionFlag on elements. --> + +<xsl:param name="show.revisionflag" select="'1'"/> + +<xsl:template name="system.head.content"> +<style type="text/css"> +<xsl:text> +div.added { background-color: #ffff99; } +div.deleted { text-decoration: line-through; + background-color: #FF7F7F; } +div.changed { background-color: #99ff99; } +div.off { } + +span.added { background-color: #ffff99; } +span.deleted { text-decoration: line-through; + background-color: #FF7F7F; } +span.changed { background-color: #99ff99; } +span.off { } +</xsl:text> +</style> +</xsl:template> + +<xsl:template match="*[@revisionflag]"> + <xsl:choose> + <xsl:when test="local-name(.) = 'para' or local-name(.) = 'simpara' or local-name(.) = 'formalpara' or local-name(.) = 'section' or local-name(.) = 'sect1' or local-name(.) = 'sect2' or local-name(.) = 'sect3' or local-name(.) = 'sect4' or local-name(.) = 'sect5' or local-name(.) = 'chapter' or local-name(.) = 'preface' or local-name(.) = 'itemizedlist' or local-name(.) = 'varlistentry' or local-name(.) = 'glossary' or local-name(.) = 'bibliography' or local-name(.) = 'index' or local-name(.) = 'appendix'"> + <div class="{@revisionflag}"> + <xsl:apply-imports/> + </div> + </xsl:when> + <xsl:when test="local-name(.) = 'phrase' or local-name(.) = 'ulink' or local-name(.) = 'link' or local-name(.) = 'filename' or local-name(.) = 'literal' or local-name(.) = 'member' or local-name(.) = 'glossterm' or local-name(.) = 'sgmltag' or local-name(.) = 'quote' or local-name(.) = 'emphasis' or local-name(.) = 'command' or local-name(.) = 'xref'"> + <span class="{@revisionflag}"> + <xsl:apply-imports/> + </span> + </xsl:when> + <xsl:when test="local-name(.) = 'listitem' or local-name(.) = 'entry' or local-name(.) = 'title'"> + <!-- nop; these are handled directly in the stylesheet --> + <xsl:apply-imports/> + </xsl:when> + <xsl:otherwise> + <xsl:message> + <xsl:text>Revisionflag on unexpected element: </xsl:text> + <xsl:value-of select="local-name(.)"/> + <xsl:text> (Assuming block)</xsl:text> + </xsl:message> + <div class="{@revisionflag}"> + <xsl:apply-imports/> + </div> + </xsl:otherwise> + </xsl:choose> +</xsl:template> + + +<!-- The default uses short chapter titles in the TOC! I want them only for +use in footer lines in printed output. So we have to modify this template. I +changed "titleabbrev.markup" to "title.markup". --> + +<xsl:template name="toc.line"> + <xsl:param name="toc-context" select="."/> + <xsl:param name="depth" select="1"/> + <xsl:param name="depth.from.context" select="8"/> + + <span> + <xsl:attribute name="class"><xsl:value-of select="local-name(.)"/></xsl:attribute> + <a> + <xsl:attribute name="href"> + <xsl:call-template name="href.target"> + <xsl:with-param name="context" select="$toc-context"/> + </xsl:call-template> + </xsl:attribute> + + <xsl:variable name="label"> + <xsl:apply-templates select="." mode="label.markup"/> + </xsl:variable> + <xsl:copy-of select="$label"/> + <xsl:if test="$label != ''"> + <xsl:value-of select="$autotoc.label.separator"/> + </xsl:if> + + <xsl:apply-templates select="." mode="title.markup"/> + </a> + </span> +</xsl:template> + + +<!-- The default stylesheets generate both chapters and sections with <h2> +headings in the HTML. The argument is that the HTML headings don't go deep +enough to match the DocBook levels. But surely it would be better to stop them +at the bottom end? Anyway, the Exim documents have only one level of section +within chapters, and even if they went to two, it wouldn't exhaust HTML's +capabilities. So I have copied the style stuff here, making a 1-character +change from "+ 1" to "+ 2" in roughly the middle. --> + +<xsl:template name="section.heading"> + <xsl:param name="section" select="."/> + <xsl:param name="level" select="1"/> + <xsl:param name="allow-anchors" select="1"/> + <xsl:param name="title"/> + <xsl:param name="class" select="'title'"/> + + <xsl:variable name="id"> + <xsl:choose> + <!-- if title is in an *info wrapper, get the grandparent --> + <xsl:when test="contains(local-name(..), 'info')"> + <xsl:call-template name="object.id"> + <xsl:with-param name="object" select="../.."/> + </xsl:call-template> + </xsl:when> + <xsl:otherwise> + <xsl:call-template name="object.id"> + <xsl:with-param name="object" select=".."/> + </xsl:call-template> + </xsl:otherwise> + </xsl:choose> + </xsl:variable> + + <!-- HTML H level is two higher than section level --> + <xsl:variable name="hlevel" select="$level + 2"/> + <xsl:element name="h{$hlevel}"> + <xsl:attribute name="class"><xsl:value-of select="$class"/></xsl:attribute> + <xsl:if test="$css.decoration != '0'"> + <xsl:if test="$hlevel<3"> + <xsl:attribute name="style">clear: both</xsl:attribute> + </xsl:if> + </xsl:if> + <xsl:if test="$allow-anchors != 0"> + <xsl:call-template name="anchor"> + <xsl:with-param name="node" select="$section"/> + <xsl:with-param name="conditional" select="0"/> + </xsl:call-template> + </xsl:if> + <xsl:copy-of select="$title"/> + </xsl:element> +</xsl:template> + + +</xsl:stylesheet> diff --git a/doc/doc-docbook/MyStyle-nochunk-html.xsl b/doc/doc-docbook/MyStyle-nochunk-html.xsl new file mode 100644 index 000000000..d067173a3 --- /dev/null +++ b/doc/doc-docbook/MyStyle-nochunk-html.xsl @@ -0,0 +1,11 @@ +<!-- $Cambridge: exim/doc/doc-docbook/MyStyle-nochunk-html.xsl,v 1.1 2005/06/16 10:32:31 ph10 Exp $ --> + +<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version='1.0'> + +<!-- This stylesheet driver imports the DocBook XML stylesheet for unchunked +HTML output, and then imports my common stylesheet for HTML output. --> + +<xsl:import href="/usr/share/sgml/docbook/xsl-stylesheets-1.66.1/xhtml/docbook.xsl"/> +<xsl:import href="MyStyle-html.xsl"/> + +</xsl:stylesheet> diff --git a/doc/doc-docbook/MyStyle-spec-fo.xsl b/doc/doc-docbook/MyStyle-spec-fo.xsl new file mode 100644 index 000000000..ead674c7c --- /dev/null +++ b/doc/doc-docbook/MyStyle-spec-fo.xsl @@ -0,0 +1,17 @@ +<!-- $Cambridge: exim/doc/doc-docbook/MyStyle-spec-fo.xsl,v 1.1 2005/06/16 10:32:31 ph10 Exp $ --> + +<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version='1.0'> + +<!-- This stylesheet driver imports the DocBook XML stylesheet for FO output, +and then imports my common stylesheet that makes changes that are wanted for +all forms of output. Then it imports my FO stylesheet that contains changes for +all printed output. Finally, there are some changes that apply only when +printing the Exim specification document. --> + +<xsl:import href="/usr/share/sgml/docbook/xsl-stylesheets-1.66.1/fo/docbook.xsl"/> +<xsl:import href="MyStyle.xsl"/> +<xsl:import href="MyStyle-fo.xsl"/> + +<!-- Nothing special for the full spec document yet --> + +</xsl:stylesheet> diff --git a/doc/doc-docbook/MyStyle-txt-html.xsl b/doc/doc-docbook/MyStyle-txt-html.xsl new file mode 100644 index 000000000..7ec02ec5c --- /dev/null +++ b/doc/doc-docbook/MyStyle-txt-html.xsl @@ -0,0 +1,23 @@ +<!-- $Cambridge: exim/doc/doc-docbook/MyStyle-txt-html.xsl,v 1.1 2005/06/16 10:32:31 ph10 Exp $ --> + +<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version='1.0'> + +<!-- This stylesheet driver imports the DocBook XML stylesheet for unchunked +HTML output, and then imports my common stylesheet for HTML output. Then it +adds an instruction to use "(c)" for copyright rather than the Unicode +character. --> + +<xsl:import href="/usr/share/sgml/docbook/xsl-stylesheets-1.66.1/xhtml/docbook.xsl"/> +<xsl:import href="MyStyle-html.xsl"/> + +<xsl:template name="dingbat.characters"> + <xsl:param name="dingbat">bullet</xsl:param> + <xsl:choose> + <xsl:when test="$dingbat='copyright'">(c)</xsl:when> + <xsl:otherwise> + <xsl:text>?</xsl:text> + </xsl:otherwise> + </xsl:choose> +</xsl:template> + +</xsl:stylesheet> diff --git a/doc/doc-docbook/MyStyle.xsl b/doc/doc-docbook/MyStyle.xsl new file mode 100644 index 000000000..a3e05cccb --- /dev/null +++ b/doc/doc-docbook/MyStyle.xsl @@ -0,0 +1,202 @@ +<!-- $Cambridge: exim/doc/doc-docbook/MyStyle.xsl,v 1.1 2005/06/16 10:32:31 ph10 Exp $ --> + +<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version='1.0'> + +<!-- This file contains changes to the Docbook XML stylesheets that I want to +have happen in all forms of output. It is imported by all the drivers. --> + + +<!-- Set body font size --> + +<xsl:param name="body.font.master">11</xsl:param> + +<!-- Set no relative indent for titles and body --> + +<xsl:param name="title.margin.left">0pt</xsl:param> + + +<!-- This removes the dot at the end of run-in titles, which we use +for formal paragraphs for command line options. --> + +<xsl:param name="runinhead.default.title.end.punct" select="' '"></xsl:param> + + +<!-- Without this setting, variable lists get misformatted in the FO case, +causing overprinting. Maybe with a later release of fop the need to do this +might go away. --> + +<xsl:param name="variablelist.as.blocks" select="1"></xsl:param> + + +<!-- +Cause sections to be numbered, and to include the outer component number. +--> + +<xsl:param name="section.autolabel">1</xsl:param> +<xsl:param name="section.label.includes.component.label">1</xsl:param> + + +<!-- +Specify TOCs only for top-level things. No TOCs for components (e.g. chapters) +--> + +<xsl:param name="generate.toc"> +article toc,title +book toc,title +</xsl:param> + + +<!-- Turn off the poor hyphenation --> + +<xsl:param name="hyphenate">false</xsl:param> + + +<!-- +Generate only numbers, no titles, in cross references. +--> + +<xsl:param name="xref.with.number.and.title">0</xsl:param> + + +<!-- Hopefully this might do something useful? It doesn't seem to. --> + +<xsl:param name="fop.extensions" select="1"></xsl:param> + + +<!-- Output variable names in italic rather than the default monospace. --> + +<xsl:template match="varname"> + <xsl:call-template name="inline.italicseq"/> +</xsl:template> + + +<!-- Output file names in italic rather than the default monospace. --> + +<xsl:template match="filename"> + <xsl:call-template name="inline.italicseq"/> +</xsl:template> + + +<!-- Output options in bold rather than the default monospace. --> + +<xsl:template match="option"> + <xsl:call-template name="inline.boldseq"/> +</xsl:template> + + +<!-- +Make a number of more detailed changes to the style that involve more than just +fiddling with a parameter. +--> + +<xsl:param name="local.l10n.xml" select="document('')"/> +<l:i18n xmlns:l="http://docbook.sourceforge.net/xmlns/l10n/1.0"> + <l:l10n language="en"> + + <!-- The default (as modified above) gives us "Chapter xxx" or "Section + xxx", with a capital letter at the start. So we have to make an more + complicated explicit change to give just the number. --> + + <l:context name="xref-number"> + <l:template name="chapter" text="%n"/> + <l:template name="sect1" text="%n"/> + <l:template name="sect2" text="%n"/> + <l:template name="section" text="%n"/> + </l:context> + + <!-- I think that having a trailing dot after section numbers looks fussy, + whereas you need it after just the digits of a chapter number. In both + cases we want to get rid of the word "chapter" or "section". --> + + <l:context name="title-numbered"> + <l:template name="chapter" text="%n. %t"/> + <l:template name="sect1" text="%n %t"/> + <l:template name="sect2" text="%n %t"/> + <l:template name="section" text="%n %t"/> + </l:context> + + </l:l10n> +</l:i18n> + + +<!-- The default has far too much space on either side of displays and lists --> + +<xsl:attribute-set name="verbatim.properties"> + <xsl:attribute name="space-before.minimum">0em</xsl:attribute> + <xsl:attribute name="space-before.optimum">0em</xsl:attribute> + <xsl:attribute name="space-before.maximum">0em</xsl:attribute> + <xsl:attribute name="space-after.minimum">0em</xsl:attribute> + <xsl:attribute name="space-after.optimum">0em</xsl:attribute> + <xsl:attribute name="space-after.maximum">0em</xsl:attribute> + <xsl:attribute name="start-indent">0.3in</xsl:attribute> +</xsl:attribute-set> + +<xsl:attribute-set name="list.block.spacing"> + <xsl:attribute name="space-before.optimum">0em</xsl:attribute> + <xsl:attribute name="space-before.minimum">0em</xsl:attribute> + <xsl:attribute name="space-before.maximum">0em</xsl:attribute> + <xsl:attribute name="space-after.optimum">0em</xsl:attribute> + <xsl:attribute name="space-after.minimum">0em</xsl:attribute> + <xsl:attribute name="space-after.maximum">0em</xsl:attribute> +</xsl:attribute-set> + +<!-- List item spacing --> + +<xsl:attribute-set name="list.item.spacing"> + <xsl:attribute name="space-before.optimum">0.8em</xsl:attribute> + <xsl:attribute name="space-before.minimum">0.8em</xsl:attribute> + <xsl:attribute name="space-before.maximum">1em</xsl:attribute> +</xsl:attribute-set> + +<!-- Reduce the space after informal tables --> + +<xsl:attribute-set name="informal.object.properties"> + <xsl:attribute name="space-before.minimum">1em</xsl:attribute> + <xsl:attribute name="space-before.optimum">1em</xsl:attribute> + <xsl:attribute name="space-before.maximum">2em</xsl:attribute> + <xsl:attribute name="space-after.minimum">0em</xsl:attribute> + <xsl:attribute name="space-after.optimum">0em</xsl:attribute> + <xsl:attribute name="space-after.maximum">0em</xsl:attribute> +</xsl:attribute-set> + +<!-- Reduce the space after section titles. 0 is not small enough. --> + +<xsl:attribute-set name="section.title.level1.properties"> + <xsl:attribute name="space-after.minimum">-6pt</xsl:attribute> + <xsl:attribute name="space-after.optimum">-4pt</xsl:attribute> + <xsl:attribute name="space-after.maximum">0pt</xsl:attribute> +</xsl:attribute-set> + +<!-- Slightly reduce the space before paragraphs --> + +<xsl:attribute-set name="normal.para.spacing"> + <xsl:attribute name="space-before.optimum">0.8em</xsl:attribute> + <xsl:attribute name="space-before.minimum">0.8em</xsl:attribute> + <xsl:attribute name="space-before.maximum">1.0em</xsl:attribute> +</xsl:attribute-set> + + +<xsl:attribute-set name="table.cell.padding"> + <xsl:attribute name="padding-left">2pt</xsl:attribute> + <xsl:attribute name="padding-right">2pt</xsl:attribute> + <xsl:attribute name="padding-top">0pt</xsl:attribute> + <xsl:attribute name="padding-bottom">0pt</xsl:attribute> +</xsl:attribute-set> + + + +<!-- Turn off page header rule --> +<xsl:param name="header.rule" select="0"></xsl:param> + +<!-- Remove page header content --> +<xsl:template name="header.content"/> + +<!-- Remove space for page header --> +<xsl:param name="body.margin.top" select="'0in'"></xsl:param> +<xsl:param name="region.before.extent" select="'0in'"></xsl:param> + +<!-- Turn off page footer rule --> +<xsl:param name="footer.rule" select="0"></xsl:param> + + +</xsl:stylesheet> diff --git a/doc/doc-docbook/MyTitlepage.templates.xml b/doc/doc-docbook/MyTitlepage.templates.xml new file mode 100644 index 000000000..27c4c8a63 --- /dev/null +++ b/doc/doc-docbook/MyTitlepage.templates.xml @@ -0,0 +1,101 @@ +<!DOCTYPE t:templates [ +<!ENTITY hsize0 "10pt"> +<!ENTITY hsize1 "12pt"> +<!ENTITY hsize2 "14.4pt"> +<!ENTITY hsize3 "17.28pt"> +<!ENTITY hsize4 "20.736pt"> +<!ENTITY hsize5 "24.8832pt"> +<!ENTITY hsize0space "7.5pt"> <!-- 0.75 * hsize0 --> +<!ENTITY hsize1space "9pt"> <!-- 0.75 * hsize1 --> +<!ENTITY hsize2space "10.8pt"> <!-- 0.75 * hsize2 --> +<!ENTITY hsize3space "12.96pt"> <!-- 0.75 * hsize3 --> +<!ENTITY hsize4space "15.552pt"> <!-- 0.75 * hsize4 --> +<!ENTITY hsize5space "18.6624pt"> <!-- 0.75 * hsize5 --> +]> + +<!-- $Cambridge: exim/doc/doc-docbook/MyTitlepage.templates.xml,v 1.1 2005/06/16 10:32:31 ph10 Exp $ --> + +<!-- This document is copied from the DocBook XSL stylesheets, and modified to +do what I want it to do for the Exim reference manual. Process this document +with: + +xsltproc -output MyTitleStyle.xsl \ + /usr/share/sgml/docbook/xsl-stylesheets-1.66.1/template/titlepage.xsl \ + MyTitlepage.templates.xml + +in order to generate a style sheet called MyTitleStyle.xsl. That is then +included in my customization stylesheet. What a lot of heavyweight apparatus we +need to set up! --> + + +<t:templates xmlns:t="http://nwalsh.com/docbook/xsl/template/1.0" + xmlns:param="http://nwalsh.com/docbook/xsl/template/1.0/param" + xmlns:fo="http://www.w3.org/1999/XSL/Format" + xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> + +<!-- ******************************************************************** + $Id: titlepage.templates.xml,v 1.23 2003/12/16 00:30:49 bobstayton Exp $ + ******************************************************************** + + This file is part of the DocBook XSL Stylesheet distribution. + See ../README or http://docbook.sf.net/ for copyright + and other information. + + ******************************************************************** --> + +<!-- ==================================================================== --> + + <t:titlepage t:element="book" t:wrapper="fo:block"> + <t:titlepage-content t:side="recto"> + <title + t:named-template="division.title" + param:node="ancestor-or-self::book[1]" + text-align="center" + font-size="&hsize5;" + space-before="&hsize5space;" + font-weight="bold" + font-family="{$title.fontset}"/> + <subtitle + text-align="center" + font-size="&hsize4;" + space-before="&hsize4space;" + font-family="{$title.fontset}"/> + <corpauthor font-size="&hsize3;" + keep-with-next="always" + space-before="2in"/> + <authorgroup space-before="2in"/> + <author font-size="&hsize3;" + space-before="&hsize2space;" + keep-with-next="always"/> + </t:titlepage-content> + + <t:titlepage-content t:side="verso"> + <title + t:named-template="book.verso.title" + font-size="&hsize2;" + font-weight="bold" + font-family="{$title.fontset}"/> + <corpauthor/> + <authorgroup t:named-template="verso.authorgroup"/> + <author/> + <othercredit/> + <pubdate space-before="1em"/> + <abstract/> + <copyright/> + <legalnotice font-size="8pt"/> + </t:titlepage-content> + +<!-- This change stops it putting a blank page after the verso --> + <t:titlepage-separator> +<!-- <fo:block break-after="page"/> --> + </t:titlepage-separator> + + <t:titlepage-before t:side="recto"> + </t:titlepage-before> + + <t:titlepage-before t:side="verso"> + <fo:block break-after="page"/> + </t:titlepage-before> +</t:titlepage> + +</t:templates> diff --git a/doc/doc-docbook/Myhtml.css b/doc/doc-docbook/Myhtml.css new file mode 100644 index 000000000..8a6981774 --- /dev/null +++ b/doc/doc-docbook/Myhtml.css @@ -0,0 +1,31 @@ +# $Cambridge: exim/doc/doc-docbook/Myhtml.css,v 1.1 2005/06/16 10:32:31 ph10 Exp $ + +.screen { + font-family: monospace; + font-size: 1em; + display: block; + padding: 10px; + border: 1px solid #bbb; + background-color: #eee; + color: #000; + overflow: auto; + border-radius: 2.5px; + -moz-border-radius: 2.5px; + margin: 0.5em 2em; + +} + +.programlisting { + font-family: monospace; + font-size: 1em; + display: block; + padding: 10px; + border: 1px solid #bbb; + background-color: #ddd; + color: #000; + overflow: auto; + border-radius: 2.5px; + -moz-border-radius: 2.5px; + margin: 0.5em 2em; +} + diff --git a/doc/doc-docbook/Pre-xml b/doc/doc-docbook/Pre-xml new file mode 100755 index 000000000..113e6f9d0 --- /dev/null +++ b/doc/doc-docbook/Pre-xml @@ -0,0 +1,173 @@ +#! /usr/bin/perl + +# $Cambridge: exim/doc/doc-docbook/Pre-xml,v 1.1 2005/06/16 10:32:31 ph10 Exp $ + +# Script to pre-process XML input before processing it for various purposes. +# Options specify which transformations are to be done. Monospaced literal +# layout blocks are never touched. + +# Changes: + +# -abstract: Remove the <abstract> element + +# -ascii: Replace &8230; (sic, no x) with ... +# Replace ’ by ' +# Replace “ by " +# Replace ” by " +# Replace – by - +# Replace † by * +# Replace ‡ by ** +# Replace   by a space +# Replace © by (c) +# Put quotes round <literal> text +# Put quotes round <quote> text + +# -bookinfo: Remove the <bookinfo> element from the file + +# -fi: Replace "fi" by fi except when it is in an XML element, or +# inside a <literal>. + +# -noindex Remove the XML to generate a Concept and an Options index. +# -oneindex Ditto, but add XML to generate a single index. + + + +# The function that processes non-literal monospaced text + +sub process() +{ +my($s) = $_[0]; + +$s =~ s/fi(?![^<>]*>)/fi/g if $ligatures; + +if ($ascii) + { + $s =~ s/…/.../g; + $s =~ s/’/'/g; + $s =~ s/“/"/g; + $s =~ s/”/"/g; + $s =~ s/–/-/g; + $s =~ s/†/*/g; + $s =~ s/‡/**/g; + $s =~ s/ / /g; + $s =~ s/©/(c)/g; + $s =~ s/<quote>/"/g; + $s =~ s/<\/quote>/"/g; + } + +$s; +} + + +# The main program + +$abstract = 0; +$ascii = 0; +$bookinfo = 0; +$inliteral = 0; +$ligatures = 0; +$madeindex = 0; +$noindex = 0; +$oneindex = 0; + +foreach $arg (@ARGV) + { + if ($arg eq "-fi") { $ligatures = 1; } + elsif ($arg eq "-abstract") { $abstract = 1; } + elsif ($arg eq "-ascii") { $ascii = 1; } + elsif ($arg eq "-bookinfo") { $bookinfo = 1; } + elsif ($arg eq "-noindex") { $noindex = 1; } + elsif ($arg eq "-oneindex") { $oneindex = 1; } + else { die "** Pre-xml: Unknown option \"$arg\"\n"; } + } + +while (<STDIN>) + { + # Remove <abstract> if required + + next if ($abstract && /^\s*<abstract>/); + + # Remove <bookinfo> if required + + if ($bookinfo && /^<bookinfo/) + { + while (<STDIN>) { last if /^<\/bookinfo/; } + next; + } + + # Copy monospaced literallayout blocks + + if (/^<literallayout class="monospaced">/) + { + print; + while (<STDIN>) + { + print; + last if /^<\/literallayout>/; + } + next; + } + + # Adjust index-generation code if required + + if (($noindex || $oneindex) && /^<index[\s>]/) + { + while (<STDIN>) + { + last if /^<\/index>/; + } + + if ($oneindex && !$madeindex) + { + $madeindex = 1; + print "<index><title>Index</title></index>\n"; + } + + next; + } + + # A line that is not in a monospaced literal block; keep track of which + # parts are in <literal> and which not. The latter get processed by the + # function above. + + for (;;) + { + if ($inliteral) + { + if (/^(.*?)<\/literal>(.*)$/) + { + print $1; + print "\"" if $ascii; + print "</literal>"; + $inliteral = 0; + $_ = "$2\n"; + } + else + { + print; + last; + } + } + + # Not in literal state + + else + { + if (/^(.*?)<literal>(.*)$/) + { + print &process($1); + print "<literal>"; + print "\"" if $ascii; + $inliteral = 1; + $_ = "$2\n"; + } + else + { + print &process($_); + last; + } + } + } # Loop for different parts of one line + } # Loop for multiple lines + +# End diff --git a/doc/doc-docbook/TidyHTML-filter b/doc/doc-docbook/TidyHTML-filter new file mode 100755 index 000000000..f23a9a728 --- /dev/null +++ b/doc/doc-docbook/TidyHTML-filter @@ -0,0 +1,79 @@ +#! /usr/bin/perl + +# $Cambridge: exim/doc/doc-docbook/TidyHTML-filter,v 1.1 2005/06/16 10:32:31 ph10 Exp $ + +# Script to tidy up the filter HTML file that is generated by xmlto. The +# following changes are made: +# +# 1. Split very long lines. +# 2. Create reverse links from chapter and section titles back to the TOC. + + +$tocref = 1; + +# Read in the filter.html file. + +open(IN, "filter.html") || die "Failed to open filter.html for reading: $!\n"; +@text = <IN>; +close(IN); + +# Insert a newline after every > because the whole toc is generated as one +# humungous line that is hard to check. Then split the lines so that each one +# is a separate element in the vector. + +foreach $line (@text) { $line =~ s/>\s*/>\n/g; } +for ($i = 0; $i < scalar(@text); $i++) + { splice @text, $i, 1, (split /(?<=\n)/, $text[$i]); } + +# We want to create reverse links from each chapter and section title back to +# the relevant place in the TOC. Scan the TOC for the relevant entries. Add +# an id to each entry, and create tables that remember the new link ids. We +# detect the start of the TOC by <div class="toc" and the end of the TOC by +# <div class="chapter". + +# Skip to start of TOC + +for ($i = 0; $i < scalar(@text); $i++) + { + last if $text[$i] =~ /^<div class="toc"/; + } + +# Scan the TOC + +for (; $i < scalar(@text); $i++) + { + last if $text[$i] =~ /^<div class="chapter"/; + if ($text[$i] =~ /^<a href="(#[^"]+)">/) + { + my($ss) = $1; + my($id) = sprintf "%04d", $tocref++; + $text[$i] =~ s/<a/<a id="toc$id"/; + $backref{"$ss"} = "toc$id"; + } + } + +# Scan remainder of the document + +for (; $i < scalar(@text); $i++) + { + if ($text[$i] =~ /^<h[23] /) + { + $i++; + if ($text[$i] =~ /^<a( xmlns="[^"]+")? id="([^"]+)">$/) + { + my($ref) = $backref{"#$2"}; + $text[$i++] = "<a$1 href=\"#$ref\" id=\"$2\">\n"; + my($temp) = $text[$i]; + $text[$i] = $text[$i+1]; + $text[++$i] = $temp; + } + } + } + +# Write out the revised file + +open(OUT, ">filter.html") || die "Failed to open filter.html for writing: $!\n"; +print OUT @text; +close(OUT); + +# End diff --git a/doc/doc-docbook/TidyHTML-spec b/doc/doc-docbook/TidyHTML-spec new file mode 100755 index 000000000..8459bcf17 --- /dev/null +++ b/doc/doc-docbook/TidyHTML-spec @@ -0,0 +1,139 @@ +#! /usr/bin/perl + +# $Cambridge: exim/doc/doc-docbook/TidyHTML-spec,v 1.1 2005/06/16 10:32:31 ph10 Exp $ + +# Script to tidy up the spec HTML files that are generated by xmlto. The +# following changes are made: +# +# 1. Tidy the index.html file by splitting the very long lines. +# 2. Create reverse links from chapter and section titles back to the TOC. +# 3. Tidy the ix01.html file - the actual index - by splitting long lines. +# 4. Insert links from the letter divisions to the top of the Index. + +chdir "spec.html"; + +$tocref = 1; + +# Read in the index.html file. It's really the TOC. + +open(IN, "index.html") || die "Failed to open index.html for reading: $!\n"; +@toc = <IN>; +close(IN); + +# Insert a newline after every > because the whole toc is generated as one +# humungous line that is hard to check. Then split the lines so that each one +# is a separate element in the vector. + +foreach $line (@toc) { $line =~ s/>\s*/>\n/g; } +for ($i = 0; $i < scalar(@toc); $i++) + { splice @toc, $i, 1, (split /(?<=\n)/, $toc[$i]); } + +# We want to create reverse links from each chapter and section title back to +# the relevant place in the TOC. Scan the TOC for the relevant entries. Add +# an id to each entry, and create tables that remember the file names and the +# new link ids. + +foreach $line (@toc) + { + if ($line =~ /^<a href="((?:ch|ix)\d+\.html)(#[^"]+)?">/) + { + my($chix) = $1; + my($ss) = $2; + my($id) = sprintf "%04d", $tocref++; + $line =~ s/<a/<a id="toc$id"/; + $backref{"$chix$ss"} = "toc$id"; + push @chlist, $chix; + } + } + +# Write out the modified index.html file. + +open (OUT, ">index.html") || die "Failed to open index.html for writing: $!\n"; +print OUT @toc; +close(OUT); + +# Now scan each of the other page files and insert the reverse links. + +foreach $file (@chlist) + { + open(IN, "$file") || die "Failed to open $file for reading: $!\n"; + @text = <IN>; + close(IN); + + foreach $line (@text) + { + if ($line =~ /^(.*?)<a( xmlns="[^"]+")? id="([^"]+)"><\/a>(.+?)<\/h(.*)$/) + { + my($pre, $opt, $id, $title, $post) = ($1, $2, $3, $4, $5); + + # Section reference + my($ref) = $backref{"$file#$id"}; + + # If not found, try for a chapter reference + $ref = $backref{"$file"} if !defined $ref; + + # Adjust the line + $line = "$pre<a$opt href=\"index.html#$ref\" id=\"$id\">$title</a></h$post"; + } + } + + open(OUT, ">$file") || die "Failed to open $file for writing: $!\n"; + print OUT @text; + close(OUT); + } + +# Now process the ix01.html file + +open(IN, "ix01.html") || die "Failed to open ix01.html for reading: $!\n"; +@index = <IN>; +close(IN); + +# Insert a newline after every > because the whole index is generated as one +# humungous line that is hard to check. Then split the lines so that each one +# is a separate element in the vector. + +foreach $line (@index) { $line =~ s/>\s*/>\n/g; } +for ($i = 0; $i < scalar(@index); $i++) + { splice @index, $i, 1, (split /(?<=\n)/, $index[$i]); } + +# We want to add a list of letters at the top of the index, and link back +# to them from each letter heading. First find the index title and remember +# where to insert the list of letters. + +for ($i = 0; $i < scalar(@index); $i++) + { + if ($index[$i] =~ /^<\/h2>$/) + { + $listindex = $i; + last; + } + } + +# Now scan through for the letter headings and build the cross references, +# while also building up the list to insert. + +$list = "<h4>\n"; +for (; $i < scalar(@index); $i++) + { + if ($index[$i] =~ /^(.)<\/h3>$/) + { + $letter = $1; + $index[$i-1] =~ s/^/<a id="${letter}B" href="#${letter}T">/; + $index[$i] =~ s/$/<\/a>/; + $list .= "<a id=\"${letter}T\" href=\"#${letter}B\"> $letter</a>\n"; + } + } + +# Now we know which letters we have, we can insert the list. + +$list .= "</h4>\n"; +splice @index, $listindex, 0, $list; + +# Write out the modified index.html file. + +open (OUT, ">ix01.html") || die "Failed to open ix01.html for writing: $!\n"; +print OUT @index; +close(OUT); + + +# End diff --git a/doc/doc-docbook/Tidytxt b/doc/doc-docbook/Tidytxt new file mode 100755 index 000000000..02bf9dbd4 --- /dev/null +++ b/doc/doc-docbook/Tidytxt @@ -0,0 +1,21 @@ +#! /usr/bin/perl + +# $Cambridge: exim/doc/doc-docbook/Tidytxt,v 1.1 2005/06/16 10:32:31 ph10 Exp $ + +# Script to tidy up the output of w3m when it makes a text file. We convert +# sequences of blank lines into a single blank line. + +$blanks = 0; +while (<>) + { + if (/^\s*$/) + { + $blanks++; + next; + } + print "\n" if $blanks > 0; + $blanks = 0; + print; + } + +# End diff --git a/doc/doc-docbook/filter.ascd b/doc/doc-docbook/filter.ascd new file mode 100644 index 000000000..8fd9c7e3c --- /dev/null +++ b/doc/doc-docbook/filter.ascd @@ -0,0 +1,1759 @@ +/// +$Cambridge: exim/doc/doc-docbook/filter.ascd,v 1.1 2005/06/16 10:32:31 ph10 Exp $ + +This file contains the Asciidoc source for the document that describes Exim's +filtering facilities from a user's point of view. See the file AdMarkup.txt for +an explanation of the markup that is used. It is more or less standard +Asciidoc, but with a few changes and additions. +/// + + +/// +This preliminary stuff creates a <bookinfo> entry in the XML. This is removed +when creating the PostScript/PDF output, because we do not want a full-blown +title page created for those versions. The stylesheet fudges up a title line to +replace the text "Table of contents". However, for the other forms of output, +the <bookinfo> element is retained and used. +/// + +Exim's interfaces to mail filtering +=================================== +:author: Philip Hazel +:copyright: University of Cambridge +:cpyear: 2005 +:date: 13 May 2005 +:doctitleabbrev: Exim filtering +:revision: 4.50 + + +////////////////////////////////////////////////////////////////////////////// +***WARNING*** Do not put anything, not even a titleabbrev setting, before +the first chapter (luckily it does not need one) because if you do, AsciiDoc +creates an empty <preface> element, which we do not want. +////////////////////////////////////////////////////////////////////////////// + + +Forwarding and filtering in Exim +-------------------------------- + +This document describes the user interfaces to Exim's in-built mail filtering +facilities, and is copyright (C) University of Cambridge 2005. It corresponds +to Exim version 4.50. + + + +Introduction +~~~~~~~~~~~~ +Most Unix mail transfer agents (programs that deliver mail) permit individual +users to specify automatic forwarding of their mail, usually by placing a list +of forwarding addresses in a file called '.forward' in their home directories. +Exim extends this facility by allowing the forwarding instructions to be a set +of rules rather than just a list of addresses, in effect providing ``'.forward' +with conditions''. Operating the set of rules is called 'filtering', and the +file that contains them is called a 'filter file'. + +Exim supports two different kinds of filter file. An 'Exim filter' contains +instructions in a format that is unique to Exim. A 'Sieve filter' contains +instructions in the Sieve format that is defined by RFC 3028. As this is a +standard format, Sieve filter files may already be familiar to some users. +Sieve files should also be portable between different environments. However, +the Exim filtering facility contains more features (such as variable +expansion), and better integration with the host environment (such as the use +of external processes and pipes). + +The choice of which kind of filter to use can be left to the end-user, provided +that the system administrator has configured Exim appropriately for both kinds +of filter. However, if interoperability is important, Sieve is the only +choice. + +The ability to use filtering or traditional forwarding has to be enabled by the +system administrator, and some of the individual facilities can be separately +enabled or disabled. A local document should be provided to describe exactly +what has been enabled. In the absence of this, consult your system +administrator. + +This document describes how to use a filter file and the format of its +contents. It is intended for use by end-users. Both Sieve filters and Exim +filters are covered. However, for Sieve filters, only issues that relate to the +Exim implementation are discussed, since Sieve itself is described elsewhere. + +The contents of traditional '.forward' files are not described here. They +normally contain just a list of addresses, file names, or pipe commands, +separated by commas or newlines, but other types of item are also available. +The full details can be found in the chapter on the ^redirect^ router in the +Exim specification, which also describes how the system administrator can set +up and control the use of filtering. + + + +Filter operation +~~~~~~~~~~~~~~~~ +It is important to realize that, in Exim, no deliveries are actually made while +a filter or traditional '.forward' file is being processed. Running a filter +or processing a traditional '.forward' file sets up future delivery +operations, but does not carry them out. + +The result of filter or '.forward' file processing is a list of destinations +to which a message should be delivered. The deliveries themselves take place +later, along with all other deliveries for the message. This means that it is +not possible to test for successful deliveries while filtering. It also means +that any duplicate addresses that are generated are dropped, because Exim never +delivers the same message to the same address more than once. + + + + +[[SECTtesting]] +Testing a new filter file +~~~~~~~~~~~~~~~~~~~~~~~~~ +Filter files, especially the more complicated ones, should always be tested, as +it is easy to make mistakes. Exim provides a facility for preliminary testing +of a filter file before installing it. This tests the syntax of the file and +its basic operation, and can also be used with traditional '.forward' files. + +Because a filter can do tests on the content of messages, a test message is +required. Suppose you have a new filter file called 'myfilter' and a test +message called 'test-message'. Assuming that Exim is installed with the +conventional path name '/usr/sbin/sendmail' (some operating systems use +'/usr/lib/sendmail'), the following command can be used: + + /usr/sbin/sendmail -bf myfilter <test-message + +The %-bf% option tells Exim that the following item on the command line is the +name of a filter file that is to be tested. There is also a %-bF% option, +which is similar, but which is used for testing system filter files, as opposed +to user filter files, and which is therefore of use only to the system +administrator. + +The test message is supplied on the standard input. If there are no +message-dependent tests in the filter, an empty file ('/dev/null') can be +used. A supplied message must start with header lines or the ``From'' message +separator line which is found in many multi-message folder files. Note that +blank lines at the start terminate the header lines. A warning is given if no +header lines are read. + +The result of running this command, provided no errors are detected in the +filter file, is a list of the actions that Exim would try to take if presented +with the message for real. +For example, for an Exim filter, the output + + Deliver message to: gulliver@lilliput.fict.example + Save message to: /home/lemuel/mail/archive + +means that one copy of the message would be sent to +'gulliver@lilliput.fict.example', and another would be added to the file +_/home/lemuel/mail/archive_, if all went well. + +The actions themselves are not attempted while testing a filter file in this +way; there is no check, for example, that any forwarding addresses are valid. +For an Exim filter, +if you want to know why a particular action is being taken, add the %-v% +option to the command. This causes Exim to output the results of any +conditional tests and to indent its output according to the depth of nesting of +^if^ commands. Further additional output from a filter test can be generated +by the ^testprint^ command, which is described below. + +When Exim is outputting a list of the actions it would take, if any text +strings are included in the output, non-printing characters therein are +converted to escape sequences. In particular, if any text string contains a +newline character, this is shown as ``\n'' in the testing output. + +When testing a filter in this way, Exim makes up an ``envelope'' for the message. +The recipient is by default the user running the command, and so is the sender, +but the command can be run with the %-f% option to supply a different sender. +For example, + +... +/usr/sbin/sendmail -bf myfilter \ + -f islington@never.where <test-message +... + +Alternatively, if the %-f% option is not used, but the first line of the +supplied message is a ``From'' separator from a message folder file (not the same +thing as a 'From:' header line), the sender is taken from there. If %-f% is +present, the contents of any ``From'' line are ignored. + +The ``return path'' is the same as the envelope sender, unless the message +contains a 'Return-path:' header, in which case it is taken from there. You +need not worry about any of this unless you want to test out features of a +filter file that rely on the sender address or the return path. + +It is possible to change the envelope recipient by specifying further options. +The %-bfd% option changes the domain of the recipient address, while the +%-bfl% option changes the ``local part'', that is, the part before the @ sign. +An adviser could make use of these to test someone else's filter file. + +The %-bfp% and %-bfs% options specify the prefix or suffix for the local part. +These are relevant only when support for multiple personal mailboxes is +implemented; see the description in section <<SECTmbox>> below. + + +Installing a filter file +~~~~~~~~~~~~~~~~~~~~~~~~ +A filter file is normally installed under the name '.forward' in your home +directory -- it is distinguished from a conventional '.forward' file by its +first line (described below). However, the file name is configurable, and some +system administrators may choose to use some different name or location for +filter files. + + +Testing an installed filter file +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Testing a filter file before installation cannot find every potential problem; +for example, it does not actually run commands to which messages are piped. +Some ``live'' tests should therefore also be done once a filter is installed. + +If at all possible, test your filter file by sending messages from some other +account. If you send a message to yourself from the filtered account, and +delivery fails, the error message will be sent back to the same account, which +may cause another delivery failure. It won't cause an infinite sequence of such +messages, because delivery failure messages do not themselves generate further +messages. However, it does mean that the failure won't be returned to you, and +also that the postmaster will have to investigate the stuck message. + +If you have to test an Exim filter from the same account, a sensible precaution +is to include the line + + if error_message then finish endif + +as the first filter command, at least while testing. This causes filtering to +be abandoned for a delivery failure message, and since no destinations are +generated, the message goes on to be delivered to the original address. Unless +there is a good reason for not doing so, it is recommended that the above test +be left in all Exim filter files. +(This does not apply to Sieve files.) + + + +Details of filtering commands +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +The filtering commands for Sieve and Exim filters are completely different in +syntax and semantics. The Sieve mechanism is defined in RFC 3028; in the next +chapter we describe how it is integrated into Exim. The subsequent chapter +covers Exim filtering commands in detail. + + + +[[CHAPsievefilter]] +Sieve filter files +------------------ +The code for Sieve filtering in Exim was contributed by Michael Haardt, and +most of the content of this chapter is taken from the notes he provided. Since +Sieve is a extensible language, it is important to understand ``Sieve'' in this +context as ``the specific implementation of Sieve for Exim''. + +This chapter does not contain a description of Sieve, since that can be found +in RFC 3028, which should be read in conjunction with these notes. + +The Exim Sieve implementation offers the core as defined by RFC 3028, +comparison tests, the *copy*, *envelope*, *fileinto*, and *vacation* +extensions, but not the *reject* extension. Exim does not support message +delivery notifications (MDNs), so adding it just to the Sieve filter (as +required for *reject*) makes little sense. + +In order for Sieve to work properly in Exim, the system administrator needs to +make some adjustments to the Exim configuration. These are described in the +chapter on the ^redirect^ router in the full Exim specification. + + +Recognition of Sieve filters +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +A filter file is interpreted as a Sieve filter if its first line is + + # Sieve filter + +This is what distinguishes it from a conventional '.forward' file or an Exim +filter file. + + + +Saving to specified folders +~~~~~~~~~~~~~~~~~~~~~~~~~~~ +If the system administrator has set things up as suggested in the Exim +specification, and you use *keep* or *fileinto* to save a mail into a +folder, absolute files are stored where specified, relative files are stored +relative to $home$, and *inbox* goes to the standard mailbox location. + + + +Strings containing header names +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +RFC 3028 does not specify what happens if a string denoting a header field does +not contain a valid header name, for example, it contains a colon. This +implementation generates an error instead of ignoring the header field in order +to ease script debugging, which fits in the common picture of Sieve. + + + +Exists test with empty list of headers +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +The *exists* test succeeds only if all specified headers exist. RFC 3028 +does not explicitly specify what happens on an empty list of headers. This +implementation evaluates that condition as true, interpreting the RFC in a +strict sense. + + + +Header test with invalid MIME encoding in header +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Some MUAs process invalid base64 encoded data, generating junk. +Others ignore junk after seeing an equal sign in base64 encoded data. +RFC 2047 does not specify how to react in this case, other than stating +that a client must not forbid to process a message for that reason. +RFC 2045 specifies that invalid data should be ignored (apparently +looking at end of line characters). It also specifies that invalid data +may lead to rejecting messages containing them (and there it appears to +talk about true encoding violations), which is a clear contradiction to +ignoring them. + +RFC 3028 does not specify how to process incorrect MIME words. +This implementation treats them literally, as it does if the word is +correct but its character set cannot be converted to UTF-8. + + + +Address test for multiple addresses per header +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +A header may contain multiple addresses. RFC 3028 does not explicitly +specify how to deal with them, but since the address test checks if +anything matches anything else, matching one address suffices to +satisfy the condition. That makes it impossible to test if a header +contains a certain set of addresses and no more, but it is more logical +than letting the test fail if the header contains an additional address +besides the one the test checks for. + + + +Semantics of keep +~~~~~~~~~~~~~~~~~ +The *keep* command is equivalent to + + fileinto "inbox"; + +It saves the message and resets the implicit keep flag. It does not set the +implicit keep flag; there is no command to set it once it has been reset. + + + +Semantics of fileinto +~~~~~~~~~~~~~~~~~~~~~ +RFC 3028 does not specify whether %fileinto% should try to create a mail folder +if it does not exist. This implementation allows the sysadmin to configure that +aspect using the ^appendfile^ transport options %create_directory%, +%create_file%, and %file_must_exist%. See the ^appendfile^ transport in +the Exim specification for details. + + + +Semantics of redirect +~~~~~~~~~~~~~~~~~~~~~ +Sieve scripts are supposed to be interoperable between servers, so this +implementation does not allow mail to be redirected to unqualified addresses, +because the domain would depend on the system being used. On systems with +virtual mail domains, the default domain is probably not what the user expects +it to be. + + + +String arguments +~~~~~~~~~~~~~~~~ +There has been confusion if the string arguments to *require* are to be +matched case-sensitively or not. This implementation matches them with +the match type ^:is^ (default, see section 2.7.1) and the comparator +^i;ascii-casemap^ (default, see section 2.7.3). The RFC defines the +command defaults clearly, so any different implementations violate RFC +3028. The same is valid for comparator names, also specified as strings. + + + +Number units +~~~~~~~~~~~~ +There is a mistake in RFC 3028: the suffix G denotes gibi-, not tebibyte. +The mistake is obvious, because RFC 3028 specifies G to denote 2^30 +(which is gibi, not tebi), and that is what this implementation uses as +scaling factor for the suffix G. + + + +RFC compliance +~~~~~~~~~~~~~~ +Exim requires the first line of a Sieve filter to be + + # Sieve filter + +Of course the RFC does not specify that line. Do not expect examples to work +without adding it, though. + +RFC 3028 requires the use of CRLF to terminate a line. +The rationale was that CRLF is universally used in network protocols +to mark the end of the line. This implementation does not embed Sieve +in a network protocol, but uses Sieve scripts as part of the Exim MTA. +Since all parts of Exim use LF as newline character, this implementation +does, too, by default, though the system administrator may choose (at Exim +compile time) to use CRLF instead. + +Exim violates RFC 2822, section 3.6.8, by accepting 8-bit header names, so +this implementation repeats this violation to stay consistent with Exim. +This is in preparation to UTF-8 data. + +Sieve scripts cannot contain NUL characters in strings, but mail +headers could contain MIME encoded NUL characters, which could never +be matched by Sieve scripts using exact comparisons. For that reason, +this implementation extends the Sieve quoted string syntax with \0 +to describe a NUL character, violating \0 being the same as 0 in +RFC 3028. Even without using \0, the following tests are all true in +this implementation. Implementations that use C-style strings will only +evaluate the first test as true. + + Subject: =?iso-8859-1?q?abc=00def + + header :contains "Subject" ["abc"] + header :contains "Subject" ["def"] + header :matches "Subject" ["abc?def"] + +Note that by considering Sieve to be a MUA, RFC 2047 can be interpreted +in a way that NUL characters truncating strings is allowed for Sieve +implementations, although not recommended. It is further allowed to use +encoded NUL characters in headers, but that's not recommended either. +The above example shows why. + +RFC 3028 states that if an implementation fails to convert a character +set to UTF-8, two strings cannot be equal if one contains octets greater +than 127. Assuming that all unknown character sets are one-byte character +sets with the lower 128 octets being US-ASCII is not sound, so this +implementation violates RFC 3028 and treats such MIME words literally. +That way at least something could be matched. + +The folder specified by *fileinto* must not contain the character +sequence ``..'' to avoid security problems. RFC 3028 does not specify the +syntax of folders apart from *keep* being equivalent to + + fileinto "INBOX"; + +This implementation uses _inbox_ instead. + +Sieve script errors currently cause messages to be silently filed into +_inbox_. RFC 3028 requires that the user is notified of that condition. +This may be implemented in future by adding a header line to mails that +are filed into _inbox_ due to an error in the filter. + + + +[[CHAPeximfilter]] +Exim filter files +----------------- +This chapter contains a full description of the contents of Exim filter files. + + +Format of Exim filter files +~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Apart from leading white space, the first text in an Exim filter file must be + + # Exim filter + +This is what distinguishes it from a conventional '.forward' file or a Sieve +filter file. If the file does not have this initial line (or the equivalent for +a Sieve filter), it is treated as a conventional '.forward' file, both when +delivering mail and when using the %-bf% testing mechanism. The white space in +the line is optional, and any capitalization may be used. Further text on the +same line is treated as a comment. For example, you could have + + # Exim filter <<== do not edit or remove this line! + +The remainder of the file is a sequence of filtering commands, which consist of +keywords and data values. For example, in the command + + deliver gulliver@lilliput.fict.example + +the keyword is `deliver` and the data value is +`gulliver@lilliput.fict.example`. White space or line breaks separate the +components of a command, except in the case of conditions for the ^if^ command, +where round brackets (parentheses) also act as separators. Complete commands +are separated from each other by white space or line breaks; there are no +special terminators. Thus, several commands may appear on one line, or one +command may be spread over a number of lines. + +If the character # follows a separator anywhere in a command, everything from +# up to the next newline is ignored. This provides a way of including comments +in a filter file. + + +Data values in filter commands +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +There are two ways in which a data value can be input: + +- If the text contains no white space then it can be typed verbatim. However, if +it is part of a condition, it must also be free of round brackets +(parentheses), as these are used for grouping in conditions. + +- Otherwise, it must be enclosed in double quotation marks. In this case, the +character \ (backslash) is treated as an ``escape character'' within the string, +causing the following character or characters to be treated specially: + +&&&& +`\n` is replaced by a newline +`\r` is replaced by a carriage return +`\t` is replaced by a tab +&&&& + +Backslash followed by up to three octal digits is replaced by the character +specified by those digits, and \x followed by up to two hexadecimal digits is +treated similarly. Backslash followed by any other character is replaced +by the second character, so that in particular, \\" becomes " and \\ becomes +\. A data item enclosed in double quotes can be continued onto the next line +by ending the first line with a backslash. Any leading white space at the start +of the continuation line is ignored. + +In addition to the escape character processing that occurs when strings are +enclosed in quotes, most data values are also subject to 'string expansion' +(as described in the next section), in which case the characters `\$` and `\` +are also significant. This means that if a single backslash is actually +required in such a string, and the string is also quoted, \\\\ has to be +entered. + +The maximum permitted length of a data string, before expansion, is 1024 +characters. + + +++++++++++++ +<?hard-pagebreak?> +++++++++++++ + +[[SECTfilterstringexpansion]] +String expansion +~~~~~~~~~~~~~~~~ +Most data values are expanded before use. Expansion consists of replacing +substrings beginning with `\$` with other text. The full expansion facilities +available in Exim are extensive. If you want to know everything that Exim can +do with strings, you should consult the chapter on string expansion in the Exim +documentation. + +In filter files, by far the most common use of string expansion is the +substitution of the contents of a variable. For example, the substring + + $reply_address + +is replaced by the address to which replies to the message should be sent. If +such a variable name is followed by a letter or digit or underscore, it must be +enclosed in curly brackets (braces), for example, + + ${reply_address} + +If a `\$` character is actually required in an expanded string, it must be +escaped with a backslash, and because backslash is also an escape character in +quoted input strings, it must be doubled in that case. The following two +examples illustrate two different ways of testing for a `\$` character in a +message: + + if $message_body contains \$ then ... + if $message_body contains "\\$" then ... + +You can prevent part of a string from being expanded by enclosing it between +two occurrences of `\N`. For example, + + if $message_body contains \N$$$$\N then ... + +tests for a run of four dollar characters. + + +Some useful general variables +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +A complete list of the available variables is given in the Exim documentation. +This shortened list contains the ones that are most likely to be useful in +personal filter files: + +$body_linecount$: The number of lines in the body of the message. + +$body_zerocount$: The number of binary zero characters in the body of the +message. + + +$home$: In conventional configurations, this variable normally contains the +user's home directory. The system administrator can, however, change this. + +$local_part$: The part of the email address that precedes the @ sign -- +normally the user's login name. If support for multiple personal mailboxes is +enabled (see section <<SECTmbox>> below) and a prefix or suffix for the local +part was recognized, it is removed from the string in this variable. + +$local_part_prefix$: If support for multiple personal mailboxes is enabled +(see section <<SECTmbox>> below), and a local part prefix was recognized, +this variable contains the prefix. Otherwise it contains an empty string. + +$local_part_suffix$: If support for multiple personal mailboxes is enabled +(see section <<SECTmbox>> below), and a local part suffix was recognized, +this variable contains the suffix. Otherwise it contains an empty string. + +$message_body$: The initial portion of the body of the message. By default, +up to 500 characters are read into this variable, but the system administrator +can configure this to some other value. Newlines in the body are converted into +single spaces. + +$message_body_end$: The final portion of the body of the message, formatted +and limited in the same way as $message_body$. + +$message_body_size$: The size of the body of the message, in bytes. + +$message_headers$: The header lines of the message, concatenated into a +single string, with newline characters between them. + +$message_id$: The message's local identification string, which is unique for +each message handled by a single host. + +$message_size$: The size of the entire message, in bytes. + +$original_local_part$: When an address that arrived with the message is +being processed, this contains the same value as the variable $local_part$. +However, if an address generated by an alias, forward, or filter file is being +processed, this variable contains the local part of the original address. + +$reply_address$: The contents of the 'Reply-to:' header, if the message +has one; otherwise the contents of the 'From:' header. It is the address to +which normal replies to the message should be sent. + +$return_path$: The return path -- that is, the sender field that will be +transmitted as part of the message's envelope if the message is sent to another +host. This is the address to which delivery errors are sent. In many cases, +this variable has the same value as $sender_address$, but if, for example, +an incoming message to a mailing list has been expanded, $return_path$ may +have been changed to contain the address of the list maintainer. + +$sender_address$: The sender address that was received in the envelope of +the message. This is not necessarily the same as the contents of the 'From:' +or 'Sender:' header lines. For delivery error messages (``bounce messages'') +there is no sender address, and this variable is empty. + +$tod_full$: A full version of the time and date, for example: Wed, 18 Oct +1995 09:51:40 +0100. The timezone is always given as a numerical offset from +GMT. + +$tod_log$: The time and date in the format used for writing Exim's log files, +without the timezone, for example: 1995-10-12 15:32:29. + +$tod_zone$: The local timezone offset, for example: +0100. + + + +[[SECTheadervariables]] +Header variables +~~~~~~~~~~~~~~~~ +There is a special set of expansion variables containing the header lines of +the message being processed. These variables have names beginning with +$header_$ followed by the name of the header line, terminated by a colon. +For example, + + $header_from: + $header_subject: + +The whole item, including the terminating colon, is replaced by the contents of +the message header line. If there is more than one header line with the same +name, their contents are concatenated. For header lines whose data consists of +a list of addresses (for example, 'From:' and 'To:'), a comma and newline is +inserted between each set of data. For all other header lines, just a newline +is used. + +Leading and trailing white space is removed from header line data, and if there +are any MIME ``words'' that are encoded as defined by RFC 2047 (because they +contain non-ASCII characters), they are decoded and translated, if possible, to +a local character set. Translation is attempted only on operating systems that +have the ^^iconv()^^ function. This makes the header line look the same as it +would when displayed by an MUA. The default character set is ISO-8859-1, but +this can be changed by means of the ^headers^ command (see below). + +If you want to see the actual characters that make up a header line, you can +specify $rheader_$ instead of $header_$. This inserts the ``raw'' +header line, unmodified. + +There is also an intermediate form, requested by $bheader_$, which removes +leading and trailing space and decodes MIME ``words'', but does not do any +character translation. If an attempt to decode what looks superficially like a +MIME ``word'' fails, the raw string is returned. If decoding produces a binary +zero character, it is replaced by a question mark. + +The capitalization of the name following $header_$ is not significant. +Because any printing character except colon may appear in the name of a +message's header (this is a requirement of RFC 2822, the document that +describes the format of a mail message) curly brackets must 'not' be used in +this case, as they will be taken as part of the header name. Two shortcuts are +allowed in naming header variables: + +- The initiating $header_$, $rheader_$, or $bheader_$ can be +abbreviated to $h_$, $rh_$, or $bh_$, respectively. + +- The terminating colon can be omitted if the next character is white space. The +white space character is retained in the expanded string. However, this is not +recommended, because it makes it easy to forget the colon when it really is +needed. + +If the message does not contain a header of the given name, an empty string is +substituted. Thus it is important to spell the names of headers correctly. Do +not use $header_Reply_to$ when you really mean $header_Reply-to$. + + +User variables +~~~~~~~~~~~~~~ +There are ten user variables with names $n0$ -- $n9$ that can be +incremented by the ^add^ command (see section <<SECTadd>>). These can be used +for ``scoring'' messages in various ways. If Exim is configured to run a +``system filter'' on every message, the values left in these variables are +copied into the variables $sn0$ -- $sn9$ at the end of the system filter, thus +making them available to users' filter files. How these values are used is +entirely up to the individual installation. + + +Current directory +~~~~~~~~~~~~~~~~~ +The contents of your filter file should not make any assumptions about the +current directory. It is best to use absolute paths for file names; you +can normally make use of the $home$ variable to refer to your home directory. +The ^save^ command automatically inserts $home$ at the start of non-absolute +paths. + + + + +[[SECTsigdel]] +Significant deliveries +~~~~~~~~~~~~~~~~~~~~~~ +When in the course of delivery a message is processed by a filter file, what +happens next, that is, after the filter file has been processed, depends on +whether or not the filter sets up any 'significant deliveries'. If at least +one significant delivery is set up, the filter is considered to have handled +the entire delivery arrangements for the current address, and no further +processing of the address takes place. If, however, no significant deliveries +are set up, Exim continues processing the current address as if there were no +filter file, and typically sets up a delivery of a copy of the message into a +local mailbox. In particular, this happens in the special case of a filter file +containing only comments. + +The delivery commands ^deliver^, ^save^, and ^pipe^ are by default +significant. However, if such a command is preceded by the word ^unseen^, its +delivery is not considered to be significant. In contrast, other commands such +as ^mail^ and ^vacation^ do not set up significant deliveries unless +preceded by the word ^seen^. + +The following example commands set up significant deliveries: + + deliver jack@beanstalk.example + pipe $home/bin/mymailscript + seen mail subject "message discarded" + seen finish + +The following example commands do not set up significant deliveries: + + unseen deliver jack@beanstalk.example + unseen pipe $home/bin/mymailscript + mail subject "message discarded" + finish + + + + +Filter commands +~~~~~~~~~~~~~~~ +The filter commands that are described in subsequent sections are listed +below, with the section in which they are described in brackets: + +[frame="none"] +`-------------`----------------------------------------------- +^add^ ~~increment a user variable (section <<SECTadd>>) +^deliver^ ~~deliver to an email address (section <<SECTdeliver>>) +^fail^ ~~force delivery failure (sysadmin use) (section <<SECTfail>>) +^finish^ ~~end processing (section <<SECTfinish>>) +^freeze^ ~~freeze message (sysadmin use) (section <<SECTfreeze>>) +^headers^ ~~set the header character set (section <<SECTheaders>>) +^if^ ~~test condition(s) (section <<SECTif>>) +^logfile^ ~~define log file (section <<SECTlog>>) +^logwrite^ ~~write to log file (section <<SECTlog>>) +^mail^ ~~send a reply message (section <<SECTmail>>) +^pipe^ ~~pipe to a command (section <<SECTpipe>>) +^save^ ~~save to a file (section <<SECTsave>>) +^testprint^ ~~print while testing (section <<SECTtestprint>>) +^vacation^ ~~tailored form of ^mail^ (section <<SECTmail>>) +-------------------------------------------------------------- + +The ^headers^ command has additional parameters that can be used only in a +system filter. The ^fail^ and ^freeze^ commands are available only when +Exim's filtering facilities are being used as a system filter, and are +therefore usable only by the system administrator and not by ordinary users. +They are mentioned only briefly in this document; for more information, see the +main Exim specification. + + + +[[SECTadd]] +The add command +~~~~~~~~~~~~~~~ +&&& +` add `<'number'>` to `<'user variable'> +`e.g. add 2 to n3` +&&& + +There are 10 user variables of this type, with names $n0$ -- $n9$. Their +values can be obtained by the normal expansion syntax (for example $n3$) in +other commands. At the start of filtering, these variables all contain zero. +Both arguments of the ^add^ command are expanded before use, making it +possible to add variables to each other. Subtraction can be obtained by adding +negative numbers. + + + +[[SECTdeliver]] +The deliver command +~~~~~~~~~~~~~~~~~~~ + +&&& +` deliver` <'mail address'> +`e.g. deliver "Dr Livingstone <David@somewhere.africa.example>"` +&&& + +This command provides a forwarding operation. The delivery that it sets up is +significant unless the command is preceded by ^unseen^ (see section +<<SECTsigdel>>). The message is sent on to the given address, exactly as +happens if the address had appeared in a traditional '.forward' file. If you +want to deliver the message to a number of different addresses, you can use +more than one ^deliver^ command (each one may have only one address). However, +duplicate addresses are discarded. + +To deliver a copy of the message to your normal mailbox, your login name can be +given as the address. Once an address has been processed by the filtering +mechanism, an identical generated address will not be so processed again, so +doing this does not cause a loop. + +However, if you have a mail alias, you should 'not' refer to it here. For +example, if the mail address 'L.Gulliver' is aliased to 'lg303' then all +references in Gulliver's '.forward' file should be to 'lg303'. A reference +to the alias will not work for messages that are addressed to that alias, +since, like '.forward' file processing, aliasing is performed only once on an +address, in order to avoid looping. + +Following the new address, an optional second address, preceded by +^errors_to^ may appear. This changes the address to which delivery errors on +the forwarded message will be sent. Instead of going to the message's original +sender, they go to this new address. For ordinary users, the only value that is +permitted for this address is the user whose filter file is being processed. +For example, the user 'lg303' whose mailbox is in the domain +'lilliput.example' could have a filter file that contains + + deliver jon@elsewhere.example errors_to lg303@lilliput.example + +Clearly, using this feature makes sense only in situations where not all +messages are being forwarded. In particular, bounce messages must not be +forwarded in this way, as this is likely to create a mail loop if something +goes wrong. + + + +[[SECTsave]] +The save command +~~~~~~~~~~~~~~~~ +&&& +` save `<'file name'> +`e.g. save $home/mail/bookfolder` +&&& + +This command specifies that a copy of the message is to be appended to the +given file (that is, the file is to be used as a mail folder). The delivery +that ^save^ sets up is significant unless the command is preceded by +^unseen^ (see section <<SECTsigdel>>). + +More than one ^save^ command may be obeyed; each one causes a copy of the +message to be written to its argument file, provided they are different +(duplicate ^save^ commands are ignored). + +If the file name does not start with a / character, the contents of the +$home$ variable are prepended, unless it is empty. In conventional +configurations, this variable is normally set in a user filter to the user's +home directory, but the system administrator may set it to some other path. In +some configurations, $home$ may be unset, in which case a non-absolute path +name may be generated. Such configurations convert this to an absolute path +when the delivery takes place. In a system filter, $home$ is never set. + +The user must of course have permission to write to the file, and the writing +of the file takes place in a process that is running as the user, under the +user's primary group. Any secondary groups to which the user may belong are not +normally taken into account, though the system administrator can configure Exim +to set them up. In addition, the ability to use this command at all is +controlled by the system administrator -- it may be forbidden on some systems. + +An optional mode value may be given after the file name. The value for the mode +is interpreted as an octal number, even if it does not begin with a zero. For +example: + + save /some/folder 640 + +This makes it possible for users to override the system-wide mode setting for +file deliveries, which is normally 600. If an existing file does not have the +correct mode, it is changed. + +An alternative form of delivery may be enabled on your system, in which each +message is delivered into a new file in a given directory. If this is the case, +this functionality can be requested by giving the directory name terminated by +a slash after the ^save^ command, for example + + save separated/messages/ + +There are several different formats for such deliveries; check with your system +administrator or local documentation to find out which (if any) are available +on your system. If this functionality is not enabled, the use of a path name +ending in a slash causes an error. + + + +[[SECTpipe]] +The pipe command +~~~~~~~~~~~~~~~~ +&&& +` pipe `<'command'> +`e.g. pipe "$home/bin/countmail $sender_address"` +&&& + +This command specifies that the message is to be delivered to the specified +command using a pipe. The delivery that it sets up is significant unless the +command is preceded by ^unseen^ (see section <<SECTsigdel>>). Remember, +however, that no deliveries are done while the filter is being processed. All +deliveries happen later on. Therefore, the result of running the pipe is not +available to the filter. + +When the deliveries are done, a separate process is run, and a copy of the +message is passed on its standard input. The process runs as the user, under +the user's primary group. Any secondary groups to which the user may belong are +not normally taken into account, though the system administrator can configure +Exim to set them up. More than one ^pipe^ command may appear; each one causes +a copy of the message to be written to its argument pipe, provided they are +different (duplicate ^pipe^ commands are ignored). + +When the time comes to transport the message, +the command supplied to ^pipe^ is split up by Exim into a command name and a +number of arguments. These are delimited by white space except for arguments +enclosed in double quotes, in which case backslash is interpreted as an escape, +or in single quotes, in which case no escaping is recognized. Note that as the +whole command is normally supplied in double quotes, a second level of quoting +is required for internal double quotes. For example: + + pipe "$home/myscript \"size is $message_size\"" + +String expansion is performed on the separate components after the line has +been split up, and the command is then run directly by Exim; it is not run +under a shell. Therefore, substitution cannot change the number of arguments, +nor can quotes, backslashes or other shell metacharacters in variables cause +confusion. + +Documentation for some programs that are normally run via this kind of pipe +often suggest that the command should start with + + IFS=" " + +This is a shell command, and should 'not' be present in Exim filter files, +since it does not normally run the command under a shell. + +However, there is an option that the administrator can set to cause a shell to +be used. In this case, the entire command is expanded as a single string and +passed to the shell for interpretation. It is recommended that this be avoided +if at all possible, since it can lead to problems when inserted variables +contain shell metacharacters. + +The default PATH set up for the command is determined by the system +administrator, usually containing at least _/usr/bin_ so that common commands +are available without having to specify an absolute file name. However, it is +possible for the system administrator to restrict the pipe facility so that the +command name must not contain any / characters, and must be found in one of the +directories in the configured PATH. It is also possible for the system +administrator to lock out the use of the ^pipe^ command altogether. + +When the command is run, a number of environment variables are set up. The +complete list for pipe deliveries may be found in the Exim reference manual. +Those that may be useful for pipe deliveries from user filter files are: + +&&& +`DOMAIN ` the domain of the address +`HOME ` your home directory +`LOCAL_PART ` see below +`LOCAL_PART_PREFIX ` see below +`LOCAL_PART_SUFFIX ` see below +`LOGNAME ` your login name +`MESSAGE_ID ` the unique id of the message +`PATH ` the command search path +`RECIPIENT ` the complete recipient address +`SENDER ` the sender of the message +`SHELL ` `/bin/sh` +`USER ` see below +&&& + +LOCAL_PART, LOGNAME, and USER are all set to the same value, +namely, your login id. LOCAL_PART_PREFIX and LOCAL_PART_SUFFIX may +be set if Exim is configured to recognize prefixes or suffixes in the local +parts of addresses. For example, a message addressed to +'pat-suf2@domain.example' may cause the filter for user 'pat' to be run. If +this sets up a pipe delivery, LOCAL_PART_SUFFIX is `-suf2` when the +pipe command runs. The system administrator has to configure Exim specially for +this feature to be available. + +If you run a command that is a shell script, be very careful in your use of +data from the incoming message in the commands in your script. RFC 2822 is very +generous in the characters that are permitted to appear in mail addresses, and +in particular, an address may begin with a vertical bar or a slash. For this +reason you should always use quotes round any arguments that involve data from +the message, like this: + + /some/command '$SENDER' + +so that inserted shell meta-characters do not cause unwanted effects. + +Remember that, as was explained earlier, the pipe command is not run at the +time the filter file is interpreted. The filter just defines what deliveries +are required for one particular addressee of a message. The deliveries +themselves happen later, once Exim has decided everything that needs to be done +for the message. + +A consequence of this is that you cannot inspect the return code from the pipe +command from within the filter. Nevertheless, the code returned by the command +is important, because Exim uses it to decide whether the delivery has succeeded +or failed. + +The command should return a zero completion code if all has gone well. Most +non-zero codes are treated by Exim as indicating a failure of the pipe. This is +treated as a delivery failure, causing the message to be returned to its +sender. However, there are some completion codes that are treated as temporary +errors. The message remains on Exim's spool disk, and the delivery is tried +again later, though it will ultimately time out if the delivery failures go on +too long. The completion codes to which this applies can be specified by the +system administrator; the default values are 73 and 75. + +The pipe command should not normally write anything to its standard output or +standard error file descriptors. If it does, whatever is written is normally +returned to the sender of the message as a delivery error, though this action +can be varied by the system administrator. + + + +[[SECTmail]] +Mail commands +~~~~~~~~~~~~~ +There are two commands that cause the creation of a new mail message, neither +of which count as a significant delivery unless the command is preceded by the +word ^seen^ (see section <<SECTsigdel>>). This is a powerful facility, but it +should be used with care, because of the danger of creating infinite sequences +of messages. The system administrator can forbid the use of these commands +altogether. + +To help prevent runaway message sequences, these commands have no effect when +the incoming message is a bounce (delivery error) message, and messages sent by +this means are treated as if they were reporting delivery errors. Thus, they +should never themselves cause a bounce message to be returned. The basic +mail-sending command is + +&&& +`mail [to `<'address-list'>`]` +` [cc `<'address-list'>`]` +` [bcc `<'address-list'>`]` +` [from `<'address'>`]` +` [reply_to `<'address'>`]` +` [subject `<'text'>`]` +` [extra_headers `<'text'>`]` +` [text `<'text'>`]` +` [[expand] file `<'filename'>`]` +` [return message]` +` [log `<'log file name'>`]` +` [once `<'note file name'>`]` +` [once_repeat `<'time interval'>`]` + +`e.g. mail text "Your message about $h_subject: has been received"` +&&& + +Each <'address-list'> can contain a number of addresses, separated by commas, +in the format of a 'To:' or 'Cc:' header line. In fact, the text you supply +here is copied exactly into the appropriate header line. It may contain +additional information as well as email addresses. For example: + +... +mail to "Julius Caesar <jc@rome.example>, \ + <ma@rome.example> (Mark A.)" +... + +Similarly, the texts supplied for ^from^ and ^reply_to^ are copied into +their respective header lines. + +As a convenience for use in one common case, there is also a command called +^vacation^. It behaves in the same way as ^mail^, except that the defaults for +the %subject%, %file%, %log%, %once%, and %once_repeat% options are + + subject "On vacation" + expand file .vacation.msg + log .vacation.log + once .vacation + once_repeat 7d + +respectively. These are the same file names and repeat period used by the +traditional Unix ^vacation^ command. The defaults can be overridden by +explicit settings, but if a file name is given its contents are expanded only +if explicitly requested. + +*Warning*: The ^vacation^ command should always be used conditionally, +subject to at least the ^personal^ condition (see section <<SECTpersonal>> +below) so as not to send automatic replies to non-personal messages from +mailing lists or elsewhere. Sending an automatic response to a mailing list or +a mailing list manager is an Internet Sin. + +For both commands, the key/value argument pairs can appear in any order. At +least one of ^text^ or ^file^ must appear (except with ^vacation^, where +there is a default for ^file^); if both are present, the text string appears +first in the message. If ^expand^ precedes ^file^, each line of the file is +subject to string expansion before it is included in the message. + +Several lines of text can be supplied to ^text^ by including the escape +sequence ``\n'' in the string wherever a newline is required. If the command is +output during filter file testing, newlines in the text are shown as ``\n''. + +Note that the keyword for creating a 'Reply-To:' header is ^reply_to^, +because Exim keywords may contain underscores, but not hyphens. If the ^from^ +keyword is present and the given address does not match the user who owns the +forward file, Exim normally adds a 'Sender:' header to the message, +though it can be configured not to do this. + +The %extra_headers% keyword allows you to add custom header lines to the +message. The text supplied must be one or more syntactically valid RFC 2882 +header lines. You can use ``\n'' within quoted text to specify newlines between +headers, and also to define continued header lines. For example: + + extra_headers "h1: first\nh2: second\n continued\nh3: third" + +No newline should appear at the end of the final header line. + +If no ^to^ argument appears, the message is sent to the address in the +$reply_address$ variable (see section <<SECTfilterstringexpansion>> above). +An 'In-Reply-To:' header is automatically included in the created message, +giving a reference to the message identification of the incoming message. + +If ^return message^ is specified, the incoming message that caused the filter +file to be run is added to the end of the message, subject to a maximum size +limitation. + +If a log file is specified, a line is added to it for each message sent. + +If a ^once^ file is specified, it is used to hold a database for remembering +who has received a message, and no more than one message is ever sent to any +particular address, unless ^once_repeat^ is set. This specifies a time +interval after which another copy of the message is sent. The interval is +specified as a sequence of numbers, each followed by the initial letter of one +of ``seconds'', ``minutes'', ``hours'', ``days'', or ``weeks''. For example, + + once_repeat 5d4h + +causes a new message to be sent if 5 days and 4 hours have elapsed since the +last one was sent. There must be no white space in a time interval. + +Commonly, the file name specified for ^once^ is used as the base name for +direct-access (DBM) file operations. There are a number of different DBM +libraries in existence. Some operating systems provide one as a default, but +even in this case a different one may have been used when building Exim. With +some DBM libraries, specifying ^once^ results in two files being created, +with the suffixes _.dir_ and _.pag_ being added to the given name. With +some others a single file with the suffix _.db_ is used, or the name is used +unchanged. + +Using a DBM file for implementing the ^once^ feature means that the file +grows as large as necessary. This is not usually a problem, but some system +administrators want to put a limit on it. The facility can be configured not to +use a DBM file, but instead, to use a regular file with a maximum size. The +data in such a file is searched sequentially, and if the file fills up, the +oldest entry is deleted to make way for a new one. This means that some +correspondents may receive a second copy of the message after an unpredictable +interval. Consult your local information to see if your system is configured +this way. + +More than one ^mail^ or ^vacation^ command may be obeyed in a single filter +run; they are all honoured, even when they are to the same recipient. + + + +[[SECTlog]] +Logging commands +~~~~~~~~~~~~~~~~ +A log can be kept of actions taken by a filter file. This facility is normally +available in conventional configurations, but there are some situations where +it might not be. Also, the system administrator may choose to disable it. Check +your local information if in doubt. + +Logging takes place while the filter file is being interpreted. It does not +queue up for later like the delivery commands. The reason for this is so that a +log file need be opened only once for several write operations. There are two +commands, neither of which constitutes a significant delivery. The first +defines a file to which logging output is subsequently written: + +&&& +` logfile `<'file name'> +`e.g. logfile $home/filter.log` +&&& + +The file name must be fully qualified. You can use $home$, as in this +example, to refer to your home directory. The file name may optionally be +followed by a mode for the file, which is used if the file has to be created. +For example, + + logfile $home/filter.log 0644 + +The number is interpreted as octal, even if it does not begin with a zero. +The default for the mode is 600. It is suggested that the ^logfile^ command +normally appear as the first command in a filter file. Once ^logfile^ has +been obeyed, the ^logwrite^ command can be used to write to the log file: + +&&& +` logwrite "`<'some text string'>`"` +`e.g. logwrite "$tod_log $message_id processed"` +&&& + +It is possible to have more than one ^logfile^ command, to specify writing to +different log files in different circumstances. Writing takes place at the end +of the file, and a newline character is added to the end of each string if +there isn't one already there. Newlines can be put in the middle of the string +by using the ``\n'' escape sequence. Lines from simultaneous deliveries may get +interleaved in the file, as there is no interlocking, so you should plan your +logging with this in mind. However, data should not get lost. + + + +[[SECTfinish]] +The finish command +~~~~~~~~~~~~~~~~~~ +The command ^finish^, which has no arguments, causes Exim to stop +interpreting the filter file. This is not a significant action unless preceded +by ^seen^. A filter file containing only ^seen finish^ is a black hole. + + +[[SECTtestprint]] +The testprint command +~~~~~~~~~~~~~~~~~~~~~ +It is sometimes helpful to be able to print out the values of variables when +testing filter files. The command + +&&& +` testprint `<'text'> +`e.g. testprint "home=$home reply_address=$reply_address"` +&&& + +does nothing when mail is being delivered. However, when the filtering code is +being tested by means of the %-bf% option (see section <<SECTtesting>> above), +the value of the string is written to the standard output. + + +++++++++++++ +<?hard-pagebreak?> +++++++++++++ +[[SECTfail]] +The fail command +~~~~~~~~~~~~~~~~ +When Exim's filtering facilities are being used as a system filter, the +^fail^ command is available, to force delivery failure. Because this command +is normally usable only by the system administrator, and not enabled for use by +ordinary users, it is described in more detail in the main Exim specification +rather than in this document. + + +[[SECTfreeze]] +The freeze command +~~~~~~~~~~~~~~~~~~ +When Exim's filtering facilities are being used as a system filter, the +^freeze^ command is available, to freeze a message on the queue. Because this +command is normally usable only by the system administrator, and not enabled +for use by ordinary users, it is described in more detail in the main Exim +specification rather than in this document. + + + +[[SECTheaders]] +The headers command +~~~~~~~~~~~~~~~~~~~ +The ^headers^ command can be used to change the target character set that is +used when translating the contents of encoded header lines for insertion by the +$header_$ mechanism (see section <<SECTheadervariables>> above). The default +can be set in the Exim configuration; if not specified, ISO-8859-1 is used. The +only currently supported format for the ^headers^ command in user filters is as +in this example: + + headers charset "UTF-8" + +That is, ^headers^ is followed by the word ^charset^ and then the name of a +character set. This particular example would be useful if you wanted to compare +the contents of a header to a UTF-8 string. + +In system filter files, the ^headers^ command can be used to add or remove +header lines from the message. These features are described in the main Exim +specification. + + + +[[SECTif]] +Obeying commands conditionally +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Most of the power of filtering comes from the ability to test conditions and +obey different commands depending on the outcome. The ^if^ command is used to +specify conditional execution, and its general form is + +&&& +`if `<'condition'> +`then `<'commands'> +`elif `<'condition'> +`then `<'commands'> +`else `<'commands'> +`endif` +&&& + +There may be any number of ^elif^ and ^then^ sections (including none) and +the ^else^ section is also optional. Any number of commands, including nested +^if^ commands, may appear in any of the <'commands'> sections. + +Conditions can be combined by using the words ^and^ and ^or^, and round +brackets (parentheses) can be used to specify how several conditions are to +combine. Without brackets, ^and^ is more binding than ^or^. +For example, + + if + $h_subject: contains "Make money" or + $h_precedence: is "junk" or + ($h_sender: matches ^\\d{8}@ and not personal) or + $message_body contains "this is not spam" + then + seen finish + endif + +A condition can be preceded by ^not^ to negate it, and there are also some +negative forms of condition that are more English-like. + + + +++++++++++++ +<?hard-pagebreak?> +++++++++++++ +String testing conditions +~~~~~~~~~~~~~~~~~~~~~~~~~ +There are a number of conditions that operate on text strings, using the words +``begins'', ``ends'', ``is'', ``contains'' and ``matches''. If you want to apply the same +test to more than one header line, you can easily concatenate them into a +single string for testing, as in this example: + + if "$h_to:, $h_cc:" contains me@domain.example then ... + +If a string-testing condition name is written in lower case, the testing +of letters is done without regard to case; if it is written in upper case +(for example, ``CONTAINS''), the case of letters is taken into account. + +&&& +` `<'text1'>` begins `<'text2'> +` `<'text1'>` does not begin `<'text2'> +`e.g. $header_from: begins "Friend@"` +&&& + +A ``begins'' test checks for the presence of the second string at the start of +the first, both strings having been expanded. + +&&& +` `<'text1'>` ends `<'text2'> +` `<'text1'>` does not end `<'text2'> +`e.g. $header_from: ends "public.com.example"` +&&& + +An ``ends'' test checks for the presence of the second string at the end of +the first, both strings having been expanded. + +&&& +` `<'text1'>` is `<'text2'> +` `<'text1'>` is not `<'text2'> +`e.g. $local_part_suffix is "-foo"` +&&& + +An ``is'' test does an exact match between the strings, having first expanded +both strings. + +&&& +` `<'text1'>` contains `<'text2'> +` `<'text1'>` does not contain `<'text2'> +`e.g. $header_subject: contains "evolution"` +&&& + +A ``contains'' test does a partial string match, having expanded both strings. + +&&& +` `<'text1'>` matches `<'text2'> +` `<'text1'>` does not match `<'text2'> +`e.g. $sender_address matches "(bill|john)@"` +&&& + +For a ``matches'' test, after expansion of both strings, the second one is +interpreted as a regular expression. Exim uses the PCRE regular expression +library, which provides regular expressions that are compatible with Perl. + +The match succeeds if the regular expression matches any part of the first +string. If you want a regular expression to match only at the start or end of +the subject string, you must encode that requirement explicitly, using the `^` +or `$` metacharacters. The above example, which is not so constrained, matches +all these addresses: + + bill@test.example + john@some.example + spoonbill@example.com + littlejohn@example.com + +To match only the first two, you could use this: + + if $sender_address matches "^(bill|john)@" then ... + +Care must be taken if you need a backslash in a regular expression, because +backslashes are interpreted as escape characters both by the string expansion +code and by Exim's normal processing of strings in quotes. For example, if you +want to test the sender address for a domain ending in '.com' the regular +expression is + + \.com$ + +The backslash and dollar sign in that expression have to be escaped when used +in a filter command, as otherwise they would be interpreted by the expansion +code. Thus, what you actually write is + + if $sender_address matches \\.com\$ + +An alternative way of handling this is to make use of the `\N` expansion +flag for suppressing expansion: + + if $sender_address matches \N\.com$\N + +Everything between the two occurrences of `\N` is copied without change by +the string expander (and in fact you do not need the final one, because it is +at the end of the string). If the regular expression is given in quotes +(mandatory only if it contains white space) you have to write either + + if $sender_address matches "\\\\.com\\$" + +or + + if $sender_address matches "\\N\\.com$\\N" + + +If the regular expression contains bracketed sub-expressions, numeric +variable substitutions such as $1$ can be used in the subsequent actions +after a successful match. If the match fails, the values of the numeric +variables remain unchanged. Previous values are not restored after ^endif^. +In other words, only one set of values is ever available. If the condition +contains several sub-conditions connected by ^and^ or ^or^, it is the +strings extracted from the last successful match that are available in +subsequent actions. Numeric variables from any one sub-condition are also +available for use in subsequent sub-conditions, because string expansion of a +condition occurs just before it is tested. + + +Numeric testing conditions +~~~~~~~~~~~~~~~~~~~~~~~~~~ +The following conditions are available for performing numerical tests: + +&&& +` `<'number1'>` is above `<'number2'> +` `<'number1'>` is not above `<'number2'> +` `<'number1'>` is below `<'number2'> +` `<'number1'>` is not below `<'number2'> +`e.g. $message_size is not above 10k` +&&& + +The <'number'> arguments must expand to strings of digits, optionally followed +by one of the letters K or M (upper case or lower case) which cause +multiplication by 1024 and 1024x1024 respectively. + + +Testing for significant deliveries +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +You can use the ^delivered^ condition to test whether or not any previously +obeyed filter commands have set up a significant delivery. For example: + + if not delivered then save mail/anomalous endif + +``Delivered'' is perhaps a poor choice of name for this condition, because the +message has not actually been delivered; rather, a delivery has been set up for +later processing. + + +Testing for error messages +~~~~~~~~~~~~~~~~~~~~~~~~~~ +The condition ^error_message^ is true if the incoming message is a bounce +(mail delivery error) message. Putting the command + + if error_message then finish endif + +at the head of your filter file is a useful insurance against things going +wrong in such a way that you cannot receive delivery error reports. *Note*: +^error_message^ is a condition, not an expansion variable, and therefore is +not preceded by `$`. + + +Testing a list of addresses +~~~~~~~~~~~~~~~~~~~~~~~~~~~ +There is a facility for looping through a list of addresses and applying a +condition to each of them. It takes the form + +&&& +`foranyaddress `<'string'>` (`<'condition'>`)` +&&& + +where <'string'> is interpreted as a list of RFC 2822 addresses, as in a +typical header line, and <'condition'> is any valid filter condition or +combination of conditions. The ``group'' syntax that is defined for certain +header lines that contain addresses is supported. + +The parentheses surrounding the condition are mandatory, to delimit it from +possible further sub-conditions of the enclosing ^if^ command. Within the +condition, the expansion variable $thisaddress$ is set to the non-comment +portion of each of the addresses in the string in turn. For example, if the +string is + + B.Simpson <bart@sfld.example>, lisa@sfld.example (his sister) + +then $thisaddress$ would take on the values `bart@sfld.example` and +`lisa@sfld.example` in turn. + +If there are no valid addresses in the list, the whole condition is false. If +the internal condition is true for any one address, the overall condition is +true and the loop ends. If the internal condition is false for all addresses in +the list, the overall condition is false. This example tests for the presence +of an eight-digit local part in any address in a 'To:' header: + + if foranyaddress $h_to: ( $thisaddress matches ^\\d{8}@ ) then ... + +When the overall condition is true, the value of $thisaddress$ in the +commands that follow ^then^ is the last value it took on inside the loop. At +the end of the ^if^ command, the value of $thisaddress$ is reset to what it +was before. It is best to avoid the use of multiple occurrences of +^foranyaddress^, nested or otherwise, in a single ^if^ command, if the +value of $thisaddress$ is to be used afterwards, because it isn't always +clear what the value will be. Nested ^if^ commands should be used instead. + +Header lines can be joined together if a check is to be applied to more than +one of them. For example: + + if foranyaddress $h_to:,$h_cc: .... + +scans through the addresses in both the 'To:' and the 'Cc:' headers. + + +[[SECTpersonal]] +Testing for personal mail +~~~~~~~~~~~~~~~~~~~~~~~~~ +A common requirement is to distinguish between incoming personal mail and mail +from a mailing list, or from a robot or other automatic process (for example, a +bounce message). In particular, this test is normally required for ``vacation +messages''. + +The ^personal^ condition checks that the message is not a bounce message and +that the current user's email address appears in the 'To:' header. It also +checks that the sender is not the current user or one of a number of common +daemons, and that there are no header lines starting 'List-' in the message. +Finally, it checks the content of the 'Precedence:' header line, if there is +one. + +You should always use the ^personal^ condition when generating automatic +responses. This example shows the use of ^personal^ in a filter file that is +sending out vacation messages: + + if personal then + mail to $reply_address + subject "I am on holiday" + file $home/vacation/message + once $home/vacation/once + once_repeat 10d + endif + +It is tempting, when writing commands like the above, to quote the original +subject in the reply. For example: + + subject "Re: $h_subject:" + +There is a danger in doing this, however. It may allow a third party to +subscribe you to an opt-in mailing list, provided that the list accepts bounce +messages as subscription confirmations. (Messages sent from filters are always +sent as bounce messages.) Well-managed lists require a non-bounce message to +confirm a subscription, so the danger is relatively small. + +If prefixes or suffixes are in use for local parts -- something which depends +on the configuration of Exim (see section <<SECTmbox>> below) -- the tests for +the current user are done with the full address (including the prefix and +suffix, if any) as well as with the prefix and suffix removed. If the system is +configured to rewrite local parts of mail addresses, for example, to rewrite +`dag46` as `Dirk.Gently`, the rewritten form of the address is also used in +the tests. + + + +Alias addresses for the personal condition +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +It is quite common for people who have mail accounts on a number of different +systems to forward all their mail to one system, and in this case a check for +personal mail should test all their various mail addresses. To allow for this, +the ^personal^ condition keyword can be followed by + +&&& +`alias `<'address'> +&&& + +any number of times, for example + + if personal alias smith@else.where.example + alias jones@other.place.example + then ... + +The alias addresses are treated as alternatives to the current user's email +address when testing the contents of header lines. + + +Details of the personal condition +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +The basic ^personal^ test is roughly equivalent to the following: + + not error_message and + $message_headers does not contain "\nList-" and + $header_auto-submitted: does not contain "auto-" and + $header_precedence: does not contain "bulk" and + $header_precedence: does not contain "list" and + $header_precedence: does not contain "junk" and + foranyaddress $header_to: + ( $thisaddress contains "$local_part$domain" ) and + not foranyaddress $header_from: + ( + $thisaddress contains "$local_partdomain" or + $thisaddress contains "server" or + $thisaddress contains "daemon" or + $thisaddress contains "root" or + $thisaddress contains "listserv" or + $thisaddress contains "majordomo" or + $thisaddress contains "-request" or + $thisaddress matches "^owner-[^]+" + ) + +The variable $local_part$ contains the local part of the mail address of +the user whose filter file is being run -- it is normally your login id. The +$domain$ variable contains the mail domain. As explained above, if aliases +or rewriting are defined, or if prefixes or suffixes are in use, the tests for +the current user are also done with alternative addresses. + + + + +Testing delivery status +~~~~~~~~~~~~~~~~~~~~~~~ +There are two conditions that are intended mainly for use in system filter +files, but which are available in users' filter files as well. The condition +^first_delivery^ is true if this is the first process that is attempting to +deliver the message, and false otherwise. This indicator is not reset until the +first delivery process successfully terminates; if there is a crash or a power +failure (for example), the next delivery attempt is also a ``first delivery''. + +In a user filter file ^first_delivery^ will be false if there was previously an +error in the filter, or if a delivery for the user failed owing to, for +example, a quota error, or if forwarding to a remote address was deferred for +some reason. + +The condition ^manually_thawed^ is true if the message was ``frozen'' for some +reason, and was subsequently released by the system administrator. It is +unlikely to be of use in users' filter files. + + +[[SECTmbox]] +Multiple personal mailboxes +~~~~~~~~~~~~~~~~~~~~~~~~~~~ +The system administrator can configure Exim so that users can set up variants +on their email addresses and handle them separately. Consult your system +administrator or local documentation to see if this facility is enabled on your +system, and if so, what the details are. + +The facility involves the use of a prefix or a suffix on an email address. For +example, all mail addressed to 'lg303-'<'something'> would be the property of +user 'lg303', who could determine how it was to be handled, depending on the +value of <'something'>. + +There are two possible ways in which this can be set up. The first possibility +is the use of multiple '.forward' files. In this case, mail to 'lg303-foo', +for example, is handled by looking for a file called _.forward-foo_ in +'lg303'{ap}s home directory. If such a file does not exist, delivery fails and the +message is returned to its sender. + +The alternative approach is to pass all messages through a single _.forward_ +file, which must be a filter file so that it can distinguish between the +different cases by referencing the variables $local_part_prefix$ or +$local_part_suffix$, as in the final example in section <<SECTex>> below. + +It is possible to configure Exim to support both schemes at once. In this case, +a specific _.forward-foo_ file is first sought; if it is not found, the basic +_.forward_ file is used. + +The ^personal^ test (see section <<SECTpersonal>>) includes prefixes and +suffixes in its checking. + + + +Ignoring delivery errors +~~~~~~~~~~~~~~~~~~~~~~~~ +As was explained above, filtering just sets up addresses for delivery -- no +deliveries are actually done while a filter file is active. If any of the +generated addresses subsequently suffers a delivery failure, an error message +is generated in the normal way. However, if a filter command that sets up a +delivery is preceded by the word ^noerror^, errors for that delivery, +'and any deliveries consequent on it' (that is, from alias, forwarding, or +filter files it invokes) are ignored. + + + +[[SECTex]] +Examples of Exim filter commands +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Simple forwarding: + + # Exim filter + deliver baggins@rivendell.middle-earth.example + +Vacation handling using traditional means, assuming that the _.vacation.msg_ +and other files have been set up in your home directory: + + # Exim filter + unseen pipe "/usr/ucb/vacation \"$local_part\"" + +Vacation handling inside Exim, having first created a file called +_.vacation.msg_ in your home directory: + + # Exim filter + if personal then vacation endif + +File some messages by subject: + + # Exim filter + if $header_subject: contains "empire" or + $header_subject: contains "foundation" + then + save $home/mail/f+e + endif + +Save all non-urgent messages by weekday: + + # Exim filter + if $header_subject: does not contain "urgent" and + $tod_full matches "^(...)," + then + save $home/mail/$1 + endif + +Throw away all mail from one site, except from postmaster: + + # Exim filter + if $reply_address contains "@spam.site.example" and + $reply_address does not contain "postmaster@" + then + seen finish + endif + +Handle multiple personal mailboxes + + # Exim filter + if $local_part_suffix is "-foo" + then + save $home/mail/foo + elif $local_part_suffix is "-bar" + then + save $home/mail/bar + endif + + diff --git a/doc/doc-docbook/spec.ascd b/doc/doc-docbook/spec.ascd new file mode 100644 index 000000000..88b6440b5 --- /dev/null +++ b/doc/doc-docbook/spec.ascd @@ -0,0 +1,33111 @@ +//////////////////////////////////////////////////////////////////////////// +$Cambridge: exim/doc/doc-docbook/spec.ascd,v 1.1 2005/06/16 10:32:31 ph10 Exp $ + +This is the primary source of the Exim Manual. It is an AsciiDoc document +that is converted into DocBook XML for subsequent conversion into printing +and online formats. The markup used herein is traditional AsciiDoc markup, +with some extras. The markup is summarized in a file called AdMarkup.txt. A +private AsciiDoc configuration file specifies how the extra markup is to be +translated into DocBook XML. You MUST use this private AsciiDoc markup if you +want to get sensible results from processing this document. +//////////////////////////////////////////////////////////////////////////// + + + +//////////////////////////////////////////////////////////////////////////// +I am abusing the <abstract> DocBook element as the only trivial way of getting +this information onto the title verso page in the printed renditions. A better +title page would be a useful improvement. The <abstract> element is removed by +preprocessing for the HTML renditions, and the whole <docbookinfo> element is +removed for ascii output formats. +//////////////////////////////////////////////////////////////////////////// + +Specification of the Exim Mail Transfer Agent +============================================= +:abstract: University of Cambridge Computing Service, New Museums Site, Pembroke Street, Cambridge CB2 3QH, England +:author: Philip Hazel +:copyright: University of Cambridge +:cpyear: 2005 +:date: 13 May 2005 +:doctitleabbrev: The Exim MTA +:revision: 4.50 + + +////////////////////////////////////////////////////////////////////////////// +***WARNING*** Do not put anything, not even a titleabbrev, setting before +the first chapter (luckily it does not need one) because if you do, AsciiDoc +creates an empty <preface> element, which we do not want. +////////////////////////////////////////////////////////////////////////////// + +Introduction +------------ + +//////////////////////////////////////////////////////////////////////////// +These are definitions of AsciiDoc "attributes" that are in effect "variables" +whose values can be substituted. The first makes index entries shorter. The +second avoids problems with literal asterisks getting tangled up with bold +emphasis quotes. The others are here for convenience of editing. + +***WARNING*** The positioning of these definitions, after the first Chapter +title, seems to be important. If they are placed earlier, they give rise to +incorrect XML. +//////////////////////////////////////////////////////////////////////////// + +:ACL: access control lists (ACLs) +:star: * +:previousversion: 4.40 +:version: 4.50 + + +//////////////////////////////////////////////////////////////////////////// +This chunk of literal XML implements index entries of the form "x, see y" and +"x, see also y". It didn't seem worth inventing AsciiDoc markup for this, +because is it not something that is likely to change often. +//////////////////////////////////////////////////////////////////////////// + +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +<indexterm role="concept"> + <primary>$1, $2, etc.</primary> + <see><emphasis>numerical variables</emphasis></see> +</indexterm> +<indexterm role="concept"> + <primary>address</primary> + <secondary>rewriting</secondary> + <see><emphasis>rewriting</emphasis></see> +</indexterm> +<indexterm role="concept"> + <primary>CR character</primary> + <see><emphasis>carriage return</emphasis></see> +</indexterm> +<indexterm role="concept"> + <primary>CRL</primary> + <see><emphasis>certificate revocation list</emphasis></see> +</indexterm> +<indexterm role="concept"> + <primary>delivery</primary> + <secondary>failure report</secondary> + <see><emphasis>bounce message</emphasis></see> +</indexterm> +<indexterm role="concept"> + <primary>dialup</primary> + <see><emphasis>intermittently connected hosts</emphasis></see> +</indexterm> +<indexterm role="concept"> + <primary>exiscan</primary> + <see><emphasis>content scanning</emphasis></see> +</indexterm> +<indexterm role="concept"> + <primary>failover</primary> + <see><emphasis>fallback</emphasis></see> +</indexterm> +<indexterm role="concept"> + <primary>fallover</primary> + <see><emphasis>fallback</emphasis></see> +</indexterm> +<indexterm role="concept"> + <primary>filter</primary> + <secondary>Sieve</secondary> + <see><emphasis>Sieve filter</emphasis></see> +</indexterm> +<indexterm role="concept"> + <primary>ident</primary> + <see><emphasis>RFC 1413</emphasis></see> +</indexterm> +<indexterm role="concept"> + <primary>LF character</primary> + <see><emphasis>linefeed</emphasis></see> +</indexterm> +<indexterm role="concept"> + <primary>maximum</primary> + <see><emphasis>limit</emphasis></see> +</indexterm> +<indexterm role="concept"> + <primary>no_<emphasis>xxx</emphasis></primary> + <see>entry for xxx</see> +</indexterm> +<indexterm role="concept"> + <primary>NUL</primary> + <see><emphasis>binary zero</emphasis></see> +</indexterm> +<indexterm role="concept"> + <primary>passwd file</primary> + <see><emphasis>/etc/passwd</emphasis></see> +</indexterm> +<indexterm role="concept"> + <primary>process id</primary> + <see><emphasis>pid</emphasis></see> +</indexterm> +<indexterm role="concept"> + <primary>RBL</primary> + <see><emphasis>DNS list</emphasis></see> +</indexterm> +<indexterm role="concept"> + <primary>redirection</primary> + <see><emphasis>address redirection</emphasis></see> +</indexterm> +<indexterm role="concept"> + <primary>return path</primary> + <seealso><emphasis>envelope sender</emphasis></seealso> +</indexterm> +<indexterm role="concept"> + <primary>scanning</primary> + <see><emphasis>content scanning</emphasis></see> +</indexterm> +<indexterm role="concept"> + <primary>SSL</primary> + <see><emphasis>TLS</emphasis></see> +</indexterm> +<indexterm role="concept"> + <primary>string</primary> + <secondary>expansion</secondary> + <see><emphasis>expansion</emphasis></see> +</indexterm> +<indexterm role="concept"> + <primary>top bit</primary> + <see><emphasis>8-bit characters</emphasis></see> +</indexterm> +<indexterm role="concept"> + <primary>variables</primary> + <see><emphasis>expansion, variables</emphasis></see> +</indexterm> +<indexterm role="concept"> + <primary>zero, binary</primary> + <see><emphasis>binary zero</emphasis></see> +</indexterm> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + +//////////////////////////////////////////////////////////////////////////// +OK, now we start with the real data for this first chapter. +//////////////////////////////////////////////////////////////////////////// + +Exim is a mail transfer agent (MTA) for hosts that are running Unix or +Unix-like operating systems. It was designed on the assumption that it would be +run on hosts that are permanently connected to the Internet. However, it can be +used on intermittently connected hosts with suitable configuration adjustments. + +Configuration files currently exist for the following operating systems: AIX, +BSD/OS (aka BSDI), Darwin (Mac OS X), DGUX, FreeBSD, GNU/Hurd, GNU/Linux, +HI-OSF (Hitachi), HP-UX, IRIX, MIPS RISCOS, NetBSD, OpenBSD, QNX, SCO, SCO +SVR4.2 (aka UNIX-SV), Solaris (aka SunOS5), SunOS4, Tru64-Unix (formerly +Digital UNIX, formerly DEC-OSF1), Ultrix, and Unixware. Some of these operating +systems are no longer current and cannot easily be tested, so the configuration +files may no longer work in practice. + +There are also configuration files for compiling Exim in the Cygwin environment +that can be installed on systems running Windows. However, this document does +not contain any information about running Exim in the Cygwin environment. + +The terms and conditions for the use and distribution of Exim are contained in +the file _NOTICE_. Exim is distributed under the terms of the GNU General +Public Licence, a copy of which may be found in the file _LICENCE_. + +The use, supply or promotion of Exim for the purpose of sending bulk, +unsolicited electronic mail is incompatible with the basic aims of the program, +which revolve around the free provision of a service that enhances the quality +of personal communications. The author of Exim regards indiscriminate +mass-mailing as an antisocial, irresponsible abuse of the Internet. + +Exim owes a great deal to Smail 3 and its author, Ron Karr. Without the +experience of running and working on the Smail 3 code, I could never have +contemplated starting to write a new MTA. Many of the ideas and user interfaces +were originally taken from Smail 3, though the actual code of Exim is entirely +new, and has developed far beyond the initial concept. + +Many people, both in Cambridge and around the world, have contributed to the +development and the testing of Exim, and to porting it to various operating +systems. I am grateful to them all. The distribution now contains a file called +_ACKNOWLEDGMENTS_, in which I have started recording the names of +contributors. + + + +Exim documentation +~~~~~~~~~~~~~~~~~~ +[revisionflag="changed"] +cindex:[documentation] +This edition of the Exim specification applies to version {version} of Exim. +Substantive changes from the {previousversion} edition are marked in some +renditions of the document; this paragraph is so marked if the rendition is +capable of showing a change indicator. + +This document is very much a reference manual; it is not a tutorial. The reader +is expected to have some familiarity with the SMTP mail transfer protocol and +with general Unix system administration. Although there are some discussions +and examples in places, the information is mostly organized in a way that makes +it easy to look up, rather than in a natural order for sequential reading. +Furthermore, the manual aims to cover every aspect of Exim in detail, including +a number of rarely-used, special-purpose features that are unlikely to be of +very wide interest. + +cindex:[books about Exim] +An ``easier'' discussion of Exim which provides more in-depth explanatory, +introductory, and tutorial material can be found in a book entitled +'The Exim SMTP Mail Server', published by UIT Cambridge +(*http://www.uit.co.uk/exim-book/[]*). + +This book also contains a chapter that gives a general introduction to SMTP and +Internet mail. Inevitably, however, the book is unlikely to be fully up-to-date +with the latest release of Exim. (Note that the earlier book about Exim, +published by O'Reilly, covers Exim 3, and many things have changed in Exim 4.) + +cindex:[_doc/NewStuff_] +cindex:[_doc/ChangeLog_] +cindex:[change log] +As the program develops, there may be features in newer versions that have not +yet made it into this document, which is updated only when the most significant +digit of the fractional part of the version number changes. Specifications of +new features that are not yet in this manual are placed in the file +_doc/NewStuff_ in the Exim distribution. + +Some features may be classified as ``experimental''. These may change +incompatibly while they are developing, or even be withdrawn. For this reason, +they are not documented in this manual. Information about experimental features +can be found in the file _doc/experimental.txt_. + +All changes to the program (whether new features, bug fixes, or other kinds of +change) are noted briefly in the file called _doc/ChangeLog_. + +cindex:[_doc/spec.txt_] +This specification itself is available as an ASCII file in _doc/spec.txt_ so +that it can easily be searched with a text editor. Other files in the _doc_ +directory are: + +[frame="none"] +`--------------------`------------------------------------------ +_OptionLists.txt_ list of all options in alphabetical order +_dbm.discuss.txt_ discussion about DBM libraries +_exim.8_ a man page of Exim's command line options +_experimental.txt_ documentation of experimental features +_filter.txt_ specification of the filter language +_pcrepattern.txt_ specification of PCRE regular expressions +_pcretest.txt_ specification of the PCRE testing program +_Exim3.upgrade_ upgrade notes from release 2 to release 3 +_Exim4.upgrade_ upgrade notes from release 3 to release 4 +---------------------------------------------------------------- + +The main specification and the specification of the filtering language are also +available in other formats (HTML, PostScript, PDF, and Texinfo). Section +<<SECTavail>> below tells you how to get hold of these. + + + +FTP and web sites +~~~~~~~~~~~~~~~~~ +cindex:[web site] +cindex:[FTP site] +The primary distribution site for Exim is currently the University of +Cambridge's FTP site, whose contents are described in 'Where to find the Exim +distribution' below. In addition, there is a web site and an FTP site at +%exim.org%. These are now also hosted at the University of Cambridge. The +%exim.org% site was previously hosted for a number of years by Energis Squared, +formerly Planet Online Ltd, whose support I gratefully acknowledge. + +As well as Exim distribution tar files, the Exim web site contains a number of +differently formatted versions of the documentation, including the +cindex:[FAQ] FAQ in both text and HTML formats. The HTML version comes with +a keyword-in-context index. A recent addition to the online information is the +cindex:[wiki] +Exim wiki (*http://www.exim.org/eximwiki/[]*). +We hope that this will make it easier for Exim users to contribute examples, +tips, and know-how for the benefit of others. + + + +Mailing lists +~~~~~~~~~~~~~ +cindex:[mailing lists,for Exim users] +The following are the three main Exim mailing lists: + +[frame="none"] +`-------------------------------`---------------------------------------- +'exim-users@exim.org' general discussion list +'exim-dev@exim.org' discussion of bugs, enhancements, etc. +'exim-announce@exim.org' moderated, low volume announcements list +------------------------------------------------------------------------- + +You can subscribe to these lists, change your existing subscriptions, and view +or search the archives via the mailing lists link on the Exim home page. The +'exim-users' mailing list is also forwarded to +*http://www.egroups.com/list/exim-users[]*, an archiving system with searching +capabilities. + + +Exim training +~~~~~~~~~~~~~ +cindex:[training courses] +From time to time (approximately annually at the time of writing), +lecture-based training courses are run by the author of Exim in Cambridge, UK. +Details can be found on the web site +*http://www-tus.csx.cam.ac.uk/courses/exim/[]*. + + +Bug reports +~~~~~~~~~~~ +cindex:[bug reports] +cindex:[reporting bugs] +Reports of obvious bugs should be emailed to 'bugs@exim.org'. However, if +you are unsure whether some behaviour is a bug or not, the best thing to do is +to post a message to the 'exim-users' mailing list and have it discussed. + + + +[[SECTavail]] +Where to find the Exim distribution +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[FTP site] +cindex:[distribution,ftp site] +The master ftp site for the Exim distribution is + +&&& +*ftp://ftp.csx.cam.ac.uk/pub/software/email/exim[]* +&&& + +This is mirrored by + +&&& +*ftp://ftp.exim.org/pub/exim[]* +&&& + +The file references that follow are relative to the _exim_ directories at these +sites. There are now quite a number of independent mirror sites around the +world. Those that I know about are listed in the file called _Mirrors_. + +Within the _exim_ directory there are subdirectories called _exim3_ (for +previous Exim 3 distributions), _exim4_ (for the latest Exim 4 +distributions), and _Testing_ for testing versions. In the _exim4_ +subdirectory, the current release can always be found in files called + +&&& +_exim-n.nn.tar.gz_ +_exim-n.nn.tar.bz2_ +&&& + +where 'n.nn' is the highest such version number in the directory. The two +files contain identical data; the only difference is the type of compression. +The _.bz2_ file is usually a lot smaller than the _.gz_ file. + +cindex:[distribution,signing details] +cindex:[distribution,public key] +cindex:[public key for signed distribution] +The distributions are currently signed with Philip Hazel's GPG key. The +corresponding public key is available from a number of keyservers, and there is +also a copy in the file _Public-Key_. The signatures for the tar bundles are +in: + +&&& +_exim-n.nn.tar.gz.sig_ +_exim-n.nn.tar.bz2.sig_ +&&& + +For each released version, the log of changes is made separately available in a +separate file in the directory _ChangeLogs_ so that it is possible to +find out what has changed without having to download the entire distribution. + +cindex:[documentation,available formats] +The main distribution contains ASCII versions of this specification and other +documentation; other formats of the documents are available in separate files +inside the _exim4_ directory of the FTP site: + +&&& +_exim-html-n.nn.tar.gz_ +_exim-pdf-n.nn.tar.gz_ +_exim-postscript-n.nn.tar.gz_ +_exim-texinfo-n.nn.tar.gz_ +&&& + +These tar files contain only the _doc_ directory, not the complete +distribution, and are also available in _.bz2_ as well as _.gz_ forms. +cindex:[FAQ] +The FAQ is available for downloading in two different formats in these files: + +&&& +_exim4/FAQ.txt.gz_ +_exim4/FAQ.html.tar.gz_ +&&& + +The first of these is a single ASCII file that can be searched with a text +editor. The second is a directory of HTML files, normally accessed by starting +at _index.html_. The HTML version of the FAQ (which is also included in the +HTML documentation tarbundle) includes a keyword-in-context index, which is +often the most convenient way of finding your way around. + + +Wish list +~~~~~~~~~ +cindex:[wish list] +A wish list is maintained, containing ideas for new features that have been +submitted. From time to time the file is exported to the ftp site into the file +_exim4/WishList_. Items are removed from the list if they get implemented. + + + +Contributed material +~~~~~~~~~~~~~~~~~~~~ +cindex:[contributed material] +At the ftp site, there is a directory called _Contrib_ that contains +miscellaneous files contributed to the Exim community by Exim users. There is +also a collection of contributed configuration examples in +_exim4/config.samples.tar.gz_. These samples are referenced from the FAQ. + + + +Limitations +~~~~~~~~~~~ +- cindex:[limitations of Exim] +Exim is designed for use as an Internet MTA, and therefore handles addresses +in RFC 2822 domain format only. +cindex:[bang paths,not handled by Exim] +It cannot handle UUCP ``bang paths'', though simple two-component bang paths can +be converted by a straightforward rewriting configuration. This restriction +does not prevent Exim from being interfaced to UUCP as a transport mechanism, +provided that domain addresses are used. + +- cindex:[domainless addresses] +cindex:[address,without domain] +Exim insists that every address it handles has a domain attached. For incoming +local messages, domainless addresses are automatically qualified with a +configured domain value. Configuration options specify from which remote +systems unqualified addresses are acceptable. These are then qualified on +arrival. + +- cindex:[transport,external] +cindex:[external transports] +The only external transport currently implemented is an SMTP transport over a +TCP/IP network (using sockets, including support for IPv6). However, a pipe +transport is available, and there are facilities for writing messages to files +and pipes, optionally in 'batched SMTP' format; these facilities can be used +to send messages to some other transport mechanism such as UUCP, provided it +can handle domain-style addresses. Batched SMTP input is also catered for. + +- Exim is not designed for storing mail for dial-in hosts. When the volumes of +such mail are large, it is better to get the messages ``delivered'' into files +(that is, off Exim's queue) and subsequently passed on to the dial-in hosts by +other means. + +- Although Exim does have basic facilities for scanning incoming messages, these +are not comprehensive enough to do full virus or spam scanning. Such operations +are best carried out using additional specialized software packages. If you +compile Exim with the content-scanning extension, straightforward interfaces to +a number of common scanners are provided. + + + + + +Run time configuration +~~~~~~~~~~~~~~~~~~~~~~ +Exim's run time configuration is held in a single text file that is divided +into a number of sections. The entries in this file consist of keywords and +values, in the style of Smail 3 configuration files. A default configuration +file which is suitable for simple online installations is provided in the +distribution, and is described in chapter <<CHAPdefconfil>> below. + + + +Calling interface +~~~~~~~~~~~~~~~~~ +cindex:[Sendmail compatibility,command line interface] +Like many MTAs, Exim has adopted the Sendmail command line interface so that it +can be a straight replacement for _/usr/lib/sendmail_ or +_/usr/sbin/sendmail_ when sending mail, but you do not need to know anything +about Sendmail in order to run Exim. For actions other than sending messages, +Sendmail-compatible options also exist, but those that produce output (for +example, %-bp%, which lists the messages on the queue) do so in Exim's own +format. There are also some additional options that are compatible with Smail +3, and some further options that are new to Exim. Chapter <<CHAPcommandline>> +documents all Exim's command line options. This information is automatically +made into the man page that forms part of the Exim distribution. + +Control of messages on the queue can be done via certain privileged command +line options. There is also an optional monitor program called 'eximon', which +displays current information in an X window, and which contains a menu +interface to Exim's command line administration options. + + + +Terminology +~~~~~~~~~~~ +cindex:[terminology definitions] +cindex:[body of message,definition of] +The 'body' of a message is the actual data that the sender wants to transmit. +It is the last part of a message, and is separated from the 'header' (see +below) by a blank line. + +cindex:[bounce message,definition of] +When a message cannot be delivered, it is normally returned to the sender in a +delivery failure message or a ``non-delivery report'' (NDR). The term 'bounce' +is commonly used for this action, and the error reports are often called +'bounce messages'. This is a convenient shorthand for ``delivery failure error +report''. Such messages have an empty sender address in the message's +'envelope' (see below) to ensure that they cannot themselves give rise to +further bounce messages. + +The term 'default' appears frequently in this manual. It is used to qualify a +value which is used in the absence of any setting in the configuration. It may +also qualify an action which is taken unless a configuration setting specifies +otherwise. + +The term 'defer' is used when the delivery of a message to a specific +destination cannot immediately take place for some reason (a remote host may be +down, or a user's local mailbox may be full). Such deliveries are 'deferred' +until a later time. + +The word 'domain' is sometimes used to mean all but the first component of a +host's name. It is 'not' used in that sense here, where it normally +refers to the part of an email address following the @ sign. + +cindex:[envelope, definition of] +cindex:[sender,definition of] +A message in transit has an associated 'envelope', as well as a header and a +body. The envelope contains a sender address (to which bounce messages should +be delivered), and any number of recipient addresses. References to the +sender or the recipients of a message usually mean the addresses in the +envelope. An MTA uses these addresses for delivery, and for returning bounce +messages, not the addresses that appear in the header lines. + +cindex:[message header, definition of] +cindex:[header section,definition of] +The 'header' of a message is the first part of a message's text, consisting +of a number of lines, each of which has a name such as 'From:', 'To:', +'Subject:', etc. Long header lines can be split over several text lines by +indenting the continuations. The header is separated from the body by a blank +line. + +cindex:[local part,definition of] +cindex:[domain,definition of] +The term 'local part', which is taken from RFC 2822, is used to refer to that +part of an email address that precedes the @ sign. The part that follows the +@ sign is called the 'domain' or 'mail domain'. + +cindex:[local delivery,definition of] +cindex:[remote delivery, definition of] +The terms 'local delivery' and 'remote delivery' are used to distinguish +delivery to a file or a pipe on the local host from delivery by SMTP over +TCP/IP to a remote host. + +cindex:[return path,definition of] +'Return path' is another name that is used for the sender address in a +message's envelope. + +cindex:[queue,definition of] +The term 'queue' is used to refer to the set of messages awaiting delivery, +because this term is in widespread use in the context of MTAs. However, in +Exim's case the reality is more like a pool than a queue, because there is +normally no ordering of waiting messages. + +cindex:[queue runner,definition of] +The term 'queue runner' is used to describe a process that scans the queue +and attempts to deliver those messages whose retry times have come. This term +is used by other MTAs, and also relates to the command %runq%, but in Exim +the waiting messages are normally processed in an unpredictable order. + +cindex:[spool directory,definition of] +The term 'spool directory' is used for a directory in which Exim keeps the +messages on its queue -- that is, those that it is in the process of +delivering. This should not be confused with the directory in which local +mailboxes are stored, which is called a ``spool directory'' by some people. In +the Exim documentation, ``spool'' is always used in the first sense. + + + + + + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// + +Incorporated code +----------------- +cindex:[incorporated code] +cindex:[regular expressions,library] +cindex:[PCRE] +A number of pieces of external code are included in the Exim distribution. + +- Regular expressions are supported in the main Exim program and in the Exim +monitor using the freely-distributable PCRE library, copyright (c) University +of Cambridge. The source is distributed in the directory _src/pcre_. However, +this is a cut-down version of PCRE. If you want to use the PCRE library in +other programs, you should obtain and install the full version from +*ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre[]*. + +- cindex:[cdb,acknowledgement] +Support for the cdb (Constant DataBase) lookup method is provided by code +contributed by Nigel Metheringham of (at the time he contributed it) Planet +Online Ltd. which contains the following statements: ++ +Copyright (c) 1998 Nigel Metheringham, Planet Online Ltd ++ +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation; either version 2 of the License, or (at your option) any later +version. ++ +This code implements Dan Bernstein's Constant DataBase (cdb) spec. Information, +the spec and sample code for cdb can be obtained from +*http://www.pobox.com/{tl}djb/cdb.html[]*. This implementation borrows some code +from Dan Bernstein's implementation (which has no license restrictions applied +to it). ++ +The implementation is completely contained within the code of Exim. +It does not link against an external cdb library. + +- cindex:[SPA authentication] +cindex:[Samba project] +cindex:[Microsoft Secure Password Authentication] +Client support for Microsoft's 'Secure Password Authentication' is provided +by code contributed by Marc Prud'hommeaux. Server support was contributed by +Tom Kistner. This includes code taken from the Samba project, which is released +under the Gnu GPL. + +- cindex:[Cyrus] +cindex:['pwcheck' daemon] +cindex:['pwauthd' daemon] +Support for calling the Cyrus 'pwcheck' and 'saslauthd' daemons is provided +by code taken from the Cyrus-SASL library and adapted by Alexander S. +Sabourenkov. The permission notice appears below, in accordance with the +conditions expressed therein. ++ +Copyright (c) 2001 Carnegie Mellon University. All rights reserved. ++ +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: ++ +. Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + +. Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in +the documentation and/or other materials provided with the +distribution. + +. The name ``Carnegie Mellon University'' must not be used to +endorse or promote products derived from this software without +prior written permission. For permission or any other legal +details, please contact ++ +&&& +Office of Technology Transfer +Carnegie Mellon University +5000 Forbes Avenue +Pittsburgh, PA 15213-3890 +(412) 268-4387, fax: (412) 268-7395 +tech-transfer@andrew.cmu.edu +&&& + +. Redistributions of any form whatsoever must retain the following +acknowledgment: ++ +'This product includes software developed by Computing Services +at Carnegie Mellon University (*http://www.cmu.edu/computing/[]*).' ++ +CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO +THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE +FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN +AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING +OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +. cindex:[monitor] +cindex:[X-windows] +cindex:[Athena] +The Exim Monitor program, which is an X-Window application, includes +modified versions of the Athena StripChart and TextPop widgets. +This code is copyright by DEC and MIT, and their permission notice appears +below, in accordance with the conditions expressed therein. ++ +Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts, +and the Massachusetts Institute of Technology, Cambridge, Massachusetts. ++ +All Rights Reserved ++ +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the names of Digital or MIT not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. ++ +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +. Many people have contributed code fragments, some large, some small, that were +not covered by any specific licence requirements. It is assumed that the +contributors are happy to see their code incoporated into Exim under the GPL. + + + + + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// + +[titleabbrev="Receiving and delivering mail"] +How Exim receives and delivers mail +----------------------------------- + + +Overall philosophy +~~~~~~~~~~~~~~~~~~ +cindex:[design philosophy] +Exim is designed to work efficiently on systems that are permanently connected +to the Internet and are handling a general mix of mail. In such circumstances, +most messages can be delivered immediately. Consequently, Exim does not +maintain independent queues of messages for specific domains or hosts, though +it does try to send several messages in a single SMTP connection after a host +has been down, and it also maintains per-host retry information. + + + +Policy control +~~~~~~~~~~~~~~ +cindex:[policy control,overview] +Policy controls are now an important feature of MTAs that are connected to the +Internet. Perhaps their most important job is to stop MTAs being abused as +``open relays'' by misguided individuals who send out vast amounts of unsolicited +junk, and want to disguise its source. Exim provides flexible facilities for +specifying policy controls on incoming mail: + +- cindex:[{ACL},introduction] +Exim 4 (unlike previous versions of Exim) implements policy controls on +incoming mail by means of 'Access Control Lists' (ACLs). Each list is a +series of statements that may either grant or deny access. ACLs can be used at +several places in the SMTP dialogue while receiving a message from a remote +host. However, the most common places are after each RCPT command, and at +the very end of the message. The sysadmin can specify conditions for accepting +or rejecting individual recipients or the entire message, respectively, at +these two points (see chapter <<CHAPACL>>). Denial of access results in an SMTP +error code. + +- An ACL is also available for locally generated, non-SMTP messages. In this +case, the only available actions are to accept or deny the entire message. + +- When Exim is compiled with the content-scanning extension, facilities are +provided in the ACL mechanism for passing the message to external virus and/or +spam scanning software. The result of such a scan is passed back to the ACL, +which can then use it to decide what to do with the message. + +- When a message has been received, either from a remote host or from the local +host, but before the final acknowledgement has been sent, a locally supplied C +function called 'local_scan()' can be run to inspect the message and decide +whether to accept it or not (see chapter <<CHAPlocalscan>>). If the message is +accepted, the list of recipients can be modified by the function. + +- Using the 'local_scan()' mechanism is another way of calling external +scanner software. The %SA-Exim% add-on package works this way. It does not +require Exim to be compiled with the content-scanning extension. + +- After a message has been accepted, a further checking mechanism is available in +the form of the 'system filter' (see chapter <<CHAPsystemfilter>>). This runs +at the start of every delivery process. + + + +User filters +~~~~~~~~~~~~ +cindex:[filter,introduction] +cindex:[Sieve filter] +In a conventional Exim configuration, users are able to run private filters by +setting up appropriate _.forward_ files in their home directories. See +chapter <<CHAPredirect>> (about the ^redirect^ router) for the configuration +needed to support this, and the separate document entitled 'Exim's interfaces +to mail filtering' for user details. Two different kinds of filtering are +available: + +- Sieve filters are written in the standard filtering language that is defined +by RFC 3028. + +- Exim filters are written in a syntax that is unique to Exim, but which is more +powerful than Sieve, which it pre-dates. + +User filters are run as part of the routing process, described below. + + + +[[SECTmessiden]] +Message identification +~~~~~~~~~~~~~~~~~~~~~~ +cindex:[message ids, details of format] +cindex:[format,of message id] +cindex:[id of message] +cindex:[base62] +cindex:[base36] +cindex:[Darwin] +cindex:[Cygwin] +Every message handled by Exim is given a 'message id' which is sixteen +characters long. It is divided into three parts, separated by hyphens, for +example `16VDhn-0001bo-D3`. Each part is a sequence of letters and digits, +normally encoding numbers in base 62. However, in the Darwin operating +system (Mac OS X) and when Exim is compiled to run under Cygwin, base 36 +(avoiding the use of lower case letters) is used instead, because the message +id is used to construct file names, and the names of files in those systems are +not case-sensitive. + +cindex:[pid (process id),re-use of] +The detail of the contents of the message id have changed as Exim has evolved. +Earlier versions relied on the operating system not re-using a process id (pid) +within one second. On modern operating systems, this assumption can no longer +be made, so the algorithm had to be changed. To retain backward compatibility, +the format of the message id was retained, which is why the following rules are +somewhat eccentric: + +- The first six characters of the message id are the time at which the message +started to be received, to a granularity of one second. That is, this field +contains the number of seconds since the start of the epoch (the normal Unix +way of representing the date and time of day). + +- After the first hyphen, the next six characters are the id of the process that +received the message. + +- There are two different possibilities for the final two characters: + +. cindex:[%localhost_number%] +If %localhost_number% is not set, this value is the fractional part of the +time of reception, normally in units of 1/2000 of a second, but for systems +that must use base 36 instead of base 62 (because of case-insensitive file +systems), the units are 1/1000 of a second. + +. If %localhost_number% is set, it is multiplied by 200 (100) and added to +the fractional part of the time, which in this case is in units of 1/200 +(1/100) of a second. + +After a message has been received, Exim waits for the clock to tick at the +appropriate resolution before proceeding, so that if another message is +received by the same process, or by another process with the same (re-used) +pid, it is guaranteed that the time will be different. In most cases, the clock +will already have ticked while the message was being received. + + +Receiving mail +~~~~~~~~~~~~~~ +cindex:[receiving mail] +cindex:[message,reception] +The only way Exim can receive mail from a remote host is using SMTP over +TCP/IP, in which case the sender and recipient addresses are tranferred using +SMTP commands. However, from a locally running process (such as a user's MUA), +there are several possibilities: + +- If the process runs Exim with the %-bm% option, the message is read +non-interactively (usually via a pipe), with the recipients taken from the +command line, or from the body of the message if %-t% is also used. + +- If the process runs Exim with the %-bS% option, the message is also read +non-interactively, but in this case the recipients are listed at the start of +the message in a series of SMTP RCPT commands, terminated by a DATA +command. This is so-called ``batch SMTP'' format, +but it isn't really SMTP. The SMTP commands are just another way of passing +envelope addresses in a non-interactive submission. + +- If the process runs Exim with the %-bs% option, the message is read +interactively, using the SMTP protocol. A two-way pipe is normally used for +passing data between the local process and the Exim process. +This is ``real'' SMTP and is handled in the same way as SMTP over TCP/IP. For +example, the ACLs for SMTP commands are used for this form of submission. + +- A local process may also make a TCP/IP call to the host's loopback address +(127.0.0.1) or any other of its IP addresses. When receiving messages, Exim +does not treat the loopback address specially. It treats all such connections +in the same way as connections from other hosts. + + +cindex:[message sender, constructed by Exim] +cindex:[sender,constructed by Exim] +In the three cases that do not involve TCP/IP, the sender address is +constructed from the login name of the user that called Exim and a default +qualification domain (which can be set by the %qualify_domain% configuration +option). For local or batch SMTP, a sender address that is passed using the +SMTP MAIL command is ignored. However, the system administrator may allow +certain users (``trusted users'') to specify a different sender address +unconditionally, or all users to specify certain forms of different sender +address. The %-f% option or the SMTP MAIL command is used to specify these +different addresses. See section <<SECTtrustedadmin>> for details of trusted +users, and the %untrusted_set_sender% option for a way of allowing untrusted +users to change sender addresses. + +Messages received by either of the non-interactive mechanisms are subject to +checking by the non-SMTP ACL, if one is defined. Messages received using SMTP +(either over TCP/IP, or interacting with a local process) can be checked by a +number of ACLs that operate at different times during the SMTP session. Either +individual recipients, or the entire message, can be rejected if local policy +requirements are not met. The 'local_scan()' function (see chapter +<<CHAPlocalscan>>) is run for all incoming messages. + +Exim can be configured not to start a delivery process when a message is +received; this can be unconditional, or depend on the number of incoming SMTP +connections or the system load. In these situations, new messages wait on the +queue until a queue runner process picks them up. However, in standard +configurations under normal conditions, delivery is started as soon as a +message is received. + + + + + +Handling an incoming message +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[spool directory,files that hold a message] +cindex:[file,how a message is held] +When Exim accepts a message, it writes two files in its spool directory. The +first contains the envelope information, the current status of the message, and +the header lines, and the second contains the body of the message. The names of +the two spool files consist of the message id, followed by `-H` for the +file containing the envelope and header, and `-D` for the data file. + +cindex:[spool directory,_input_ sub-directory] +By default all these message files are held in a single directory called +_input_ inside the general Exim spool directory. Some operating systems do +not perform very well if the number of files in a directory gets very large; to +improve performance in such cases, the %split_spool_directory% option can be +used. This causes Exim to split up the input files into 62 sub-directories +whose names are single letters or digits. + +The envelope information consists of the address of the message's sender and +the addresses of the recipients. This information is entirely separate from +any addresses contained in the header lines. The status of the message includes +a list of recipients who have already received the message. The format of the +first spool file is described in chapter <<CHAPspool>>. + +cindex:[rewriting,addresses] +Address rewriting that is specified in the rewrite section of the configuration +(see chapter <<CHAPrewrite>>) is done once and for all on incoming addresses, +both in the header lines and the envelope, at the time the message is accepted. +If during the course of delivery additional addresses are generated (for +example, via aliasing), these new addresses are rewritten as soon as they are +generated. At the time a message is actually delivered (transported) further +rewriting can take place; because this is a transport option, it can be +different for different forms of delivery. It is also possible to specify the +addition or removal of certain header lines at the time the message is +delivered (see chapters <<CHAProutergeneric>> and <<CHAPtransportgeneric>>). + + + +Life of a message +~~~~~~~~~~~~~~~~~ +cindex:[message,life of] +cindex:[message,frozen] +A message remains in the spool directory until it is completely delivered to +its recipients or to an error address, or until it is deleted by an +administrator or by the user who originally created it. In cases when delivery +cannot proceed -- for example, when a message can neither be delivered to its +recipients nor returned to its sender, the message is marked ``frozen'' on the +spool, and no more deliveries are attempted. + +cindex:[frozen messages,thawing] +cindex:[message,thawing frozen] +An administrator can ``thaw'' such messages when the problem has been corrected, +and can also freeze individual messages by hand if necessary. In addition, an +administrator can force a delivery error, causing a bounce message to be sent. + +cindex:[%auto_thaw%] +There is an option called %auto_thaw%, which can be used to cause Exim to +retry frozen messages after a certain time. When this is set, no message will +remain on the queue for ever, because the delivery timeout will eventually be +reached. Delivery failure reports (bounce messages) that reach this timeout are +discarded. + +cindex:[%timeout_frozen_after%] +There is also an option called %timeout_frozen_after%, which discards frozen +messages after a certain time. + +cindex:[message,log file for] +cindex:[log,file for each message] +While Exim is working on a message, it writes information about each delivery +attempt to the main log file. This includes successful, unsuccessful, and +delayed deliveries for each recipient (see chapter <<CHAPlog>>). The log lines +are also written to a separate 'message log' file for each message. These +logs are solely for the benefit of the administrator, and are normally deleted +along with the spool files when processing of a message is complete. +The use of individual message logs can be disabled by setting +%no_message_logs%; this might give an improvement in performance on very +busy systems. + +cindex:[journal file] +cindex:[file,journal] +All the information Exim itself needs to set up a delivery is kept in the first +spool file, along with the header lines. When a successful delivery occurs, the +address is immediately written at the end of a journal file, whose name is the +message id followed by `-J`. At the end of a delivery run, if there are some +addresses left to be tried again later, the first spool file (the `-H` file) +is updated to indicate which these are, and the journal file is then deleted. +Updating the spool file is done by writing a new file and renaming it, to +minimize the possibility of data loss. + +Should the system or the program crash after a successful delivery but before +the spool file has been updated, the journal is left lying around. The next +time Exim attempts to deliver the message, it reads the journal file and +updates the spool file before proceeding. This minimizes the chances of double +deliveries caused by crashes. + + + +[[SECTprocaddress]] +Processing an address for delivery +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[drivers,definition of] +cindex:[router,definition of] +cindex:[transport,definition of] +The main delivery processing elements of Exim are called 'routers' and +'transports', and collectively these are known as 'drivers'. Code for a +number of them is provided in the source distribution, and compile-time options +specify which ones are included in the binary. Run time options specify which +ones are actually used for delivering messages. + +cindex:[drivers,instance definition] +Each driver that is specified in the run time configuration is an 'instance' +of that particular driver type. Multiple instances are allowed; for example, +you can set up several different ^smtp^ transports, each with different +option values that might specify different ports or different timeouts. Each +instance has its own identifying name. In what follows we will normally use the +instance name when discussing one particular instance (that is, one specific +configuration of the driver), and the generic driver name when discussing +the driver's features in general. + +A 'router' is a driver that operates on an address, either determining how +its delivery should happen, by routing it to a specific transport, or +converting the address into one or more new addresses (for example, via an +alias file). A router may also explicitly choose to fail an address, causing it +to be bounced. + +A 'transport' is a driver that transmits a copy of the message from Exim's +spool to some destination. There are two kinds of transport: for a 'local' +transport, the destination is a file or a pipe on the local host, whereas for a +'remote' transport the destination is some other host. A message is passed +to a specific transport as a result of successful routing. If a message has +several recipients, it may be passed to a number of different transports. + +cindex:[preconditions,definition of] +An address is processed by passing it to each configured router instance in +turn, subject to certain preconditions, until a router accepts the address or +specifies that it should be bounced. We will describe this process in more +detail shortly. As a simple example, the diagram below illustrates how each +recipient address in a message is processed in a small configuration of three +routers that are configured in various ways. + +To make this a more concrete example, we'll describe it in terms of some actual +routers, but remember, this is only an example. You can configure Exim's +routers in many different ways, and there may be any number of routers in a +configuration. + +The first router that is specified in a configuration is often one that handles +addresses in domains that are not recognized specially by the local host. These +are typically addresses for arbitrary domains on the Internet. A precondition +is set up which looks for the special domains known to the host (for example, +its own domain name), and the router is run for addresses that do 'not' +match. Typically, this is a router that looks up domains in the DNS in order to +find the hosts to which this address routes. If it succeeds, the address is +queued for a suitable SMTP transport; if it does not succeed, the router is +configured to fail the address. + +/// +The example pictured could be a configuration of this type. The second and +third routers can only be run for addresses for which the preconditions for +the first router are not met. If one of these preconditions checks the +domain, the second and third routers are run only for domains that are somehow +special to the local host. +/// + +The second router does redirection -- also known as aliasing and forwarding. +When it generates one or more new addresses from the original, each of them is +routed independently from the start. Otherwise, the router may cause an address +to fail, or it may simply decline to handle the address, in which case the +address is passed to the next router. + +The final router in many configurations is one that checks to see if the +address belongs to a local mailbox. The precondition may involve a check to +see if the local part is the name of a login account, or it may look up the +local part in a file or a database. If its preconditions are not met, or if +the router declines, we have reached the end of the routers. When this happens, +the address is bounced. + + + +Processing an address for verification +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[router,for verification] +cindex:[verifying address, overview] +As well as being used to decide how to deliver to an address, Exim's routers +are also used for 'address verification'. Verification can be requested as +one of the checks to be performed in an ACL for incoming messages, on both +sender and recipient addresses, and it can be tested using the %-bv% and +%-bvs% command line options. + +When an address is being verified, the routers are run in ``verify mode''. This +does not affect the way the routers work, but it is a state that can be +detected. By this means, a router can be skipped or made to behave differently +when verifying. A common example is a configuration in which the first router +sends all messages to a message-scanning program, unless they have been +previously scanned. Thus, the first router accepts all addresses without any +checking, making it useless for verifying. Normally, the %no_verify% option +would be set for such a router, causing it to be skipped in verify mode. + + + + +[[SECTrunindrou]] +Running an individual router +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[router,running details] +cindex:[preconditions,checking] +cindex:[router,result of running] +As explained in the example above, a number of preconditions are checked before +running a router. If any are not met, the router is skipped, and the address is +passed to the next router. When all the preconditions on a router 'are' met, +the router is run. What happens next depends on the outcome, which is one of +the following: + +- 'accept': The router accepts the address, and either queues it for a +transport, or generates one or more ``child'' addresses. Processing the original +address ceases, +cindex:[%unseen% option] +unless the %unseen% option is set on the router. This option +can be used to set up multiple deliveries with different routing (for example, +for keeping archive copies of messages). When %unseen% is set, the address is +passed to the next router. Normally, however, an 'accept' return marks the +end of routing. ++ +cindex:[case of local parts] +cindex:[address duplicate, discarding] +If child addresses are generated, Exim checks to see whether they are +duplicates of any existing recipient addresses. During this check, local parts +are treated as case-sensitive. Duplicate addresses are discarded. Each of the +remaining child addresses is then processed independently, starting with the +first router by default. It is possible to change this by setting the +%redirect_router% option to specify which router to start at for child +addresses. Unlike %pass_router% (see below) the router specified by +%redirect_router% may be anywhere in the router configuration. + +- 'pass': The router recognizes the address, but cannot handle it itself. It +requests that the address be passed to another router. By default the address +is passed to the next router, but this can be changed by setting the +%pass_router% option. However, (unlike %redirect_router%) the named router +must be below the current router (to avoid loops). + +- 'decline': The router declines to accept the address because it does not +recognize it at all. By default, the address is passed to the next router, but +this can be prevented by setting the %no_more% option. When %no_more% is set, +all the remaining routers are skipped. + +- 'fail': The router determines that the address should fail, and queues it for +the generation of a bounce message. There is no further processing of the +original address unless %unseen% is set on the router. + +- 'defer': The router cannot handle the address at the present time. (A database +may be offline, or a DNS lookup may have timed out.) No further processing of +the address happens in this delivery attempt. It is tried again next time the +message is considered for delivery. + +- 'error': There is some error in the router (for example, a syntax error in +its configuration). The action is as for defer. + +If an address reaches the end of the routers without having been accepted by +any of them, it is bounced as unrouteable. +The default error message in this situation is ``unrouteable address'', but you +can set your own message by making use of the %cannot_route_message% option. +This can be set for any router; the value from the last router that ``saw'' +the address is used. + +Sometimes while routing you want to fail a delivery when some conditions are +met but others are not, instead of passing the address on for further routing. +You can do this by having a second router that explicitly fails the delivery +when the relevant conditions are met. The ^redirect^ router has a ``fail'' +facility for this purpose. + + + + +[[SECTrouprecon]] +Router preconditions +~~~~~~~~~~~~~~~~~~~~ +cindex:[router preconditions, order of processing] +cindex:[preconditions,order of processing] +The preconditions that are tested for each router are listed below, in the +order in which they are tested. The individual configuration options are +described in more detail in chapter <<CHAProutergeneric>>. + +- The %local_part_prefix% and %local_part_suffix% options can specify that +the local parts handled by the router may or must have certain prefixes and/or +suffixes. If a mandatory affix (prefix or suffix) is not present, the router is +skipped. These conditions are tested first. When an affix is present, it is +removed from the local part before further processing, including the evaluation +of any other conditions. + +- Routers can be designated for use only when not verifying an address, that is, +only when routing it for delivery (or testing its delivery routing). If the +%verify% option is set false, the router is skipped when Exim is verifying an +address. +Setting the %verify% option actually sets two options, %verify_sender% and +%verify_recipient%, which independently control the use of the router for +sender and recipient verification. You can set these options directly if +you want a router to be used for only one type of verification. + +- If the %address_test% option is set false, the router is skipped when Exim is +run with the %-bt% option to test an address routing. This can be helpful when +the first router sends all new messages to a scanner of some sort; it makes it +possible to use %-bt% to test subsequent delivery routing without having to +simulate the effect of the scanner. + +- Routers can be designated for use only when verifying an address, as +opposed to routing it for delivery. The %verify_only% option controls this. + +- Certain routers can be explicitly skipped when running the routers to check an +address given in the SMTP EXPN command (see the %expn% option). + +- If the %domains% option is set, the domain of the address must be in the set of +domains that it defines. + +- If the %local_parts% option is set, the local part of the address must be in +the set of local parts that it defines. If %local_part_prefix% or +%local_part_suffix% is in use, the prefix or suffix is removed from the local +part before this check. If you want to do precondition tests on local parts +that include affixes, you can do so by using a %condition% option (see below) +that uses the variables $local_part$, $local_part_prefix$, and +$local_part_suffix$ as necessary. + +- If the %check_local_user% option is set, the local part must be the name of +an account on the local host. +If this check succeeds, the uid and gid of the local user are placed in +$local_user_uid$ and $local_user_gid$; these values can be used in the +remaining preconditions. + +- If the %router_home_directory% option is set, it is expanded at this point, +because it overrides the value of $home$. If this expansion were left till +later, the value of $home$ as set by %check_local_user% would be used in +subsequent tests. Having two different values of $home$ in the same router +could lead to confusion. + +- If the %senders% option is set, the envelope sender address must be in the set +of addresses that it defines. + +- If the %require_files% option is set, the existence or non-existence of +specified files is tested. + +- cindex:[customizing,precondition] +If the %condition% option is set, it is evaluated and tested. This option uses +an expanded string to allow you to set up your own custom preconditions. +Expanded strings are described in chapter <<CHAPexpand>>. + + +Note that %require_files% comes near the end of the list, so you cannot use it +to check for the existence of a file in which to lookup up a domain, local +part, or sender. However, as these options are all expanded, you can use the +%exists% expansion condition to make such tests within each condition. The +%require_files% option is intended for checking files that the router may be +going to use internally, or which are needed by a specific transport (for +example, _.procmailrc_). + + + +Delivery in detail +~~~~~~~~~~~~~~~~~~ +cindex:[delivery,in detail] +When a message is to be delivered, the sequence of events is as follows: + +- If a system-wide filter file is specified, the message is passed to it. The +filter may add recipients to the message, replace the recipients, discard the +message, cause a new message to be generated, or cause the message delivery to +fail. The format of the system filter file is the same as for Exim user filter +files, described in the separate document entitled +'Exim's interfaces to mail filtering'. +cindex:[Sieve filter,not available for system filter] +(*Note*: Sieve cannot be used for system filter files.) ++ +Some additional features are available in system filters -- see chapter +<<CHAPsystemfilter>> for details. Note that a message is passed to the system +filter only once per delivery attempt, however many recipients it has. However, +if there are several delivery attempts because one or more addresses could not +be immediately delivered, the system filter is run each time. The filter +condition %first_delivery% can be used to detect the first run of the system +filter. + +- Each recipient address is offered to each configured router in turn, subject +to its preconditions, until one is able to handle it. If no router can handle +the address, that is, if they all decline, the address is failed. Because +routers can be targeted at particular domains, several locally handled domains +can be processed entirely independently of each other. + +- cindex:[routing,loops in] +cindex:[loop,while routing] +A router that accepts an address may set up a local or a remote transport for +it. However, the transport is not run at this time. Instead, the address is +placed on a list for the particular transport, to be run later. Alternatively, +the router may generate one or more new addresses (typically from alias, +forward, or filter files). New addresses are fed back into this process from +the top, but in order to avoid loops, a router ignores any address which has an +identically-named ancestor that was processed by itself. + +- When all the routing has been done, addresses that have been successfully +handled are passed to their assigned transports. When local transports are +doing real local deliveries, they handle only one address at a time, but if a +local transport is being used as a pseudo-remote transport (for example, to +collect batched SMTP messages for transmission by some other means) multiple +addresses can be handled. Remote transports can always handle more than one +address at a time, but can be configured not to do so, or to restrict multiple +addresses to the same domain. + +- Each local delivery to a file or a pipe runs in a separate process under a +non-privileged uid, and these deliveries are run one at a time. Remote +deliveries also run in separate processes, normally under a uid that is private +to Exim (``the Exim user''), but in this case, several remote deliveries can be +run in parallel. The maximum number of simultaneous remote deliveries for any +one message is set by the %remote_max_parallel% option. +The order in which deliveries are done is not defined, except that all local +deliveries happen before any remote deliveries. + +- cindex:[queue runner] +When it encounters a local delivery during a queue run, Exim checks its retry +database to see if there has been a previous temporary delivery failure for the +address before running the local transport. If there was a previous failure, +Exim does not attempt a new delivery until the retry time for the address is +reached. However, this happens only for delivery attempts that are part of a +queue run. Local deliveries are always attempted when delivery immediately +follows message reception, even if retry times are set for them. This makes for +better behaviour if one particular message is causing problems (for example, +causing quota overflow, or provoking an error in a filter file). + +- cindex:[delivery,retry in remote transports] +Remote transports do their own retry handling, since an address may be +deliverable to one of a number of hosts, each of which may have a different +retry time. If there have been previous temporary failures and no host has +reached its retry time, no delivery is attempted, whether in a queue run or +not. See chapter <<CHAPretry>> for details of retry strategies. + +- If there were any permanent errors, a bounce message is returned to an +appropriate address (the sender in the common case), with details of the error +for each failing address. Exim can be configured to send copies of bounce +messages to other addresses. + +- cindex:[delivery,deferral] +If one or more addresses suffered a temporary failure, the message is left on +the queue, to be tried again later. Delivery of these addresses is said to be +'deferred'. + +- When all the recipient addresses have either been delivered or bounced, +handling of the message is complete. The spool files and message log are +deleted, though the message log can optionally be preserved if required. + + + + +Retry mechanism +~~~~~~~~~~~~~~~ +cindex:[delivery,retry mechanism] +cindex:[retry,description of mechanism] +cindex:[queue runner] +Exim's mechanism for retrying messages that fail to get delivered at the first +attempt is the queue runner process. You must either run an Exim daemon that +uses the %-q% option with a time interval to start queue runners at regular +intervals, or use some other means (such as 'cron') to start them. If you do +not arrange for queue runners to be run, messages that fail temporarily at the +first attempt will remain on your queue for ever. A queue runner process works +it way through the queue, one message at a time, trying each delivery that has +passed its retry time. +You can run several queue runners at once. + +Exim uses a set of configured rules to determine when next to retry the failing +address (see chapter <<CHAPretry>>). These rules also specify when Exim should +give up trying to deliver to the address, at which point it generates a bounce +message. If no retry rules are set for a particular host, address, and error +combination, no retries are attempted, and temporary errors are treated as +permanent. + + + +Temporary delivery failure +~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[delivery,temporary failure] +There are many reasons why a message may not be immediately deliverable to a +particular address. Failure to connect to a remote machine (because it, or the +connection to it, is down) is one of the most common. Temporary failures may be +detected during routing as well as during the transport stage of delivery. +Local deliveries may be delayed if NFS files are unavailable, or if a mailbox +is on a file system where the user is over quota. Exim can be configured to +impose its own quotas on local mailboxes; where system quotas are set they will +also apply. + +If a host is unreachable for a period of time, a number of messages may be +waiting for it by the time it recovers, and sending them in a single SMTP +connection is clearly beneficial. Whenever a delivery to a remote host is +deferred, + +cindex:[hints database] +Exim makes a note in its hints database, and whenever a successful +SMTP delivery has happened, it looks to see if any other messages are waiting +for the same host. If any are found, they are sent over the same SMTP +connection, subject to a configuration limit as to the maximum number in any +one connection. + + + + +Permanent delivery failure +~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[delivery,permanent failure] +cindex:[bounce message,when generated] +When a message cannot be delivered to some or all of its intended recipients, a +bounce message is generated. Temporary delivery failures turn into permanent +errors when their timeout expires. All the addresses that fail in a given +delivery attempt are listed in a single message. If the original message has +many recipients, it is possible for some addresses to fail in one delivery +attempt and others to fail subsequently, giving rise to more than one bounce +message. The wording of bounce messages can be customized by the administrator. +See chapter <<CHAPemsgcust>> for details. + +cindex:['X-Failed-Recipients:' header line] +Bounce messages contain an 'X-Failed-Recipients:' header line that lists the +failed addresses, for the benefit of programs that try to analyse such messages +automatically. + +cindex:[bounce message,recipient of] +A bounce message is normally sent to the sender of the original message, as +obtained from the message's envelope. For incoming SMTP messages, this is the +address given in the MAIL command. However, when an address is +expanded via a forward or alias file, an alternative address can be specified +for delivery failures of the generated addresses. For a mailing list expansion +(see section <<SECTmailinglists>>) it is common to direct bounce messages to the +manager of the list. + + + + +Failures to deliver bounce messages +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[bounce message,failure to deliver] +If a bounce message (either locally generated or received from a remote host) +itself suffers a permanent delivery failure, the message is left on the queue, +but it is frozen, awaiting the attention of an administrator. There are options +which can be used to make Exim discard such failed messages, or to keep them +for only a short time (see %timeout_frozen_after% and +%ignore_bounce_errors_after%). + + + + + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// + +Building and installing Exim +---------------------------- + +cindex:[building Exim] + +Unpacking +~~~~~~~~~ +Exim is distributed as a gzipped or bzipped tar file which, when upacked, +creates a directory with the name of the current release (for example, +_exim-{version}_) into which the following files are placed: + +[frame="none"] +`--------------------`-------------------------------------------------------- +_ACKNOWLEDGMENTS_ contains some acknowledgments +_CHANGES_ contains a reference to where changes are documented +_LICENCE_ the GNU General Public Licence +_Makefile_ top-level make file +_NOTICE_ conditions for the use of Exim +_README_ list of files, directories and simple build instructions +------------------------------------------------------------------------------ + +Other files whose names begin with _README_ may also be present. The +following subdirectories are created: + +[frame="none"] +`--------------------`------------------------------------------------ +_Local_ an empty directory for local configuration files +_OS_ OS-specific files +_doc_ documentation files +_exim_monitor_ source files for the Exim monitor +_scripts_ scripts used in the build process +_src_ remaining source files +_util_ independent utilities +---------------------------------------------------------------------- + +The main utility programs are contained in the _src_ directory, and are built +with the Exim binary. The _util_ directory contains a few optional scripts +that may be useful to some sites. + + +Multiple machine architectures and operating systems +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[building Exim,multiple OS/architectures] +The building process for Exim is arranged to make it easy to build binaries for +a number of different architectures and operating systems from the same set of +source files. Compilation does not take place in the _src_ directory. Instead, +a 'build directory' is created for each architecture and operating system. + +cindex:[symbolic link,to build directory] +Symbolic links to the sources are installed in this directory, which is where +the actual building takes place. + +In most cases, Exim can discover the machine architecture and operating system +for itself, but the defaults can be overridden if necessary. + + +[[SECTdb]] +DBM libraries +~~~~~~~~~~~~~ +cindex:[DBM libraries, discussion of] +cindex:[hints database,DBM files used for] +Even if you do not use any DBM files in your configuration, Exim still needs a +DBM library in order to operate, because it uses indexed files for its hints +databases. Unfortunately, there are a number of DBM libraries in existence, and +different operating systems often have different ones installed. + +cindex:[Solaris,DBM library for] +cindex:[IRIX, DBM library for] +cindex:[BSD, DBM library for] +cindex:[Linux, DBM library for] +If you are using Solaris, IRIX, one of the modern BSD systems, or a modern +Linux distribution, the DBM configuration should happen automatically, and you +may be able to ignore this section. Otherwise, you may have to learn more than +you would like about DBM libraries from what follows. + +cindex:['ndbm' DBM library] +Licensed versions of Unix normally contain a library of DBM functions operating +via the 'ndbm' interface, and this is what Exim expects by default. Free +versions of Unix seem to vary in what they contain as standard. In particular, +some early versions of Linux have no default DBM library, and different +distributors have chosen to bundle different libraries with their packaged +versions. However, the more recent releases seem to have standardised on the +Berkeley DB library. + +Different DBM libraries have different conventions for naming the files they +use. When a program opens a file called _dbmfile_, there are four +possibilities: + +. A traditional 'ndbm' implementation, such as that supplied as part of +Solaris, operates on two files called _dbmfile.dir_ and _dbmfile.pag_. + +. cindex:['gdbm' DBM library] +The GNU library, 'gdbm', operates on a single file. If used via its 'ndbm' +compatibility interface it makes two different hard links to it with names +_dbmfile.dir_ and _dbmfile.pag_, but if used via its native interface, the +file name is used unmodified. + +. cindex:[Berkeley DB library] +The Berkeley DB package, if called via its 'ndbm' compatibility interface, +operates on a single file called _dbmfile.db_, but otherwise looks to the +programmer exactly the same as the traditional 'ndbm' implementation. + +. If the Berkeley package is used in its native mode, it operates on a single +file called _dbmfile_; the programmer's interface is somewhat different to +the traditional 'ndbm' interface. + +. To complicate things further, there are several very different versions of the +Berkeley DB package. Version 1.85 was stable for a very long time, releases +2.'x' and 3.'x' were current for a while, but the latest versions are now +numbered 4.'x'. Maintenance of some of the earlier releases has ceased. All +versions of Berkeley DB can be obtained from ++ +&&& +*http://www.sleepycat.com/[]* +&&& + +. cindex:['tdb' DBM library] +Yet another DBM library, called 'tdb', has become available from ++ +&&& +*http://download.sourceforge.net/tdb[]* +&&& ++ +It has its own interface, and also operates on a single file. + +cindex:[USE_DB] +cindex:[DBM libraries, configuration for building] +Exim and its utilities can be compiled to use any of these interfaces. In order +to use any version of the Berkeley DB package in native mode, you must set +USE_DB in an appropriate configuration file (typically +_Local/Makefile_). For example: + + USE_DB=yes + +Similarly, for gdbm you set USE_GDBM, and for tdb you set USE_TDB. An +error is diagnosed if you set more than one of these. + +At the lowest level, the build-time configuration sets none of these options, +thereby assuming an interface of type (1). However, some operating system +configuration files (for example, those for the BSD operating systems and +Linux) assume type (4) by setting USE_DB as their default, and the +configuration files for Cygwin set USE_GDBM. Anything you set in +_Local/Makefile_, however, overrides these system defaults. + +As well as setting USE_DB, USE_GDBM, or USE_TDB, it may also be +necessary to set DBMLIB, to cause inclusion of the appropriate library, as +in one of these lines: + + DBMLIB = -ldb + DBMLIB = -ltdb + +Settings like that will work if the DBM library is installed in the standard +place. Sometimes it is not, and the library's header file may also not be in +the default path. You may need to set INCLUDE to specify where the header +file is, and to specify the path to the library more fully in DBMLIB, as in +this example: + + INCLUDE=-I/usr/local/include/db-4.1 + DBMLIB=/usr/local/lib/db-4.1/libdb.a + + +There is further detailed discussion about the various DBM libraries in the +file _doc/dbm.discuss.txt_ in the Exim distribution. + + + +Pre-building configuration +~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[building Exim,pre-building configuration] +cindex:[configuration for building Exim] +cindex:[_Local/Makefile_] +cindex:[_src/EDITME_] +Before building Exim, a local configuration file that specifies options +independent of any operating system has to be created with the name +_Local/Makefile_. A template for this file is supplied as the file +_src/EDITME_, and it contains full descriptions of all the option settings +therein. These descriptions are therefore not repeated here. If you are +building Exim for the first time, the simplest thing to do is to copy +_src/EDITME_ to _Local/Makefile_, then read it and edit it appropriately. + +There are three settings that you must supply, because Exim will not build +without them. They are the location of the run time configuration file +(CONFIGURE_FILE), the directory in which Exim binaries will be installed +(BIN_DIRECTORY), and the identity of the Exim user (EXIM_USER and +maybe EXIM_GROUP as well). The value of CONFIGURE_FILE can in fact be +a colon-separated list of file names; Exim uses the first of them that exists. + +There are a few other parameters that can be specified either at build time or +at run time, to enable the same binary to be used on a number of different +machines. However, if the locations of Exim's spool directory and log file +directory (if not within the spool directory) are fixed, it is recommended that +you specify them in _Local/Makefile_ instead of at run time, so that errors +detected early in Exim's execution (such as a malformed configuration file) can +be logged. + +cindex:[content scanning,specifying at build time] +Exim's interfaces for calling virus and spam scanning sofware directly from +access control lists are not compiled by default. If you want to include these +facilities, you need to set + + WITH_CONTENT_SCAN=yes + +in your _Local/Makefile_. For details of the facilities themselves, see +chapter <<CHAPexiscan>>. + + +cindex:[_Local/eximon.conf_] +cindex:[_exim_monitor/EDITME_] +If you are going to build the Exim monitor, a similar configuration process is +required. The file _exim_monitor/EDITME_ must be edited appropriately for +your installation and saved under the name _Local/eximon.conf_. If you are +happy with the default settings described in _exim_monitor/EDITME_, +_Local/eximon.conf_ can be empty, but it must exist. + +This is all the configuration that is needed in straightforward cases for known +operating systems. However, the building process is set up so that it is easy +to override options that are set by default or by operating-system-specific +configuration files, for example to change the name of the C compiler, which +defaults to %gcc%. See section <<SECToverride>> below for details of how to do +this. + + + +Support for iconv() +~~~~~~~~~~~~~~~~~~~ +cindex:['iconv()' support] +The contents of header lines in messages may be encoded according to the rules +described RFC 2047. This makes it possible to transmit characters that are not +in the ASCII character set, and to label them as being in a particular +character set. When Exim is inspecting header lines by means of the %\$h_% +mechanism, it decodes them, and translates them into a specified character set +(default ISO-8859-1). The translation is possible only if the operating system +supports the 'iconv()' function. + +However, some of the operating systems that supply 'iconv()' do not support +very many conversions. The GNU %libiconv% library (available from +*http://www.gnu.org/software/libiconv/[]*) can be installed on such systems to +remedy this deficiency, as well as on systems that do not supply 'iconv()' at +all. After installing %libiconv%, you should add + + HAVE_ICONV=yes + +to your _Local/Makefile_ and rebuild Exim. + + + +[[SECTinctlsssl]] +Including TLS/SSL encryption support +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[TLS,including support for TLS] +cindex:[encryption,including support for] +cindex:[SUPPORT_TLS] +cindex:[OpenSSL,building Exim with] +cindex:[GnuTLS,building Exim with] +Exim can be built to support encrypted SMTP connections, using the STARTTLS +command as per RFC 2487. It can also support legacy clients that expect to +start a TLS session immediately on connection to a non-standard port (see the +%tls_on_connect_ports% runtime option and the %-tls-on-connect% command +line option). + +If you want to build Exim with TLS support, you must first install either the +OpenSSL or GnuTLS library. There is no cryptographic code in Exim itself for +implementing SSL. + +If OpenSSL is installed, you should set + + SUPPORT_TLS=yes + TLS_LIBS=-lssl -lcrypto + +in _Local/Makefile_. You may also need to specify the locations of the +OpenSSL library and include files. For example: + + SUPPORT_TLS=yes + TLS_LIBS=-L/usr/local/openssl/lib -lssl -lcrypto + TLS_INCLUDE=-I/usr/local/openssl/include/ + +cindex:[USE_GNUTLS] +If GnuTLS is installed, you should set + + SUPPORT_TLS=yes + USE_GNUTLS=yes + TLS_LIBS=-lgnutls -ltasn1 -lgcrypt + +in _Local/Makefile_, and again you may need to specify the locations of the +library and include files. For example: + + SUPPORT_TLS=yes + USE_GNUTLS=yes + TLS_LIBS=-L/usr/gnu/lib -lgnutls -ltasn1 -lgcrypt + TLS_INCLUDE=-I/usr/gnu/include + +You do not need to set TLS_INCLUDE if the relevant directory is already +specified in INCLUDE. Details of how to configure Exim to make use of TLS +are given in chapter <<CHAPTLS>>. + + + + +Use of tcpwrappers +~~~~~~~~~~~~~~~~~~ +cindex:[tcpwrappers, building Exim to support] +cindex:[USE_TCP_WRAPPERS] +Exim can be linked with the 'tcpwrappers' library in order to check incoming +SMTP calls using the 'tcpwrappers' control files. This may be a convenient +alternative to Exim's own checking facilities for installations that are +already making use of 'tcpwrappers' for other purposes. To do this, you should +set USE_TCP_WRAPPERS in _Local/Makefile_, arrange for the file +_tcpd.h_ to be available at compile time, and also ensure that the library +_libwrap.a_ is available at link time, typically by including %-lwrap% in +EXTRALIBS_EXIM. For example, if 'tcpwrappers' is installed in +_/usr/local_, you might have + + USE_TCP_WRAPPERS=yes + CFLAGS=-O -I/usr/local/include + EXTRALIBS_EXIM=-L/usr/local/lib -lwrap + +in _Local/Makefile_. The name to use in the 'tcpwrappers' control files is +``exim''. For example, the line + + exim : LOCAL 192.168.1. .friendly.domain.example + +in your _/etc/hosts.allow_ file allows connections from the local host, from +the subnet 192.168.1.0/24, and from all hosts in 'friendly.domain.example'. +All other connections are denied. Consult the 'tcpwrappers' documentation for +further details. + + + +Including support for IPv6 +~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[IPv6,including support for] +Exim contains code for use on systems that have IPv6 support. Setting +`HAVE_IPV6=YES` in _Local/Makefile_ causes the IPv6 code to be included; +it may also be necessary to set IPV6_INCLUDE and IPV6_LIBS on systems +where the IPv6 support is not fully integrated into the normal include and +library files. + +Two different types of DNS record for handling IPv6 addresses have been +defined. AAAA records (analagous to A records for IPv4) are in use, and are +currently seen as the mainstream. Another record type called A6 was proposed +as better than AAAA because it had more flexibility. However, it was felt to be +over-complex, and its status was reduced to ``experimental''. It is not known +if anyone is actually using A6 records. Exim has support for A6 records, but +this is included only if you set `SUPPORT_A6=YES` in _Local/Makefile_. The +support has not been tested for some time. + + + +The building process +~~~~~~~~~~~~~~~~~~~~ +cindex:[build directory] +Once _Local/Makefile_ (and _Local/eximon.conf_, if required) have been +created, run 'make' at the top level. It determines the architecture and +operating system types, and creates a build directory if one does not exist. +For example, on a Sun system running Solaris 8, the directory +_build-SunOS5-5.8-sparc_ is created. +cindex:[symbolic link,to source files] +Symbolic links to relevant source files are installed in the build directory. + +*Warning*: The %-j% (parallel) flag must not be used with 'make'; the +building process fails if it is set. + +If this is the first time 'make' has been run, it calls a script that builds +a make file inside the build directory, using the configuration files from the +_Local_ directory. The new make file is then passed to another instance of +'make'. This does the real work, building a number of utility scripts, and +then compiling and linking the binaries for the Exim monitor (if configured), a +number of utility programs, and finally Exim itself. The command 'make +makefile' can be used to force a rebuild of the make file in the build +directory, should this ever be necessary. + +If you have problems building Exim, check for any comments there may be in the +_README_ file concerning your operating system, and also take a look at the +FAQ, where some common problems are covered. + + + + +[[SECToverride]] +Overriding build-time options for Exim +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[build-time options, overriding] +The main make file that is created at the beginning of the building process +consists of the concatenation of a number of files which set configuration +values, followed by a fixed set of 'make' instructions. If a value is set +more than once, the last setting overrides any previous ones. This provides a +convenient way of overriding defaults. The files that are concatenated are, in +order: + +&&& +_OS/Makefile-Default_ +_OS/Makefile-_<'ostype'> +_Local/Makefile_ +_Local/Makefile-_<'ostype'> +_Local/Makefile-_<'archtype'> +_Local/Makefile-_<'ostype'>-<'archtype'> +_OS/Makefile-Base_ +&&& + +cindex:[_Local/Makefile_] +cindex:[building Exim,operating system type] +cindex:[building Exim,architecture type] +where <'ostype'> is the operating system type and <'archtype'> is the +architecture type. _Local/Makefile_ is required to exist, and the building +process fails if it is absent. The other three _Local_ files are optional, +and are often not needed. + +The values used for <'ostype'> and <'archtype'> are obtained from scripts +called _scripts/os-type_ and _scripts/arch-type_ respectively. If either of +the environment variables EXIM_OSTYPE or EXIM_ARCHTYPE is set, their +values are used, thereby providing a means of forcing particular settings. +Otherwise, the scripts try to get values from the %uname% command. If this +fails, the shell variables OSTYPE and ARCHTYPE are inspected. A number +of 'ad hoc' transformations are then applied, to produce the standard names +that Exim expects. You can run these scripts directly from the shell in order +to find out what values are being used on your system. + + +_OS/Makefile-Default_ contains comments about the variables that are set +therein. Some (but not all) are mentioned below. If there is something that +needs changing, review the contents of this file and the contents of the make +file for your operating system (_OS/Makefile-<ostype>_) to see what the +default values are. + + +cindex:[building Exim,overriding default settings] +If you need to change any of the values that are set in _OS/Makefile-Default_ +or in _OS/Makefile-<ostype>_, or to add any new definitions, you do not +need to change the original files. Instead, you should make the changes by +putting the new values in an appropriate _Local_ file. For example, +cindex:[Tru64-Unix build-time settings] +when building Exim in many releases of the Tru64-Unix (formerly Digital UNIX, +formerly DEC-OSF1) operating system, it is necessary to specify that the C +compiler is called 'cc' rather than 'gcc'. Also, the compiler must be +called with the option %-std1%, to make it recognize some of the features of +Standard C that Exim uses. (Most other compilers recognize Standard C by +default.) To do this, you should create a file called _Local/Makefile-OSF1_ +containing the lines + + CC=cc + CFLAGS=-std1 + +If you are compiling for just one operating system, it may be easier to put +these lines directly into _Local/Makefile_. + +Keeping all your local configuration settings separate from the distributed +files makes it easy to transfer them to new versions of Exim simply by copying +the contents of the _Local_ directory. + + +cindex:[NIS lookup type,including support for] +cindex:[NIS+ lookup type,including support for] +cindex:[LDAP,including support for] +cindex:[lookup,inclusion in binary] +Exim contains support for doing LDAP, NIS, NIS+, and other kinds of file +lookup, but not all systems have these components installed, so the default is +not to include the relevant code in the binary. All the different kinds of file +and database lookup that Exim supports are implemented as separate code modules +which are included only if the relevant compile-time options are set. In the +case of LDAP, NIS, and NIS+, the settings for _Local/Makefile_ are: + + LOOKUP_LDAP=yes + LOOKUP_NIS=yes + LOOKUP_NISPLUS=yes + +and similar settings apply to the other lookup types. They are all listed in +_src/EDITME_. In most cases the relevant include files and interface +libraries need to be installed before compiling Exim. +cindex:[cdb,including support for] +However, in the case of cdb, which is included in the binary only if + + LOOKUP_CDB=yes + +is set, the code is entirely contained within Exim, and no external include +files or libraries are required. When a lookup type is not included in the +binary, attempts to configure Exim to use it cause run time configuration +errors. + +cindex:[Perl,including support for] +Exim can be linked with an embedded Perl interpreter, allowing Perl +subroutines to be called during string expansion. To enable this facility, + + EXIM_PERL=perl.o + +must be defined in _Local/Makefile_. Details of this facility are given in +chapter <<CHAPperl>>. + +cindex:[X11 libraries, location of] +The location of the X11 libraries is something that varies a lot between +operating systems, and of course there are different versions of X11 to cope +with. Exim itself makes no use of X11, but if you are compiling the Exim +monitor, the X11 libraries must be available. +The following three variables are set in _OS/Makefile-Default_: + + X11=/usr/X11R6 + XINCLUDE=-I$(X11)/include + XLFLAGS=-L$(X11)/lib + +These are overridden in some of the operating-system configuration files. For +example, in _OS/Makefile-SunOS5_ there is + + X11=/usr/openwin + XINCLUDE=-I$(X11)/include + XLFLAGS=-L$(X11)/lib -R$(X11)/lib + +If you need to override the default setting for your operating system, place a +definition of all three of these variables into your +_Local/Makefile-<ostype>_ file. + +cindex:[EXTRALIBS] +If you need to add any extra libraries to the link steps, these can be put in a +variable called EXTRALIBS, which appears in all the link commands, but by +default is not defined. In contrast, EXTRALIBS_EXIM is used only on the +command for linking the main Exim binary, and not for any associated utilities. + +cindex:[DBM libraries, configuration for building] +There is also DBMLIB, which appears in the link commands for binaries that +use DBM functions (see also section <<SECTdb>>). Finally, there is +EXTRALIBS_EXIMON, which appears only in the link step for the Exim monitor +binary, and which can be used, for example, to include additional X11 +libraries. + +cindex:[configuration file,editing] +The make file copes with rebuilding Exim correctly if any of the configuration +files are edited. However, if an optional configuration file is deleted, it is +necessary to touch the associated non-optional file (that is, _Local/Makefile_ +or _Local/eximon.conf_) before rebuilding. + + +OS-specific header files +~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[_os.h_] +cindex:[building Exim,OS-specific C header files] +The _OS_ directory contains a number of files with names of the form +_os.h-<ostype>_. These are system-specific C header files that should not +normally need to be changed. There is a list of macro settings that are +recognized in the file _OS/os.configuring_, which should be consulted if you +are porting Exim to a new operating system. + + + +Overriding build-time options for the monitor +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[building Eximon,overriding default options] +A similar process is used for overriding things when building the Exim monitor, +where the files that are involved are + +&&& +_OS/eximon.conf-Default_ +_OS/eximon.conf-_<'ostype'> +_Local/eximon.conf_ +_Local/eximon.conf-_<'ostype'> +_Local/eximon.conf-_<'archtype'> +_Local/eximon.conf-_<'ostype'>-<'archtype'> +&&& + +cindex:[_Local/eximon.conf_] +As with Exim itself, the final three files need not exist, and in this case the +_OS/eximon.conf-<ostype>_ file is also optional. The default values in +_OS/eximon.conf-Default_ can be overridden dynamically by setting environment +variables of the same name, preceded by EXIMON_. For example, setting +EXIMON_LOG_DEPTH in the environment overrides the value of +LOG_DEPTH at run time. + + + + +Installing Exim binaries and scripts +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[installing Exim] +cindex:[BIN_DIRECTORY] +The command 'make install' runs the 'exim_install' script with no +arguments. The script copies binaries and utility scripts into the directory +whose name is specified by the BIN_DIRECTORY setting in +_Local/Makefile_. + +cindex:[CONFIGURE_FILE] +Exim's run time configuration file is named by the CONFIGURE_FILE setting +in _Local/Makefile_. If this names a single file, and the file does not +exist, the default configuration file _src/configure.default_ is copied there +by the installation script. If a run time configuration file already exists, it +is left alone. If CONFIGURE_FILE is a colon-separated list, naming several +alternative files, no default is installed. + +cindex:[system aliases file] +cindex:[_/etc/aliases_] +One change is made to the default configuration file when it is installed: the +default configuration contains a router that references a system aliases file. +The path to this file is set to the value specified by +SYSTEM_ALIASES_FILE in _Local/Makefile_ (_/etc/aliases_ by default). +If the system aliases file does not exist, the installation script creates it, +and outputs a comment to the user. + +The created file contains no aliases, but it does contain comments about the +aliases a site should normally have. Mail aliases have traditionally been +kept in _/etc/aliases_. However, some operating systems are now using +_/etc/mail/aliases_. You should check if yours is one of these, and change +Exim's configuration if necessary. + +The default configuration uses the local host's name as the only local domain, +and is set up to do local deliveries into the shared directory _/var/mail_, +running as the local user. System aliases and _.forward_ files in users' home +directories are supported, but no NIS or NIS+ support is configured. Domains +other than the name of the local host are routed using the DNS, with delivery +over SMTP. + +cindex:[setuid,installing Exim with] +The install script copies files only if they are newer than the files they are +going to replace. The Exim binary is required to be owned by root and have the +'setuid' bit set, for normal configurations. Therefore, you must run 'make +install' as root so that it can set up the Exim binary in this way. However, in +some special situations (for example, if a host is doing no local deliveries) +it may be possible to run Exim without making the binary setuid root (see +chapter <<CHAPsecurity>> for details). + +It is possible to install Exim for special purposes (such as building a binary +distribution) in a private part of the file system. You can do this by a +command such as + + make DESTDIR=/some/directory/ install + +This has the effect of pre-pending the specified directory to all the file +paths, except the name of the system aliases file that appears in the default +configuration. (If a default alias file is created, its name 'is' modified.) +For backwards compatibility, ROOT is used if DESTDIR is not set, +but this usage is deprecated. + +cindex:[installing Exim,what is not installed] +Running 'make install' does not copy the Exim 4 conversion script +'convert4r4', or the 'pcretest' test program. You will probably run the +first of these only once (if you are upgrading from Exim 3), and the second +isn't really part of Exim. None of the documentation files in the _doc_ +directory are copied, except for the info files when you have set +INFO_DIRECTORY, as described in section <<SECTinsinfdoc>> below. + +For the utility programs, old versions are renamed by adding the suffix _.O_ +to their names. The Exim binary itself, however, is handled differently. It is +installed under a name that includes the version number and the compile number, +for example _exim-{version}-1_. The script then arranges for a symbolic link +called _exim_ to point to the binary. If you are updating a previous version +of Exim, the script takes care to ensure that the name _exim_ is never absent +from the directory (as seen by other processes). + +cindex:[installing Exim,testing the script] +If you want to see what the 'make install' will do before running it for +real, you can pass the %-n% option to the installation script by this command: + + make INSTALL_ARG=-n install + +The contents of the variable INSTALL_ARG are passed to the installation +script. You do not need to be root to run this test. Alternatively, you can run +the installation script directly, but this must be from within the build +directory. For example, from the top-level Exim directory you could use this +command: + + (cd build-SunOS5-5.5.1-sparc; ../scripts/exim_install -n) + +cindex:[installing Exim,install script options] +There are two other options that can be supplied to the installation script. + +- %-no_chown% bypasses the call to change the owner of the installed binary +to root, and the call to make it a setuid binary. + +- %-no_symlink% bypasses the setting up of the symbolic link _exim_ to the +installed binary. + +INSTALL_ARG can be used to pass these options to the script. For example: + + make INSTALL_ARG=-no_symlink install + + +The installation script can also be given arguments specifying which files are +to be copied. For example, to install just the Exim binary, and nothing else, +without creating the symbolic link, you could use: + + make INSTALL_ARG='-no_symlink exim' install + + + + +[[SECTinsinfdoc]] +Installing info documentation +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[installing Exim,'info' documentation] +Not all systems use the GNU 'info' system for documentation, and for this +reason, the Texinfo source of Exim's documentation is not included in the main +distribution. Instead it is available separately from the ftp site (see section +<<SECTavail>>). + +If you have defined INFO_DIRECTORY in _Local/Makefile_ and the Texinfo +source of the documentation is found in the source tree, running 'make +install' automatically builds the info files and installs them. + + + +Setting up the spool directory +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[spool directory,creating] +When it starts up, Exim tries to create its spool directory if it does not +exist. The Exim uid and gid are used for the owner and group of the spool +directory. Sub-directories are automatically created in the spool directory as +necessary. + + + + +Testing +~~~~~~~ +cindex:[testing,installation] +Having installed Exim, you can check that the run time configuration file is +syntactically valid by running the following command, which assumes that the +Exim binary directory is within your PATH environment variable: + + exim -bV + +If there are any errors in the configuration file, Exim outputs error messages. +Otherwise it outputs the version number and build date, +the DBM library that is being used, and information about which drivers and +other optional code modules are included in the binary. +Some simple routing tests can be done by using the address testing option. For +example, + + exim -bt <local username> + +should verify that it recognizes a local mailbox, and + + exim -bt <remote address> + +a remote one. Then try getting it to deliver mail, both locally and remotely. +This can be done by passing messages directly to Exim, without going through a +user agent. For example: + + exim -v postmaster@your.domain.example + From: user@your.domain.example + To: postmaster@your.domain.example + Subject: Testing Exim + + This is a test message. + ^D + +The %-v% option causes Exim to output some verification of what it is doing. +In this case you should see copies of three log lines, one for the message's +arrival, one for its delivery, and one containing ``Completed''. + +cindex:[delivery,problems with] +If you encounter problems, look at Exim's log files ('mainlog' and +'paniclog') to see if there is any relevant information there. Another source +of information is running Exim with debugging turned on, by specifying the +%-d% option. If a message is stuck on Exim's spool, you can force a delivery +with debugging turned on by a command of the form + + exim -d -M <message-id> + +You must be root or an ``admin user'' in order to do this. The %-d% option +produces rather a lot of output, but you can cut this down to specific areas. +For example, if you use %-d-all+route% only the debugging information relevant +to routing is included. (See the %-d% option in chapter <<CHAPcommandline>> for +more details.) + +cindex:[``sticky'' bit] +cindex:[lock files] +One specific problem that has shown up on some sites is the inability to do +local deliveries into a shared mailbox directory, because it does not have the +``sticky bit'' set on it. By default, Exim tries to create a lock file before +writing to a mailbox file, and if it cannot create the lock file, the delivery +is deferred. You can get round this either by setting the ``sticky bit'' on the +directory, or by setting a specific group for local deliveries and allowing +that group to create files in the directory (see the comments above the +^local_delivery^ transport in the default configuration file). Another +approach is to configure Exim not to use lock files, but just to rely on +'fcntl()' locking instead. However, you should do this only if all user +agents also use 'fcntl()' locking. For further discussion of locking issues, +see chapter <<CHAPappendfile>>. + +One thing that cannot be tested on a system that is already running an MTA is +the receipt of incoming SMTP mail on the standard SMTP port. However, the +%-oX% option can be used to run an Exim daemon that listens on some other +port, or 'inetd' can be used to do this. The %-bh% option and the +'exim_checkaccess' utility can be used to check out policy controls on +incoming SMTP mail. + +Testing a new version on a system that is already running Exim can most easily +be done by building a binary with a different CONFIGURE_FILE setting. From +within the run time configuration, all other file and directory names +that Exim uses can be altered, in order to keep it entirely clear of the +production version. + + +Replacing another MTA with Exim +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[replacing another MTA] +Building and installing Exim for the first time does not of itself put it in +general use. The name by which the system's MTA is called by mail user agents +is either _/usr/sbin/sendmail_, or _/usr/lib/sendmail_ (depending on the +operating system), and it is necessary to make this name point to the 'exim' +binary in order to get the user agents to pass messages to Exim. This is +normally done by renaming any existing file and making _/usr/sbin/sendmail_ +or _/usr/lib/sendmail_ + +cindex:[symbolic link,to 'exim' binary] +a symbolic link to the 'exim' binary. It is a good idea to remove any setuid +privilege and executable status from the old MTA. It is then necessary to stop +and restart the mailer daemon, if one is running. + +cindex:[FreeBSD, MTA indirection] +cindex:[_/etc/mail/mailer.conf_] +Some operating systems have introduced alternative ways of switching MTAs. For +example, if you are running FreeBSD, you need to edit the file +_/etc/mail/mailer.conf_ instead of setting up a symbolic link as just +described. A typical example of the contents of this file for running Exim is +as follows: + + sendmail /usr/exim/bin/exim + send-mail /usr/exim/bin/exim + mailq /usr/exim/bin/exim -bp + newaliases /usr/bin/true + + +Once you have set up the symbolic link, or edited _/etc/mail/mailer.conf_, +your Exim installation is ``live''. Check it by sending a message from your +favourite user agent. + +You should consider what to tell your users about the change of MTA. Exim may +have different capabilities to what was previously running, and there are +various operational differences such as the text of messages produced by +command line options and in bounce messages. If you allow your users to make +use of Exim's filtering capabilities, you should make the document entitled +'Exim's interface to mail filtering' +available to them. + + + +Upgrading Exim +~~~~~~~~~~~~~~ +cindex:[upgrading Exim] +If you are already running Exim on your host, building and installing a new +version automatically makes it available to MUAs, or any other programs that +call the MTA directly. However, if you are running an Exim daemon, you do need +to send it a HUP signal, to make it re-exec itself, and thereby pick up the new +binary. You do not need to stop processing mail in order to install a new +version of Exim. + + + +Stopping the Exim daemon on Solaris +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[Solaris,stopping Exim on] +The standard command for stopping the mailer daemon on Solaris is + + /etc/init.d/sendmail stop + +If _/usr/lib/sendmail_ has been turned into a symbolic link, this script +fails to stop Exim because it uses the command 'ps -e' and greps the output +for the text ``sendmail''; this is not present because the actual program name +(that is, ``exim'') is given by the 'ps' command with these options. A solution +is to replace the line that finds the process id with something like + + pid=`cat /var/spool/exim/exim-daemon.pid` + +to obtain the daemon's pid directly from the file that Exim saves it in. + +Note, however, that stopping the daemon does not ``stop Exim''. Messages can +still be received from local processes, and if automatic delivery is configured +(the normal case), deliveries will still occur. + + + + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// + +[[CHAPcommandline]] +The Exim command line +--------------------- +cindex:[command line,options] +cindex:[options,command line] +Exim's command line takes the standard Unix form of a sequence of options, +each starting with a hyphen character, followed by a number of arguments. The +options are compatible with the main options of Sendmail, and there are also +some additional options, some of which are compatible with Smail 3. Certain +combinations of options do not make sense, and provoke an error if used. +The form of the arguments depends on which options are set. + + +Setting options by program name +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:['mailq'] +If Exim is called under the name 'mailq', it behaves as if the option %-bp% +were present before any other options. +The %-bp% option requests a listing of the contents of the mail queue on the +standard output. +This feature is for compatibility with some systems that contain a command of +that name in one of the standard libraries, symbolically linked to +_/usr/sbin/sendmail_ or _/usr/lib/sendmail_. + +cindex:['rsmtp'] +If Exim is called under the name 'rsmtp' it behaves as if the option %-bS% +were present before any other options, for compatibility with Smail. The %-bS% +option is used for reading in a number of messages in batched SMTP format. + +cindex:['rmail'] +If Exim is called under the name 'rmail' it behaves as if the %-i% and +%-oee% options were present before any other options, for compatibility with +Smail. The name 'rmail' is used as an interface by some UUCP systems. + +cindex:['runq'] +cindex:[queue runner] +If Exim is called under the name 'runq' it behaves as if the option %-q% were +present before any other options, for compatibility with Smail. The %-q% +option causes a single queue runner process to be started. + +cindex:['newaliases'] +cindex:[alias file,building] +cindex:[Sendmail compatibility,calling Exim as 'newaliases'] +If Exim is called under the name 'newaliases' it behaves as if the option +%-bi% were present before any other options, for compatibility with Sendmail. +This option is used for rebuilding Sendmail's alias file. Exim does not have +the concept of a single alias file, but can be configured to run a given +command if called with the %-bi% option. + + +[[SECTtrustedadmin]] +Trusted and admin users +~~~~~~~~~~~~~~~~~~~~~~~ +Some Exim options are available only to 'trusted users' and others are +available only to 'admin users'. In the description below, the phrases ``Exim +user'' and ``Exim group'' mean the user and group defined by EXIM_USER and +EXIM_GROUP in _Local/Makefile_ or set by the %exim_user% and +%exim_group% options. These do not necessarily have to use the name ``exim''. + +- cindex:[trusted user,definition of] +cindex:[user, trusted definition of] +The trusted users are root, the Exim user, any user listed in the +%trusted_users% configuration option, and any user whose current group or any +supplementary group is one of those listed in the %trusted_groups% +configuration option. Note that the Exim group is not automatically trusted. ++ +cindex:[``From'' line] +cindex:[envelope sender] +Trusted users are always permitted to use the %-f% option or a leading ``From '' +line to specify the envelope sender of a message that is passed to Exim through +the local interface (see the %-bm% and %-f% options below). See the +%untrusted_set_sender% option for a way of permitting non-trusted users to +set envelope senders. ++ +cindex:['From:' header line] +cindex:['Sender:' header line] +For a trusted user, there is never any check on the contents of the 'From:' +header line, and a 'Sender:' line is never added. Furthermore, any existing +'Sender:' line in incoming local (non-TCP/IP) messages is not removed. ++ +Trusted users may also specify a host name, host address, interface address, +protocol name, ident value, and authentication data when submitting a message +locally. Thus, they are able to insert messages into Exim's queue locally that +have the characteristics of messages received from a remote host. Untrusted +users may in some circumstances use %-f%, but can never set the other values +that are available to trusted users. + +- cindex:[user, admin definition of] +cindex:[admin user,definition of] +The admin users are root, the Exim user, and any user that is a member of the +Exim group or of any group listed in the %admin_groups% configuration option. +The current group does not have to be one of these groups. ++ +Admin users are permitted to list the queue, and to carry out certain +operations on messages, for example, to force delivery failures. It is also +necessary to be an admin user in order to see the full information provided by +the Exim monitor, and full debugging output. ++ +By default, the use of the %-M%, %-q%, %-R%, and %-S% options to cause Exim +to attempt delivery of messages on its queue is restricted to admin users. +However, this restriction can be relaxed by setting the %prod_requires_admin% +option false (that is, specifying %no_prod_requires_admin%). ++ +Similarly, the use of the %-bp% option to list all the messages in the queue +is restricted to admin users unless %queue_list_requires_admin% is set +false. + + +*Warning*: If you configure your system so that admin users are able to +edit Exim's configuration file, you are giving those users an easy way of +getting root. There is further discussion of this issue at the start of chapter +<<CHAPconf>>. + + + + +Command line options +~~~~~~~~~~~~~~~~~~~~ +The command options are described in alphabetical order below. + +/// +We insert a stylized DocBook comment here, to identify the start of the command +line options. This is for the benefit of the Perl script that automatically +creates a man page for the options. +/// + +++++ +<!-- === Start of command line options === --> +++++ + + +*{hh}*:: +oindex:[{hh}] +cindex:[options, command line; terminating] +This is a pseudo-option whose only purpose is to terminate the options and +therefore to cause subsequent command line items to be treated as arguments +rather than options, even if they begin with hyphens. + +*--help*:: +oindex:[%{hh}help%] +This option causes Exim to output a few sentences stating what it is. +The same output is generated if the Exim binary is called with no options and +no arguments. + +*-B*<'type'>:: +oindex:[%-B%] +cindex:[8-bit characters] +cindex:[Sendmail compatibility,8-bit characters] +This is a Sendmail option for selecting 7 or 8 bit processing. Exim is 8-bit +clean; it ignores this option. + +*-bd*:: +oindex:[%-bd%] +cindex:[daemon] +cindex:[SMTP listener] +cindex:[queue runner] +This option runs Exim as a daemon, awaiting incoming SMTP connections. Usually +the %-bd% option is combined with the %-q%<'time'> option, to specify that +the daemon should also initiate periodic queue runs. ++ +The %-bd% option can be used only by an admin user. If either of the %-d% +(debugging) or %-v% (verifying) options are set, the daemon does not +disconnect from the controlling terminal. When running this way, it can be +stopped by pressing ctrl-C. ++ +By default, Exim listens for incoming connections to the standard SMTP port on +all the host's running interfaces. However, it is possible to listen on other +ports, on multiple ports, and only on specific interfaces. Chapter +<<CHAPinterfaces>> contains a description of the options that control this. ++ +When a listening daemon +cindex:[daemon,process id (pid)] +cindex:[pid (process id),of daemon] +is started without the use of %-oX% (that is, without overriding the normal +configuration), it writes its process id to a file called _exim-daemon.pid_ in +Exim's spool directory. This location can be overridden by setting +PID_FILE_PATH in _Local/Makefile_. The file is written while Exim is still +running as root. ++ +When %-oX% is used on the command line to start a listening daemon, the +process id is not written to the normal pid file path. However, %-oP% can be +used to specify a path on the command line if a pid file is required. ++ +The SIGHUP signal +cindex:[SIGHUP] +can be used to cause the daemon to re-exec itself. This should be done whenever +Exim's configuration file, or any file that is incorporated into it by means of +the %.include% facility, is changed, and also whenever a new version of Exim is +installed. It is not necessary to do this when other files that are referenced +from the configuration (for example, alias files) are changed, because these +are reread each time they are used. + +*-bdf*:: +oindex:[%-bdf%] +This option has the same effect as %-bd% except that it never disconnects from +the controlling terminal, even when no debugging is specified. + +*-be*:: +oindex:[%-be%] +cindex:[testing,string expansion] +cindex:[expansion,testing] +Run Exim in expansion testing mode. Exim discards its root privilege, to +prevent ordinary users from using this mode to read otherwise inaccessible +files. If no arguments are given, Exim runs interactively, prompting for lines +of data. ++ +If Exim was built with USE_READLINE=yes in _Local/Makefile_, it tries +to load the %libreadline% library dynamically whenever the %-be% option is +used without command line arguments. If successful, it uses the 'readline()' +function, which provides extensive line-editing facilities, for reading the +test data. A line history is supported. ++ +Long expansion expressions can be split over several lines by using backslash +continuations. As in Exim's run time configuration, whitespace at the start of +continuation lines is ignored. Each argument or data line is passed through the +string expansion mechanism, and the result is output. Variable values from the +configuration file (for example, $qualify_domain$) are available, but no +message-specific values (such as $domain$) are set, because no message is +being processed. + +*-bF*~<'filename'>:: +oindex:[%-bF%] +cindex:[system filter,testing] +cindex:[testing,system filter] +This option is the same as %-bf% except that it assumes that the filter being +tested is a system filter. The additional commands that are available only in +system filters are recognized. + +*-bf*~<'filename'>:: +oindex:[%-bf%] +cindex:[filter,testing] +cindex:[testing,filter file] +cindex:[forward file,testing] +cindex:[testing,forward file] +cindex:[Sieve filter,testing] +This option runs Exim in user filter testing mode; the file is the filter file +to be tested, and a test message must be supplied on the standard input. If +there are no message-dependent tests in the filter, an empty file can be +supplied. ++ +If you want to test a system filter file, use %-bF% instead of %-bf%. You can +use both %-bF% and %-bf% on the same command, in order to +test a system filter and a user filter in the same run. For example: + + exim -bF /system/filter -bf /user/filter </test/message ++ +This is helpful when the system filter adds header lines or sets filter +variables that are used by the user filter. ++ +If the test filter file does not begin with one of the special lines + + # Exim filter + # Sieve filter ++ +it is taken to be a normal _.forward_ file, and is tested for validity under +that interpretation. See sections <<SECTitenonfilred>> to <<SECTspecitredli>> for a +description of the possible contents of non-filter redirection lists. ++ +The result of an Exim command that uses %-bf%, provided no errors are +detected, is a list of the actions that Exim would try to take if presented +with the message for real. More details of filter testing are given in the +separate document entitled 'Exim's interfaces to mail filtering'. ++ +When testing a filter file, +cindex:[``From'' line] +cindex:[envelope sender] +cindex:[%-f% option,for filter testing] +the envelope sender can be set by the %-f% option, +or by a ``From '' line at the start of the test message. Various parameters that +would normally be taken from the envelope recipient address of the message can +be set by means of additional command line options (see the next four options). + +*-bfd*~<'domain'>:: +oindex:[%-bfd%] +This sets the domain of the recipient address when a filter file is being +tested by means of the %-bf% option. The default is the value of +$qualify_domain$. + +*-bfl*~<'local~part'>:: +oindex:[%-bfl%] +This sets the local part of the recipient address when a filter file is being +tested by means of the %-bf% option. The default is the username of the +process that calls Exim. A local part should be specified with any prefix or +suffix stripped, because that is how it appears to the filter when a message is +actually being delivered. + +*-bfp*~<'prefix'>:: +oindex:[%-bfp%] +This sets the prefix of the local part of the recipient address when a filter +file is being tested by means of the %-bf% option. The default is an empty +prefix. + +*-bfs*~<'suffix'>:: +oindex:[%-bfs%] +This sets the suffix of the local part of the recipient address when a filter +file is being tested by means of the %-bf% option. The default is an empty +suffix. + +*-bh*~<'IP~address'>:: +oindex:[%-bh%] +cindex:[testing,incoming SMTP] +cindex:[SMTP,testing incoming] +cindex:[testing,relay control] +cindex:[relaying,testing configuration] +cindex:[policy control,testing] +cindex:[debugging,%-bh% option] +This option runs a fake SMTP session as if from the given IP address, using the +standard input and output. The IP address may include a port number at the end, +after a full stop. For example: + + exim -bh 10.9.8.7.1234 + exim -bh fe80::a00:20ff:fe86:a061.5678 ++ +When an IPv6 address is given, it is converted into canonical form. In the case +of the second example above, the value of $sender_host_address$ after +conversion to the canonical form is `fe80:0000:0000:0a00:20ff:fe86:a061.5678`. ++ +Comments as to what is going on are written to the standard error file. These +include lines beginning with ``LOG'' for anything that would have been logged. +This facility is provided for testing configuration options for incoming +messages, to make sure they implement the required policy. For example, you can +test your relay controls using %-bh%. ++ +*Warning 1*: +cindex:[RFC 1413] +You cannot test features of the configuration that rely on +ident (RFC 1413) callouts. These cannot be done when testing using +%-bh% because there is no incoming SMTP connection. ++ +*Warning 2*: Address verification callouts (see section <<SECTcallver>>) are +also skipped when testing using %-bh%. If you want these callouts to occur, +use %-bhc% instead. ++ +Messages supplied during the testing session are discarded, and nothing is +written to any of the real log files. There may be pauses when DNS (and other) +lookups are taking place, and of course these may time out. The %-oMi% option +can be used to specify a specific IP interface and port if this is important. ++ +The 'exim_checkaccess' utility is a ``packaged'' version of %-bh% whose +output just states whether a given recipient address from a given host is +acceptable or not. See section <<SECTcheckaccess>>. + +*-bhc*~<'IP~address'>:: +oindex:[%-bhc%] +This option operates in the same way as %-bh%, except that address +verification callouts are performed if required. This includes consulting and +updating the callout cache database. + +*-bi*:: +oindex:[%-bi%] +cindex:[alias file,building] +cindex:[building alias file] +cindex:[Sendmail compatibility,%-bi% option] +Sendmail interprets the %-bi% option as a request to rebuild its alias file. +Exim does not have the concept of a single alias file, and so it cannot mimic +this behaviour. However, calls to _/usr/lib/sendmail_ with the %-bi% option +tend to appear in various scripts such as NIS make files, so the option must be +recognized. ++ +If %-bi% is encountered, the command specified by the %bi_command% +configuration option is run, under the uid and gid of the caller of Exim. If +the %-oA% option is used, its value is passed to the command as an argument. +The command set by %bi_command% may not contain arguments. The command can use +the 'exim_dbmbuild' utility, or some other means, to rebuild alias files if +this is required. If the %bi_command% option is not set, calling Exim with +%-bi% is a no-op. + +*-bm*:: +oindex:[%-bm%] +cindex:[local message reception] +This option runs an Exim receiving process that accepts an incoming, +locally-generated message on the current input. The recipients are given as the +command arguments (except when %-t% is also present -- see below). Each +argument can be a comma-separated list of RFC 2822 addresses. This is the +default option for selecting the overall action of an Exim call; it is assumed +if no other conflicting option is present. ++ +If any addresses in the message are unqualified (have no domain), they are +qualified by the values of the %qualify_domain% or %qualify_recipient% +options, as appropriate. The %-bnq% option (see below) provides a way of +suppressing this for special cases. ++ +Policy checks on the contents of local messages can be enforced by means of +the non-SMTP ACL. See chapter <<CHAPACL>> for details. ++ +The return code +cindex:[return code,for %-bm%] +is zero if the message is successfully accepted. Otherwise, the +action is controlled by the %-oe'x'% option setting -- see below. ++ +The format +cindex:[message,format] +cindex:[format,message] +cindex:[``From'' line] +cindex:[UUCP,``From'' line] +cindex:[Sendmail compatibility,``From'' line] +of the message must be as defined in RFC 2822, except that, for +compatibility with Sendmail and Smail, a line in one of the forms + + From sender Fri Jan 5 12:55 GMT 1997 + From sender Fri, 5 Jan 97 12:55:01 ++ +(with the weekday optional, and possibly with additional text after the date) +is permitted to appear at the start of the message. There appears to be no +authoritative specification of the format of this line. Exim recognizes it by +matching against the regular expression defined by the %uucp_from_pattern% +option, which can be changed if necessary. ++ +The +cindex:[%-f% option,overriding ``From'' line] +specified sender is treated as if it were given as the argument to the +%-f% option, but if a %-f% option is also present, its argument is used in +preference to the address taken from the message. The caller of Exim must be a +trusted user for the sender of a message to be set in this way. + +*-bnq*:: +oindex:[%-bnq%] +cindex:[address qualification, suppressing] +By default, Exim automatically qualifies unqualified addresses (those +without domains) that appear in messages that are submitted locally (that +is, not over TCP/IP). This qualification applies both to addresses in +envelopes, and addresses in header lines. Sender addresses are qualified using +%qualify_domain%, and recipient addresses using %qualify_recipient% (which +defaults to the value of %qualify_domain%). ++ +Sometimes, qualification is not wanted. For example, if %-bS% (batch SMTP) is +being used to re-submit messages that originally came from remote hosts after +content scanning, you probably do not want to qualify unqualified addresses in +header lines. (Such lines will be present only if you have not enabled a header +syntax check in the appropriate ACL.) ++ +The %-bnq% option suppresses all qualification of unqualified addresses in +messages that originate on the local host. When this is used, unqualified +addresses in the envelope provoke errors (causing message rejection) and +unqualified addresses in header lines are left alone. + + +*-bP*:: +oindex:[%-bP%] +cindex:[configuration options, extracting] +cindex:[options,configuration -- extracting] +If this option is given with no arguments, it causes the values of all Exim's +main configuration options to be written to the standard output. The values +of one or more specific options can be requested by giving their names as +arguments, for example: + + exim -bP qualify_domain hold_domains ++ +However, any option setting that is preceded by the word ``hide'' in the +configuration file is not shown in full, except to an admin user. For other +users, the output is as in this example: + + mysql_servers = <value not displayable> ++ +If %configure_file% is given as an argument, the name of the run time +configuration file is output. +If a list of configuration files was supplied, the value that is output here +is the name of the file that was actually used. ++ +cindex:[daemon,process id (pid)] +cindex:[pid (process id),of daemon] +If %log_file_path% or %pid_file_path% are given, the names of the directories +where log files and daemon pid files are written are output, respectively. If +these values are unset, log files are written in a sub-directory of the spool +directory called %log%, and the pid file is written directly into the spool +directory. ++ +If %-bP% is followed by a name preceded by `+`, for example, + + exim -bP +local_domains ++ +it searches for a matching named list of any type (domain, host, address, or +local part) and outputs what it finds. ++ +If +cindex:[options,router -- extracting] +cindex:[options,transport -- extracting] +one of the words %router%, %transport%, or %authenticator% is given, +followed by the name of an appropriate driver instance, the option settings for +that driver are output. For example: + + exim -bP transport local_delivery ++ +The generic driver options are output first, followed by the driver's private +options. A list of the names of drivers of a particular type can be obtained by +using one of the words %router_list%, %transport_list%, or +%authenticator_list%, and a complete list of all drivers with their option +settings can be obtained by using %routers%, %transports%, or %authenticators%. + + +*-bp*:: +oindex:[%-bp%] +cindex:[queue,listing messages on] +cindex:[listing,messages on the queue] +This option requests a listing of the contents of the mail queue on the +standard output. If the %-bp% option is followed by a list of message ids, +just those messages are listed. By default, this option can be used only by an +admin user. However, the %queue_list_requires_admin% option can be set false +to allow any user to see the queue. ++ +Each message on the queue is displayed as in the following example: + + 25m 2.9K 0t5C6f-0000c8-00 <alice@wonderland.fict.example> + red.king@looking-glass.fict.example + <other addresses> ++ +The +cindex:[message,size in queue listing] +cindex:[size,of message] +first line contains the length of time the message has been on the queue +(in this case 25 minutes), the size of the message (2.9K), the unique local +identifier for the message, and the message sender, as contained in the +envelope. For bounce messages, the sender address is empty, and appears as +``<>''. If the message was submitted locally by an untrusted user who overrode +the default sender address, the user's login name is shown in parentheses +before the sender address. ++ +If +cindex:[frozen messages,in queue listing] +the message is frozen (attempts to deliver it are suspended) then the text +``\*\*\* frozen \*\*\*'' is displayed at the end of this line. ++ +The recipients of the message (taken from the envelope, not the headers) are +displayed on subsequent lines. Those addresses to which the message has already +been delivered are marked with the letter D. If an original address gets +expanded into several addresses via an alias or forward file, the original is +displayed with a D only when deliveries for all of its child addresses are +complete. + + +*-bpa*:: +oindex:[%-bpa%] +This option operates like %-bp%, but in addition it shows delivered addresses +that were generated from the original top level address(es) in each message by +alias or forwarding operations. These addresses are flagged with ``+D'' instead +of just ``D''. + + +*-bpc*:: +oindex:[%-bpc%] +cindex:[queue,count of messages on] +This option counts the number of messages on the queue, and writes the total +to the standard output. It is restricted to admin users, unless +%queue_list_requires_admin% is set false. + + +*-bpr*:: +oindex:[%-bpr%] +This option operates like %-bp%, but the output is not sorted into +chronological order of message arrival. This can speed it up when there are +lots of messages on the queue, and is particularly useful if the output is +going to be post-processed in a way that doesn't need the sorting. + +*-bpra*:: +oindex:[%-bpra%] +This option is a combination of %-bpr% and %-bpa%. + +*-bpru*:: +oindex:[%-bpru%] +This option is a combination of %-bpr% and %-bpu%. + + +*-bpu*:: +oindex:[%-bpu%] +This option operates like %-bp% but shows only undelivered top-level addresses +for each message displayed. Addresses generated by aliasing or forwarding are +not shown, unless the message was deferred after processing by a router with +the %one_time% option set. + + +*-brt*:: +oindex:[%-brt%] +cindex:[testing,retry configuration] +cindex:[retry,configuration testing] +This option is for testing retry rules, and it must be followed by up to three +arguments. It causes Exim to look for a retry rule that matches the values +and to write it to the standard output. For example: + + exim -brt bach.comp.mus.example + Retry rule: *.comp.mus.example F,2h,15m; F,4d,30m; ++ +See chapter <<CHAPretry>> for a description of Exim's retry rules. The first +argument, which is required, can be a complete address in the form +'local_part@domain', or it can be just a domain name. The second argument is +an optional second domain name; if no retry rule is found for the first +argument, the second is tried. This ties in with Exim's behaviour when looking +for retry rules for remote hosts -- if no rule is found that matches the host, +one that matches the mail domain is sought. The final argument is the name of a +specific delivery error, as used in setting up retry rules, for example +``quota_3d''. + +*-brw*:: +oindex:[%-brw%] +cindex:[testing,rewriting] +cindex:[rewriting,testing] +This option is for testing address rewriting rules, and it must be followed by +a single argument, consisting of either a local part without a domain, or a +complete address with a fully qualified domain. Exim outputs how this address +would be rewritten for each possible place it might appear. See chapter +<<CHAPrewrite>> for further details. + +*-bS*:: +oindex:[%-bS%] +cindex:[SMTP,batched incoming] +cindex:[batched SMTP input] +This option is used for batched SMTP input, which is an alternative interface +for non-interactive local message submission. A number of messages can be +submitted in a single run. However, despite its name, this is not really SMTP +input. Exim reads each message's envelope from SMTP commands on the standard +input, but generates no responses. If the caller is trusted, or +%untrusted_set_sender% is set, the senders in the SMTP MAIL commands are +believed; otherwise the sender is always the caller of Exim. ++ +The message itself is read from the standard input, in SMTP format (leading +dots doubled), terminated by a line containing just a single dot. An error is +provoked if the terminating dot is missing. A further message may then follow. ++ +As for other local message submissions, the contents of incoming batch SMTP +messages can be checked using the non-SMTP ACL (see chapter <<CHAPACL>>). +Unqualified addresses are automatically qualified using %qualify_domain% and +%qualify_recipient%, as appropriate, unless the %-bnq% option is used. ++ +Some other SMTP commands are recognized in the input. HELO and EHLO act +as RSET; VRFY, EXPN, ETRN, and HELP act as NOOP; +QUIT quits, ignoring the rest of the standard input. ++ +cindex:[return code,for %-bS%] +If any error is encountered, reports are written to the standard output and +error streams, and Exim gives up immediately. The return code is 0 if no error +was detected; it is 1 if one or more messages were accepted before the error +was detected; otherwise it is 2. ++ +More details of input using batched SMTP are given in section +<<SECTincomingbatchedSMTP>>. + +*-bs*:: +oindex:[%-bs%] +cindex:[SMTP,local input] +cindex:[local SMTP input] +This option causes Exim to accept one or more messages by reading SMTP commands +on the standard input, and producing SMTP replies on the standard output. SMTP +policy controls, as defined in ACLs (see chapter <<CHAPACL>>) are applied. +Some user agents use this interface as a way of passing locally-generated +messages to the MTA. ++ +In +cindex:[sender,source of] +this usage, if the caller of Exim is trusted, or %untrusted_set_sender% is +set, the senders of messages are taken from the SMTP MAIL commands. +Otherwise the content of these commands is ignored and the sender is set up as +the calling user. Unqualified addresses are automatically qualified using +%qualify_domain% and %qualify_recipient%, as appropriate, unless the %-bnq% +option is used. ++ +cindex:[inetd] +The +%-bs% option is also used to run Exim from 'inetd', as an alternative to using +a listening daemon. Exim can distinguish the two cases by checking whether the +standard input is a TCP/IP socket. When Exim is called from 'inetd', the source +of the mail is assumed to be remote, and the comments above concerning senders +and qualification do not apply. In this situation, Exim behaves in exactly the +same way as it does when receiving a message via the listening daemon. + +*-bt*:: +oindex:[%-bt%] +cindex:[testing,addresses] +cindex:[address,testing] +This option runs Exim in address testing mode, in which each argument is taken +as an address to be tested for deliverability. The results are written to the +standard output. If a test fails, and the caller is not an admin user, no +details of the failure are output, because these might contain sensitive +information such as usernames and passwords for database lookups. ++ +If no arguments are given, Exim runs in an interactive manner, prompting with a +right angle bracket for addresses to be tested. ++ +Unlike the %-be% test option, you cannot arrange for Exim to use the +'readline()' function, because it is running as 'root' and there are +security issues. ++ +Each address is handled as if it were the recipient address of a message +(compare the %-bv% option). It is passed to the routers and the result is +written to the standard output. However, any router that has +%no_address_test% set is bypassed. This can make %-bt% easier to use for +genuine routing tests if your first router passes everything to a scanner +program. ++ +The +cindex:[return code,for %-bt%] +return code is 2 if any address failed outright; it is 1 if no address +failed outright but at least one could not be resolved for some reason. Return +code 0 is given only when all addresses succeed. ++ +*Warning*: %-bt% can only do relatively simple testing. If any of the +routers in the configuration makes any tests on the sender address of a +message, +cindex:[%-f% option,for address testing] +you can use the %-f% option to set an appropriate sender when running +%-bt% tests. Without it, the sender is assumed to be the calling user at the +default qualifying domain. However, if you have set up (for example) routers +whose behaviour depends on the contents of an incoming message, you cannot test +those conditions using %-bt%. The %-N% option provides a possible way of +doing such tests. + +*-bV*:: +oindex:[%-bV%] +cindex:[version number of Exim, verifying] +This option causes Exim to write the current version number, compilation +number, and compilation date of the 'exim' binary to the standard output. +It also lists the DBM library this is being used, the optional modules (such as +specific lookup types), the drivers that are included in the binary, and the +name of the run time configuration file that is in use. ++ +As part of its operation, %-bV% causes Exim to read and syntax check its +configuration file. However, this is a static check only. It cannot check +values that are to be expanded. For example, although a misspelt ACL verb is +detected, an error in the verb's arguments is not. You cannot rely on %-bV% +alone to discover (for example) all the typos in the configuration; some +realistic testing is needed. The %-bh% and %-N% options provide more dynamic +testing facilities. + +*-bv*:: +oindex:[%-bv%] +cindex:[verifying address, using %-bv%] +cindex:[address,verification] +This option runs Exim in address verification mode, in which each argument is +taken as an address to be verified. During normal operation, verification +happens mostly as a consequence processing a %verify% condition in an ACL (see +chapter <<CHAPACL>>). If you want to test an entire ACL, see the %-bh% option. ++ +If verification fails, and the caller is not an admin user, no details of the +failure are output, because these might contain sensitive information such as +usernames and passwords for database lookups. ++ +If no arguments are given, Exim runs in an interactive manner, prompting with a +right angle bracket for addresses to be verified. ++ +Unlike the %-be% test option, you cannot arrange for Exim to use the +'readline()' function, because it is running as 'exim' and there are +security issues. ++ +Verification differs from address testing (the %-bt% option) in that routers +that have %no_verify% set are skipped, and if the address is accepted by a +router that has %fail_verify% set, verification fails. The address is verified +as a recipient if %-bv% is used; to test verification for a sender address, +%-bvs% should be used. ++ +If the %-v% option is not set, the output consists of a single line for each +address, stating whether it was verified or not, and giving a reason in the +latter case. Otherwise, more details are given of how the address has been +handled, and in the case of address redirection, all the generated addresses +are also considered. Without %-v%, generating more than one address by +redirection causes verification to end sucessfully. ++ +The +cindex:[return code,for %-bv%] +return code is 2 if any address failed outright; it is 1 if no address +failed outright but at least one could not be resolved for some reason. Return +code 0 is given only when all addresses succeed. ++ +If any of the routers in the configuration makes any tests on the sender +address of a message, you should use the %-f% option to set an appropriate +sender when running %-bv% tests. Without it, the sender is assumed to be the +calling user at the default qualifying domain. + +*-bvs*:: +oindex:[%-bvs%] +This option acts like %-bv%, but verifies the address as a sender rather +than a recipient address. This affects any rewriting and qualification that +might happen. + +*-C*~<'filelist'>:: +oindex:[%-C%] +cindex:[configuration file,alternate] +cindex:[CONFIGURE_FILE] +cindex:[alternate configuration file] +This option causes Exim to find the run time configuration file from the given +list instead of from the list specified by the CONFIGURE_FILE +compile-time setting. Usually, the list will consist of just a single file +name, but it can be a colon-separated list of names. In this case, the first +file that exists is used. Failure to open an existing file stops Exim from +proceeding any further along the list, and an error is generated. ++ +When this option is used by a caller other than root or the Exim user, and the +list is different from the compiled-in list, Exim gives up its root privilege +immediately, and runs with the real and effective uid and gid set to those of +the caller. However, if ALT_CONFIG_ROOT_ONLY is defined in +_Local/Makefile_, root privilege is retained for %-C% only if the caller of +Exim is root. ++ +That is, the Exim user is no longer privileged in this regard. This build-time +option is not set by default in the Exim source distribution tarbundle. +However, if you are using a ``packaged'' version of Exim (source or binary), the +packagers might have enabled it. ++ +Setting ALT_CONFIG_ROOT_ONLY locks out the possibility of testing a +configuration using %-C% right through message reception and delivery, even if +the caller is root. The reception works, but by that time, Exim is running as +the Exim user, so when it re-execs to regain privilege for the delivery, the +use of %-C% causes privilege to be lost. However, root can test reception and +delivery using two separate commands (one to put a message on the queue, using +%-odq%, and another to do the delivery, using %-M%). ++ +If ALT_CONFIG_PREFIX is defined _in Local/Makefile_, it specifies a +prefix string with which any file named in a %-C% command line option +must start. In addition, the file name must not contain the sequence `/../`. +However, if the value of the %-C% option is identical to the value of +CONFIGURE_FILE in _Local/Makefile_, Exim ignores %-C% and proceeds as +usual. There is no default setting for ALT_CONFIG_PREFIX; when it is +unset, any file name can be used with %-C%. ++ +ALT_CONFIG_PREFIX can be used to confine alternative configuration files +to a directory to which only root has access. This prevents someone who has +broken into the Exim account from running a privileged Exim with an arbitrary +configuration file. ++ +The %-C% facility is useful for ensuring that configuration files are +syntactically correct, but cannot be used for test deliveries, unless the +caller is privileged, or unless it is an exotic configuration that does not +require privilege. No check is made on the owner or group of the files +specified by this option. + +*-D*<'macro'>=<'value'>:: +oindex:[%-D%] +cindex:[macro,setting on command line] +This option can be used to override macro definitions in the configuration file +(see section <<SECTmacrodefs>>). However, like %-C%, if it is used by an +unprivileged caller, it causes Exim to give up its root privilege. +If DISABLE_D_OPTION is defined in _Local/Makefile_, the use of %-D% is +completely disabled, and its use causes an immediate error exit. ++ +The entire option (including equals sign if present) must all be within one +command line item. %-D% can be used to set the value of a macro to the empty +string, in which case the equals sign is optional. These two commands are +synonymous: + + exim -DABC ... + exim -DABC= ... ++ +To include spaces in a macro definition item, quotes must be used. If you use +quotes, spaces are permitted around the macro name and the equals sign. For +example: + + exim '-D ABC = something' ... ++ +%-D% may be repeated up to 10 times on a command line. + +*-d*<'debug~options'>:: +oindex:[%-d%] +cindex:[debugging,list of selectors] +cindex:[debugging,%-d% option] +This option causes debugging information to be written to the standard +error stream. It is restricted to admin users because debugging output may show +database queries that contain password information. Also, the details of users' +filter files should be protected. When %-d% is used, %-v% is assumed. If +%-d% is given on its own, a lot of standard debugging data is output. This can +be reduced, or increased to include some more rarely needed information, by +following %-d% with a string made up of names preceded by plus or minus +characters. These add or remove sets of debugging data, respectively. For +example, %-d+filter% adds filter debugging, whereas %-d-all+filter% selects +only filter debugging. The available debugging categories are: ++ +&&& +`acl ` ACL interpretation +`auth ` authenticators +`deliver ` general delivery logic +`dns ` DNS lookups (see also resolver) +`dnsbl ` DNS black list (aka RBL) code +`exec ` arguments for ^^execv()^^ calls +`expand ` detailed debugging for string expansions +`filter ` filter handling +`hints_lookup ` hints data lookups +`host_lookup ` all types of name-to-IP address handling +`ident ` ident lookup +`interface ` lists of local interfaces +`lists ` matching things in lists +`load ` system load checks +`local_scan ` can be used by ^^local_scan()^^ (see chapter <<CHAPlocalscan>>) +`lookup ` general lookup code and all lookups +`memory ` memory handling +`pid ` add pid to debug output lines +`process_info ` setting info for the process log +`queue_run ` queue runs +`receive ` general message reception logic +`resolver ` turn on the DNS resolver's debugging output +`retry ` retry handling +`rewrite ` address rewriting +`route ` address routing +`timestamp ` add timestamp to debug output lines +`tls ` TLS logic +`transport ` transports +`uid ` changes of uid/gid and looking up uid/gid +`verify ` address verification logic +`all ` all of the above, and also %-v% +&&& ++ +The +cindex:[resolver, debugging output] +cindex:[DNS resolver, debugging output] +`resolver` option produces output only if the DNS resolver was compiled +with DEBUG enabled. This is not the case in some operating systems. Also, +unfortunately, debugging output from the DNS resolver is written to stdout +rather than stderr. ++ +The default (%-d% with no argument) omits `expand`, `filter`, +`interface`, `load`, `memory`, `pid`, `resolver`, and `timestamp`. +However, the `pid` selector is forced when debugging is turned on for a +daemon, which then passes it on to any re-executed Exims. Exim also +automatically adds the pid to debug lines when several remote deliveries are +run in parallel. ++ +The `timestamp` selector causes the current time to be inserted at the start +of all debug output lines. This can be useful when trying to track down delays +in processing. ++ +If the %debug_print% option is set in any driver, it produces output whenever +any debugging is selected, or if %-v% is used. + +*-dd*<'debug~options'>:: +oindex:[%-dd%] +This option behaves exactly like %-d% except when used on a command that +starts a daemon process. In that case, debugging is turned off for the +subprocesses that the daemon creates. Thus, it is useful for monitoring the +behaviour of the daemon without creating as much output as full debugging does. + +*-dropcr*:: +oindex:[%-dropcr%] +This is an obsolete option that is now a no-op. It used to affect the way Exim +handled CR and LF characters in incoming messages. What happens now is +described in section <<SECTlineendings>>. + +*-E*:: +oindex:[%-E%] +cindex:[bounce message,generating] +This option specifies that an incoming message is a locally-generated delivery +failure report. It is used internally by Exim when handling delivery failures +and is not intended for external use. Its only effect is to stop Exim +generating certain messages to the postmaster, as otherwise message cascades +could occur in some situations. As part of the same option, a message id may +follow the characters %-E%. If it does, the log entry for the receipt of the +new message contains the id, following ``R='', as a cross-reference. + +*-e*'x':: +oindex:[%-e'x'%] +There are a number of Sendmail options starting with %-oe% which seem to be +called by various programs without the leading %o% in the option. For example, +the %vacation% program uses %-eq%. Exim treats all options of the form +%-e'x'% as synonymous with the corresponding %-oe'x'% options. + +*-F*~<'string'>:: +oindex:[%-F%] +cindex:[sender,name] +cindex:[name,of sender] +This option sets the sender's full name for use when a locally-generated +message is being accepted. In the absence of this option, the user's 'gecos' +entry from the password data is used. As users are generally permitted to alter +their 'gecos' entries, no security considerations are involved. White space +between %-F% and the <'string'> is optional. + +*-f*~<'address'>:: +oindex:[%-f%] +cindex:[sender,address] +cindex:[address,sender] +cindex:[trusted user] +cindex:[envelope sender] +cindex:[user,trusted] +This option sets the address of the envelope sender of a locally-generated +message (also known as the return path). The option can normally be used only +by a trusted user, but %untrusted_set_sender% can be set to allow untrusted +users to use it. ++ +Processes running as root or the Exim user are always trusted. Other +trusted users are defined by the %trusted_users% or %trusted_groups% options. +In the absence of %-f%, or if the caller is not trusted, the sender of a local +message is set to the caller's login name at the default qualify domain. ++ +There is one exception to the restriction on the use of %-f%: an empty sender +can be specified by any user, trusted or not, to create a message that can +never provoke a bounce. An empty sender can be specified either as an empty +string, or as a pair of angle brackets with nothing between them, as in these +examples of shell commands: + + exim -f '<>' user@domain + exim -f "" user@domain ++ +In addition, the use of %-f% is not restricted when testing a filter file with +%-bf% or when testing or verifying addresses using the %-bt% or %-bv% +options. ++ +Allowing untrusted users to change the sender address does not of itself make +it possible to send anonymous mail. Exim still checks that the 'From:' header +refers to the local user, and if it does not, it adds a 'Sender:' header, +though this can be overridden by setting %no_local_from_check%. ++ +White +cindex:[``From'' line] +space between %-f% and the <'address'> is optional (that is, they can be given +as two arguments or one combined argument). The sender of a locally-generated +message can also be set (when permitted) by an initial ``From '' line in the +message -- see the description of %-bm% above -- but if %-f% is also present, +it overrides ``From''. + +*-G*:: +oindex:[%-G%] +cindex:[Sendmail compatibility,%-G% option ignored] +This is a Sendmail option which is ignored by Exim. + +*-h*~<'number'>:: +oindex:[%-h%] +cindex:[Sendmail compatibility,%-h% option ignored] +This option is accepted for compatibility with Sendmail, but has no effect. (In +Sendmail it overrides the ``hop count'' obtained by counting 'Received:' +headers.) + +*-i*:: +oindex:[%-i%] +cindex:[Solaris,'mail' command] +cindex:[dot in incoming, non-SMTP message] +This option, which has the same effect as %-oi%, specifies that a dot on a line +by itself should not terminate an incoming, non-SMTP message. I can find no +documentation for this option in Solaris 2.4 Sendmail, but the 'mailx' command +in Solaris 2.4 uses it. See also %-ti%. + +*-M*~<'message~id'>~<'message~id'>~...:: +oindex:[%-M%] +cindex:[forcing delivery] +cindex:[delivery,forcing attempt] +cindex:[frozen messages,forcing delivery] +This option requests Exim to run a delivery attempt on each message in turn. If +any of the messages are frozen, they are automatically thawed before the +delivery attempt. The settings of %queue_domains%, %queue_smtp_domains%, and +%hold_domains% are ignored. ++ +Retry +cindex:[hints database,overriding retry hints] +hints for any of the addresses are overridden -- Exim tries to deliver even if +the normal retry time has not yet been reached. This option requires the caller +to be an admin user. However, there is an option called %prod_requires_admin% +which can be set false to relax this restriction (and also the same requirement +for the %-q%, %-R%, and %-S% options). + +*-Mar*~<'message~id'>~<'address'>~<'address'>~...:: +oindex:[%-Mar%] +cindex:[message,adding recipients] +cindex:[recipient,adding] +This option requests Exim to add the addresses to the list of recipients of the +message (``ar'' for ``add recipients''). The first argument must be a message id, +and the remaining ones must be email addresses. However, if the message is +active (in the middle of a delivery attempt), it is not altered. This option +can be used only by an admin user. + +*-MC*~<'transport'>~<'hostname'>~<'sequence~number'>~<'message~id'>:: +oindex:[%-MC%] +cindex:[SMTP,passed connection] +cindex:[SMTP,multiple deliveries] +cindex:[multiple SMTP deliveries] +This option is not intended for use by external callers. It is used internally +by Exim to invoke another instance of itself to deliver a waiting message using +an existing SMTP connection, which is passed as the standard input. Details are +given in chapter <<CHAPSMTP>>. This must be the final option, and the caller must +be root or the Exim user in order to use it. + +*-MCA*:: +oindex:[%-MCA%] +This option is not intended for use by external callers. It is used internally +by Exim in conjunction with the %-MC% option. It signifies that the connection +to the remote host has been authenticated. + +*-MCP*:: +oindex:[%-MCP%] +This option is not intended for use by external callers. It is used internally +by Exim in conjunction with the %-MC% option. It signifies that the server to +which Exim is connected supports pipelining. + +*-MCQ*~<'process~id'>~<'pipe~fd'>:: +oindex:[%-MCQ%] +This option is not intended for use by external callers. It is used internally +by Exim in conjunction with the %-MC% option when the original delivery was +started by a queue runner. It passes on the process id of the queue runner, +together with the file descriptor number of an open pipe. Closure of the pipe +signals the final completion of the sequence of processes that are passing +messages through the same SMTP connection. + +*-MCS*:: +oindex:[%-MCS%] +This option is not intended for use by external callers. It is used internally +by Exim in conjunction with the %-MC% option, and passes on the fact that the +SMTP SIZE option should be used on messages delivered down the existing +connection. + +*-MCT*:: +oindex:[%-MCT%] +This option is not intended for use by external callers. It is used internally +by Exim in conjunction with the %-MC% option, and passes on the fact that the +host to which Exim is connected supports TLS encryption. + +*-Mc*~<'message~id'>~<'message~id'>~...:: +oindex:[%-Mc%] +cindex:[hints database,not overridden by %-Mc%] +cindex:[delivery,manually started -- not forced] +This option requests Exim to run a delivery attempt on each message in turn, +but unlike the %-M% option, it does check for retry hints, and respects any +that are found. This option is not very useful to external callers. It is +provided mainly for internal use by Exim when it needs to re-invoke itself in +order to regain root privilege for a delivery (see chapter <<CHAPsecurity>>). +However, %-Mc% can be useful when testing, in order to run a delivery that +respects retry times and other options such as %hold_domains% that are +overridden when %-M% is used. Such a delivery does not count as a queue run. +If you want to run a specific delivery as if in a queue run, you should use +%-q% with a message id argument. A distinction between queue run deliveries +and other deliveries is made in one or two places. + +*-Mes*~<'message~id'>~<'address'>:: +oindex:[%-Mes%] +cindex:[message,changing sender] +cindex:[sender,changing] +This option requests Exim to change the sender address in the message to the +given address, which must be a fully qualified address or ``<>'' (``es'' for ``edit +sender''). There must be exactly two arguments. The first argument must be a +message id, and the second one an email address. However, if the message is +active (in the middle of a delivery attempt), its status is not altered. This +option can be used only by an admin user. + +*-Mf*~<'message~id'>~<'message~id'>~...:: +oindex:[%-Mf%] +cindex:[freezing messages] +cindex:[message,manually freezing] +This option requests Exim to mark each listed message as ``frozen''. This +prevents any delivery attempts taking place until the message is ``thawed'', +either manually or as a result of the %auto_thaw% configuration option. +However, if any of the messages are active (in the middle of a delivery +attempt), their status is not altered. This option can be used only by an admin +user. + +*-Mg*~<'message~id'>~<'message~id'>~...:: +oindex:[%-Mg%] +cindex:[giving up on messages] +cindex:[message,abandoning delivery attempts] +cindex:[delivery,abandoning further attempts] +This option requests Exim to give up trying to deliver the listed messages, +including any that are frozen. However, if any of the messages are active, +their status is not altered. For non-bounce messages, a delivery error message +is sent to the sender, containing the text ``cancelled by administrator''. +Bounce messages are just discarded. This option can be used only by an admin +user. + +*-Mmad*~<'message~id'>~<'message~id'>~...:: +oindex:[%-Mmad%] +cindex:[delivery,cancelling all] +This option requests Exim to mark all the recipient addresses in the messages +as already delivered (``mad'' for ``mark all delivered''). However, if any +message is active (in the middle of a delivery attempt), its status is not +altered. This option can be used only by an admin user. + +*-Mmd*~<'message~id'>~<'address'>~<'address'>~...:: +oindex:[%-Mmd%] +cindex:[delivery,cancelling by address] +cindex:[recipient,removing] +cindex:[removing recipients] +This option requests Exim to mark the given addresses as already delivered +(``md'' for ``mark delivered''). The first argument must be a message id, and +the remaining ones must be email addresses. These are matched to recipient +addresses in the message in a case-sensitive manner. If the message is active +(in the middle of a delivery attempt), its status is not altered. This option +can be used only by an admin user. + +*-Mrm*~<'message~id'>~<'message~id'>~...:: +oindex:[%-Mrm%] +cindex:[removing messages] +cindex:[abandoning mail] +cindex:[message,manually discarding] +This option requests Exim to remove the given messages from the queue. No +bounce messages are sent; each message is simply forgotten. However, if any of +the messages are active, their status is not altered. This option can be used +only by an admin user or by the user who originally caused the message to be +placed on the queue. + +*-Mt*~<'message~id'>~<'message~id'>~...:: +oindex:[%-Mt%] +cindex:[thawing messages] +cindex:[unfreezing messages] +cindex:[frozen messages,thawing] +cindex:[message,thawing frozen] +This option requests Exim to ``thaw'' any of the listed messages that are +``frozen'', so that delivery attempts can resume. However, if any of the messages +are active, their status is not altered. This option can be used only by an +admin user. + +*-Mvb*~<'message~id'>:: +oindex:[%-Mvb%] +cindex:[listing,message body] +cindex:[message,listing body of] +This option causes the contents of the message body (-D) spool file to be +written to the standard output. This option can be used only by an admin user. + +*-Mvh*~<'message~id'>:: +oindex:[%-Mvh%] +cindex:[listing,message headers] +cindex:[header lines,listing] +cindex:[message,listing header lines] +This option causes the contents of the message headers (-H) spool file to be +written to the standard output. This option can be used only by an admin user. + +*-Mvl*~<'message~id'>:: +oindex:[%-Mvl%] +cindex:[listing,message log] +cindex:[message,listing message log] +This option causes the contents of the message log spool file to be written to +the standard output. This option can be used only by an admin user. + +*-m*:: +oindex:[%-m%] +This is apparently a synonym for %-om% that is accepted by Sendmail, so Exim +treats it that way too. + +*-N*:: +oindex:[%-N%] +cindex:[debugging,%-N% option] +cindex:[debugging,suppressing delivery] +This is a debugging option that inhibits delivery of a message at the transport +level. It implies %-v%. Exim goes through many of the motions of delivery -- +it just doesn't actually transport the message, but instead behaves as if it +had successfully done so. However, it does not make any updates to the retry +database, and the log entries for deliveries are flagged with ``\*>'' rather +than ``=>''. ++ +Because %-N% discards any message to which it applies, only root or the Exim +user are allowed to use it with %-bd%, %-q%, %-R% or %-M%. In other words, +an ordinary user can use it only when supplying an incoming message to which it +will apply. Although transportation never fails when %-N% is set, an address +may be deferred because of a configuration problem on a transport, or a routing +problem. Once %-N% has been used for a delivery attempt, it sticks to the +message, and applies to any subsequent delivery attempts that may happen for +that message. + +*-n*:: +oindex:[%-n%] +cindex:[Sendmail compatibility,%-n% option ignored] +This option is interpreted by Sendmail to mean ``no aliasing''. It is ignored by +Exim. + +*-O*~<'data'>:: +oindex:[%-O%] +This option is interpreted by Sendmail to mean `set option`. It is ignored by +Exim. + +*-oA*~<'file~name'>:: +oindex:[%-oA%] +cindex:[Sendmail compatibility,%-oA% option] +This option is used by Sendmail in conjunction with %-bi% to specify an +alternative alias file name. Exim handles %-bi% differently; see the +description above. + +*-oB*~<'n'>:: +oindex:[%-oB%] +cindex:[SMTP,passed connection] +cindex:[SMTP,multiple deliveries] +cindex:[multiple SMTP deliveries] +This is a debugging option which limits the maximum number of messages that can +be delivered down one SMTP connection, overriding the value set in any ^smtp^ +transport. If <'n'> is omitted, the limit is set to 1. + +*-odb*:: +oindex:[%-odb%] +cindex:[background delivery] +cindex:[delivery,in the background] +This option applies to all modes in which Exim accepts incoming messages, +including the listening daemon. It requests ``background'' delivery of such +messages, which means that the accepting process automatically starts a +delivery process for each message received, but does not wait for the delivery +processes to finish. ++ +When all the messages have been received, the reception process exits, +leaving the delivery processes to finish in their own time. The standard output +and error streams are closed at the start of each delivery process. +This is the default action if none of the %-od% options are present. ++ +If one of the queueing options in the configuration file +(%queue_only% or %queue_only_file%, for example) is in effect, %-odb% +overrides it if %queue_only_override% is set true, which is the default +setting. If %queue_only_override% is set false, %-odb% has no effect. + +*-odf*:: +oindex:[%-odf%] +cindex:[foreground delivery] +cindex:[delivery,in the foreground] +This option requests ``foreground'' (synchronous) delivery when Exim has accepted +a locally-generated message. (For the daemon it is exactly the same as +%-odb%.) A delivery process is automatically started to deliver the +message, and Exim waits for it to complete before proceeding. ++ +The original Exim reception process does not finish until the delivery +process for the final message has ended. The standard error stream is left open +during deliveries. ++ +However, like %-odb%, this option has no effect if %queue_only_override% is +false and one of the queueing options in the configuration file is in effect. ++ +If there is a temporary delivery error during foreground delivery, the +message is left on the queue for later delivery, and the original reception +process exists. See chapter <<CHAPnonqueueing>> for a way of setting up a +restricted configuration that never queues messages. + + +*-odi*:: +oindex:[%-odi%] +This option is synonymous with %-odf%. It is provided for compatibility with +Sendmail. + +*-odq*:: +oindex:[%-odq%] +cindex:[non-immediate delivery] +cindex:[delivery,suppressing immediate] +cindex:[queueing incoming messages] +This option applies to all modes in which Exim accepts incoming messages, +including the listening daemon. It specifies that the accepting process should +not automatically start a delivery process for each message received. Messages +are placed on the queue, and remain there until a subsequent queue runner +process encounters them. There are several configuration options (such as +%queue_only%) that can be used to queue incoming messages under certain +conditions. This option overrides all of them and also %-odqs%. It always +forces queueing. + +*-odqs*:: +oindex:[%-odqs%] +cindex:[SMTP,delaying delivery] +This option is a hybrid between %-odb%/%-odi% and %-odq%. +However, like %-odb% and %-odi%, this option has no effect if +%queue_only_override% is false and one of the queueing options in the +configuration file is in effect. ++ +When %-odqs% does operate, a delivery process is started for each incoming +message, in the background by default, but in the foreground if %-odi% is also +present. The recipient addresses are routed, and local deliveries are done in +the normal way. However, if any SMTP deliveries are required, they are not done +at this time, so the message remains on the queue until a subsequent queue +runner process encounters it. Because routing was done, Exim knows which +messages are waiting for which hosts, and so a number of messages for the same +host can be sent in a single SMTP connection. The %queue_smtp_domains% +configuration option has the same effect for specific domains. See also the +%-qq% option. + +*-oee*:: +oindex:[%-oee%] +cindex:[error,reporting] +If an error is detected while a non-SMTP message is being received (for +example, a malformed address), the error is reported to the sender in a mail +message. ++ +Provided +cindex:[return code,for %-oee%] +this error message is successfully sent, the Exim receiving process +exits with a return code of zero. If not, the return code is 2 if the problem +is that the original message has no recipients, or 1 any other error. This is +the default %-oe'x'% option if Exim is called as 'rmail'. + +*-oem*:: +oindex:[%-oem%] +cindex:[error,reporting] +cindex:[return code,for %-oem%] +This is the same as %-oee%, except that Exim always exits with a non-zero +return code, whether or not the error message was successfully sent. +This is the default %-oe'x'% option, unless Exim is called as 'rmail'. + +*-oep*:: +oindex:[%-oep%] +cindex:[error,reporting] +If an error is detected while a non-SMTP message is being received, the +error is reported by writing a message to the standard error file (stderr). +cindex:[return code,for %-oep%] +The return code is 1 for all errors. + +*-oeq*:: +oindex:[%-oeq%] +cindex:[error,reporting] +This option is supported for compatibility with Sendmail, but has the same +effect as %-oep%. + +*-oew*:: +oindex:[%-oew%] +cindex:[error,reporting] +This option is supported for compatibility with Sendmail, but has the same +effect as %-oem%. + +*-oi*:: +oindex:[%-oi%] +cindex:[dot in incoming, non-SMTP message] +This option, which has the same effect as %-i%, specifies that a dot on a line +by itself should not terminate an incoming, non-SMTP message. +Otherwise, a single dot does terminate, though Exim does no special processing +for other lines that start with a dot. +This option is set by default if Exim is called as 'rmail'. See also %-ti%. + +*-oitrue*:: +oindex:[%-oitrue%] +This option is treated as synonymous with %-oi%. + +*-oMa*~<'host~address'>:: +oindex:[%-oMa%] +cindex:[sender host address, specifying for local message] +A number of options starting with %-oM% can be used to set values associated +with remote hosts on locally-submitted messages (that is, messages not received +over TCP/IP). These options can be used by any caller in conjunction with the +%-bh%, %-be%, %-bf%, %-bF%, %-bt%, or %-bv% testing options. In other +circumstances, they are ignored unless the caller is trusted. ++ +The %-oMa% option sets the sender host address. This may include a port number +at the end, after a full stop (period). For example: + + exim -bs -oMa 10.9.8.7.1234 ++ +An alternative syntax is to enclose the IP address in square brackets, +followed by a colon and the port number: + + exim -bs -oMa [10.9.8.7]:1234 ++ +The IP address is placed in the $sender_host_address$ variable, and the +port, if present, in $sender_host_port$. + +*-oMaa*~<'name'>:: +oindex:[%-oMaa%] +cindex:[authentication name, specifying for local message] +See %-oMa% above for general remarks about the %-oM% options. The %-oMaa% +option sets the value of $sender_host_authenticated$ (the authenticator +name). See chapter <<CHAPSMTPAUTH>> for a discussion of SMTP authentication. + +*-oMai*~<'string'>:: +oindex:[%-oMai%] +cindex:[authentication id, specifying for local message] +See %-oMa% above for general remarks about the %-oM% options. The %-oMai% +option sets the value of $authenticated_id$ (the id that was authenticated). +This overrides the default value (the caller's login id) for messages from +local sources. See chapter <<CHAPSMTPAUTH>> for a discussion of authenticated +ids. + +*-oMas*~<'address'>:: +oindex:[%-oMas%] +cindex:[authentication sender, specifying for local message] +See %-oMa% above for general remarks about the %-oM% options. The %-oMas% +option sets the authenticated sender value in $authenticated_sender$. It +overrides the sender address that is created from the caller's login id for +messages from local sources. See chapter <<CHAPSMTPAUTH>> for a discussion of +authenticated senders. + +*-oMi*~<'interface~address'>:: +oindex:[%-oMi%] +cindex:[interface address, specifying for local message] +See %-oMa% above for general remarks about the %-oM% options. The %-oMi% option +sets the IP interface address value. A port number may be included, using the +same syntax as for %-oMa%. The interface address is placed in +$interface_address$ and the port number, if present, in $interface_port$. + +*-oMr*~<'protocol~name'>:: +oindex:[%-oMr%] +cindex:[protocol,incoming -- specifying for local message] +See %-oMa% above for general remarks about the %-oM% options. The %-oMr% option +sets the received protocol value that is stored in $received_protocol$. +However, this applies only when %-bs% is not used. For interactive SMTP input +(%-bs%), the protocol is always ``local-'' followed by one of the standard SMTP +protocol names (see the description of $received_protocol$ in section +<<SECTexpvar>>). For %-bS% (batch SMTP) however, the protocol can be set by +<<%-oMr%. + +*-oMs*~<'host~name'>:: +oindex:[%-oMs%] +cindex:[sender host name, specifying for local message] +See %-oMa% above for general remarks about the %-oM% options. The %-oMs% option +sets the sender host name in $sender_host_name$. When this option is present, +Exim does not attempt to look up a host name from an IP address; it uses the +name it is given. + +*-oMt*~<'ident~string'>:: +oindex:[%-oMt%] +cindex:[sender ident string, specifying for local message] +See %-oMa% above for general remarks about the %-oM% options. The %-oMt% option +sets the sender ident value in $sender_ident$. The default setting for local +callers is the login id of the calling process. + +*-om*:: +oindex:[%-om%] +cindex:[Sendmail compatibility,%-om% option ignored] +In Sendmail, this option means ``me too'', indicating that the sender of a +message should receive a copy of the message if the sender appears in an alias +expansion. Exim always does this, so the option does nothing. + +*-oo*:: +oindex:[%-oo%] +cindex:[Sendmail compatibility,%-oo% option ignored] +This option is ignored. In Sendmail it specifies ``old style headers'', whatever +that means. + +*-oP*~<'path'>:: +oindex:[%-oP%] +cindex:[pid (process id),of daemon] +cindex:[daemon,process id (pid)] +This option is useful only in conjunction with %-bd% or %-q% with a time +value. The option specifies the file to which the process id of the daemon is +written. When %-oX% is used with %-bd%, or when %-q% with a time is used +without %-bd%, this is the only way of causing Exim to write a pid file, +because in those cases, the normal pid file is not used. + +*-or*~<'time'>:: +oindex:[%-or%] +cindex:[timeout,for non-SMTP input] +This option sets a timeout value for incoming non-SMTP messages. If it is not +set, Exim will wait forever for the standard input. The value can also be set +by the %receive_timeout% option. The format used for specifying times is +described in section <<SECTtimeformat>>. + +*-os*~<'time'>:: +oindex:[%-os%] +cindex:[timeout,for SMTP input] +cindex:[SMTP timeout, input] +This option sets a timeout value for incoming SMTP messages. The timeout +applies to each SMTP command and block of data. The value can also be set by +the %smtp_receive_timeout% option; it defaults to 5 minutes. The format used +for specifying times is described in section <<SECTtimeformat>>. + +*-ov*:: +oindex:[%-ov%] +This option has exactly the same effect as %-v%. + +*-oX*~<'number~or~string'>:: +oindex:[%-oX%] +cindex:[TCP/IP,setting listening ports] +cindex:[TCP/IP,setting listening interfaces] +cindex:[port,receiving TCP/IP] +This option is relevant only when the %-bd% (start listening daemon) option is +also given. It controls which ports and interfaces the daemon uses. Details of +the syntax, and how it interacts with configuration file options, are given in +chapter <<CHAPinterfaces>>. When %-oX% is used to start a daemon, no pid file is +written unless %-oP% is also present to specify a pid file name. + +*-pd*:: +oindex:[%-pd%] +cindex:[Perl,starting the interpreter] +This option applies when an embedded Perl interpreter is linked with Exim (see +chapter <<CHAPperl>>). It overrides the setting of the %perl_at_start% option, +forcing the starting of the interpreter to be delayed until it is needed. + +*-ps*:: +oindex:[%-ps%] +cindex:[Perl,starting the interpreter] +This option applies when an embedded Perl interpreter is linked with Exim (see +chapter <<CHAPperl>>). It overrides the setting of the %perl_at_start% option, +forcing the starting of the interpreter to occur as soon as Exim is started. + +*-p*<'rval'>:<'sval'>:: +oindex:[%-p%] +For compatibility with Sendmail, this option is equivalent to + + -oMr <rval> -oMs <sval> ++ +It sets the incoming protocol and host name (for trusted callers). The +host name and its colon can be omitted when only the protocol is to be set. +Note the Exim already has two private options, %-pd% and %-ps%, that refer to +embedded Perl. It is therefore impossible to set a protocol value of `p` or +`s` using this option (but that does not seem a real limitation). + +*-q*:: +oindex:[%-q%] +cindex:[queue runner,starting manually] +This option is normally restricted to admin users. However, there is a +configuration option called %prod_requires_admin% which can be set false to +relax this restriction (and also the same requirement for the %-M%, %-R%, and +%-S% options). ++ +The +cindex:[queue runner,description of operation] +%-q% option starts one queue runner process. This scans the queue of +waiting messages, and runs a delivery process for each one in turn. It waits +for each delivery process to finish before starting the next one. A delivery +process may not actually do any deliveries if the retry times for the addresses +have not been reached. Use %-qf% (see below) if you want to override this. ++ +If +cindex:[SMTP,passed connection] +cindex:[SMTP,multiple deliveries] +cindex:[multiple SMTP deliveries] +the delivery process spawns other processes to deliver other messages down +passed SMTP connections, the queue runner waits for these to finish before +proceeding. ++ +When all the queued messages have been considered, the original queue runner +process terminates. In other words, a single pass is made over the waiting +mail, one message at a time. Use %-q% with a time (see below) if you want this +to be repeated periodically. ++ +Exim processes the waiting messages in an unpredictable order. It isn't very +random, but it is likely to be different each time, which is all that matters. +If one particular message screws up a remote MTA, other messages to the same +MTA have a chance of getting through if they get tried first. ++ +It is possible to cause the messages to be processed in lexical message id +order, which is essentially the order in which they arrived, by setting the +%queue_run_in_order% option, but this is not recommended for normal use. + +*-q*<'qflags'>:: +The %-q% option may be followed by one or more flag letters that change its +behaviour. They are all optional, but if more than one is present, they must +appear in the correct order. Each flag is described in a separate item below. + +*-qq...*:: +oindex:[%-qq%] +cindex:[queue,double scanning] +cindex:[queue,routing] +cindex:[routing,whole queue before delivery] +An option starting with %-qq% requests a two-stage queue run. In the first +stage, the queue is scanned as if the %queue_smtp_domains% option matched +every domain. Addresses are routed, local deliveries happen, but no remote +transports are run. ++ +The +cindex:[hints database,remembering routing] +hints database that remembers which messages are waiting for specific hosts is +updated, as if delivery to those hosts had been deferred. After this is +complete, a second, normal queue scan happens, with routing and delivery taking +place as normal. Messages that are routed to the same host should mostly be +delivered down a single SMTP +cindex:[SMTP,passed connection] +cindex:[SMTP,multiple deliveries] +cindex:[multiple SMTP deliveries] +connection because of the hints that were set up during the first queue scan. +This option may be useful for hosts that are connected to the Internet +intermittently. + +*-q[q]i...*:: +oindex:[%-qi%] +cindex:[queue,initial delivery] +If the 'i' flag is present, the queue runner runs delivery processes only for +those messages that haven't previously been tried. ('i' stands for ``initial +delivery''.) This can be helpful if you are putting messages on the queue using +%-odq% and want a queue runner just to process the new messages. + +*-q[q][i]f...*:: +oindex:[%-qf%] +cindex:[queue,forcing delivery] +cindex:[delivery,forcing in queue run] +If one 'f' flag is present, a delivery attempt is forced for each non-frozen +message, whereas without %f% only those non-frozen addresses that have passed +their retry times are tried. + +*-q[q][i]ff...*:: +oindex:[%-qff%] +cindex:[frozen messages,forcing delivery] +If 'ff' is present, a delivery attempt is forced for every message, whether +frozen or not. + +*-q[q][i][f[f]]l*:: +oindex:[%-ql%] +cindex:[queue,local deliveries only] +The 'l' (the letter ``ell'') flag specifies that only local deliveries are to be +done. If a message requires any remote deliveries, it remains on the queue for +later delivery. + +*-q*<'qflags'>~<'start~id'>~<'end~id'>:: +cindex:[queue,delivering specific messages] +When scanning the queue, Exim can be made to skip over messages whose ids are +lexically less than a given value by following the %-q% option with a starting +message id. For example: + + exim -q 0t5C6f-0000c8-00 ++ +Messages that arrived earlier than `0t5C6f-0000c8-00` are not inspected. If a +second message id is given, messages whose ids are lexically greater than it +are also skipped. If the same id is given twice, for example, + + exim -q 0t5C6f-0000c8-00 0t5C6f-0000c8-00 ++ +just one delivery process is started, for that message. This differs from %-M% +in that retry data is respected, and it also differs from %-Mc% in that it +counts as a delivery from a queue run. Note that the selection mechanism does +not affect the order in which the messages are scanned. There are also other +ways of selecting specific sets of messages for delivery in a queue run -- see +%-R% and %-S%. + +*-q*<'qflags'><'time'>:: +cindex:[queue runner,starting periodically] +cindex:[periodic queue running] +When a time value is present, the %-q% option causes Exim to run as a daemon, +starting a queue runner process at intervals specified by the given time value +(whose format is described in section <<SECTtimeformat>>). This form of the %-q% +option is commonly combined with the %-bd% option, in which case a single +daemon process handles both functions. A common way of starting up a combined +daemon at system boot time is to use a command such as + + /usr/exim/bin/exim -bd -q30m ++ +Such a daemon listens for incoming SMTP calls, and also starts a queue runner +process every 30 minutes. ++ +When a daemon is started by %-q% with a time value, but without %-bd%, no pid +file is written unless one is explicitly requested by the %-oP% option. + +*-qR*<'rsflags'>~<'string'>:: +oindex:[%-qR%] +This option is synonymous with %-R%. It is provided for Sendmail compatibility. + +*-qS*<'rsflags'>~<'string'>:: +oindex:[%-qS%] +This option is synonymous with %-S%. + +*-R*<'rsflags'>~<'string'>:: +oindex:[%-R%] +cindex:[queue runner,for specific recipients] +cindex:[delivery,to given domain] +cindex:[domain,delivery to] +The <'rsflags'> may be empty, in which case the white space before the string +is optional, unless the string is 'f', 'ff', 'r', 'rf', or 'rff', which are the +possible values for <'rsflags'>. White space is required if <'rsflags'> is not +empty. ++ +This option is similar to %-q% with no time value, that is, it causes Exim to +perform a single queue run, except that, when scanning the messages on the +queue, Exim processes only those that have at least one undelivered recipient +address containing the given string, which is checked in a case-independent +way. If the <'rsflags'> start with 'r', <'string'> is interpreted as a regular +expression; otherwise it is a literal string. ++ +Once a message is selected, all its addresses are processed. For the first +selected message, Exim overrides any retry information and forces a delivery +attempt for each undelivered address. This means that if delivery of any +address in the first message is successful, any existing retry information is +deleted, and so delivery attempts for that address in subsequently selected +messages (which are processed without forcing) will run. However, if delivery +of any address does not succeed, the retry information is updated, and in +subsequently selected messages, the failing address will be skipped. ++ +If the <'rsflags'> contain 'f' or 'ff', the delivery forcing applies to all +selected messages, not just the first; +cindex:[frozen messages,forcing delivery] +frozen messages are included when 'ff' is present. ++ +The %-R% option makes it straightforward to initiate delivery of all messages +to a given domain after a host has been down for some time. When the SMTP +command ETRN is accepted by its ACL (see chapter <<CHAPACL>>), its default +effect is to run Exim with the %-R% option, but it can be configured to run an +arbitrary command instead. + +*-r*:: +oindex:[%-r%] +This is a documented (for Sendmail) obsolete alternative name for %-f%. + +*-S*<'rsflags'>~<'string'>:: +oindex:[%-S%] +cindex:[delivery,from given sender] +cindex:[queue runner,for specific senders] +This option acts like %-R% except that it checks the string against each +message's sender instead of against the recipients. If %-R% is also set, both +conditions must be met for a message to be selected. If either of the options +has 'f' or 'ff' in its flags, the associated action is taken. + +*-Tqt*~<'times'>:: +oindex:[%-Tqt%] +This an option that is exclusively for use by the Exim testing suite. It is not +recognized when Exim is run normally. It allows for the setting up of explicit +``queue times'' so that various warning/retry features can be tested. + +*-t*:: +oindex:[%-t%] +cindex:[recipient,extracting from header lines] +cindex:['Bcc:' header line] +cindex:['Cc:' header line] +cindex:['To:' header line] +When Exim is receiving a locally-generated, non-SMTP message on its standard +input, the %-t% option causes the recipients of the message to be obtained +from the 'To:', 'Cc:', and 'Bcc:' header lines in the message instead of from +the command arguments. The addresses are extracted before any rewriting takes +place. ++ +If +cindex:[Sendmail compatibility,%-t% option] +the command has any arguments, they specify addresses to which the message +is 'not' to be delivered. That is, the argument addresses are removed from +the recipients list obtained from the headers. This is compatible with Smail 3 +and in accordance with the documented behaviour of several versions of +Sendmail, as described in man pages on a number of operating systems (e.g. +Solaris 8, IRIX 6.5, HP-UX 11). However, some versions of Sendmail 'add' +argument addresses to those obtained from the headers, and the O'Reilly +Sendmail book documents it that way. Exim can be made to add argument addresses +instead of subtracting them by setting the option +%extract_addresses_remove_arguments% false. ++ +If a 'Bcc:' header line is present, it is removed from the message unless +there is no 'To:' or 'Cc:', in which case a 'Bcc:' line with no data is +created. This is necessary for conformity with the original RFC 822 standard; +the requirement has been removed in RFC 2822, but that is still very new. ++ +If +cindex:[%Resent-% header lines,with %-t%] +there are any %Resent-% header lines in the message, Exim extracts +recipients from all 'Resent-To:', 'Resent-Cc:', and 'Resent-Bcc:' header +lines instead of from 'To:', 'Cc:', and 'Bcc:'. This is for compatibility +with Sendmail and other MTAs. (Prior to release 4.20, Exim gave an error if +%-t% was used in conjunction with %Resent-% header lines.) ++ +RFC 2822 talks about different sets of %Resent-% header lines (for when a +message is resent several times). The RFC also specifies that they should be +added at the front of the message, and separated by 'Received:' lines. It is +not at all clear how %-t% should operate in the present of multiple sets, +nor indeed exactly what constitutes a ``set''. +In practice, it seems that MUAs do not follow the RFC. The %Resent-% lines are +often added at the end of the header, and if a message is resent more than +once, it is common for the original set of %Resent-% headers to be renamed as +%X-Resent-% when a new set is added. This removes any possible ambiguity. + +*-ti*:: +oindex:[%-ti%] +This option is exactly equivalent to %-t% %-i%. It is provided for +compatibility with Sendmail. + +*-tls-on-connect*:: +oindex:[%-tls-on-connect%] +cindex:[TLS,use without STARTTLS] +cindex:[TLS,automatic start] +This option is available when Exim is compiled with TLS support. It forces all +incoming SMTP connections to behave as if the incoming port is listed in the +%tls_on_connect_ports% option. See section <<SECTsupobssmt>> and chapter +<<CHAPTLS>> for further details. + + +*-U*:: +oindex:[%-U%] +cindex:[Sendmail compatibility,%-U% option ignored] +Sendmail uses this option for ``initial message submission'', and its +documentation states that in future releases, it may complain about +syntactically invalid messages rather than fixing them when this flag is not +set. Exim ignores this option. + +*-v*:: +oindex:[%-v%] +This option causes Exim to write information to the standard error stream, +describing what it is doing. In particular, it shows the log lines for +receiving and delivering a message, and if an SMTP connection is made, the SMTP +dialogue is shown. Some of the log lines shown may not actually be written to +the log if the setting of %log_selector% discards them. Any relevant selectors +are shown with each log line. If none are shown, the logging is unconditional. + +*-x*:: +oindex:[%-x%] +AIX uses %-x% for a private purpose (``mail from a local mail program has +National Language Support extended characters in the body of the mail item''). +It sets %-x% when calling the MTA from its %mail% command. Exim ignores this +option. + +/// +We insert a stylized DocBook comment here, to identify the end of the command +line options. This is for the benefit of the Perl script that automatically +creates a man page for the options. +/// + +++++ +<!-- === End of command line options === --> +++++ + + + + + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// + + +[[CHAPconf]] +[titleabbrev="The runtime configuration file"] +The Exim run time configuration file +------------------------------------ + +cindex:[run time configuration] +cindex:[configuration file,general description] +cindex:[CONFIGURE_FILE] +cindex:[configuration file,errors in] +cindex:[error,in configuration file] +cindex:[return code,for bad configuration] +Exim uses a single run time configuration file that is read whenever an Exim +binary is executed. Note that in normal operation, this happens frequently, +because Exim is designed to operate in a distributed manner, without central +control. + +If a syntax error is detected while reading the configuration file, Exim +writes a message on the standard error, and exits with a non-zero return code. +The message is also written to the panic log. *Note*: only simple syntax +errors can be detected at this time. The values of any expanded options are +not checked until the expansion happens, even when the expansion does not +actually alter the string. + + + +The name of the configuration file is compiled into the binary for security +reasons, and is specified by the CONFIGURE_FILE compilation option. In +most configurations, this specifies a single file. However, it is permitted to +give a colon-separated list of file names, in which case Exim uses the first +existing file in the list. + +cindex:[EXIM_USER] +cindex:[EXIM_GROUP] +cindex:[CONFIGURE_OWNER] +cindex:[CONFIGURE_GROUP] +cindex:[configuration file,ownership] +cindex:[ownership,configuration file] +The run time configuration file must be owned by root or by the user that is +specified at compile time by the EXIM_USER option, or by the user that is +specified at compile time by the CONFIGURE_OWNER option (if set). The +configuration file must not be world-writeable or group-writeable, unless its +group is the one specified at compile time by the EXIM_GROUP option + +or by the CONFIGURE_GROUP option. + + +*Warning*: In a conventional configuration, where the Exim binary is setuid +to root, anybody who is able to edit the run time configuration file has an +easy way to run commands as root. If you make your mail administrators members +of the Exim group, but do not trust them with root, make sure that the run time +configuration is not group writeable. + +A default configuration file, which will work correctly in simple situations, +is provided in the file _src/configure.default_. If CONFIGURE_FILE +defines just one file name, the installation process copies the default +configuration to a new file of that name if it did not previously exist. If +CONFIGURE_FILE is a list, no default is automatically installed. Chapter +<<CHAPdefconfil>> is a ``walk-through'' discussion of the default configuration. + + + +Using a different configuration file +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[configuration file,alternate] +A one-off alternate configuration can be specified by the %-C% command line +option, which may specify a single file or a list of files. However, when %-C% +is used, Exim gives up its root privilege, unless called by root or the Exim +user (or unless the argument for %-C% is identical to the built-in value from +CONFIGURE_FILE). %-C% is useful mainly for checking the syntax of +configuration files before installing them. No owner or group checks are done +on a configuration file specified by %-C%. + +The privileged use of %-C% by the Exim user can be locked out by setting +ALT_CONFIG_ROOT_ONLY in _Local/Makefile_ when building Exim. However, +if you do this, you also lock out the possibility of testing a +configuration using %-C% right through message reception and delivery, even if +the caller is root. The reception works, but by that time, Exim is running as +the Exim user, so when it re-execs to regain privilege for the delivery, the +use of %-C% causes privilege to be lost. However, root can test reception and +delivery using two separate commands (one to put a message on the queue, using +%-odq%, and another to do the delivery, using %-M%). + +If ALT_CONFIG_PREFIX is defined _in Local/Makefile_, it specifies a +prefix string with which any file named in a %-C% command line option must +start. In addition, the file name must not contain the sequence `/../`. There +is no default setting for ALT_CONFIG_PREFIX; when it is unset, any file +name can be used with %-C%. + +One-off changes to a configuration can be specified by the %-D% command line +option, which defines and overrides values for macros used inside the +configuration file. However, like %-C%, the use of this option by a +non-privileged user causes Exim to discard its root privilege. +If DISABLE_D_OPTION is defined in _Local/Makefile_, the use of %-D% is +completely disabled, and its use causes an immediate error exit. + +Some sites may wish to use the same Exim binary on different machines that +share a file system, but to use different configuration files on each machine. +If CONFIGURE_FILE_USE_NODE is defined in _Local/Makefile_, Exim first +looks for a file whose name is the configuration file name followed by a dot +and the machine's node name, as obtained from the 'uname()' function. If this +file does not exist, the standard name is tried. This processing occurs for +each file name in the list given by CONFIGURE_FILE or %-C%. + +In some esoteric situations different versions of Exim may be run under +different effective uids and the CONFIGURE_FILE_USE_EUID is defined to +help with this. See the comments in _src/EDITME_ for details. + + + +[[SECTconffilfor]] +Configuration file format +~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[configuration file,format of] +cindex:[format,configuration file] +Exim's configuration file is divided into a number of different parts. General +option settings must always appear at the start of the file. The other parts +are all optional, and may appear in any order. Each part other than the first +is introduced by the word ``begin'' followed by the name of the part. The +optional parts are: + +- 'ACL': Access control lists for controlling incoming SMTP mail. + +- cindex:[AUTH,configuration] +'authenticators': Configuration settings for the authenticator drivers. These +are concerned with the SMTP AUTH command (see chapter <<CHAPSMTPAUTH>>). + +- 'routers': Configuration settings for the router drivers. Routers process +addresses and determine how the message is to be delivered. + +- 'transports': Configuration settings for the transport drivers. Transports +define mechanisms for copying messages to destinations. + +- 'retry': Retry rules, for use when a message cannot be immediately delivered. + +- 'rewrite': Global address rewriting rules, for use when a message arrives and +when new addresses are generated during delivery. + +- 'local_scan': Private options for the 'local_scan()' function. If you +want to use this feature, you must set + + LOCAL_SCAN_HAS_OPTIONS=yes ++ +in _Local/Makefile_ before building Exim. Full details of the +'local_scan()' facility are given in chapter <<CHAPlocalscan>>. + +cindex:[configuration file,leading whitespace in] +cindex:[configuration file,trailing whitespace in] +cindex:[whitespace,in configuration file] +Leading and trailing whitespace in configuration lines is always ignored. + +Blank lines in the file, and lines starting with a # character (ignoring +leading white space) are treated as comments and are ignored. *Note*: a +# character other than at the beginning of a line is not treated specially, +and does not introduce a comment. + +Any non-comment line can be continued by ending it with a backslash. Note that +the general rule for whitespace means that trailing white space after the +backslash is ignored, and leading white space at the start of continuation +lines is also ignored. Comment lines beginning with # (but not empty lines) may +appear in the middle of a sequence of continuation lines. + +A convenient way to create a configuration file is to start from the +default, which is supplied in _src/configure.default_, and add, delete, or +change settings as required. + +The ACLs, retry rules, and rewriting rules have their own syntax which is +described in chapters <<CHAPACL>>, <<CHAPretry>>, and <<CHAPrewrite>>, +respectively. The other parts of the configuration file have some syntactic +items in common, and these are described below, from section <<SECTcos>> +onwards. Before that, the inclusion, macro, and conditional facilities are +described. + + + +File inclusions in the configuration file +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[inclusions in configuration file] +cindex:[configuration file,including other files] +cindex:[.include in configuration file] +cindex:[.include_if_exists in configuration file] +You can include other files inside Exim's run time configuration file by +using this syntax: + + .include <file name> + +or + + .include_if_exists <file name> + +on a line by itself. Double quotes round the file name are optional. If you use +the first form, a configuration error occurs if the file does not exist; the +second form does nothing for non-existent files. + +Includes may be nested to any depth, but remember that Exim reads its +configuration file often, so it is a good idea to keep them to a minimum. +If you change the contents of an included file, you must HUP the daemon, +because an included file is read only when the configuration itself is read. + +The processing of inclusions happens early, at a physical line level, so, like +comment lines, an inclusion can be used in the middle of an option setting, +for example: + +.... +hosts_lookup = a.b.c \ + .include /some/file +.... + +Include processing happens after macro processing (see below). Its effect is to +process the lines of the file as if they occurred inline where the inclusion +appears. + + + +[[SECTmacrodefs]] +Macros in the configuration file +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[macro,description of] +cindex:[configuration file,macros] +If a line in the main part of the configuration (that is, before the first +``begin'' line) begins with an upper case letter, it is taken as a macro +definition, and must be of the form + +&&& +<'name'> = <'rest of line'> +&&& + +The name must consist of letters, digits, and underscores, and need not all be +in upper case, though that is recommended. The rest of the line, including any +continuations, is the replacement text, and has leading and trailing white +space removed. Quotes are not removed. The replacement text can never end with +a backslash character, but this doesn't seem to be a serious limitation. + +Once a macro is defined, all subsequent lines in the file (and any included +files) are scanned for the macro name; if there are several macros, the line is +scanned for each in turn, in the order in which they are defined. The +replacement text is not re-scanned for the current macro, though it is scanned +for subsequently defined macros. For this reason, a macro name may not contain +the name of a previously defined macro as a substring. You could, for example, +define + +&&& +`ABCD_XYZ = `<'something'> +`ABCD = `<'something else'> +&&& + +but putting the definitions in the opposite order would provoke a configuration +error. + +Macro expansion is applied to individual lines from the file, before checking +for line continuation or file inclusion (see below). If a line consists solely +of a macro name, and the expansion of the macro is empty, the line is ignored. +A macro at the start of a line may turn the line into a comment line or a +`.include` line. + +As an example of macro usage, consider a configuration where aliases are looked +up in a MySQL database. It helps to keep the file less cluttered if long +strings such as SQL statements are defined separately as macros, for example: + +.... +ALIAS_QUERY = select mailbox from user where \ + login=${quote_mysql:$local_part}; +.... + +This can then be used in a ^redirect^ router setting like this: + + data = ${lookup mysql{ALIAS_QUERY}} + +In earlier versions of Exim macros were sometimes used for domain, host, or +address lists. In Exim 4 these are handled better by named lists -- see section +<<SECTnamedlists>>. + +Macros in the configuration file can be overridden by the %-D% command line +option, but Exim gives up its root privilege when %-D% is used, unless called +by root or the Exim user. + + + +Conditional skips in the configuration file +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[configuration file,conditional skips] +cindex:[.ifdef] +You can use the directives `.ifdef`, `.ifndef`, `.elifdef`, +`.elifndef`, `.else`, and `.endif` to dynamically include or exclude +portions of the configuration file. The processing happens whenever the file is +read (that is, when an Exim binary starts to run). + +The implementation is very simple. Instances of the first four directives must +be followed by text that includes the names of one or macros. The condition +that is tested is whether or not any macro substitution has taken place in the +line. Thus: + + .ifdef AAA + message_size_limit = 50M + .else + message_size_limit = 100M + .endif + +sets a message size limit of 50M if the macro `AAA` is defined, and 100M +otherwise. If there is more than one macro named on the line, the condition +is true if any of them are defined. That is, it is an ``or'' condition. To +obtain an ``and'' condition, you need to use nested `.ifdef`##s. + +Although you can use a macro expansion to generate one of these directives, +it is not very useful, because the condition ``there was a macro substitution +in this line'' will always be true. + +Text following `.else` and `.endif` is ignored, and can be used as comment +to clarify complicated nestings. + + + +[[SECTcos]] +Common option syntax +~~~~~~~~~~~~~~~~~~~~ +cindex:[common option syntax] +cindex:[syntax of common options] +cindex:[configuration file,common option syntax] +For the main set of options, driver options, and 'local_scan()' options, +each setting is on a line by itself, and starts with a name consisting of +lower-case letters and underscores. Many options require a data value, and in +these cases the name must be followed by an equals sign (with optional white +space) and then the value. For example: + + qualify_domain = mydomain.example.com + +Some option settings may contain sensitive data, for example, passwords for +accessing databases. To stop non-admin users from using the %-bP% command line +option to read these values, you can precede the option settings with the word +``hide''. For example: + + hide mysql_servers = localhost/users/admin/secret-password + +For non-admin users, such options are displayed like this: + + mysql_servers = <value not displayable> + +If ``hide'' is used on a driver option, it hides the value of that option on all +instances of the same driver. + +The following sections describe the syntax used for the different data types +that are found in option settings. + + +Boolean options +~~~~~~~~~~~~~~~ +cindex:[format,boolean] +cindex:[boolean configuration values] +Options whose type is given as boolean are on/off switches. There are two +different ways of specifying such options: with and without a data value. If +the option name is specified on its own without data, the switch is turned on; +if it is preceded by ``no_'' or ``not_'' the switch is turned off. However, +boolean options may optionally be followed by an equals sign and one of the +words ``true'', ``false'', ``yes'', or ``no'', as an alternative syntax. For example, +the following two settings have exactly the same effect: + + queue_only + queue_only = true + +The following two lines also have the same (opposite) effect: + + no_queue_only + queue_only = false + +You can use whichever syntax you prefer. + + + + +Integer values +~~~~~~~~~~~~~~ +cindex:[integer configuration values] +cindex:[format,integer] +If an integer data item starts with the characters ``0x'', the remainder of it +is interpreted as a hexadecimal number. Otherwise, it is treated as octal if it +starts with the digit 0, and decimal if not. If an integer value is followed by +the letter K, it is multiplied by 1024; if it is followed by the letter M, it +is multiplied by 1024x1024. + +When the values of integer option settings are output, values which are an +exact multiple of 1024 or 1024x1024 are +sometimes, but not always, +printed using the letters K and M. The printing style is independent of the +actual input format that was used. + + +Octal integer values +~~~~~~~~~~~~~~~~~~~~ +cindex:[integer format] +cindex:[format,octal integer] +The value of an option specified as an octal integer is always interpreted in +octal, whether or not it starts with the digit zero. Such options are always +output in octal. + + + +Fixed point number values +~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[fixed point configuration values] +cindex:[format,fixed point] +A fixed point number consists of a decimal integer, optionally followed by a +decimal point and up to three further digits. + + + +[[SECTtimeformat]] +Time interval values +~~~~~~~~~~~~~~~~~~~~ +cindex:[time interval,specifying in configuration] +cindex:[format,time interval] +A time interval is specified as a sequence of numbers, each followed by one of +the following letters, with no intervening white space: + +[frame="none"] +`-`-----`-------- + %s% seconds + %m% minutes + %h% hours + %d% days + %w% weeks +----------------- + +For example, ``3h50m'' specifies 3 hours and 50 minutes. The values of time +intervals are output in the same format. Exim does not restrict the values; it +is perfectly acceptable, for example, to specify ``90m'' instead of ``1h30m''. + + + +[[SECTstrings]] +String values +~~~~~~~~~~~~~ +cindex:[string,format of configuration values] +cindex:[format,string] +If a string data item does not start with a double-quote character, it is taken +as consisting of the remainder of the line plus any continuation lines, +starting at the first character after any leading white space, with trailing +white space characters removed, and with no interpretation of the characters in +the string. Because Exim removes comment lines (those beginning with #) at an +early stage, they can appear in the middle of a multi-line string. The +following settings are therefore equivalent: + +.... +trusted_users = uucp:mail + +trusted_users = uucp:\ + # This comment line is ignored + mail +.... + +cindex:[string,quoted] +cindex:[escape characters in quoted strings] +If a string does start with a double-quote, it must end with a closing +double-quote, and any backslash characters other than those used for line +continuation are interpreted as escape characters, as follows: + +[frame="none"] +`-`----------------------`-------------------------------------------------- + `\\` single backslash + `\n` newline + `\r` carriage return + `\t` tab + `\`<'octal digits'> up to 3 octal digits specify one character + `\x`<'hex digits'> up to 2 hexadecimal digits specify one character +---------------------------------------------------------------------------- + +If a backslash is followed by some other character, including a double-quote +character, that character replaces the pair. + +Quoting is necessary only if you want to make use of the backslash escapes to +insert special characters, or if you need to specify a value with leading or +trailing spaces. These cases are rare, so quoting is almost never needed in +current versions of Exim. In versions of Exim before 3.14, quoting was required +in order to continue lines, so you may come across older configuration files +and examples that apparently quote unnecessarily. + + +Expanded strings +~~~~~~~~~~~~~~~~ +cindex:[string expansion, definition of] +cindex:[expansion,definition of] +Some strings in the configuration file are subjected to 'string expansion', +by which means various parts of the string may be changed according to the +circumstances (see chapter <<CHAPexpand>>). The input syntax for such strings is +as just described; in particular, the handling of backslashes in quoted strings +is done as part of the input process, before expansion takes place. However, +backslash is also an escape character for the expander, so any backslashes that +are required for that reason must be doubled if they are within a quoted +configuration string. + + +User and group names +~~~~~~~~~~~~~~~~~~~~ +cindex:[user name,format of] +cindex:[format,user name] +cindex:[group,name format] +cindex:[format,group name] +User and group names are specified as strings, using the syntax described +above, but the strings are interpreted specially. A user or group name must +either consist entirely of digits, or be a name that can be looked up using the +'getpwnam()' or 'getgrnam()' function, as appropriate. + + +[[SECTlistconstruct]] +List construction +~~~~~~~~~~~~~~~~~ +cindex:[list,syntax of in configuration] +cindex:[format,list item in configuration] +cindex:[string list, definition] +The data for some configuration options is a list of items, with colon as the +default separator. Many of these options are shown with type ``string list'' in +the descriptions later in this document. Others are listed as ``domain list'', +``host list'', ``address list'', or ``local part list''. Syntactically, they are all +the same; however, those other than ``string list'' are subject to particular +kinds of interpretation, as described in chapter <<CHAPdomhosaddlists>>. + +In all these cases, the entire list is treated as a single string as far as the +input syntax is concerned. The %trusted_users% setting in section +<<SECTstrings>> above is an example. If a colon is actually needed in an item in +a list, it must be entered as two colons. Leading and trailing white space on +each item in a list is ignored. This makes it possible to include items that +start with a colon, and in particular, certain forms of IPv6 address. For +example, the list + + local_interfaces = 127.0.0.1 : ::::1 + ++contains two IP addresses, the IPv4 address 127.0.0.1 and the IPv6 address +1. + +cindex:[list separator, changing] +cindex:[IPv6,addresses in lists] +Doubling colons in IPv6 addresses is an unwelcome chore, so a mechanism was +introduced to allow the separator character to be changed. If a list begins +with a left angle bracket, followed by any punctuation character, that +character is used instead of colon as the list separator. For example, the list +above can be rewritten to use a semicolon separator like this: + + local_interfaces = <; 127.0.0.1 ; ::1 + +This facility applies to all lists, with the exception of the list in +%log_file_path%. It is recommended that the use of non-colon separators be +confined to circumstances where they really are needed. + + + +[[SECTempitelis]] +Empty items in lists +~~~~~~~~~~~~~~~~~~~~ +cindex:[list,empty item in] +An empty item at the end of a list is always ignored. In other words, trailing +separator characters are ignored. Thus, the list in + + senders = user@domain : + +contains only a single item. If you want to include an empty string as one item +in a list, it must not be the last item. For example, this list contains three +items, the second of which is empty: + + senders = user1@domain : : user2@domain + +*Note*: there must be whitespace between the two colons, as otherwise they +are interpreted as representing a single colon data character (and the list +would then contain just one item). If you want to specify a list that contains +just one, empty item, you can do it as in this example: + + senders = : + +In this case, the first item is empty, and the second is discarded because it +is at the end of the list. + + + + +[[SECTfordricon]] +Format of driver configurations +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[drivers,configuration format] +There are separate parts in the configuration for defining routers, transports, +and authenticators. In each part, you are defining a number of driver +instances, each with its own set of options. Each driver instance is defined by +a sequence of lines like this: + +&&& +<'instance name'>: + <'option'> + ... + <'option'> +&&& + +In the following example, the instance name is ^localuser^, and it is +followed by three options settings: + + localuser: + driver = accept + check_local_user + transport = local_delivery + +For each driver instance, you specify which Exim code module it uses -- by the +setting of the %driver% option -- and (optionally) some configuration settings. +For example, in the case of transports, if you want a transport to deliver with +SMTP you would use the ^smtp^ driver; if you want to deliver to a local file +you would use the ^appendfile^ driver. Each of the drivers is described in +detail in its own separate chapter later in this manual. + +You can have several routers, transports, or authenticators that are based on +the same underlying driver (each must have a different name). + +The order in which routers are defined is important, because addresses are +passed to individual routers one by one, in order. The order in which +transports are defined does not matter at all. The order in which +authenticators are defined is used only when Exim, as a client, is searching +them to find one that matches an authentication mechanism offered by the +server. + +cindex:[generic options] +cindex:[options, generic -- definition of] +Within a driver instance definition, there are two kinds of option: +'generic' and 'private'. The generic options are those that apply to all +drivers of the same type (that is, all routers, all transports or all +authenticators). +The %driver% option is a generic option that must appear in every definition. + +cindex:[private options] +The private options are special for each driver, and none need appear, because +they all have default values. + +The options may appear in any order, except that the %driver% option must +precede any private options, since these depend on the particular driver. For +this reason, it is recommended that %driver% always be the first option. + +Driver instance names, which are used for reference in log entries and +elsewhere, can be any sequence of letters, digits, and underscores (starting +with a letter) and must be unique among drivers of the same type. A router and +a transport (for example) can each have the same name, but no two router +instances can have the same name. The name of a driver instance should not be +confused with the name of the underlying driver module. For example, the +configuration lines: + + remote_smtp: + driver = smtp + +create an instance of the ^smtp^ transport driver whose name is +^remote_smtp^. The same driver code can be used more than once, with +different instance names and different option settings each time. A second +instance of the ^smtp^ transport, with different options, might be defined +thus: + + special_smtp: + driver = smtp + port = 1234 + command_timeout = 10s + +The names ^remote_smtp^ and ^special_smtp^ would be used to reference +these transport instances from routers, and these names would appear in log +lines. + +Comment lines may be present in the middle of driver specifications. The full +list of option settings for any particular driver instance, including all the +defaulted values, can be extracted by making use of the %-bP% command line +option. + + + + + + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// + +[[CHAPdefconfil]] +The default configuration file +------------------------------ +cindex:[configuration file,default ``walk through''] +cindex:[default,configuration file ``walk through''] +The default configuration file supplied with Exim as _src/configure.default_ +is sufficient for a host with simple mail requirements. As an introduction to +the way Exim is configured, this chapter ``walks through'' the default +configuration, giving brief explanations of the settings. Detailed descriptions +of the options are given in subsequent chapters. The default configuration file +itself contains extensive comments about ways you might want to modify the +initial settings. However, note that there are many options that are not +mentioned at all in the default configuration. + + + +Main configuration settings +~~~~~~~~~~~~~~~~~~~~~~~~~~~ +The main (global) configuration option settings must always come first in the +file. The first thing you'll see in the file, after some initial comments, is +the line + + # primary_hostname = + +This is a commented-out setting of the %primary_hostname% option. Exim needs +to know the official, fully qualified name of your host, and this is where you +can specify it. However, in most cases you do not need to set this option. When +it is unset, Exim uses the 'uname()' system function to obtain the host name. + +The first three non-comment configuration lines are as follows: + + domainlist local_domains = @ + domainlist relay_to_domains = + hostlist relay_from_hosts = 127.0.0.1 + +These are not, in fact, option settings. They are definitions of two named +domain lists and one named host list. Exim allows you to give names to lists of +domains, hosts, and email addresses, in order to make it easier to manage the +configuration file (see section <<SECTnamedlists>>). + +The first line defines a domain list called 'local_domains'; this is used +later in the configuration to identify domains that are to be delivered +on the local host. + +cindex:[@ in a domain list] +There is just one item in this list, the string ``@''. This is a special form of +entry which means ``the name of the local host''. Thus, if the local host is +called 'a.host.example', mail to 'any.user@a.host.example' is expected to +be delivered locally. Because the local host's name is referenced indirectly, +the same configuration file can be used on different hosts. + +The second line defines a domain list called 'relay_to_domains', but the +list itself is empty. Later in the configuration we will come to the part that +controls mail relaying through the local host; it allows relaying to any +domains in this list. By default, therefore, no relaying on the basis of a mail +domain is permitted. + +The third line defines a host list called 'relay_from_hosts'. This list is +used later in the configuration to permit relaying from any host or IP address +that matches the list. The default contains just the IP address of the IPv4 +loopback interface, which means that processes on the local host are able to +submit mail for relaying by sending it over TCP/IP to that interface. No other +hosts are permitted to submit messages for relaying. + +Just to be sure there's no misunderstanding: at this point in the configuration +we aren't actually setting up any controls. We are just defining some domains +and hosts that will be used in the controls that are specified later. + +The next configuration line is a genuine option setting: + + acl_smtp_rcpt = acl_check_rcpt + +This option specifies an 'Access Control List' (ACL) which is to be used +during an incoming SMTP session for every recipient of a message (every +RCPT command). The name of the list is 'acl_check_rcpt', and we will +come to its definition below, in the ACL section of the configuration. ACLs +control which recipients are accepted for an incoming message -- if a +configuration does not provide an ACL to check recipients, no SMTP mail can be +accepted. + +Two commented-out options settings are next: + + # qualify_domain = + # qualify_recipient = + +The first of these specifies a domain that Exim uses when it constructs a +complete email address from a local login name. This is often needed when Exim +receives a message from a local process. If you do not set %qualify_domain%, +the value of %primary_hostname% is used. If you set both of these options, you +can have different qualification domains for sender and recipient addresses. If +you set only the first one, its value is used in both cases. + +cindex:[domain literal,recognizing format] +The following line must be uncommented if you want Exim to recognize +addresses of the form 'user@[10.11.12.13]' that is, with a ``domain literal'' +(an IP address) instead of a named domain. + + # allow_domain_literals + +The RFCs still require this form, but many people think that in the modern +Internet it makes little sense to permit mail to be sent to specific hosts by +quoting their IP addresses. This ancient format has been used by people who +try to abuse hosts by using them for unwanted relaying. However, some +people believe there are circumstances (for example, messages addressed to +'postmaster') where domain literals are still useful. + +The next configuration line is a kind of trigger guard: + + never_users = root + +It specifies that no delivery must ever be run as the root user. The normal +convention is to set up 'root' as an alias for the system administrator. This +setting is a guard against slips in the configuration. +The list of users specified by %never_users% is not, however, the complete +list; the build-time configuration in _Local/Makefile_ has an option called +FIXED_NEVER_USERS specifying a list that cannot be overridden. The +contents of %never_users% are added to this list. By default +FIXED_NEVER_USERS also specifies root. + +When a remote host connects to Exim in order to send mail, the only information +Exim has about the host's identity is its IP address. The next configuration +line, + + host_lookup = * + +specifies that Exim should do a reverse DNS lookup on all incoming connections, +in order to get a host name. This improves the quality of the logging +information, but if you feel it is too expensive, you can remove it entirely, +or restrict the lookup to hosts on ``nearby'' networks. +Note that it is not always possible to find a host name from an IP address, +because not all DNS reverse zones are maintained, and sometimes DNS servers are +unreachable. + +The next two lines are concerned with 'ident' callbacks, as defined by RFC +1413 (hence their names): + + rfc1413_hosts = * + rfc1413_query_timeout = 30s + +These settings cause Exim to make ident callbacks for all incoming SMTP calls. +You can limit the hosts to which these calls are made, or change the timeout +that is used. If you set the timeout to zero, all ident calls are disabled. +Although they are cheap and can provide useful information for tracing problem +messages, some hosts and firewalls have problems with ident calls. This can +result in a timeout instead of an immediate refused connection, leading to +delays on starting up an incoming SMTP session. + +When Exim receives messages over SMTP connections, it expects all addresses to +be fully qualified with a domain, as required by the SMTP definition. However, +if you are running a server to which simple clients submit messages, you may +find that they send unqualified addresses. The two commented-out options: + + # sender_unqualified_hosts = + # recipient_unqualified_hosts = + +show how you can specify hosts that are permitted to send unqualified sender +and recipient addresses, respectively. + +The %percent_hack_domains% option is also commented out: + + # percent_hack_domains = + +It provides a list of domains for which the ``percent hack'' is to operate. This +is an almost obsolete form of explicit email routing. If you do not know +anything about it, you can safely ignore this topic. + +The last two settings in the main part of the default configuration are +concerned with messages that have been ``frozen'' on Exim's queue. When a message +is frozen, Exim no longer continues to try to deliver it. Freezing occurs when +a bounce message encounters a permanent failure because the sender address of +the original message that caused the bounce is invalid, so the bounce cannot be +delivered. This is probably the most common case, but there are also other +conditions that cause freezing, and frozen messages are not always bounce +messages. + + ignore_bounce_errors_after = 2d + timeout_frozen_after = 7d + +The first of these options specifies that failing bounce messages are to be +discarded after 2 days on the queue. The second specifies that any frozen +message (whether a bounce message or not) is to be timed out (and discarded) +after a week. In this configuration, the first setting ensures that no failing +bounce message ever lasts a week. + + + +ACL configuration +~~~~~~~~~~~~~~~~~ +cindex:[default,ACLs] +cindex:[{ACL},default configuration] +In the default configuration, the ACL section follows the main configuration. +It starts with the line + + begin acl + +and it contains the definition of one ACL called 'acl_check_rcpt' that was +referenced in the setting of %acl_smtp_rcpt% above. + +cindex:[RCPT,ACL for] +This ACL is used for every RCPT command in an incoming SMTP message. Each +RCPT command specifies one of the message's recipients. The ACL statements +are considered in order, until the recipient address is either accepted or +rejected. The RCPT command is then accepted or rejected, according to the +result of the ACL processing. + + acl_check_rcpt: + +This line, consisting of a name terminated by a colon, marks the start of the +ACL, and names it. + + accept hosts = : + +This ACL statement accepts the recipient if the sending host matches the list. +But what does that strange list mean? It doesn't actually contain any host +names or IP addresses. The presence of the colon puts an empty item in the +list; Exim matches this only if the incoming message didn't come from a remote +host. The colon is important. Without it, the list itself is empty, and can +never match anything. + +What this statement is doing is to accept unconditionally all recipients in +messages that are submitted by SMTP from local processes using the standard +input and output (that is, not using TCP/IP). A number of MUAs operate in this +manner. + + deny domains = +local_domains + local_parts = ^[.] : ^.*[@%!/|] + + deny domains = !+local_domains + local_parts = ^[./|] : ^.*[@%!] : ^.*/\\.\\./ + +These statements are concerned with local parts that contain any of the +characters ``@'', ``%'', ``!'', ``/'', ``|'', or dots in unusual places. Although these +characters are entirely legal in local parts (in the case of ``@'' and leading +dots, only if correctly quoted), they do not commonly occur in Internet mail +addresses. + +The first three have in the past been associated with explicitly routed +addresses (percent is still sometimes used -- see the %percent_hack_domains% +option). Addresses containing these characters are regularly tried by spammers +in an attempt to bypass relaying restrictions, and also by open relay testing +programs. Unless you really need them it is safest to reject these characters +at this early stage. This configuration is heavy-handed in rejecting these +characters for all messages it accepts from remote hosts. This is a deliberate +policy of being as safe as possible. + +The first rule above is stricter, and is applied to messages that are addressed +to one of the local domains handled by this host. This is implemented by the +first condition, which restricts it to domains that are listed in the +'local_domains' domain list. The ``+'' character is used to indicate a +reference to a named list. In this configuration, there is just one domain in +'local_domains', but in general there may be many. + +The second condition on the first statement uses two regular expressions to +block local parts that begin with a dot or contain ``@'', ``%'', ``!'', ``/'', or ``|''. +If you have local accounts that include these characters, you will have to +modify this rule. + +Empty components (two dots in a row) are not valid in RFC 2822, but Exim +allows them because they have been encountered in practice. (Consider local +parts constructed as ``first-initial.second-initial.family-name'' when applied to +someone like the author of Exim, who has no second initial.) However, a local +part starting with a dot or containing ``/../'' can cause trouble if it is used +as part of a file name (for example, for a mailing list). This is also true for +local parts that contain slashes. A pipe symbol can also be troublesome if the +local part is incorporated unthinkingly into a shell command line. + +The second rule above applies to all other domains, and is less strict. This +allows your own users to send outgoing messages to sites that use slashes +and vertical bars in their local parts. It blocks local parts that begin +with a dot, slash, or vertical bar, but allows these characters within the +local part. However, the sequence ``/../'' is barred. The use of ``@'', ``%'', and +``!'' is blocked, as before. The motivation here is to prevent your users (or +your users' viruses) from mounting certain kinds of attack on remote sites. + + accept local_parts = postmaster + domains = +local_domains + +This statement, which has two conditions, accepts an incoming address if the +local part is 'postmaster' and the domain is one of those listed in the +'local_domains' domain list. The ``+'' character is used to indicate a +reference to a named list. In this configuration, there is just one domain in +'local_domains', but in general there may be many. + +The presence of this statement means that mail to postmaster is never blocked +by any of the subsequent tests. This can be helpful while sorting out problems +in cases where the subsequent tests are incorrectly denying access. + + require verify = sender + +This statement requires the sender address to be verified before any subsequent +ACL statement can be used. If verification fails, the incoming recipient +address is refused. Verification consists of trying to route the address, to +see if a +bounce +message could be delivered to it. In the case of remote addresses, basic +verification checks only the domain, but 'callouts' can be used for more +verification if required. Section <<SECTaddressverification>> discusses the +details of address verification. + +.... +# deny message = rejected because $sender_host_address is \ +# in a black list at $dnslist_domain\n\ +# $dnslist_text +# dnslists = black.list.example +# +# warn message = X-Warning: $sender_host_address is \ +# in a black list at $dnslist_domain +# log_message = found in $dnslist_domain +# dnslists = black.list.example +.... + +These commented-out lines are examples of how you could configure Exim to check +sending hosts against a DNS black list. The first statement rejects messages +from blacklisted hosts, whereas the second merely inserts a warning header +line. + + accept domains = +local_domains + endpass + message = unknown user + verify = recipient + +This statement accepts the incoming recipient address if its domain is one of +the local domains, but only if the address can be verified. Verification of +local addresses normally checks both the local part and the domain. The +%endpass% line needs some explanation: if the condition above %endpass% fails, +that is, if the address is not in a local domain, control is passed to the next +ACL statement. However, if the condition below %endpass% fails, that is, if a +recipient in a local domain cannot be verified, access is denied and the +recipient is rejected. + +cindex:[customizing,ACL failure message] +The %message% modifier provides a customized error message for the failure. + + accept domains = +relay_to_domains + endpass + message = unrouteable address + verify = recipient + +This statement accepts the incoming recipient address if its domain is one of +the domains for which this host is a relay, but again, only if the address can +be verified. + + accept hosts = +relay_from_hosts + +Control reaches this statement only if the recipient's domain is neither a +local domain, nor a relay domain. The statement accepts the address if the +message is coming from one of the hosts that are defined as being allowed to +relay through this host. Recipient verification is omitted here, because in +many cases the clients are dumb MUAs that do not cope well with SMTP error +responses. If you are actually relaying out from MTAs, you should probably add +recipient verification here. + + accept authenticated = * + +Control reaches here for attempts to relay to arbitrary domains from arbitrary +hosts. The statement accepts the address only if the client host has +authenticated itself. The default configuration does not define any +authenticators, which means that no client can in fact authenticate. You will +need to add authenticator definitions if you want to make use of this ACL +statement. + + deny message = relay not permitted + +The final statement denies access, giving a specific error message. Reaching +the end of the ACL also causes access to be denied, but with the generic +message ``administrative prohibition''. + + + +Router configuration +~~~~~~~~~~~~~~~~~~~~ +cindex:[default,routers] +cindex:[routers,default] +The router configuration comes next in the default configuration, introduced +by the line + + begin routers + +Routers are the modules in Exim that make decisions about where to send +messages. An address is passed to each router in turn, until it is either +accepted, or failed. This means that the order in which you define the routers +matters. Each router is fully described in its own chapter later in this +manual. Here we give only brief overviews. + + # domain_literal: + # driver = ipliteral + # domains = !+local_domains + # transport = remote_smtp + +cindex:[domain literal,default router] +This router is commented out because the majority of sites do not want to +support domain literal addresses (those of the form 'user@[10.9.8.7]'). If +you uncomment this router, you also need to uncomment the setting of +%allow_domain_literals% in the main part of the configuration. + + dnslookup: + driver = dnslookup + domains = ! +local_domains + transport = remote_smtp + ignore_target_hosts = 0.0.0.0 : 127.0.0.0/8 + no_more + +The first uncommented router handles addresses that do not involve any local +domains. This is specified by the line + + domains = ! +local_domains + +The %domains% option lists the domains to which this router applies, but the +exclamation mark is a negation sign, so the router is used only for domains +that are not in the domain list called 'local_domains' (which was defined at +the start of the configuration). The plus sign before 'local_domains' +indicates that it is referring to a named list. Addresses in other domains are +passed on to the following routers. + +The name of the router driver is ^dnslookup^, +and is specified by the %driver% option. Do not be confused by the fact that +the name of this router instance is the same as the name of the driver. The +instance name is arbitrary, but the name set in the %driver% option must be one +of the driver modules that is in the Exim binary. + +The ^dnslookup^ router routes addresses by looking up their domains in the +DNS in order to obtain a list of hosts to which the address is routed. If the +router succeeds, the address is queued for the ^remote_smtp^ transport, as +specified by the %transport% option. If the router does not find the domain in +the DNS, no further routers are tried because of the %no_more% setting, so the +address fails and is bounced. + +The %ignore_target_hosts% option specifies a list of IP addresses that are to +be entirely ignored. This option is present because a number of cases have been +encountered where MX records in the DNS point to host names +whose IP addresses are 0.0.0.0 or are in the 127 subnet (typically 127.0.0.1). +Completely ignoring these IP addresses causes Exim to fail to route the +email address, so it bounces. Otherwise, Exim would log a routing problem, and +continue to try to deliver the message periodically until the address timed +out. + + system_aliases: + driver = redirect + allow_fail + allow_defer + data = ${lookup{$local_part}lsearch{/etc/aliases}} + # user = exim + file_transport = address_file + pipe_transport = address_pipe + +Control reaches this and subsequent routers only for addresses in the local +domains. This router checks to see whether the local part is defined as an +alias in the _/etc/aliases_ file, and if so, redirects it according to the +data that it looks up from that file. If no data is found for the local part, +the value of the %data% option is empty, causing the address to be passed to +the next router. + +_/etc/aliases_ is a conventional name for the system aliases file that is +often used. That is why it is referenced by from the default configuration +file. However, you can change this by setting SYSTEM_ALIASES_FILE in +_Local/Makefile_ before building Exim. + + userforward: + driver = redirect + check_local_user + file = $home/.forward + no_verify + no_expn + check_ancestor + # allow_filter + file_transport = address_file + pipe_transport = address_pipe + reply_transport = address_reply + +This is the most complicated router in the default configuration. It is another +redirection router, but this time it is looking for forwarding data set up by +individual users. The %check_local_user% setting means that the first thing it +does is to check that the local part of the address is the login name of a +local user. If it is not, the router is skipped. When a local user is found, +the file called _.forward_ in the user's home directory is consulted. If it +does not exist, or is empty, the router declines. Otherwise, the contents of +_.forward_ are interpreted as redirection data (see chapter <<CHAPredirect>> +for more details). + +cindex:[Sieve filter,enabling in default router] +Traditional _.forward_ files contain just a list of addresses, pipes, or +files. Exim supports this by default. However, if %allow_filter% is set (it is +commented out by default), the contents of the file are interpreted as a set of +Exim or Sieve filtering instructions, provided the file begins with ``#Exim +filter'' or ``#Sieve filter'', respectively. User filtering is discussed in the +separate document entitled 'Exim's interfaces to mail filtering'. + +The %no_verify% and %no_expn% options mean that this router is skipped when +verifying addresses, or when running as a consequence of an SMTP EXPN +command. +There are two reasons for doing this: + +. Whether or not a local user has a _.forward_ file is not really relevant when +checking an address for validity; it makes sense not to waste resources doing +unnecessary work. + +. More importantly, when Exim is verifying addresses or handling an EXPN +command during an SMTP session, it is running as the Exim user, not as root. +The group is the Exim group, and no additional groups are set up. +It may therefore not be possible for Exim to read users' _.forward_ files at +this time. + + +The setting of %check_ancestor% prevents the router from generating a new +address that is the same as any previous address that was redirected. (This +works round a problem concerning a bad interaction between aliasing and +forwarding -- see section <<SECTredlocmai>>). + +The final three option settings specify the transports that are to be used when +forwarding generates a direct delivery to a file, or to a pipe, or sets up an +auto-reply, respectively. For example, if a _.forward_ file contains + + a.nother@elsewhere.example, /home/spqr/archive + +the delivery to _/home/spqr/archive_ is done by running the %address_file% +transport. + + localuser: + driver = accept + check_local_user + transport = local_delivery + +The final router sets up delivery into local mailboxes, provided that the local +part is the name of a local login, by accepting the address and queuing it for +the ^local_delivery^ transport. Otherwise, we have reached the end of the +routers, so the address is bounced. + + + +Transport configuration +~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[default,transports] +cindex:[transports,default] +Transports define mechanisms for actually delivering messages. They operate +only when referenced from routers, so the order in which they are defined does +not matter. The transports section of the configuration starts with + + begin transports + +One remote transport and four local transports are defined. + + remote_smtp: + driver = smtp + +This transport is used for delivering messages over SMTP connections. All its +options are defaulted. The list of remote hosts comes from the router. + + local_delivery: + driver = appendfile + file = /var/mail/$local_part + delivery_date_add + envelope_to_add + return_path_add + # group = mail + # mode = 0660 + +This ^appendfile^ transport is used for local delivery to user mailboxes in +traditional BSD mailbox format. By default it runs under the uid and gid of the +local user, which requires the sticky bit to be set on the _/var/mail_ +directory. Some systems use the alternative approach of running mail deliveries +under a particular group instead of using the sticky bit. The commented options +show how this can be done. + +Exim adds three headers to the message as it delivers it: 'Delivery-date:', +'Envelope-to:' and 'Return-path:'. This action is requested by the three +similarly-named options above. + + address_pipe: + driver = pipe + return_output + +This transport is used for handling deliveries to pipes that are generated by +redirection (aliasing or users' _.forward_ files). The %return_output% +option specifies that any output generated by the pipe is to be returned to the +sender. + + address_file: + driver = appendfile + delivery_date_add + envelope_to_add + return_path_add + +This transport is used for handling deliveries to files that are generated by +redirection. The name of the file is not specified in this instance of +^appendfile^, because it comes from the ^redirect^ router. + + address_reply: + driver = autoreply + +This transport is used for handling automatic replies generated by users' +filter files. + + + +Default retry rule +~~~~~~~~~~~~~~~~~~ +cindex:[retry,default rule] +cindex:[default,retry rule] +The retry section of the configuration file contains rules which affect the way +Exim retries deliveries that cannot be completed at the first attempt. It is +introduced by the line + + begin retry + +In the default configuration, there is just one rule, which applies to all +errors: + +&&& +`\* \* F,2h,15m; G,16h,1h,1.5; F,4d,6h` +&&& + +This causes any temporarily failing address to be retried every 15 minutes for +2 hours, then at intervals starting at one hour and increasing by a factor of +1.5 until 16 hours have passed, then every 6 hours up to 4 days. If an address +is not delivered after 4 days of failure, it is bounced. + + + +Rewriting configuration +~~~~~~~~~~~~~~~~~~~~~~~ +The rewriting section of the configuration, introduced by + + begin rewrite + +contains rules for rewriting addresses in messages as they arrive. There are no +rewriting rules in the default configuration file. + + + +Authenticators configuration +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[AUTH,configuration] +The authenticators section of the configuration, introduced by + + begin authenticators + +defines mechanisms for the use of the SMTP AUTH command. No authenticators +are specified in the default configuration file. + + + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// + +[[CHAPregexp]] +Regular expressions +------------------- + +cindex:[regular expressions,library] +cindex:[PCRE] +Exim supports the use of regular expressions in many of its options. It +uses the PCRE regular expression library; this provides regular expression +matching that is compatible with Perl 5. The syntax and semantics of +regular expressions is discussed in many Perl reference books, and also in +Jeffrey Friedl's 'Mastering Regular Expressions', which is published by +O'Reilly (*http://www.oreilly.com/catalog/regex/[]*). + +The documentation for the syntax and semantics of the regular expressions that +are supported by PCRE is included in plain text in the file +_doc/pcrepattern.txt_ in the Exim distribution, and also in the HTML +tarbundle of Exim documentation, and as an appendix to the Exim book +(*http://www.uit.co.uk/exim-book/[]*). + +It describes in detail the features of the regular expressions that PCRE +supports, so no further description is included here. The PCRE functions are +called from Exim using the default option settings (that is, with no PCRE +options set), except that the PCRE_CASELESS option is set when the +matching is required to be case-insensitive. + +In most cases, when a regular expression is required in an Exim configuration, +it has to start with a circumflex, in order to distinguish it from plain text +or an ``ends with'' wildcard. In this example of a configuration setting, the +second item in the colon-separated list is a regular expression. + + domains = a.b.c : ^\\d{3} : *.y.z : ... + +The doubling of the backslash is required because of string expansion that +precedes interpretation -- see section <<SECTlittext>> for more discussion of +this issue, and a way of avoiding the need for doubling backslashes. The +regular expression that is eventually used in this example contains just one +backslash. The circumflex is included in the regular expression, and has the +normal effect of ``anchoring'' it to the start of the string that is being +matched. + +There are, however, two cases where a circumflex is not required for the +recognition of a regular expression: these are the %match% condition in a +string expansion, and the %matches% condition in an Exim filter file. In these +cases, the relevant string is always treated as a regular expression; if it +does not start with a circumflex, the expression is not anchored, and can match +anywhere in the subject string. + +In all cases, if you want a regular expression to match at the end of a string, +you must code the \$ metacharacter to indicate this. For example: + + domains = ^\\d{3}\\.example + +matches the domain '123.example', but it also matches '123.example.com'. +You need to use: + + domains = ^\\d{3}\\.example\$ + +if you want 'example' to be the top-level domain. (The backslash before the +\$ is another artefact of string expansion.) + + + +Testing regular expressions +~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[testing,regular expressions] +cindex:[regular expressions,testing] +cindex:['pcretest'] +A program called 'pcretest' forms part of the PCRE distribution and is built +with PCRE during the process of building Exim. It is primarily intended for +testing PCRE itself, but it can also be used for experimenting with regular +expressions. After building Exim, the binary can be found in the build +directory (it is not installed anywhere automatically). There is documentation +of various options in _doc/pcretest.txt_, but for simple testing, none are +needed. This is the output of a sample run of 'pcretest': + +&&& +` re> `*`/^([^@]+)@.+\.(ac|edu)\.(?!kr)[a-z]{2}$/`* +`data> `*`x@y.ac.uk`* +` 0: x@y.ac.uk` +` 1: x` +` 2: ac` +`data> `*`x@y.ac.kr`* +`No match` +`data> `*`x@y.edu.com`* +`No match` +`data> `*`x@y.edu.co`* +` 0: x@y.edu.co` +` 1: x` +` 2: edu` +&&& + +Input typed by the user is shown in bold face. After the ``re>'' prompt, a +regular expression enclosed in delimiters is expected. If this compiles without +error, ``data>'' prompts are given for strings against which the expression is +matched. An empty data line causes a new regular expression to be read. If the +match is successful, the captured substring values (that is, what would be in +the variables $0$, $1$, $2$, etc.) are shown. The above example tests for an +email address whose domain ends with either ``ac'' or ``edu'' followed by a +two-character top-level domain that is not ``kr''. The local part is captured +in $1$ and the ``ac'' or ``edu'' in $2$. + + + + + + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// + +[[CHAPfdlookup]] +File and database lookups +------------------------- +cindex:[file,lookup] +cindex:[database lookups] +cindex:[lookup,description of] +Exim can be configured to look up data in files or databases as it processes +messages. Two different kinds of syntax are used: + +. A string that is to be expanded may contain explicit lookup requests. These +cause parts of the string to be replaced by data that is obtained from the +lookup. + +. Lists of domains, hosts, and email addresses can contain lookup requests as a +way of avoiding excessively long linear lists. In this case, the data that is +returned by the lookup is often (but not always) discarded; whether the lookup +succeeds or fails is what really counts. These kinds of list are described in +chapter <<CHAPdomhosaddlists>>. + +It is easy to confuse the two different kinds of lookup, especially as the +lists that may contain the second kind are always expanded before being +processed as lists. Therefore, they may also contain lookups of the first kind. +Be careful to distinguish between the following two examples: + + domains = ${lookup{$sender_host_address}lsearch{/some/file}} + domains = lsearch;/some/file + +The first uses a string expansion, the result of which must be a domain list. +String expansions are described in detail in chapter <<CHAPexpand>>. The +expansion takes place first, and the file that is searched could contain lines +like this: + + 192.168.3.4: domain1 : domain2 : ... + 192.168.1.9: domain3 : domain4 : ... + +Thus, the result of the expansion is a list of domains (and possibly other +types of item that are allowed in domain lists). + +In the second case, the lookup is a single item in a domain list. It causes +Exim to use a lookup to see if the domain that is being processed can be found +in the file. The file could contains lines like this: + + domain1: + domain2: + +Any data that follows the keys is not relevant when checking that the domain +matches the list item. + +It is possible to use both kinds of lookup at once. Consider a file containing +lines like this: + + 192.168.5.6: lsearch;/another/file + +If the value of $sender_host_address$ is 192.168.5.6, expansion of the +first %domains% setting above generates the second setting, which therefore +causes a second lookup to occur. + +The rest of this chapter describes the different lookup types that are +available. Any of them can be used in either of the circumstances described +above. The syntax requirements for the two cases are described in chapters +<<CHAPexpand>> and <<CHAPdomhosaddlists>>, respectively. + + +Lookup types +~~~~~~~~~~~~ +cindex:[lookup,types of] +cindex:[single-key lookup,definition of] +Two different styles of data lookup are implemented: + +- The 'single-key' style requires the specification of a file in which to look, +and a single key to search for. The key must be a non-empty string for the +lookup to succeed. The lookup type determines how the file is searched. + +- cindex:[query-style lookup,definition of] +The 'query' style accepts a generalized database query. +No particular key value is assumed by Exim for query-style lookups. You can +use whichever Exim variable(s) you need to construct the database query. + +The code for each lookup type is in a separate source file that is included in +the binary of Exim only if the corresponding compile-time option is set. The +default settings in _src/EDITME_ are: + + LOOKUP_DBM=yes + LOOKUP_LSEARCH=yes + +which means that only linear searching and DBM lookups are included by default. +For some types of lookup (e.g. SQL databases), you need to install appropriate +libraries and header files before building Exim. + + + + +[[SECTsinglekeylookups]] +Single-key lookup types +~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[lookup,single-key types] +cindex:[single-key lookup,list of types] +The following single-key lookup types are implemented: + +- cindex:[cdb,description of] +cindex:[lookup,cdb] +cindex:[binary zero,in lookup key] +^cdb^: The given file is searched as a Constant DataBase file, using the key +string without a terminating binary zero. The cdb format is designed for +indexed files that are read frequently and never updated, except by total +re-creation. As such, it is particulary suitable for large files containing +aliases or other indexed data referenced by an MTA. Information about cdb can +be found in several places: ++ +&&& +*http://www.pobox.com/~djb/cdb.html[]* +*ftp://ftp.corpit.ru/pub/tinycdb/[]* +*http://packages.debian.org/stable/utils/freecdb.html[]* +&&& ++ +A cdb distribution is not needed in order to build Exim with cdb support, +because the code for reading cdb files is included directly in Exim itself. +However, no means of building or testing cdb files is provided with Exim, so +you need to obtain a cdb distribution in order to do this. + +- cindex:[DBM,lookup type] +cindex:[lookup,dbm] +cindex:[binary zero,in lookup key] +^dbm^: Calls to DBM library functions are used to extract data from the given +DBM file by looking up the record with the given key. A terminating binary +zero is included in the key that is passed to the DBM library. See section +<<SECTdb>> for a discussion of DBM libraries. ++ +cindex:[Berkeley DB library,file format] +For all versions of Berkeley DB, Exim uses the DB_HASH style of database +when building DBM files using the %exim_dbmbuild% utility. However, when using +Berkeley DB versions 3 or 4, it opens existing databases for reading with the +DB_UNKNOWN option. This enables it to handle any of the types of database +that the library supports, and can be useful for accessing DBM files created by +other applications. (For earlier DB versions, DB_HASH is always used.) + +- cindex:[lookup,dbmnz] +cindex:[lookup,dbm -- terminating zero] +cindex:[binary zero,in lookup key] +cindex:[Courier] +cindex:[_/etc/userdbshadow.dat_] +cindex:[dmbnz lookup type] +^dbmnz^: This is the same as ^dbm^, except that a terminating binary zero +is not included in the key that is passed to the DBM library. You may need this +if you want to look up data in files that are created by or shared with some +other application that does not use terminating zeros. For example, you need to +use ^dbmnz^ rather than ^dbm^ if you want to authenticate incoming SMTP +calls using the passwords from Courier's _/etc/userdbshadow.dat_ file. Exim's +utility program for creating DBM files ('exim_dbmbuild') includes the zeros +by default, but has an option to omit them (see section <<SECTdbmbuild>>). + +- cindex:[lookup,dsearch] +cindex:[dsearch lookup type] +^dsearch^: The given file must be a directory; this is searched for a file +whose name is the key. The key may not contain any forward slash characters. +The result of a successful lookup is the name of the file. An example of how +this lookup can be used to support virtual domains is given in section +<<SECTvirtualdomains>>. + +- cindex:[lookup,iplsearch] +cindex:[iplsearch lookup type] +^iplsearch^: The given file is a text file containing keys and data. A key is +terminated by a colon or white space or the end of the line. The keys in the +file must be IP addresses, or IP addresses with CIDR masks. Keys that involve +IPv6 addresses must be enclosed in quotes to prevent the first internal colon +being interpreted as a key terminator. For example: + + 1.2.3.4: data for 1.2.3.4 + 192.168.0.0/16 data for 192.168.0.0/16 + "abcd::cdab": data for abcd::cdab + "abcd:abcd::/32" data for abcd:abcd::/32 ++ +The key for an ^iplsearch^ lookup must be an IP address (without a mask). The +file is searched linearly, using the CIDR masks where present, until a matching +key is found. The first key that matches is used; there is no attempt to find a +``best'' match. Apart from the way the keys are matched, the processing for +^iplsearch^ is the same as for ^lsearch^. ++ +*Warning 1*: Unlike most other single-key lookup types, a file of data for +^iplsearch^ can 'not' be turned into a DBM or cdb file, because those +lookup types support only literal keys. ++ +*Warning 2*: In a host list, you must always use ^net-iplsearch^ so that +the implicit key is the host's IP address rather than its name (see section +<<SECThoslispatsikey>>). + +- cindex:[linear search] +cindex:[lookup,lsearch] +cindex:[lsearch lookup type] +^lsearch^: The given file is a text file that is searched linearly for a +line beginning with the search key, terminated by a colon or white space or the +end of the line. The first occurrence that is found in the file is used. White +space between the key and the colon is permitted. The remainder of the line, +with leading and trailing white space removed, is the data. This can be +continued onto subsequent lines by starting them with any amount of white +space, but only a single space character is included in the data at such a +junction. If the data begins with a colon, the key must be terminated by a +colon, for example: + + baduser: :fail: ++ +Empty lines and lines beginning with # are ignored, even if they occur in the +middle of an item. This is the traditional textual format of alias files. Note +that the keys in an ^lsearch^ file are literal strings. There is no +wildcarding of any kind. ++ +cindex:[lookup,lsearch -- colons in keys] +cindex:[whitespace,in lsearch key] +In most ^lsearch^ files, keys are not required to contain colons or # +characters, or whitespace. However, if you need this feature, it is available. +If a key begins with a doublequote character, it is terminated only by a +matching quote (or end of line), and the normal escaping rules apply to its +contents (see section <<SECTstrings>>). An optional colon is permitted after +quoted keys (exactly as for unquoted keys). There is no special handling of +quotes for the data part of an ^lsearch^ line. + +- cindex:[NIS lookup type] +cindex:[lookup,NIS] +cindex:[binary zero,in lookup key] +^nis^: The given file is the name of a NIS map, and a NIS lookup is done with +the given key, without a terminating binary zero. There is a variant called +^nis0^ which does include the terminating binary zero in the key. This is +reportedly needed for Sun-style alias files. Exim does not recognize NIS +aliases; the full map names must be used. + +- cindex:[wildlsearch lookup type] +cindex:[lookup,wildlsearch] +cindex:[nwildlsearch lookup type] +cindex:[lookup,nwildlsearch] +^wildlsearch^ or ^nwildlsearch^: These search a file linearly, like +^lsearch^, but instead of being interpreted as a literal string, each key may +be wildcarded. The difference between these two lookup types is that for +^wildlsearch^, each key in the file is string-expanded before being used, +whereas for ^nwildlsearch^, no expansion takes place. ++ +Like ^lsearch^, the testing is done case-insensitively. The following forms +of wildcard are recognized: ++ +-- +.. The string may begin with an asterisk to mean ``ends with''. For example: + + *.a.b.c data for anything.a.b.c + *fish data for anythingfish + +.. The string may begin with a circumflex to indicate a regular expression. For +example, for ^wildlsearch^: + + ^\N\d+\.a\.b\N data for <digits>.a.b + +Note the use of `\N` to disable expansion of the contents of the regular +expression. If you are using ^nwildlsearch^, where the keys are not +string-expanded, the equivalent entry is: + + ^\d+\.a\.b data for <digits>.a.b + +If the regular expression contains white space or colon characters, you must +either quote it (see ^lsearch^ above), or represent these characters in other +ways. For example, `\s` can be used for white space and `\x3A` for a +colon. This may be easier than quoting, because if you quote, you have to +escape all the backslashes inside the quotes. + +.. Although I cannot see it being of much use, the general matching function +that is used to implement ^(n)wildlsearch^ means that the string may begin with +a lookup name terminated by a semicolon, and followed by lookup data. For +example: + + cdb;/some/file data for keys that match the file + +The data that is obtained from the nested lookup is discarded. +-- ++ +Keys that do not match any of these patterns are interpreted literally. The +continuation rules for the data are the same as for ^lsearch^, and keys may +be followed by optional colons. ++ +*Warning*: Unlike most other single-key lookup types, a file of data for +^(n)wildlsearch^ can 'not' be turned into a DBM or cdb file, because those +lookup types support only literal keys. + + + +Query-style lookup types +~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[lookup,query-style types] +cindex:[query-style lookup,list of types] +The supported query-style lookup types are listed below. Further details about +many of them are given in later sections. + +- cindex:[DNS,as a lookup type] +cindex:[lookup,DNS] +^dnsdb^: This does a DNS search for one or more records whose domain names are +given in the supplied query. The resulting data is the contents of the records. +See section <<SECTdnsdb>>. + +- cindex:[Interbase lookup type] +cindex:[lookup,Interbase] +^ibase^: This does a lookup in an Interbase database. + +- cindex:[LDAP,lookup type] +cindex:[lookup,LDAP] +^ldap^: This does an LDAP lookup using a query in the form of a URL, and +returns attributes from a single entry. There is a variant called ^ldapm^ +that permits values from multiple entries to be returned. A third variant +called ^ldapdn^ returns the Distinguished Name of a single entry instead of +any attribute values. See section <<SECTldap>>. + +- cindex:[MySQL,lookup type] +cindex:[lookup,MySQL] +^mysql^: The format of the query is an SQL statement that is passed to a MySQL +database. See section <<SECTsql>>. + +- cindex:[NIS+ lookup type] +cindex:[lookup,NIS+] +^nisplus^: This does a NIS+ lookup using a query that can specify the name of +the field to be returned. See section <<SECTnisplus>>. + +- cindex:[Oracle,lookup type] +cindex:[lookup,Oracle] +^oracle^: The format of the query is an SQL statement that is passed to an +Oracle database. See section <<SECTsql>>. + +- cindex:[lookup,passwd] +cindex:[passwd lookup type] +cindex:[_/etc/passwd_] +^passwd^ is a query-style lookup with queries that are just user names. The +lookup calls 'getpwnam()' to interrogate the system password data, and on +success, the result string is the same as you would get from an ^lsearch^ +lookup on a traditional _/etc/passwd file_, though with `*` for the +password value. For example: + + *:42:42:King Rat:/home/kr:/bin/bash + +- cindex:[PostgreSQL lookup type] +cindex:[lookup,PostgreSQL] +^pgsql^: The format of the query is an SQL statement that is passed to a +PostgreSQL database. See section <<SECTsql>>. + +- ^testdb^: This is a lookup type that is used for testing Exim. It is +not likely to be useful in normal operation. + +- cindex:[whoson lookup type] +cindex:[lookup,whoson] +^whoson^: 'Whoson' (*http://whoson.sourceforge.net[]*) is a proposed +Internet protocol that allows Internet server programs to check whether a +particular (dynamically allocated) IP address is currently allocated to a known +(trusted) user and, optionally, to obtain the identity of the said user. In +Exim, this can be used to implement ``POP before SMTP'' checking using ACL +statements such as ++ +.... +require condition = \ + ${lookup whoson {$sender_host_address}{yes}{no}} +.... ++ +The query consists of a single IP address. The value returned is the name of +the authenticated user. + + + +Temporary errors in lookups +~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[lookup,temporary error in] +Lookup functions can return temporary error codes if the lookup cannot be +completed. For example, a NIS or LDAP database might be unavailable. For this +reason, it is not advisable to use a lookup that might do this for critical +options such as a list of local domains. + +When a lookup cannot be completed in a router or transport, delivery +of the message (to the relevant address) is deferred, as for any other +temporary error. In other circumstances Exim may assume the lookup has failed, +or may give up altogether. + + + +[[SECTdefaultvaluelookups]] +Default values in single-key lookups +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[wildcard lookups] +cindex:[lookup,default values] +cindex:[lookup,wildcard] +cindex:[lookup,\* added to type] +cindex:[default,in single-key lookups] +In this context, a ``default value'' is a value specified by the administrator +that is to be used if a lookup fails. + +If ``\*'' is added to a single-key lookup type (for example, %lsearch\*%) and +the initial lookup fails, the key ``\*'' is looked up in the file to provide +a default value. See also the section on partial matching below. + +cindex:[\*@ with single-key lookup] +cindex:[lookup,\*@ added to type] +cindex:[alias file,per-domain default] +Alternatively, if ``\*@'' is added to a single-key lookup type (for example +\dbm\*\) then, if the initial lookup fails and the key contains an @ +character, a second lookup is done with everything before the last @ replaced +by \*. This makes it possible to provide per-domain defaults in alias files +that include the domains in the keys. If the second lookup fails (or doesn't +take place because there is no @ in the key), ``\*'' is looked up. +For example, a ^redirect^ router might contain: + + data = ${lookup{$local_part@$domain}lsearch*@{/etc/mixed-aliases}} + +Suppose the address that is being processed is 'jane@eyre.example'. Exim +looks up these keys, in this order: + + jane@eyre.example + *@eyre.example + * + +The data is taken from whichever key it finds first. *Note*: in an +^lsearch^ file, this does not mean the first of these keys in the file. A +complete scan is done for each key, and only if it is not found at all does +Exim move on to try the next key. + + + +[[SECTpartiallookup]] +Partial matching in single-key lookups +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[partial matching] +cindex:[wildcard lookups] +cindex:[lookup,partial matching] +cindex:[lookup,wildcard] +cindex:[asterisk,in search type] +The normal operation of a single-key lookup is to search the file for an exact +match with the given key. However, in a number of situations where domains are +being looked up, it is useful to be able to do partial matching. In this case, +information in the file that has a key starting with ``\*.'' is matched by any +domain that ends with the components that follow the full stop. For example, if +a key in a DBM file is + + *.dates.fict.example + +then when partial matching is enabled this is matched by (amongst others) +'2001.dates.fict.example' and '1984.dates.fict.example'. It is also matched +by 'dates.fict.example', if that does not appear as a separate key in the +file. + +*Note*: Partial matching is not available for query-style lookups. It is +also not available for any lookup items in address lists (see section +<<SECTaddresslist>>). + +Partial matching is implemented by doing a series of separate lookups using +keys constructed by modifying the original subject key. This means that it can +be used with any of the single-key lookup types, provided that +partial matching keys +beginning with a special prefix (default ``\*.'') are included in the data file. +Keys in the file that do not begin with the prefix are matched only by +unmodified subject keys when partial matching is in use. + +Partial matching is requested by adding the string ``partial-'' to the front of +the name of a single-key lookup type, for example, %partial-dbm%. When this is +done, the subject key is first looked up unmodified; if that fails, ``\*.'' +is added at the start of the subject key, and it is looked up again. If that +fails, further lookups are tried with dot-separated components removed +from the start of the subject key, one-by-one, and ``\*.'' added on the front of +what remains. + +A minimum number of two non-\* components are required. This can be adjusted +by including a number before the hyphen in the search type. For example, +%partial3-lsearch% specifies a minimum of three non-\* components in the +modified keys. Omitting the number is equivalent to ``partial2-''. If the subject +key is '2250.dates.fict.example' then the following keys are looked up when +the minimum number of non-\* components is two: + + 2250.dates.fict.example + *.2250.dates.fict.example + *.dates.fict.example + *.fict.example + +As soon as one key in the sequence is successfully looked up, the lookup +finishes. + +cindex:[lookup,partial matching -- changing prefix] +cindex:[prefix,for partial matching] +The use of ``\*.'' as the partial matching prefix is a default that can be +changed. The motivation for this feature is to allow Exim to operate with file +formats that are used by other MTAs. A different prefix can be supplied in +parentheses instead of the hyphen after ``partial''. For example: + + domains = partial(.)lsearch;/some/file + +In this example, if the domain is 'a.b.c', the sequence of lookups is +`a.b.c`, `.a.b.c`, and `.b.c` (the default minimum of 2 non-wild +components is unchanged). The prefix may consist of any punctuation characters +other than a closing parenthesis. It may be empty, for example: + + domains = partial1()cdb;/some/file + +For this example, if the domain is 'a.b.c', the sequence of lookups is +`a.b.c`, `b.c`, and `c`. + +If ``partial0'' is specified, what happens at the end (when the lookup with just +one non-wild component has failed, and the original key is shortened right down +to the null string) depends on the prefix: + +- If the prefix has zero length, the whole lookup fails. + +- If the prefix has length 1, a lookup for just the prefix is done. For +example, the final lookup for ``partial0(.)'' is for `.` alone. + +- Otherwise, if the prefix ends in a dot, the dot is removed, and the +remainder is looked up. With the default prefix, therefore, the final lookup is +for ``\*'' on its own. + +- Otherwise, the whole prefix is looked up. + + +If the search type ends in ``\*'' or ``\*@'' (see section +<<SECTdefaultvaluelookups>> above), the search for an ultimate default that this +implies happens after all partial lookups have failed. If ``partial0'' is +specified, adding ``\*'' to the search type has no effect with the default +prefix, because the ``\*'' key is already included in the sequence of partial +lookups. However, there might be a use for lookup types such as +``partial0(.)lsearch\*''. + +The use of ``\*'' in lookup partial matching differs from its use as a wildcard +in domain lists and the like. Partial matching works only in terms of +dot-separated components; a key such as `*fict.example` +in a database file is useless, because the asterisk in a partial matching +subject key is always followed by a dot. + + + + +Lookup caching +~~~~~~~~~~~~~~ +cindex:[lookup,caching] +cindex:[caching,lookup data] +Exim caches all lookup results in order to avoid needless repetition of +lookups. However, because (apart from the daemon) Exim operates as a collection +of independent, short-lived processes, this caching applies only within a +single Exim process. There is no inter-process caching facility. + +For single-key lookups, Exim keeps the relevant files open in case there is +another lookup that needs them. In some types of configuration this can lead to +many files being kept open for messages with many recipients. To avoid hitting +the operating system limit on the number of simultaneously open files, Exim +closes the least recently used file when it needs to open more files than its +own internal limit, which can be changed via the %lookup_open_max% option. + +The single-key lookup files are closed and the lookup caches are flushed at +strategic points during delivery -- for example, after all routing is complete. + + + + +Quoting lookup data +~~~~~~~~~~~~~~~~~~~ +cindex:[lookup,quoting] +cindex:[quoting,in lookups] +When data from an incoming message is included in a query-style lookup, there +is the possibility of special characters in the data messing up the syntax of +the query. For example, a NIS+ query that contains + + [name=$local_part] + +will be broken if the local part happens to contain a closing square bracket. +For NIS+, data can be enclosed in double quotes like this: + + [name="$local_part"] + +but this still leaves the problem of a double quote in the data. The rule for +NIS+ is that double quotes must be doubled. Other lookup types have different +rules, and to cope with the differing requirements, an expansion operator +of the following form is provided: + + \$\{quote_<lookup-type>:<string>\} + +For example, the safest way to write the NIS+ query is + + [name="${quote_nisplus:$local_part}"] + +See chapter <<CHAPexpand>> for full coverage of string expansions. The quote +operator can be used for all lookup types, but has no effect for single-key +lookups, since no quoting is ever needed in their key strings. + + + + +[[SECTdnsdb]] +More about dnsdb +~~~~~~~~~~~~~~~~ +cindex:[dnsdb lookup] +cindex:[lookup,dnsdb] +cindex:[DNS,as a lookup type] +The ^dnsdb^ lookup type uses the DNS as its database. A simple query consists +of a record type and a domain name, separated by an equals sign. For example, +an expansion string could contain: + + ${lookup dnsdb{mx=a.b.example}{$value}fail} + +The supported DNS record types are A, CNAME, MX, NS, PTR, SRV, and TXT, and, +when Exim is compiled with IPv6 support, AAAA (and A6 if that is also +configured). If no type is given, TXT is assumed. When the type is PTR, +the data can be an IP address, written as normal; inversion and the addition of +%in-addr.arpa% or %ip6.arpa% happens automatically. For example: + + ${lookup dnsdb{ptr=192.168.4.5}{$value}fail} + +If the data for a PTR record is not a syntactically valid IP address, it is not +altered and nothing is added. + +For any record type, if multiple records are found (or, for A6 lookups, if a +single record leads to multiple addresses), the data is returned as a +concatenation, with newline as the default separator. The order, of course, +depends on the DNS resolver. You can specify a different separator character +between multiple records by putting a right angle-bracket followed immediately +by the new separator at the start of the query. For example: + + ${lookup dnsdb{>: a=host1.example}} + +It is permitted to specify a space as the separator character. Further +whitespace is ignored. + +cindex:[SRV record,in ^dnsdb^ lookup] +For SRV records, the priority, weight, port, and host name are returned for +each record, separated by spaces. + +cindex:[MX record,in ^dnsdb^ lookup] +For MX records, both the preference value and the host name are returned for +each record, separated by a space. However, if you want only host names, you +can use the pseudo-type MXH: + + ${lookup dnsdb{mxh=a.b.example}} + +In this case, the preference values are omitted. + +cindex:[name server,for enclosing domain] +Another pseudo-type is ZNS (for ``zone NS''). It performs a lookup for NS +records on the given domain, but if none are found, it removes the first +component of the domain name, and tries again. This process continues until NS +records are found or there are no more components left (or there is a DNS +error). In other words, it may return the name servers for a top-level domain, +but it never returns the root name servers. If there are no NS records for the +top-level domain, the lookup fails. Consider these examples: + + ${lookup dnsdb{zns=xxx.quercite.com}} + ${lookup dnsdb{zns=xxx.edu}} + +Assuming that in each case there are no NS records for the full domain name, +the first returns the name servers for %quercite.com%, and the second returns +the name servers for %edu%. + +You should be careful about how you use this lookup because, unless the +top-level domain does not exist, the lookup always returns some host names. The +sort of use to which this might be put is for seeing if the name servers for a +given domain are on a blacklist. You can probably assume that the name servers +for the high-level domains such as %com% or %co.uk% are not going to be on such +a list. + + + +Multiple dnsdb lookups +~~~~~~~~~~~~~~~~~~~~~~ +In the previous section, ^dnsdb^ lookups for a single domain are described. +However, you can specify a list of domains or IP addresses in a single +^dnsdb^ lookup. The list is specified in the normal Exim way, with colon as +the default separator, but with the ability to change this. For example: + + ${lookup dnsdb{one.domain.com:two.domain.com}} + ${lookup dnsdb{a=one.host.com:two.host.com}} + ${lookup dnsdb{ptr = <; 1.2.3.4 ; 4.5.6.8}} + +In order to retain backwards compatibility, there is one special case: if +the lookup type is PTR and no change of separator is specified, Exim looks +to see if the rest of the string is precisely one IPv6 address. In this +case, it does not treat it as a list. + +The data from each lookup is concatenated, with newline separators by default, +in the same way that multiple DNS records for a single item are handled. A +different separator can be specified, as described above. + +The ^dnsdb^ lookup fails only if all the DNS lookups fail. If there is a +temporary DNS error for any of them, the behaviour is controlled by +an optional keyword followed by a comma that may appear before the record +type. The possible keywords are ``defer_strict'', ``defer_never'', and +``defer_lax''. With ``strict'' behaviour, any temporary DNS error causes the +whole lookup to defer. With ``never'' behaviour, a temporary DNS error is +ignored, and the behaviour is as if the DNS lookup failed to find anything. +With ``lax'' behaviour, all the queries are attempted, but a temporary DNS +error causes the whole lookup to defer only if none of the other lookups +succeed. The default is ``lax'', so the following lookups are equivalent: + + ${lookup dnsdb{defer_lax,a=one.host.com:two.host.com}} + ${lookup dnsdb{a=one.host.com:two.host.com}} + +Thus, in the default case, as long as at least one of the DNS lookups +yields some data, the lookup succeeds. + + + + +[[SECTldap]] +More about LDAP +~~~~~~~~~~~~~~~ +cindex:[LDAP lookup] +cindex:[lookup,LDAP] +cindex:[Solaris,LDAP] +The original LDAP implementation came from the University of Michigan; this has +become ``Open LDAP'', and there are now two different releases. Another +implementation comes from Netscape, and Solaris 7 and subsequent releases +contain inbuilt LDAP support. Unfortunately, though these are all compatible at +the lookup function level, their error handling is different. For this reason +it is necessary to set a compile-time variable when building Exim with LDAP, to +indicate which LDAP library is in use. One of the following should appear in +your _Local/Makefile_: + + LDAP_LIB_TYPE=UMICHIGAN + LDAP_LIB_TYPE=OPENLDAP1 + LDAP_LIB_TYPE=OPENLDAP2 + LDAP_LIB_TYPE=NETSCAPE + LDAP_LIB_TYPE=SOLARIS + +If LDAP_LIB_TYPE is not set, Exim assumes `OPENLDAP1`, which has the +same interface as the University of Michigan version. + +There are three LDAP lookup types in Exim. These behave slightly differently in +the way they handle the results of a query: + +- ^ldap^ requires the result to contain just one entry; if there are more, it +gives an error. + +- ^ldapdn^ also requires the result to contain just one entry, but it is the +Distinguished Name that is returned rather than any attribute values. + +- ^ldapm^ permits the result to contain more than one entry; the attributes from +all of them are returned. + + +For ^ldap^ and ^ldapm^, if a query finds only entries with no attributes, +Exim behaves as if the entry did not exist, and the lookup fails. The format of +the data returned by a successful lookup is described in the next section. +First we explain how LDAP queries are coded. + + +[[SECTforldaque]] +Format of LDAP queries +~~~~~~~~~~~~~~~~~~~~~~ +cindex:[LDAP,query format] +An LDAP query takes the form of a URL as defined in RFC 2255. For example, in +the configuration of a ^redirect^ router one might have this setting: + +.... +data = ${lookup ldap \ + {ldap:///cn=$local_part,o=University%20of%20Cambridge,\ + c=UK?mailbox?base?}} +.... + +cindex:[LDAP,with TLS] +The URL may begin with `ldap` or `ldaps` if your LDAP library supports +secure (encrypted) LDAP connections. The second of these ensures that an +encrypted TLS connection is used. + + +LDAP quoting +~~~~~~~~~~~~ +cindex:[LDAP,quoting] +Two levels of quoting are required in LDAP queries, the first for LDAP itself +and the second because the LDAP query is represented as a URL. Furthermore, +within an LDAP query, two different kinds of quoting are required. For this +reason, there are two different LDAP-specific quoting operators. + +The %quote_ldap% operator is designed for use on strings that are part of +filter specifications. Conceptually, it first does the following conversions on +the string: + +.... +* => \2A +( => \28 +) => \29 +\ => \5C +.... + +in accordance with RFC 2254. The resulting string is then quoted according +to the rules for URLs, that is, all characters except + + ! $ ' - . _ ( ) * + + +are converted to their hex values, preceded by a percent sign. For example: + + ${quote_ldap: a(bc)*, a<yz>; } + +yields + + %20a%5C28bc%5C29%5C2A%2C%20a%3Cyz%3E%3B%20 + +Removing the URL quoting, this is (with a leading and a trailing space): + + a\28bc\29\2A, a<yz>; + + +The %quote_ldap_dn% operator is designed for use on strings that are part of +base DN specifications in queries. Conceptually, it first converts the string +by inserting a backslash in front of any of the following characters: + + , + " \ < > ; + +It also inserts a backslash before any leading spaces or # characters, and +before any trailing spaces. (These rules are in RFC 2253.) The resulting string +is then quoted according to the rules for URLs. For example: + + ${quote_ldap_dn: a(bc)*, a<yz>; } + +yields + + %5C%20a(bc)*%5C%2C%20a%5C%3Cyz%5C%3E%5C%3B%5C%20 + +Removing the URL quoting, this is (with a trailing space): + +.... +\ a(bc)*\, a\<yz\>\;\ +.... + +There are some further comments about quoting in the section on LDAP +authentication below. + + +LDAP connections +~~~~~~~~~~~~~~~~ +cindex:[LDAP,connections] +The connection to an LDAP server may either be over TCP/IP, or, when OpenLDAP +is in use, via a Unix domain socket. The example given above does not specify +an LDAP server. A server that is reached by TCP/IP can be specified in a query +by starting it with + + ldap://<hostname>:<port>/... + +If the port (and preceding colon) are omitted, the standard LDAP port (389) is +used. When no server is specified in a query, a list of default servers is +taken from the %ldap_default_servers% configuration option. This supplies a +colon-separated list of servers which are tried in turn until one successfully +handles a query, or there is a serious error. Successful handling either +returns the requested data, or indicates that it does not exist. Serious errors +are syntactical, or multiple values when only a single value is expected. +Errors which cause the next server to be tried are connection failures, bind +failures, and timeouts. + +For each server name in the list, a port number can be given. The standard way +of specifing a host and port is to use a colon separator (RFC 1738). Because +%ldap_default_servers% is a colon-separated list, such colons have to be +doubled. For example + + ldap_default_servers = ldap1.example.com::145:ldap2.example.com + +If %ldap_default_servers% is unset, a URL with no server name is passed +to the LDAP library with no server name, and the library's default (normally +the local host) is used. + +If you are using the OpenLDAP library, you can connect to an LDAP server using +a Unix domain socket instead of a TCP/IP connection. This is specified by using +`ldapi` instead of `ldap` in LDAP queries. What follows here applies only +to OpenLDAP. If Exim is compiled with a different LDAP library, this feature is +not available. + +For this type of connection, instead of a host name for the server, a pathname +for the socket is required, and the port number is not relevant. The pathname +can be specified either as an item in %ldap_default_servers%, or inline in +the query. In the former case, you can have settings such as + + ldap_default_servers = /tmp/ldap.sock : backup.ldap.your.domain + +When the pathname is given in the query, you have to escape the slashes as +`%2F` to fit in with the LDAP URL syntax. For example: + + ${lookup ldap {ldapi://%2Ftmp%2Fldap.sock/o=... + +When Exim processes an LDAP lookup and finds that the ``hostname'' is really +a pathname, it uses the Unix domain socket code, even if the query actually +specifies `ldap` or `ldaps`. In particular, no encryption is used for a +socket connection. This behaviour means that you can use a setting of +%ldap_default_servers% such as in the example above with traditional `ldap` +or `ldaps` queries, and it will work. First, Exim tries a connection via +the Unix domain socket; if that fails, it tries a TCP/IP connection to the +backup host. + +If an explicit `ldapi` type is given in a query when a host name is +specified, an error is diagnosed. However, if there are more items in +%ldap_default_servers%, they are tried. In other words: + +- Using a pathname with `ldap` or `ldaps` forces the use of the Unix domain +interface. + +- Using `ldapi` with a host name causes an error. + + +Using `ldapi` with no host or path in the query, and no setting of +%ldap_default_servers%, does whatever the library does by default. + + + +LDAP authentication and control information +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[LDAP,authentication] +The LDAP URL syntax provides no way of passing authentication and other control +information to the server. To make this possible, the URL in an LDAP query may +be preceded by any number of ``<''name'>=<'value'>' settings, separated by +spaces. If a value contains spaces it must be enclosed in double quotes, and +when double quotes are used, backslash is interpreted in the usual way inside +them. The following names are recognized: + +&&& +`DEREFERENCE` set the dereferencing parameter +`NETTIME ` set a timeout for a network operation +`USER ` set the DN, for authenticating the LDAP bind +`PASS ` set the password, likewise +`SIZE ` set the limit for the number of entries returned +`TIME ` set the maximum waiting time for a query +&&& + +The value of the DEREFERENCE parameter must be one of the words ``never'', +``searching'', ``finding'', or ``always''. + +The name CONNECT is an obsolete name for NETTIME, retained for +backwards compatibility. This timeout (specified as a number of seconds) is +enforced from the client end for operations that can be carried out over a +network. Specifically, it applies to network connections and calls to the +'ldap_result()' function. If the value is greater than zero, it is used if +LDAP_OPT_NETWORK_TIMEOUT is defined in the LDAP headers (OpenLDAP), or +if LDAP_X_OPT_CONNECT_TIMEOUT is defined in the LDAP headers (Netscape +SDK 4.1). A value of zero forces an explicit setting of ``no timeout'' for +Netscape SDK; for OpenLDAP no action is taken. + +The TIME parameter (also a number of seconds) is passed to the server to +set a server-side limit on the time taken to complete a search. + + +Here is an example of an LDAP query in an Exim lookup that uses some of these +values. This is a single line, folded for ease of reading: + + ${lookup ldap + {user="cn=manager,o=University of Cambridge,c=UK" pass=secret + ldap:///o=University%20of%20Cambridge,c=UK?sn?sub?(cn=foo)} + {$value}fail} + +The encoding of spaces as {pc}20 is a URL thing which should not be done for any +of the auxiliary data. Exim configuration settings that include lookups which +contain password information should be preceded by ``hide'' to prevent non-admin +users from using the %-bP% option to see their values. + +The auxiliary data items may be given in any order. The default is no +connection timeout (the system timeout is used), no user or password, no limit +on the number of entries returned, and no time limit on queries. + +When a DN is quoted in the USER= setting for LDAP authentication, Exim +removes any URL quoting that it may contain before passing it LDAP. Apparently +some libraries do this for themselves, but some do not. Removing the URL +quoting has two advantages: + +- It makes it possible to use the same %quote_ldap_dn% expansion for USER= +DNs as with DNs inside actual queries. + +- It permits spaces inside USER= DNs. + +For example, a setting such as + + USER=cn=${quote_ldap_dn:$1} + +should work even if $1$ contains spaces. + +Expanded data for the PASS= value should be quoted using the %quote% +expansion operator, rather than the LDAP quote operators. The only reason this +field needs quoting is to ensure that it conforms to the Exim syntax, which +does not allow unquoted spaces. For example: + + PASS=${quote:$3} + + +The LDAP authentication mechanism can be used to check passwords as part of +SMTP authentication. See the %ldapauth% expansion string condition in chapter +<<CHAPexpand>>. + + + +Format of data returned by LDAP +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[LDAP,returned data formats] +The ^ldapdn^ lookup type returns the Distinguished Name from a single entry as +a sequence of values, for example + + cn=manager, o=University of Cambridge, c=UK + + +The ^ldap^ lookup type generates an error if more than one entry matches the +search filter, whereas ^ldapm^ permits this case, and inserts a newline in +the result between the data from different entries. It is possible for multiple +values to be returned for both ^ldap^ and ^ldapm^, but in the former case +you know that whatever values are returned all came from a single entry in the +directory. + +In the common case where you specify a single attribute in your LDAP query, the +result is not quoted, and does not contain the attribute name. If the attribute +has multiple values, they are separated by commas. + +If you specify multiple attributes, the result contains space-separated, quoted +strings, each preceded by the attribute name and an equals sign. Within the +quotes, the quote character, backslash, and newline are escaped with +backslashes, and commas are used to separate multiple values for the attribute. +Apart from the escaping, the string within quotes takes the same form as the +output when a single attribute is requested. Specifying no attributes is the +same as specifying all of an entry's attributes. + +Here are some examples of the output format. The first line of each pair is an +LDAP query, and the second is the data that is returned. The attribute called +%attr1% has two values, whereas %attr2% has only one value: + + ldap:///o=base?attr1?sub?(uid=fred) + value1.1, value1.2 + + ldap:///o=base?attr2?sub?(uid=fred) + value two + + ldap:///o=base?attr1,attr2?sub?(uid=fred) + attr1="value1.1, value1.2" attr2="value two" + + ldap:///o=base??sub?(uid=fred) + objectClass="top" attr1="value1.1, value1.2" attr2="value two" + +The %extract% operator in string expansions can be used to pick out individual +fields from data that consists of 'key'='value' pairs. You can make use +of Exim's %-be% option to run expansion tests and thereby check the results of +LDAP lookups. + + + + +[[SECTnisplus]] +More about NIS+ +~~~~~~~~~~~~~~~ +cindex:[NIS+ lookup type] +cindex:[lookup,NIS+] +NIS+ queries consist of a NIS+ 'indexed name' followed by an optional colon +and field name. If this is given, the result of a successful query is the +contents of the named field; otherwise the result consists of a concatenation +of 'field-name=field-value' pairs, separated by spaces. Empty values and +values containing spaces are quoted. For example, the query + + [name=mg1456],passwd.org_dir + +might return the string + + name=mg1456 passwd="" uid=999 gid=999 gcos="Martin Guerre" + home=/home/mg1456 shell=/bin/bash shadow="" + +(split over two lines here to fit on the page), whereas + + [name=mg1456],passwd.org_dir:gcos + +would just return + + Martin Guerre + +with no quotes. A NIS+ lookup fails if NIS+ returns more than one table entry +for the given indexed key. The effect of the %quote_nisplus% expansion +operator is to double any quote characters within the text. + + + +[[SECTsql]] +More about MySQL, PostgreSQL, Oracle, and Interbase +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[MySQL,lookup type] +cindex:[PostgreSQL lookup type] +cindex:[lookup,MySQL] +cindex:[lookup,PostgreSQL] +cindex:[Oracle,lookup type] +cindex:[lookup,Oracle] +cindex:[Interbase lookup type] +cindex:[lookup,Interbase] +If any MySQL, PostgreSQL, Oracle, or Interbase lookups are used, the +%mysql_servers%, %pgsql_servers%, %oracle_servers%, or %ibase_servers% +option (as appropriate) must be set to a colon-separated list of server +information. Each item in the list is a slash-separated list of four items: +host name, database name, user name, and password. In the case of Oracle, the +host name field is used for the ``service name'', and the database name field is +not used and should be empty. For example: + + hide oracle_servers = oracle.plc.example//ph10/abcdwxyz + +Because password data is sensitive, you should always precede the setting with +``hide'', to prevent non-admin users from obtaining the setting via the %-bP% +option. Here is an example where two MySQL servers are listed: + +.... +hide mysql_servers = localhost/users/root/secret:\ + otherhost/users/root/othersecret +.... + +For MySQL and PostgreSQL, a host may be specified as <'name'>:<'port'> but +because this is a colon-separated list, the colon has to be doubled. + +For each query, these parameter groups are tried in order until a connection +and a query succeeds. Queries for these databases are SQL statements, so an +example might be + +.... +${lookup mysql{select mailbox from users where id='ph10'}\ + {$value}fail} +.... + +If the result of the query contains more than one field, the data for +each field in the row is returned, preceded by its name, so the result +of + +.... +${lookup pgsql{select home,name from users where id='ph10'}\ + {$value}} +.... + +might be + + home=/home/ph10 name="Philip Hazel" + +Values containing spaces and empty values are double quoted, with embedded +quotes escaped by a backslash. + +If the result of the query contains just one field, the value is passed back +verbatim, without a field name, for example: + + Philip Hazel + +If the result of the query yields more than one row, it is all concatenated, +with a newline between the data for each row. + +The %quote_mysql%, %quote_pgsql%, and %quote_oracle% expansion operators +convert newline, tab, carriage return, and backspace to \n, \t, \r, and \b +respectively, and the characters single-quote, double-quote, and backslash +itself are escaped with backslashes. The %quote_pgsql% expansion operator, in +addition, escapes the percent and underscore characters. This cannot be done +for MySQL because these escapes are not recognized in contexts where these +characters are not special. + + + +Special MySQL features +~~~~~~~~~~~~~~~~~~~~~~ +For MySQL, an empty host name or the use of ``localhost'' in %mysql_servers% +causes a connection to the server on the local host by means of a Unix domain +socket. An alternate socket can be specified in parentheses. The full syntax of +each item in %mysql_servers% is: + +&&& +<'hostname'>::<'port'>(<'socket name'>)/<'database'>/<'user'>/<'password'> +&&& + +Any of the three sub-parts of the first field can be omitted. For normal use on +the local host it can be left blank or set to just ``localhost''. + +No database need be supplied -- but if it is absent here, it must be given in +the queries. + +If a MySQL query is issued that does not request any data (an insert, update, +or delete command), the result of the lookup is the number of rows affected. + +*Warning*: this can be misleading. If an update does not actually change +anything (for example, setting a field to the value it already has), the result +is zero because no rows are affected. + + + + +Special PostgreSQL features +~~~~~~~~~~~~~~~~~~~~~~~~~~~ +PostgreSQL lookups can also use Unix domain socket connections to the database. +This is usually faster and costs less CPU time than a TCP/IP connection. +However it can be used only if the mail server runs on the same machine as the +database server. A configuration line for PostgreSQL via Unix domain sockets +looks like this: + + hide pgsql_servers = (/tmp/.s.PGSQL.5432)/db/user/password : ... + +In other words, instead of supplying a host name, a path to the socket is +given. The path name is enclosed in parentheses so that its slashes aren't +visually confused with the delimiters for the other server parameters. + +If a PostgreSQL query is issued that does not request any data (an insert, +update, or delete command), the result of the lookup is the number of rows +affected. + + + + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// + +[[CHAPdomhosaddlists]] +[titleabbrev="Domain, host, and address lists"] +Domain, host, address, and local part lists +------------------------------------------- +cindex:[list of domains; hosts; etc.] +A number of Exim configuration options contain lists of domains, hosts, +email addresses, or local parts. For example, the %hold_domains% option +contains a list of domains whose delivery is currently suspended. These lists +are also used as data in ACL statements (see chapter <<CHAPACL>>). + +Each item in one of these lists is a pattern to be matched against a domain, +host, email address, or local part, respectively. In the sections below, the +different types of pattern for each case are described, but first we cover some +general facilities that apply to all four kinds of list. + + + +Expansion of lists +~~~~~~~~~~~~~~~~~~ +cindex:[expansion,of lists] +Each list is expanded as a single string before it is used. The result of +expansion must be a list, possibly containing empty items, which is split up +into separate items for matching. By default, colon is the separator character, +but this can be varied if necessary. See sections <<SECTlistconstruct>> and +<<SECTempitelis>> for details of the list syntax; the second of these discusses +the way you specify empty list items. + + +If the string expansion is forced to fail, Exim behaves as if the item it is +testing (domain, host, address, or local part) is not in the list. Other +expansion failures cause temporary errors. + +If an item in a list is a regular expression, backslashes, dollars and possibly +other special characters in the expression must be protected against +misinterpretation by the string expander. The easiest way to do this is to use +the `\N` expansion feature to indicate that the contents of the regular +expression should not be expanded. For example, in an ACL you might have: + +.... +deny senders = \N^\d{8}\w@.*\.baddomain\.example$\N : \ + ${lookup{$domain}lsearch{/badsenders/bydomain}} +.... + +The first item is a regular expression that is protected from expansion by +`\N`, whereas the second uses the expansion to obtain a list of unwanted +senders based on the receiving domain. + + + + +Negated items in lists +~~~~~~~~~~~~~~~~~~~~~~ +cindex:[list,negation] +cindex:[negation in lists] +Items in a list may be positive or negative. Negative items are indicated by a +leading exclamation mark, which may be followed by optional white space. A list +defines a set of items (domains, etc). When Exim processes one of these lists, +it is trying to find out whether a domain, host, address, or local part +(respectively) is in the set that is defined by the list. It works like this: + +The list is scanned from left to right. If a positive item is matched, the +subject that is being checked is in the set; if a negative item is matched, the +subject is not in the set. If the end of the list is reached without the +subject having matched any of the patterns, it is in the set if the last item +was a negative one, but not if it was a positive one. For example, the list in + + domainlist relay_domains = !a.b.c : *.b.c + +matches any domain ending in '.b.c' except for 'a.b.c'. Domains that match +neither 'a.b.c' nor '*.b.c' do not match, because the last item in the +list is positive. However, if the setting were + + domainlist relay_domains = !a.b.c + +then all domains other than 'a.b.c' would match because the last item in the +list is negative. In other words, a list that ends with a negative item behaves +as if it had an extra item `:*` on the end. + +Another way of thinking about positive and negative items in lists is to read +the connector as ``or'' after a positive item and as ``and'' after a negative +item. + + + +[[SECTfilnamlis]] +File names in lists +~~~~~~~~~~~~~~~~~~~ +cindex:[list,file name in] +If an item in a domain, host, address, or local part list is an absolute file +name (beginning with a slash character), each line of the file is read and +processed as if it were an independent item in the list, except that further +file names are not allowed, +and no expansion of the data from the file takes place. +Empty lines in the file are ignored, and the file may also contain comment +lines: + +- For domain and host lists, if a # character appears anywhere in a line of the +file, it and all following characters are ignored. + +- Because local parts may legitimately contain # characters, a comment in an +address list or local part list file is recognized only if # is preceded by +white space or the start of the line. For example: + + not#comment@x.y.z # but this is a comment + +Putting a file name in a list has the same effect as inserting each line of the +file as an item in the list (blank lines and comments excepted). However, there +is one important difference: the file is read each time the list is processed, +so if its contents vary over time, Exim's behaviour changes. + +If a file name is preceded by an exclamation mark, the sense of any match +within the file is inverted. For example, if + + hold_domains = !/etc/nohold-domains + +and the file contains the lines + + !a.b.c + *.b.c + +then 'a.b.c' is in the set of domains defined by %hold_domains%, whereas any +domain matching `*.b.c` is not. + + + +An lsearch file is not an out-of-line list +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +As will be described in the sections that follow, lookups can be used in lists +to provide indexed methods of checking list membership. There has been some +confusion about the way ^lsearch^ lookups work in lists. Because +an ^lsearch^ file contains plain text and is scanned sequentially, it is +sometimes thought that it is allowed to contain wild cards and other kinds of +non-constant pattern. This is not the case. The keys in an ^lsearch^ file are +always fixed strings, just as for any other single-key lookup type. + +If you want to use a file to contain wild-card patterns that form part of a +list, just give the file name on its own, without a search type, as described +in the previous section. + + + + +[[SECTnamedlists]] +Named lists +~~~~~~~~~~~ +cindex:[named lists] +cindex:[list,named] +A list of domains, hosts, email addresses, or local parts can be given a name +which is then used to refer to the list elsewhere in the configuration. This is +particularly convenient if the same list is required in several different +places. It also allows lists to be given meaningful names, which can improve +the readability of the configuration. For example, it is conventional to define +a domain list called 'local_domains' for all the domains that are handled +locally on a host, using a configuration line such as + + domainlist local_domains = localhost:my.dom.example + +Named lists are referenced by giving their name preceded by a plus sign, so, +for example, a router that is intended to handle local domains would be +configured with the line + + domains = +local_domains + +The first router in a configuration is often one that handles all domains +except the local ones, using a configuration with a negated item like this: + + dnslookup: + driver = dnslookup + domains = ! +local_domains + transport = remote_smtp + no_more + +The four kinds of named list are created by configuration lines starting with +the words %domainlist%, %hostlist%, %addresslist%, or %localpartlist%, +respectively. Then there follows the name that you are defining, followed by an +equals sign and the list itself. For example: + + hostlist relay_hosts = 192.168.23.0/24 : my.friend.example + addresslist bad_senders = cdb;/etc/badsenders + +A named list may refer to other named lists: + + domainlist dom1 = first.example : second.example + domainlist dom2 = +dom1 : third.example + domainlist dom3 = fourth.example : +dom2 : fifth.example + + +*Warning*: If the last item in a referenced list is a negative one, the +effect may not be what you intended, because the negation does not propagate +out to the higher level. For example, consider: + + domainlist dom1 = !a.b + domainlist dom2 = +dom1 : *.b + +The second list specifies ``either in the %dom1% list or '*.b'##''. The first +list specifies just ``not 'a.b'##'', so the domain 'x.y' matches it. That means +it matches the second list as well. The effect is not the same as + + domainlist dom2 = !a.b : *.b + +where 'x.y' does not match. It's best to avoid negation altogether in +referenced lists if you can. + +Named lists may have a performance advantage. When Exim is routing an +address or checking an incoming message, it caches the result of tests on named +lists. So, if you have a setting such as + + domains = +local_domains + +on several of your routers +or in several ACL statements, +the actual test is done only for the first one. However, the caching works only +if there are no expansions within the list itself or any sublists that it +references. In other words, caching happens only for lists that are known to be +the same each time they are referenced. + +By default, there may be up to 16 named lists of each type. This limit can be +extended by changing a compile-time variable. The use of domain and host lists +is recommended for concepts such as local domains, relay domains, and relay +hosts. The default configuration is set up like this. + + + +Named lists compared with macros +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[list,named compared with macro] +cindex:[macro,compared with named list] +At first sight, named lists might seem to be no different from macros in the +configuration file. However, macros are just textual substitutions. If you +write + + ALIST = host1 : host2 + auth_advertise_hosts = !ALIST + +it probably won't do what you want, because that is exactly the same as + + auth_advertise_hosts = !host1 : host2 + +Notice that the second host name is not negated. However, if you use a host +list, and write + + hostlist alist = host1 : host2 + auth_advertise_hosts = ! +alist + +the negation applies to the whole list, and so that is equivalent to + + auth_advertise_hosts = !host1 : !host2 + + + + +Named list caching +~~~~~~~~~~~~~~~~~~ +cindex:[list,caching of named] +cindex:[caching,named lists] +While processing a message, Exim caches the result of checking a named list if +it is sure that the list is the same each time. In practice, this means that +the cache operates only if the list contains no \$ characters, which guarantees +that it will not change when it is expanded. Sometimes, however, you may have +an expanded list that you know will be the same each time within a given +message. For example: + +.... +domainlist special_domains = \ + ${lookup{$sender_host_address}cdb{/some/file}} +.... + +This provides a list of domains that depends only on the sending host's IP +address. If this domain list is referenced a number of times (for example, +in several ACL lines, or in several routers) the result of the check is not +cached by default, because Exim does not know that it is going to be the +same list each time. + +By appending `_cache` to `domainlist` you can tell Exim to go ahead and +cache the result anyway. For example: + + domainlist_cache special_domains = ${lookup{... + +If you do this, you should be absolutely sure that caching is going to do +the right thing in all cases. When in doubt, leave it out. + + + +[[SECTdomainlist]] +Domain lists +~~~~~~~~~~~~ +cindex:[domain list,patterns for] +cindex:[list,domain list] +Domain lists contain patterns that are to be matched against a mail domain. +The following types of item may appear in domain lists: + +- cindex:[primary host name] +cindex:[host name, matched in domain list] +cindex:[%primary_hostname%] +cindex:[domain list,matching primary host name] +cindex:[@ in a domain list] +If a pattern consists of a single @ character, it matches the local host name, +as set by the %primary_hostname% option (or defaulted). This makes it possible +to use the same configuration file on several different hosts that differ only +in their names. + +- cindex:[@{bk} in a domain list] +cindex:[domain list,matching local IP interfaces] +cindex:[domain literal] +If a pattern consists of the string `@[]` it matches any local IP interface +address, enclosed in square brackets, as in an email address that contains a +domain literal. +In today's Internet, the use of domain literals is controversial. + +- cindex:[@mx_any] +cindex:[@mx_primary] +cindex:[@mx_secondary] +cindex:[domain list,matching MX pointers to local host] +If a pattern consists of the string `@mx_any` it matches any domain that +has an MX record pointing to the local host or to any host that is listed in +cindex:[%hosts_treat_as_local%] +%hosts_treat_as_local%. The items `@mx_primary` and `@mx_secondary` +are similar, except that the first matches only when a primary MX target is the +local host, and the second only when no primary MX target is the local host, +but a secondary MX target is. ``Primary'' means an MX record with the lowest +preference value -- there may of course be more than one of them. ++ +The MX lookup that takes place when matching a pattern of this type is +performed with the resolver options for widening names turned off. Thus, for +example, a single-component domain will 'not' be expanded by adding the +resolver's default domain. See the %qualify_single% and %search_parents% +options of the ^dnslookup^ router for a discussion of domain widening. ++ +Sometimes you may want to ignore certain IP addresses when using one of these +patterns. You can specify this by following the pattern with `/ignore=`<'ip +list'>, where <'ip list'> is a list of IP addresses. These addresses are +ignored when processing the pattern (compare the %ignore_target_hosts% option +on a router). For example: + + domains = @mx_any/ignore=127.0.0.1 ++ +This example matches any domain that has an MX record pointing to one of +the local host's IP addresses other than 127.0.0.1. ++ +The list of IP addresses is in fact processed by the same code that processes +host lists, so it may contain CIDR-coded network specifications and it may also +contain negative items. ++ +Because the list of IP addresses is a sublist within a domain list, you have to +be careful about delimiters if there is more than one address. Like any other +list, the default delimiter can be changed. Thus, you might have: ++ +.... +domains = @mx_any/ignore=<;127.0.0.1;0.0.0.0 : \ + an.other.domain : ... +.... ++ +so that the sublist uses semicolons for delimiters. When IPv6 addresses are +involved, it is easiest to change the delimiter for the main list as well: ++ +.... +domains = <? @mx_any/ignore=<;127.0.0.1;::1 ? \ + an.other.domain ? ... +.... + +- cindex:[asterisk,in domain list] +cindex:[domain list,asterisk in] +cindex:[domain list,matching ``ends with''] +If a pattern starts with an asterisk, the remaining characters of the pattern +are compared with the terminating characters of the domain. The use of ``\*'' in +domain lists differs from its use in partial matching lookups. In a domain +list, the character following the asterisk need not be a dot, whereas partial +matching works only in terms of dot-separated components. For example, a domain +list item such as `*key.ex` matches 'donkey.ex' as well as +'cipher.key.ex'. + +- cindex:[regular expressions,in domain list] +cindex:[domain list,matching regular expression] +If a pattern starts with a circumflex character, it is treated as a regular +expression, and matched against the domain using a regular expression matching +function. The circumflex is treated as part of the regular expression. +References to descriptions of the syntax of regular expressions are given in +chapter <<CHAPregexp>>. ++ +*Warning*: Because domain lists are expanded before being processed, you +must escape any backslash and dollar characters in the regular expression, or +use the special `\N` sequence (see chapter <<CHAPexpand>>) to specify that it +is not to be expanded (unless you really do want to build a regular expression +by expansion, of course). + +- cindex:[lookup,in domain list] +cindex:[domain list,matching by lookup] +If a pattern starts with the name of a single-key lookup type followed by a +semicolon (for example, ``dbm;'' or ``lsearch;''), the remainder of the pattern +must be a file name in a suitable format for the lookup type. For example, for +``cdb;'' it must be an absolute path: + + domains = cdb;/etc/mail/local_domains.cdb ++ +The appropriate type of lookup is done on the file using the domain name as the +key. In most cases, the data that is looked up is not used; Exim is interested +only in whether or not the key is present in the file. However, when a lookup +is used for the %domains% option on a router +or a %domains% condition in an ACL statement, the data is preserved in the +$domain_data$ variable and can be referred to in other router options or +other statements in the same ACL. + +- Any of the single-key lookup type names may be preceded by ``partial<''n'>-', +where the <'n'> is optional, for example, + + domains = partial-dbm;/partial/domains ++ +This causes partial matching logic to be invoked; a description of how this +works is given in section <<SECTpartiallookup>>. + +- cindex:[asterisk,in lookup type] +Any of the single-key lookup types may be followed by an asterisk. This causes +a default lookup for a key consisting of a single asterisk to be done if the +original lookup fails. This is not a useful feature when using a domain list to +select particular domains (because any domain would match), but it might have +value if the result of the lookup is being used via the $domain_data$ +expansion variable. + +- If the pattern starts with the name of a query-style lookup type followed by a +semicolon (for example, ``nisplus;'' or ``ldap;''), the remainder of the pattern +must be an appropriate query for the lookup type, as described in chapter +<<CHAPfdlookup>>. For example: ++ +.... +hold_domains = mysql;select domain from holdlist \ + where domain = '$domain'; +.... ++ +In most cases, the data that is looked up is not used (so for an SQL query, for +example, it doesn't matter what field you select). Exim is interested only in +whether or not the query succeeds. However, when a lookup is used for the +%domains% option on a router, the data is preserved in the $domain_data$ +variable and can be referred to in other options. + +- cindex:[domain list,matching literal domain name] +If none of the above cases apply, a caseless textual comparison is made +between the pattern and the domain. + + +Here is an example that uses several different kinds of pattern: + +.... +domainlist funny_domains = \ + @ : \ + lib.unseen.edu : \ + *.foundation.fict.example : \ + \N^[1-2]\d{3}\.fict\.example$\N : \ + partial-dbm;/opt/data/penguin/book : \ + nis;domains.byname : \ + nisplus;[name=$domain,status=local],domains.org_dir +.... + +There are obvious processing trade-offs among the various matching modes. Using +an asterisk is faster than a regular expression, and listing a few names +explicitly probably is too. The use of a file or database lookup is expensive, +but may be the only option if hundreds of names are required. Because the +patterns are tested in order, it makes sense to put the most commonly matched +patterns earlier. + + + +[[SECThostlist]] +Host lists +~~~~~~~~~~ +cindex:[host list,patterns in] +cindex:[list,host list] +Host lists are used to control what remote hosts are allowed to do. For +example, some hosts may be allowed to use the local host as a relay, and some +may be permitted to use the SMTP ETRN command. Hosts can be identified in +two different ways, by name or by IP address. In a host list, some types of +pattern are matched to a host name, and some are matched to an IP address. +You need to be particularly careful with this when single-key lookups are +involved, to ensure that the right value is being used as the key. + + +Special host list patterns +~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[empty item in hosts list] +cindex:[host list,empty string in] +If a host list item is the empty string, it matches only when no remote host is +involved. This is the case when a message is being received from a local +process using SMTP on the standard input, that is, when a TCP/IP connection is +not used. + +cindex:[asterisk,in host list] +The special pattern ``\*'' in a host list matches any host or no host. Neither +the IP address nor the name is actually inspected. + + + +[[SECThoslispatip]] +Host list patterns that match by IP address +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[host list,matching IP addresses] +If an IPv4 host calls an IPv6 host and the call is accepted on an IPv6 socket, +the incoming address actually appears in the IPv6 host as +``::`ffff`:<''v4address'>'. When such an address is tested against a host +list, it is converted into a traditional IPv4 address first. (Not all operating +systems accept IPv4 calls on IPv6 sockets, as there have been some security +concerns.) + +The following types of pattern in a host list check the remote host by +inspecting its IP address: + +- If the pattern is a plain domain name (not a regular expression, not starting +with \*, not a lookup of any kind), Exim calls the operating system function +to find the associated IP address(es). Exim uses the newer +'getipnodebyname()' function when available, otherwise 'gethostbyname()'. +This typically causes a forward DNS lookup of the name. The result is compared +with the IP address of the subject host. ++ +If there is a temporary problem (such as a DNS timeout) with the host name +lookup, a temporary error occurs. For example, if the list is being used in an +ACL condition, the ACL gives a ``defer'' response, usually leading to a temporary +SMTP error code. If no IP address can be found for the host name, what happens +is described in section <<SECTbehipnot>> below. + +- cindex:[@ in a host list] +If the pattern is ``@'', the primary host name is substituted and used as a +domain name, as just described. + +- If the pattern is an IP address, it is matched against the IP address of the +subject host. IPv4 addresses are given in the normal ``dotted-quad'' notation. +IPv6 addresses can be given in colon-separated format, but the colons have to +be doubled so as not to be taken as item separators when the default list +separator is used. IPv6 addresses are recognized even when Exim is compiled +without IPv6 support. This means that if they appear in a host list on an +IPv4-only host, Exim will not treat them as host names. They are just addresses +that can never match a client host. + +- cindex:[@{bk} in a host list] +If the pattern is ``@[]'', it matches the IP address of any IP interface on +the local host. For example, if the local host is an IPv4 host with one +interface address 10.45.23.56, these two ACL statements have the same effect: + + accept hosts = 127.0.0.1 : 10.45.23.56 + accept hosts = @[] + +- cindex:[CIDR notation] +If the pattern is an IP address followed by a slash and a mask length (for +example 10.11.42.0/24), it is matched against the IP address of the subject +host under the given mask. This allows, an entire network of hosts to be +included (or excluded) by a single item. The mask uses CIDR notation; it +specifies the number of address bits that must match, starting from the most +significant end of the address. ++ +*Note*: the mask is 'not' a count of addresses, nor is it the high number +of a range of addresses. It is the number of bits in the network portion of the +address. The above example specifies a 24-bit netmask, so it matches all 256 +addresses in the 10.11.42.0 network. An item such as + + 192.168.23.236/31 ++ +matches just two addresses, 192.168.23.236 and 192.168.23.237. A mask value of +32 for an IPv4 address is the same as no mask at all; just a single address +matches. ++ +Here is another example which shows an IPv4 and an IPv6 network: ++ +.... +recipient_unqualified_hosts = 192.168.0.0/16: \ + 3ffe::ffff::836f::::/48 +.... ++ +The doubling of list separator characters applies only when these items +appear inline in a host list. It is not required when indirecting via a file. +For example, + + recipient_unqualified_hosts = /opt/exim/unqualnets ++ +could make use of a file containing + + 172.16.0.0/12 + 3ffe:ffff:836f::/48 ++ +to have exactly the same effect as the previous example. When listing IPv6 +addresses inline, it is usually more convenient to use the facility for +changing separator characters. This list contains the same two networks: ++ +.... +recipient_unqualified_hosts = <; 172.16.0.0/12; \ + 3ffe:ffff:836f::/48 +.... ++ +The separator is changed to semicolon by the leading ``<;'' at the start of the +list. + + + + +[[SECThoslispatsikey]] +Host list patterns for single-key lookups by host address +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[host list,lookup of IP address] +When a host is to be identified by a single-key lookup of its complete IP +address, the pattern takes this form: + + net-<single-key-search-type>;<search-data> + +For example: + + hosts_lookup = net-cdb;/hosts-by-ip.db + +The text form of the IP address of the subject host is used as the lookup key. +IPv6 addresses are converted to an unabbreviated form, using lower case +letters, with dots as separators because colon is the key terminator in +^lsearch^ files. [Colons can in fact be used in keys in ^lsearch^ files by +quoting the keys, but this is a facility that was added later.] The data +returned by the lookup is not used. + +cindex:[IP address,masking] +cindex:[host list,masked IP address] +Single-key lookups can also be performed using masked IP addresses, using +patterns of this form: + + net<number>-<single-key-search-type>;<search-data> + +For example: + + net24-dbm;/networks.db + +The IP address of the subject host is masked using <'number'> as the mask +length. A textual string is constructed from the masked value, followed by the +mask, and this is used as the lookup key. For example, if the host's IP address +is 192.168.34.6, the key that is looked up for the above example is +``192.168.34.0/24''. IPv6 addresses are converted to a text value using lower +case letters and dots as separators instead of the more usual colon, because +colon is the key terminator in ^lsearch^ files. Full, unabbreviated IPv6 +addresses are always used. + +*Warning*: Specifing %net32-% (for an IPv4 address) or %net128-% (for an +IPv6 address) is not the same as specifing just %net-% without a number. In +the former case the key strings include the mask value, whereas in the latter +case the IP address is used on its own. + + + +[[SECThoslispatnam]] +Host list patterns that match by host name +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[host,lookup failures] +cindex:[unknown host name] +cindex:[host list,matching host name] +There are several types of pattern that require Exim to know the name of the +remote host. These are either wildcard patterns or lookups by name. (If a +complete hostname is given without any wildcarding, it is used to find an IP +address to match against, as described in the section <<SECThoslispatip>> above.) + +If the remote host name is not already known when Exim encounters one of these +patterns, it has to be found from the IP address. +Although many sites on the Internet are conscientious about maintaining reverse +DNS data for their hosts, there are also many that do not do this. +Consequently, a name cannot always be found, and this may lead to unwanted +effects. Take care when configuring host lists with wildcarded name patterns. +Consider what will happen if a name cannot be found. + +Because of the problems of determining host names from IP addresses, matching +against host names is not as common as matching against IP addresses. + +By default, in order to find a host name, Exim first does a reverse DNS lookup; +if no name is found in the DNS, the system function ('gethostbyaddr()' or +'getipnodebyaddr()' if available) is tried. The order in which these lookups +are done can be changed by setting the %host_lookup_order% option. + +There are some options that control what happens if a host name cannot be +found. These are described in section <<SECTbehipnot>> below. + +cindex:[host,alias for] +cindex:[alias for host] +As a result of aliasing, hosts may have more than one name. When processing any +of the following types of pattern, all the host's names are checked: + +- cindex:[asterisk,in host list] +If a pattern starts with ``\*'' the remainder of the item must match the end of +the host name. For example, `*.b.c` matches all hosts whose names end in +'.b.c'. This special simple form is provided because this is a very common +requirement. Other kinds of wildcarding require the use of a regular +expression. + +- cindex:[regular expressions,in host list] +cindex:[host list,regular expression in] +If the item starts with ``^'' it is taken to be a regular expression which is +matched against the host name. For example, + + ^(a|b)\.c\.d$ ++ +is a regular expression that matches either of the two hosts 'a.c.d' or +'b.c.d'. When a regular expression is used in a host list, you must take care +that backslash and dollar characters are not misinterpreted as part of the +string expansion. The simplest way to do this is to use `\N` to mark that +part of the string as non-expandable. For example: + + sender_unqualified_hosts = \N^(a|b)\.c\.d$\N : .... ++ +*Warning*: If you want to match a complete host name, you must include the +`\$` terminating metacharacter in the regular expression, as in the above +example. Without it, a match at the start of the host name is all that is +required. + + + + +[[SECTbehipnot]] +Behaviour when an IP address or name cannot be found +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[host,lookup failures] +While processing a host list, Exim may need to look up an IP address from a +name (see section <<SECThoslispatip>>), or it may need to look up a host name +from an IP address (see section <<SECThoslispatnam>>). In either case, the +behaviour when it fails to find the information it is seeking is the same. + +cindex:[`+include_unknown`] +cindex:[`+ignore_unknown`] +By default, Exim behaves as if the host does not match the list. This may not +always be what you want to happen. To change Exim's behaviour, the special +items `+include_unknown` or `+ignore_unknown` may appear in the list (at +top level -- they are not recognized in an indirected file). + +- If any item that follows `+include_unknown` requires information that +cannot found, Exim behaves as if the host does match the list. For example, + + host_reject_connection = +include_unknown:*.enemy.ex ++ +rejects connections from any host whose name matches `*.enemy.ex`, and also +any hosts whose name it cannot find. + +- If any item that follows `+ignore_unknown` requires information that cannot +be found, Exim ignores that item and proceeds to the rest of the list. For +example: ++ +.... +accept hosts = +ignore_unknown : friend.example : \ + 192.168.4.5 +.... ++ +accepts from any host whose name is 'friend.example' and from 192.168.4.5, +whether or not its host name can be found. Without `+ignore_unknown`, if no +name can be found for 192.168.4.5, it is rejected. + +Both `+include_unknown` and `+ignore_unknown` may appear in the same +list. The effect of each one lasts until the next, or until the end of the +list. + +*Note*: This section applies to permanent lookup failures. It does 'not' +apply to temporary DNS errors. They always cause a defer action. + + + +[[SECThoslispatnamsk]] +Host list patterns for single-key lookups by host name +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[host,lookup failures] +cindex:[unknown host name] +cindex:[host list,matching host name] +If a pattern is of the form + + <single-key-search-type>;<search-data> + +for example + + dbm;/host/accept/list + +a single-key lookup is performend, using the host name as its key. If the +lookup succeeds, the host matches the item. The actual data that is looked up +is not used. + +*Reminder*: With this kind of pattern, you must have host 'names' as +keys in the file, not IP addresses. If you want to do lookups based on IP +addresses, you must precede the search type with ``net-'' (see section +<<SECThoslispatsikey>>). There is, however, no reason why you could not use two +items in the same list, one doing an address lookup and one doing a name +lookup, both using the same file. + + + +Host list patterns for query-style lookups +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +If a pattern is of the form + + <query-style-search-type>;<query> + +the query is obeyed, and if it succeeds, the host matches the item. The actual +data that is looked up is not used. The variables $sender_host_address$ and +$sender_host_name$ can be used in the query. For example: + +.... +hosts_lookup = pgsql;\ + select ip from hostlist where ip='$sender_host_address' +.... + +The value of $sender_host_address$ for an IPv6 address contains colons. You +can use the %sg% expansion item to change this if you need to. If you want to +use masked IP addresses in database queries, you can use the %mask% expansion +operator. + +If the query contains a reference to $sender_host_name$, Exim automatically +looks up the host name if has not already done so. (See section +<<SECThoslispatnam>> for comments on finding host names.) + +Historical note: prior to release 4.30, Exim would always attempt to find a +host name before running the query, unless the search type was preceded by +`net-`. This is no longer the case. For backwards compatibility, `net-` is +still recognized for query-style lookups, but its presence or absence has no +effect. (Of course, for single-key lookups, `net-` 'is' important. +See section <<SECThoslispatsikey>>.) + + + +[[SECTmixwilhos]] +Mixing wildcarded host names and addresses in host lists +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[host list,mixing names and addresses in] +If you have name lookups or wildcarded host names and IP addresses in the same +host list, you should normally put the IP addresses first. For example, in an +ACL you could have: + + accept hosts = 10.9.8.7 : *.friend.example + +The reason for this lies in the left-to-right way that Exim processes lists. +It can test IP addresses without doing any DNS lookups, but when it reaches an +item that requires a host name, it fails if it cannot find a host name to +compare with the pattern. If the above list is given in the opposite order, the +%accept% statement fails for a host whose name cannot be found, even if its +IP address is 10.9.8.7. + +If you really do want to do the name check first, and still recognize the IP +address, you can rewrite the ACL like this: + + accept hosts = *.friend.example + accept hosts = 10.9.8.7 + +If the first %accept% fails, Exim goes on to try the second one. See chapter +<<CHAPACL>> for details of ACLs. + + + + + +[[SECTaddresslist]] +Address lists +~~~~~~~~~~~~~ +cindex:[list,address list] +cindex:[address list,empty item] +cindex:[address list,patterns] +Address lists contain patterns that are matched against mail addresses. There +is one special case to be considered: the sender address of a bounce message is +always empty. You can test for this by providing an empty item in an address +list. For example, you can set up a router to process bounce messages by +using this option setting: + + senders = : + +The presence of the colon creates an empty item. If you do not provide any +data, the list is empty and matches nothing. The empty sender can also be +detected by a regular expression that matches an empty string, + +and by a query-style lookup that succeeds when $sender_address$ is empty. + +The following kinds of address list pattern can match any address, including +the empty address that is characteristic of bounce message senders: + +- As explained above, if a pattern item is empty, it matches the empty address +(and no others). + +- cindex:[regular expressions,in address list] +cindex:[address list,regular expression in] +If (after expansion) a pattern starts with ``^'', a regular expression match is +done against the complete address, with the pattern as the regular expression. +You must take care that backslash and dollar characters are not misinterpreted +as part of the string expansion. The simplest way to do this is to use `\N` +to mark that part of the string as non-expandable. For example: + + deny senders = \N^\d{8}.+@spamhaus.example$\N : ... ++ +The `\N` sequences are removed by the expansion, so the item does start +with ``^'' by the time it is being interpreted as an address pattern. + +- cindex:[address list,lookup for complete address] +Complete addresses can be looked up by using a pattern that starts with a +lookup type terminated by a semicolon, followed by the data for the lookup. For +example: ++ +.... +deny senders = cdb;/etc/blocked.senders : \ + mysql;select address from blocked where \ + address='${quote_mysql:$sender_address}' +.... ++ +Both query-style and single-key lookup types can be used. For a single-key +lookup type, Exim uses the complete address as the key. However, empty keys are +not supported for single-key lookups, so a match against the empty address +always fails. This restriction does not apply to query-style lookups. ++ +Partial matching for single-key lookups (section <<SECTpartiallookup>>) cannot +be used, and is ignored if specified, with an entry being written to the panic +log. ++ +cindex:[\*@ with single-key lookup] +However, you can configure lookup defaults, as described in section +<<SECTdefaultvaluelookups>>, but this is useful only for the ``\*@'' type of +default. For example, with this lookup: + + accept senders = lsearch*@;/some/file ++ +the file could contains lines like this: + + user1@domain1.example + *@domain2.example ++ +and for the sender address 'nimrod@jaeger.example', the sequence of keys +that are tried is: + + nimrod@jaeger.example + *@jaeger.example + * ++ +*Warning 1*: Do not include a line keyed by ``\*'' in the file, because that +would mean that every address matches, thus rendering the test useless. ++ +*Warning 2*: Do not confuse these two kinds of item: + + deny recipients = dbm*@;/some/file + deny recipients = *@dbm;/some/file ++ +The first does a whole address lookup, with defaulting, as just described, +because it starts with a lookup type. The second matches the local part and +domain independently, as described in a bullet point below. + + + +The following kinds of address list pattern can match only non-empty addresses. +If the subject address is empty, a match against any of these pattern types +always fails. + + +- cindex:[@@ with single-key lookup] +cindex:[address list,@@ lookup type] +cindex:[address list,split local part and domain] +If a pattern starts with ``@@'' followed by a single-key lookup item +(for example, `@@lsearch;/some/file`), the address that is being checked is +split into a local part and a domain. The domain is looked up in the file. If +it is not found, there is no match. If it is found, the data that is looked up +from the file is treated as a colon-separated list of local part patterns, each +of which is matched against the subject local part in turn. ++ +cindex:[asterisk,in address list] +The lookup may be a partial one, and/or one involving a search for a default +keyed by ``\*'' (see section <<SECTdefaultvaluelookups>>). The local part patterns +that are looked up can be regular expressions or begin with ``\*'', or even be +further lookups. They may also be independently negated. For example, with + + deny senders = @@dbm;/etc/reject-by-domain ++ +the data from which the DBM file is built could contain lines like + + baddomain.com: !postmaster : * ++ +to reject all senders except %postmaster% from that domain. ++ +cindex:[local part,starting with !] +If a local part that actually begins with an exclamation mark is required, it +has to be specified using a regular expression. In ^lsearch^ files, an entry +may be split over several lines by indenting the second and subsequent lines, +but the separating colon must still be included at line breaks. White space +surrounding the colons is ignored. For example: + + aol.com: spammer1 : spammer2 : ^[0-9]+$ : + spammer3 : spammer4 ++ +As in all colon-separated lists in Exim, a colon can be included in an item by +doubling. ++ +If the last item in the list starts with a right angle-bracket, the remainder +of the item is taken as a new key to look up in order to obtain a continuation +list of local parts. The new key can be any sequence of characters. Thus one +might have entries like + + aol.com: spammer1 : spammer 2 : >* + xyz.com: spammer3 : >* + *: ^\d{8}$ ++ +in a file that was searched with %@@dbm\*%, to specify a match for 8-digit +local parts for all domains, in addition to the specific local parts listed for +each domain. Of course, using this feature costs another lookup each time a +chain is followed, but the effort needed to maintain the data is reduced. ++ +cindex:[loop,in lookups] +It is possible to construct loops using this facility, and in order to catch +them, the chains may be no more than fifty items long. + +- The @@<'lookup'> style of item can also be used with a query-style +lookup, but in this case, the chaining facility is not available. The lookup +can only return a single list of local parts. + +- If a pattern contains an @ character, but is not a regular expression and does +not begin with a lookup type as described above, the local part of the subject +address is compared with the local part of the pattern, which may start with an +asterisk. If the local parts match, the domain is checked in exactly the same +way as for a pattern in a domain list. For example, the domain can be +wildcarded, refer to a named list, or be a lookup: ++ +.... +deny senders = *@*.spamming.site:\ + *@+hostile_domains:\ + bozo@partial-lsearch;/list/of/dodgy/sites:\ + *@dbm;/bad/domains.db +.... ++ +cindex:[local part,starting with !] +cindex:[address list,local part starting with !] +If a local part that begins with an exclamation mark is required, it has to be +specified using a regular expression, because otherwise the exclamation mark is +treated as a sign of negation. + +- If a pattern is not one of the above syntax forms, that is, if a +non-empty pattern that is not a regular expression or a lookup does not contain +an @ character, it is matched against the domain part of the subject address. +The only two formats that are recognized this way are a literal domain, or a +domain pattern that starts with \*. In both these cases, the effect is the same +as if `*@` preceded the pattern. + +*Warning*: there is an important difference between the address list items +in these two examples: + + senders = +my_list + senders = *@+my_list + +In the first one, `my_list` is a named address list, whereas in the second +example it is a named domain list. + + + + +[[SECTcasletadd]] +Case of letters in address lists +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[case of local parts] +cindex:[address list,case forcing] +cindex:[case forcing in address lists] +Domains in email addresses are always handled caselessly, but for local parts +case may be significant on some systems (see %caseful_local_part% for how +Exim deals with this when routing addresses). However, RFC 2505 ('Anti-Spam +Recommendations for SMTP MTAs') suggests that matching of addresses to blocking +lists should be done in a case-independent manner. Since most address lists in +Exim are used for this kind of control, Exim attempts to do this by default. + +The domain portion of an address is always lowercased before matching it to an +address list. The local part is lowercased by default, and any string +comparisons that take place are done caselessly. This means that the data in +the address list itself, in files included as plain file names, and in any file +that is looked up using the ``@@'' mechanism, can be in any case. However, the +keys in files that are looked up by a search type other than ^lsearch^ (which +works caselessly) must be in lower case, because these lookups are not +case-independent. + +cindex:[`+caseful`] +To allow for the possibility of caseful address list matching, if an item in +an address list is the string ``+caseful'', the original case of the local +part is restored for any comparisons that follow, and string comparisons are no +longer case-independent. This does not affect the domain, which remains in +lower case. However, although independent matches on the domain alone are still +performed caselessly, regular expressions that match against an entire address +become case-sensitive after ``+caseful'' has been seen. + + + +[[SECTlocparlis]] +Local part lists +~~~~~~~~~~~~~~~~ +cindex:[list,local part list] +cindex:[local part,list] +Case-sensitivity in local part lists is handled in the same way as for address +lists, as just described. The ``+caseful'' item can be used if required. In a +setting of the %local_parts% option in a router with %caseful_local_part% +set false, the subject is lowercased and the matching is initially +case-insensitive. In this case, ``+caseful'' will restore case-sensitive matching +in the local part list, but not elsewhere in the router. If +%caseful_local_part% is set true in a router, matching in the %local_parts% +option is case-sensitive from the start. + +If a local part list is indirected to a file (see section <<SECTfilnamlis>>), +comments are handled in the same way as address lists -- they are recognized +only if the # is preceded by white space or the start of the line. +Otherwise, local part lists are matched in the same way as domain lists, except +that the special items that refer to the local host (`@`, `@[]`, +`@mx_any`, `@mx_primary`, and `@mx_secondary`) are not recognized. +Refer to section <<SECTdomainlist>> for details of the other available item +types. + + + + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// + +[[CHAPexpand]] +String expansions +----------------- +cindex:[expansion,of strings] +Many strings in Exim's run time configuration are expanded before use. Some of +them are expanded every time they are used; others are expanded only once. + +When a string is being expanded it is copied verbatim from left to right except +when a dollar or backslash character is encountered. A dollar specifies the +start of a portion of the string which is interpreted and replaced as described +below in section <<SECTexpansionitems>> onwards. Backslash is used as an escape +character, as described in the following section. + + + +[[SECTlittext]] +Literal text in expanded strings +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[expansion,including literal text] +An uninterpreted dollar can be included in an expanded string by putting a +backslash in front of it. A backslash can be used to prevent any special +character being treated specially in an expansion, including itself. If the +string appears in quotes in the configuration file, two backslashes are +required because the quotes themselves cause interpretation of backslashes when +the string is read in (see section <<SECTstrings>>). + +cindex:[expansion,non-expandable substrings] +A portion of the string can specified as non-expandable by placing it between +two occurrences of `\N`. This is particularly useful for protecting regular +expressions, which often contain backslashes and dollar signs. For example: + + deny senders = \N^\d{8}[a-z]@some\.site\.example$\N + +On encountering the first `\N`, the expander copies subsequent characters +without interpretation until it reaches the next `\N` or the end of the +string. + + + +Character escape sequences in expanded strings +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[expansion,escape sequences] +A backslash followed by one of the letters ``n'', ``r'', or ``t'' in an expanded +string is recognized as an escape sequence for the character newline, carriage +return, or tab, respectively. A backslash followed by up to three octal digits +is recognized as an octal encoding for a single character, and a backslash +followed by ``x'' and up to two hexadecimal digits is a hexadecimal encoding. + +These escape sequences are also recognized in quoted strings when they are read +in. Their interpretation in expansions as well is useful for unquoted strings, +and for other cases such as looked-up strings that are then expanded. + + +Testing string expansions +~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[expansion,testing] +cindex:[testing,string expansion] +cindex:[%-be% option] +Many expansions can be tested by calling Exim with the %-be% option. This takes +the command arguments, or lines from the standard input if there are no +arguments, runs them through the string expansion code, and writes the results +to the standard output. Variables based on configuration values are set up, but +since no message is being processed, variables such as $local_part$ have no +value. Nevertheless the %-be% option can be useful for checking out file and +database lookups, and the use of expansion operators such as %sg%, %substr% and +%nhash%. + +Exim gives up its root privilege when it is called with the %-be% option, and +instead runs under the uid and gid it was called with, to prevent users from +using %-be% for reading files to which they do not have access. + + + +[[SECTforexpfai]] +Forced expansion failure +~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[expansion,forced failure] +A number of expansions that are described in the following section have +alternative ``true'' and ``false'' substrings, enclosed in curly brackets. Which +one is used depends on some condition that is evaluated as part of the +expansion. If, instead of a ``false'' substring, the word ``fail'' is used (not in +curly brackets), the entire string expansion fails in a way that can be +detected by the code that requested the expansion. This is called ``forced +expansion failure'', and its consequences depend on the circumstances. In some +cases it is no different from any other expansion failure, but in others a +different action may be taken. Such variations are mentioned in the +documentation of the option that is being expanded. + + + + +[[SECTexpansionitems]] +Expansion items +~~~~~~~~~~~~~~~ +The following items are recognized in expanded strings. White space may be used +between sub-items that are keywords or substrings enclosed in braces inside an +outer set of braces, to improve readability. *Warning*: Within braces, +white space is significant. + +*\$*<'variable~name'>~or~*\$\{*<'variable~name'>*\}*:: +cindex:[expansion,variables] +Substitute the contents of the named variable, for example + + $local_part + ${domain} ++ +The second form can be used to separate the name from subsequent alphanumeric +characters. This form (using curly brackets) is available only for variables; +it does 'not' apply to message headers. The names of the variables are given +in section <<SECTexpvar>> below. If the name of a non-existent variable is given, +the expansion fails. + +*\$\{*<'op'>*:*<'string'>*\}*:: +cindex:[expansion,operators] +The string is first itself expanded, and then the operation specified by <'op'> +is applied to it. For example, + + ${lc:$local_part} ++ +The string starts with the first character after the colon, which may be +leading white space. A list of operators is given in section <<SECTexpop>> +below. The operator notation is used for simple expansion items that have just +one argument, because it reduces the number of braces and therefore makes the +string easier to understand. + +*\$\{extract\{*<'key'>*\}\{*<'string1'>*\}\{*<'string2'>*\}\{*<'string3'>*\}\}*:: +cindex:[expansion,extracting substrings by key] +The key and <'string1'> are first expanded separately. Leading and trailing +whitespace is removed from the key (but not from any of the strings). The key +must not consist entirely of digits. The expanded <'string1'> must be of the +form: + + <key1> = <value1> <key2> = <value2> ... ++ +where the equals signs and spaces (but not both) are optional. If any of the +values contain white space, they must be enclosed in double quotes, and any +values that are enclosed in double quotes are subject to escape processing as +described in section <<SECTstrings>>. The expanded <'string1'> is searched for +the value that corresponds to the key. The search is case-insensitive. If the +key is found, <'string2'> is expanded, and replaces the whole item; otherwise +<'string3'> is used. During the expansion of <'string2'> the variable $value$ +contains the value that has been extracted. Afterwards, it is restored to any +previous value it might have had. ++ +If \{<'string3'>\} is omitted, the item is replaced by an empty string if the +key is not found. If \{<'string2'>\} is also omitted, the value that was +extracted is used. Thus, for example, these two expansions are identical, and +yield ``2001'': + + ${extract{gid}{uid=1984 gid=2001}} + ${extract{gid}{uid=1984 gid=2001}{$value}} ++ +Instead of \{<'string3'>\} the word ``fail'' (not in curly brackets) can +appear, for example: + + ${extract{Z}{A=... B=...}{$value} fail } ++ +This forces an expansion failure (see section <<SECTforexpfai>>); +{<'string2'>\} must be present for ``fail'' to be recognized. + + +*\$\{extract\{*<'number'>*\}\{*<'separators'>*\}\{*<'string1'>*\}\{*<'string2'>*\}\{*<'string3'>*\}\}*:: +cindex:[expansion,extracting substrings by number] +The <'number'> argument must consist entirely of decimal digits, +apart from leading and trailing whitespace, which is ignored. +This is what distinguishes this form of %extract% from the previous kind. It +behaves in the same way, except that, instead of extracting a named field, it +extracts from <'string1'> the field whose number is given as the first +argument. You can use $value$ in <'string2'> or `fail` instead of +<'string3'> as before. ++ +The fields in the string are separated by any one of the characters in the +separator string. These may include space or tab characters. +The first field is numbered one. If the number is negative, the fields are +counted from the end of the string, with the rightmost one numbered -1. If the +number given is zero, the entire string is returned. If the modulus of the +number is greater than the number of fields in the string, the result is the +expansion of <'string3'>, or the empty string if <'string3'> is not provided. +For example: + + ${extract{2}{:}{x:42:99:& Mailer::/bin/bash}} ++ +yields ``42'', and + + ${extract{-4}{:}{x:42:99:& Mailer::/bin/bash}} ++ +yields ``99''. Two successive separators mean that the field between them is +empty (for example, the fifth field above). + + +*\$\{hash\{*<'string1'>*\}\{*<'string2'>*\}\{*<'string3'>*\}\}*:: +cindex:[hash function,textual] +cindex:[expansion,textual hash] +This is a textual hashing function, and was the first to be implemented in +early versions of Exim. In current releases, there are other hashing functions +(numeric, MD5, and SHA-1), which are described below. ++ +The first two strings, after expansion, must be numbers. Call them <'m'> and +<'n'>. If you are using fixed values for these numbers, that is, if <'string1'> +and <'string2'> do not change when they are expanded, you can use the +simpler operator notation that avoids some of the braces: + + ${hash_<n>_<m>:<string>} ++ +The second number is optional (in both notations). ++ +If <'n'> is greater than or equal to the length of the string, the expansion +item returns the string. Otherwise it computes a new string of length <'n'> by +applying a hashing function to the string. The new string consists of +characters taken from the first <'m'> characters of the string + + abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQWRSTUVWXYZ0123456789 ++ +If <'m'> is not present the value 26 is used, so that only lower case +letters appear. For example: ++ +&&& +`\${hash{3}{monty}} ` yields `jmg` +`\${hash{5}{monty}} ` yields `monty` +`\${hash{4}{62}{monty python}}` yields `fbWx` +&&& + + +*\$header_*<'header~name'>*:*~or~*\$h_*<'header~name'>*:*:: +See *\$rheader* below. + +*\$bheader_*<'header~name'>*:*~or~*\$bh_*<'header~name'>*:*:: +See *\$rheader* below. + +*\$rheader_*<'header~name'>*:*~or~*\$rh_*<'header~name'>*:*:: +cindex:[expansion,header insertion] +cindex:[$header_$] +cindex:[$bheader_$] +cindex:[$rheader_$] +cindex:[header lines,in expansion strings] +cindex:[header lines,character sets] +cindex:[header lines,decoding] +Substitute the contents of the named message header line, for example + + $header_reply-to: ++ +The newline that terminates a header line is not included in the expansion, but +internal newlines (caused by splitting the header line over several physical +lines) may be present. ++ +The difference between %rheader%, %bheader%, and %header% is in the way the +data in the header line is interpreted. ++ +-- +- cindex:[whitespace,in header lines] +%rheader% gives the original ``raw'' content of the header line, with no +processing at all, and without the removal of leading and trailing whitespace. + +- cindex:[base64 encoding,in header lines] +%bheader% removes leading and trailing whitespace, and then decodes base64 or +quoted-printable MIME ``words'' within the header text, but does no character +set translation. If decoding of what looks superficially like a MIME ``word'' +fails, the raw string is returned. If decoding +cindex:[binary zero,in header line] +produces a binary zero character, it is replaced by a question mark -- this is +what Exim does for binary zeros that are actually received in header lines. + +- %header% tries to translate the string as decoded by %bheader% to a standard +character set. This is an attempt to produce the same string as would be +displayed on a user's MUA. If translation fails, the %bheader% string is +returned. Translation is attempted only on operating systems that support the +'iconv()' function. This is indicated by the compile-time macro +HAVE_ICONV in a system Makefile or in _Local/Makefile_. +-- ++ +In a filter file, the target character set for %header% can be specified by a +command of the following form: + + headers charset "UTF-8" ++ +This command affects all references to $h_$ (or $header_$) expansions in +subsequently obeyed filter commands. In the absence of this command, the target +character set in a filter is taken from the setting of the %headers_charset% +option in the runtime configuration. The value of this option defaults to the +value of HEADERS_CHARSET in _Local/Makefile_. The ultimate default is +ISO-8859-1. ++ +Header names follow the syntax of RFC 2822, which states that they may contain +any printing characters except space and colon. Consequently, curly brackets +'do not' terminate header names, and should not be used to enclose them as +if they were variables. Attempting to do so causes a syntax error. ++ +Only header lines that are common to all copies of a message are visible to +this mechanism. These are the original header lines that are received with the +message, and any that are added by an ACL %warn% statement or by a system +filter. Header lines that are added to a particular copy of a message by a +router or transport are not accessible. ++ +For incoming SMTP messages, no header lines are visible in ACLs that are obeyed +before the DATA ACL, because the header structure is not set up until the +message is received. Header lines that are added by %warn% statements in a +RCPT ACL (for example) are saved until the message's incoming header lines +are available, at which point they are added. When a DATA ACL is running, +however, header lines added by earlier ACLs are visible. ++ +Upper case and lower case letters are synonymous in header names. If the +following character is white space, the terminating colon may be omitted, but +this is not recommended, because you may then forget it when it is needed. When +white space terminates the header name, it is included in the expanded string. +If the message does not contain the given header, the expansion item is +replaced by an empty string. (See the %def% condition in section <<SECTexpcond>> +for a means of testing for the existence of a header.) ++ +If there is more than one header with the same name, they are all +concatenated to form the substitution string, up to a maximum length of 64K. A +newline character is inserted between each line. For the %header% expansion, +for those headers that contain lists of addresses, a comma is also inserted at +the junctions between lines. This does not happen for the %rheader% expansion. + + + +*\$\{hmac\{*<'hashname'>*\}\{*<'secret'>*\}\{*<'string'>*\}\}*:: +cindex:[expansion,hmac hashing] +This function uses cryptographic hashing (either MD5 or SHA-1) to convert a +shared secret and some text into a message authentication code, as specified in +RFC 2104. This differs from `\$\{md5:secret_text...\}` or +`\$\{sha1:secret_text...\}` in that the hmac step adds a signature to the +cryptographic hash, allowing for authentication that is not possible with MD5 +or SHA-1 alone. The hash name must expand to either `md5` or `sha1` at present. +For example: + + ${hmac{md5}{somesecret}{$primary_hostname $tod_log}} ++ +For the hostname 'mail.example.com' and time 2002-10-17 11:30:59, this +produces: + + dd97e3ba5d1a61b5006108f8c8252953 ++ +As an example of how this might be used, you might put in the main part of +an Exim configuration: + + SPAMSCAN_SECRET=cohgheeLei2thahw ++ +In a router or a transport you could then have: ++ +.... +headers_add = \ + X-Spam-Scanned: ${primary_hostname} ${message_id} \ + ${hmac{md5}{SPAMSCAN_SECRET}\ + {${primary_hostname},${message_id},$h_message-id:}} +.... ++ +Then given a message, you can check where it was scanned by looking at the +'X-Spam-Scanned:' header line. If you know the secret, you can check that this +header line is authentic by recomputing the authentication code from the host +name, message ID and the 'Message-id:' header line. This can be done using +Exim's %-be% option, or by other means, for example by using the +'hmac_md5_hex()' function in Perl. + + +*\$\{if~*<'condition'>*~\{*<'string1'>*\}\{*<'string2'>*\}\}*:: +cindex:[expansion,conditional] +If <'condition'> is true, <'string1'> is expanded and replaces the whole item; +otherwise <'string2'> is used. The available conditions are described in +section <<SECTexpcond>> below. For example: + + ${if eq {$local_part}{postmaster} {yes}{no} } ++ +The second string need not be present; if it is not and the condition is not +true, the item is replaced with nothing. Alternatively, the word ``fail'' may be +present instead of the second string (without any curly brackets). In this +case, the expansion is forced to fail if the condition is not true (see section +<<SECTforexpfai>>). ++ +If both strings are omitted, the result is the string `true` if the condition +is true, and the empty string if the condition is false. This makes it less +cumbersome to write custom ACL and router conditions. For example, instead of + + condition = ${if >{$acl_m4}{3}{true}{false}} ++ +you can use + + condition = ${if >{$acl_m4}{3}} + + + +*\$\{length\{*<'string1'>*\}\{*<'string2'>*\}\}*:: +cindex:[expansion,string truncation] +The %length% item is used to extract the initial portion of a string. Both +strings are expanded, and the first one must yield a number, <'n'>, say. If you +are using a fixed value for the number, that is, if <'string1'> does not change +when expanded, you can use the simpler operator notation that avoids some of +the braces: + + ${length_<n>:<string>} ++ +The result of this item is either the first <'n'> characters or the whole +of <'string2'>, whichever is the shorter. Do not confuse %length% with +%strlen%, which gives the length of a string. + + +*\$\{lookup\{*<'key'>*\}~*<'search~type'>*~\{*<'file'>*\}~\{*<'string1'>*\}~\{*<'string2'>*\}\}*:: +This is the first of one of two different types of lookup item, which are both +described in the next item. + +*\$\{lookup~*<'search~type'>*~\{*<'query'>*\}~\{*<'string1'>*\}~\{*<'string2'>*\}\}*:: +cindex:[expansion,lookup in] +cindex:[file,lookup] +cindex:[lookup,in expanded string] +The two forms of lookup item specify data lookups in files and databases, as +discussed in chapter <<CHAPfdlookup>>. The first form is used for single-key +lookups, and the second is used for query-style lookups. The <'key'>, <'file'>, +and <'query'> strings are expanded before use. ++ +If there is any white space in a lookup item which is part of a filter command, +a retry or rewrite rule, a routing rule for the ^manualroute^ router, or any +other place where white space is significant, the lookup item must be enclosed +in double quotes. The use of data lookups in users' filter files may be locked +out by the system administrator. ++ +cindex:[$value$] +If the lookup succeeds, <'string1'> is expanded and replaces the entire item. +During its expansion, the variable $value$ contains the data returned by the +lookup. Afterwards it reverts to the value it had previously (at the outer +level it is empty). If the lookup fails, <'string2'> is expanded and replaces +the entire item. If \{<'string2'>\} is omitted, the replacement is the empty +string on failure. If <'string2'> is provided, it can itself be a nested +lookup, thus providing a mechanism for looking up a default value when the +original lookup fails. ++ +If a nested lookup is used as part of <'string1'>, $value$ contains the data +for the outer lookup while the parameters of the second lookup are expanded, +and also while <'string2'> of the second lookup is expanded, should the second +lookup fail. + Instead of \{<'string2'>\} the word ``fail'' can appear, and in +this case, if the lookup fails, the entire expansion is forced to fail (see +section <<SECTforexpfai>>). If both \{<'string1'>\} and \{<'string2'>\} are +omitted, the result is the looked up value in the case of a successful lookup, +and nothing in the case of failure. ++ +For single-key lookups, the string ``partial'' is permitted to precede the +search type in order to do partial matching, and \* or \*@ may follow a search +type to request default lookups if the key does not match (see sections +<<SECTdefaultvaluelookups>> and <<SECTpartiallookup>> for details). ++ +cindex:[numerical variables ($1$ $2$ etc),in lookup expansion] +If a partial search is used, the variables $1$ and $2$ contain the wild +and non-wild parts of the key during the expansion of the replacement text. +They return to their previous values at the end of the lookup item. ++ +This example looks up the postmaster alias in the conventional alias file: + + ${lookup {postmaster} lsearch {/etc/aliases} {$value}} ++ +This example uses NIS+ to look up the full name of the user corresponding to +the local part of an address, forcing the expansion to fail if it is not found: ++ +.... +${lookup nisplus {[name=$local_part],passwd.org_dir:gcos} \ + {$value}fail} +.... + + +*\$\{nhash\{*<'string1'>*\}\{*<'string2'>*\}\{*<'string3'>*\}\}*:: +cindex:[expansion,numeric hash] +cindex:[hash function,numeric] +The three strings are expanded; the first two must yield numbers. Call them +<'n'> and <'m'>. If you are using fixed values for these numbers, that is, if +<'string1'> and <'string2'> do not change when they are expanded, you can use +the simpler operator notation that avoids some of the braces: + + ${nhash_<n>_<m>:<string>} ++ +The second number is optional (in both notations). If there is only one number, +the result is a number in the range 0--<'n'>-1. Otherwise, the string is +processed by a div/mod hash function that returns two numbers, separated by a +slash, in the ranges 0 to <'n'>-1 and 0 to <'m'>-1, respectively. For example, + + ${nhash{8}{64}{supercalifragilisticexpialidocious}} ++ +returns the string ``6/33''. + + + +*\$\{perl\{*<'subroutine'>*\}\{*<'arg'>*\}\{*<'arg'>*\}...\}*:: +cindex:[Perl,use in expanded string] +cindex:[expansion,calling Perl from] +This item is available only if Exim has been built to include an embedded Perl +interpreter. The subroutine name and the arguments are first separately +expanded, and then the Perl subroutine is called with those arguments. No +additional arguments need be given; the maximum number permitted, including the +name of the subroutine, is nine. ++ +The return value of the subroutine is inserted into the expanded string, unless +the return value is %undef%. In that case, the expansion fails in the same way +as an explicit ``fail'' on a lookup item. +The return value is a scalar. Whatever you return is evaluated in a scalar +context. For example, if you return the name of a Perl vector, the +return value is the size of the vector, not its contents. ++ +If the subroutine exits by calling Perl's %die% function, the expansion fails +with the error message that was passed to %die%. More details of the embedded +Perl facility are given in chapter <<CHAPperl>>. ++ +The ^redirect^ router has an option called %forbid_filter_perl% which locks +out the use of this expansion item in filter files. + + +*\$\{readfile\{*<'file~name'>*\}\{*<'eol~string'>*\}\}*:: +cindex:[expansion,inserting an entire file] +cindex:[file,inserting into expansion] +The file name and end-of-line string are first expanded separately. The file is +then read, and its contents replace the entire item. All newline characters in +the file are replaced by the end-of-line string if it is present. Otherwise, +newlines are left in the string. +String expansion is not applied to the contents of the file. If you want this, +you must wrap the item in an %expand% operator. If the file cannot be read, the +string expansion fails. ++ +The ^redirect^ router has an option called %forbid_filter_readfile% which +locks out the use of this expansion item in filter files. + + + +*\$\{readsocket\{*<'name'>*\}\{*<'request'>*\}\{*<'timeout'>*\}\{*<'eol~string'>*\}\{*<'fail~string'>*\}\}*:: +cindex:[expansion,inserting from a socket] +cindex:[socket, use of in expansion] +This item inserts data that is read from a Unix domain socket into the expanded +string. The minimal way of using it uses just two arguments: + + ${readsocket{/socket/name}{request string}} ++ +Exim connects to the socket, writes the request string (unless it is an +empty string) and reads from the socket until an end-of-file is read. A timeout +of 5 seconds is applied. Additional, optional arguments extend what can be +done. Firstly, you can vary the timeout. For example: + + ${readsocket{/socket/name}{request-string}{3s}} ++ +A fourth argument allows you to change any newlines that are in the data +that is read, in the same way as for %readfile% (see above). This example turns +them into spaces: + + ${readsocket{/socket/name}{request-string}{3s}{ }} ++ +As with all expansions, the substrings are expanded before the processing +happens. Errors in these sub-expansions cause the expansion to fail. In +addition, the following errors can occur: ++ +-- +- Failure to create a socket file descriptor; + +- Failure to connect the socket; + +- Failure to write the request-string; + +- Timeout on reading from the socket. +-- ++ +By default, any of these errors causes the expansion to fail. However, if +you supply a fifth substring, it is expanded and used when any of the above +errors occurs. For example: ++ +.... + ${readsocket{/socket/name}{request-string}{3s}{\n}\ + {socket failure}} +.... ++ +You can test for the existence of the socket by wrapping this expansion in +`\$\{if exists`, but there is a race condition between that test and the +actual opening of the socket, so it is safer to use the fifth argument if you +want to be absolutely sure of avoiding an expansion error for a non-existent +socket. ++ +The ^redirect^ router has an option called %forbid_filter_readsocket% which +locks out the use of this expansion item in filter files. + +*\$rheader_*<'header~name'>*:~or~\$rh_*<'header~name'>*:*:: +This item inserts ``raw'' header lines. It is described with the %header% +expansion item above. + + + +*\$\{run\{*<'command'>*~*<'args'>*\}\{*<'string1'>*\}\{*<'string2'>*\}\}*:: +cindex:[expansion,running a command] +The command and its arguments are first expanded separately, and then the +command is run in a separate process, but under the same uid and gid. As in +other command executions from Exim, a shell is not used by default. If you want +a shell, you must explicitly code it. ++ +cindex:[return code,from %run% expansion] +If the command succeeds (gives a zero return code) <'string1'> is expanded and +replaces the entire item; during this expansion, the standard output from the +command is in the variable $value$. If the command fails, <'string2'>, if +present, is expanded. If it is absent, the result is empty. Alternatively, +<'string2'> can be the word ``fail'' (not in braces) to force expansion failure +if the command does not succeed. If both strings are omitted, the result is the +standard output on success, and nothing on failure. ++ +The return code from the command is put in the variable $runrc$, and this +remains set afterwards, so in a filter file you can do things like this: + + if "${run{x y z}{}}$runrc" is 1 then ... + elif $runrc is 2 then ... + ... + endif ++ +If execution of the command fails (for example, the command does not exist), +the return code is 127 -- the same code that shells use for non-existent +commands. ++ +*Warning*: In a router or transport, you cannot assume the order in which +option values are expanded, except for those pre-conditions whose order of +testing is documented. Therefore, you cannot reliably expect to set $runrc$ +by the expansion of one option, and use it in another. ++ +The ^redirect^ router has an option called %forbid_filter_run% which locks +out the use of this expansion item in filter files. + + +*\$\{sg\{*<'subject'>*\}\{*<'regex'>*\}\{*<'replacement'>*\}\}*:: +cindex:[expansion,string substitution] +This item works like Perl's substitution operator (s) with the global (/g) +option; hence its name. However, unlike the Perl equivalent, Exim does not +modify the subject string; instead it returns the modified string for insertion +into the overall expansion. The item takes three arguments: the subject string, +a regular expression, and a substitution string. For example + + ${sg{abcdefabcdef}{abc}{xyz}} ++ +yields ``xyzdefxyzdef''. Because all three arguments are expanded before use, if +any \$ or \ characters are required in the regular expression or in the +substitution string, they have to be escaped. For example + + ${sg{abcdef}{^(...)(...)\$}{\$2\$1}} ++ +yields ``defabc'', and + + ${sg{1=A 4=D 3=C}{\N(\d+)=\N}{K\$1=}} ++ +yields ``K1=A K4=D K3=C''. Note the use of `\N` to protect the contents of +the regular expression from string expansion. + + + +*\$\{substr\{*<'string1'>*\}\{*<'string2'>*\}\{*<'string3'>*\}\}*:: +cindex:[%substr%] +cindex:[substring extraction] +cindex:[expansion,substring extraction] +The three strings are expanded; the first two must yield numbers. Call them +<'n'> and <'m'>. If you are using fixed values for these numbers, that is, if +<'string1'> and <'string2'> do not change when they are expanded, you can use +the simpler operator notation that avoids some of the braces: + + ${substr_<n>_<m>:<string>} ++ +The second number is optional (in both notations). +If it is absent in the simpler format, the preceding underscore must also be +omitted. ++ +The %substr% item can be used to extract more general substrings than +%length%. The first number, <'n'>, is a starting offset, and <'m'> is the +length required. For example + + ${substr{3}{2}{$local_part}} ++ +If the starting offset is greater than the string length the result is the +null string; if the length plus starting offset is greater than the string +length, the result is the right-hand part of the string, starting from the +given offset. The first character in the string has offset zero. ++ +The %substr% expansion item can take negative offset values to count +from the right-hand end of its operand. The last character is offset -1, the +second-last is offset -2, and so on. Thus, for example, + + ${substr{-5}{2}{1234567}} ++ +yields ``34''. If the absolute value of a negative offset is greater than the +length of the string, the substring starts at the beginning of the string, and +the length is reduced by the amount of overshoot. Thus, for example, + + ${substr{-5}{2}{12}} ++ +yields an empty string, but + + ${substr{-3}{2}{12}} ++ +yields ``1''. ++ +When the second number is omitted from %substr%, the remainder of the string +is taken if the offset is positive. If it is negative, all characters in the +string preceding the offset point are taken. For example, an offset of -1 and +no length, as in these semantically identical examples: + + ${substr_-1:abcde} + ${substr{-1}{abcde}} ++ +yields all but the last character of the string, that is, ``abcd''. + + + +*\$\{tr\{*<'subject'>*\}\{*<'characters'>*\}\{*<'replacements'>*\}\}*:: +cindex:[expansion,character translation] +This item does single-character translation on its subject string. The second +argument is a list of characters to be translated in the subject string. Each +matching character is replaced by the corresponding character from the +replacement list. For example + + ${tr{abcdea}{ac}{13}} ++ +yields `1b3de1`. If there are duplicates in the second character string, the +last occurrence is used. If the third string is shorter than the second, its +last character is replicated. However, if it is empty, no translation takes +place. + + + +[[SECTexpop]] +Expansion operators +~~~~~~~~~~~~~~~~~~~ +cindex:[expansion,operators] +For expansion items that perform transformations on a single argument string, +the ``operator'' notation is used because it is simpler and uses fewer braces. +The substring is first expanded before the operation is applied to it. The +following operations can be performed: + +*\$\{address:*<'string'>*\}*:: +cindex:[expansion,RFC 2822 address handling] +The string is interpreted as an RFC 2822 address, as it might appear in a +header line, and the effective address is extracted from it. If the string does +not parse successfully, the result is empty. + + +*\$\{base62:*<'digits'>*\}*:: +cindex:[base62] +cindex:[expansion,conversion to base 62] +The string must consist entirely of decimal digits. The number is converted to +base 62 (sic) and output as a string of six characters, including leading +zeros. *Note*: Just to be absolutely clear: this is 'not' base64 +encoding. + +*\$\{base62d:*<'base-62~digits'>*\}*:: +cindex:[base62] +cindex:[expansion,conversion to base 62] +The string must consist entirely of base-62 digits. The number is converted to +decimal and output as a string. + + +*\$\{domain:*<'string'>*\}*:: +cindex:[domain,extraction] +cindex:[expansion,domain extraction] +The string is interpreted as an RFC 2822 address and the domain is extracted +from it. If the string does not parse successfully, the result is empty. + + +*\$\{escape:*<'string'>*\}*:: +cindex:[expansion,escaping non-printing characters] +If the string contains any non-printing characters, they are converted to +escape sequences starting with a backslash. Whether characters with the most +significant bit set (so-called ``8-bit characters'') count as printing or not is +controlled by the %print_topbitchars% option. + + +*\$\{eval:*<'string'>*\}*:: +*\$\{eval10:*<'string'>*\}*:: +cindex:[expansion,expression evaluation] +cindex:[expansion,arithmetic expression] +These items supports simple arithmetic in expansion strings. The string (after +expansion) must be a conventional arithmetic expression, but it is limited to +the four basic operators (plus, minus, times, divide) and parentheses. All +operations are carried out using integer arithmetic. Plus and minus have a +lower priority than times and divide; operators with the same priority are +evaluated from left to right. ++ +For %eval%, numbers may be decimal, octal (starting with ``0'') or hexadecimal +(starting with ``0x''). For %eval10%, all numbers are taken as decimal, even if +they start with a leading zero. This can be useful when processing numbers +extracted from dates or times, which often do have leading zeros. ++ +A number may be followed by ``K'' or ``M'' to multiply it by 1024 or 1024\*1024, +respectively. Negative numbers are supported. The result of the computation is +a decimal representation of the answer (without ``K'' or ``M''). For example: ++ +&&& +`\${eval:1+1} ` yields 2 +`\${eval:1+2*3} ` yields 7 +`\${eval:(1+2)*3} ` yields 9 +&&& ++ +As a more realistic example, in an ACL you might have ++ +.... +deny message = Too many bad recipients + condition = \ + ${if and { \ + {>{$rcpt_count}{10}} \ + { \ + < \ + {$recipients_count} \ + {${eval:$rcpt_count/2}} \ + } \ + }{yes}{no}} +.... ++ +The condition is true if there have been more than 10 RCPT commands and +fewer than half of them have resulted in a valid recipient. + + +*\$\{expand:*<'string'>*\}*:: +cindex:[expansion,re-expansion of substring] +The %expand% operator causes a string to be expanded for a second time. For +example, + + ${expand:${lookup{$domain}dbm{/some/file}{$value}}} ++ +first looks up a string in a file while expanding the operand for %expand%, and +then re-expands what it has found. + + +*\$\{from_utf8:*<'string'>*\}*:: +cindex:[Unicode] +cindex:[UTF-8,conversion from] +cindex:[expansion,UTF-8 conversion] +The world is slowly moving towards Unicode, although there are no standards for +email yet. However, other applications (including some databases) are starting +to store data in Unicode, using UTF-8 encoding. This operator converts from a +UTF-8 string to an ISO-8859-1 string. UTF-8 code values greater than 255 are +converted to underscores. The input must be a valid UTF-8 string. If it is not, +the result is an undefined sequence of bytes. ++ +Unicode code points with values less than 256 are compatible with ASCII and +ISO-8859-1 (also known as Latin-1). +For example, character 169 is the copyright symbol in both cases, though the +way it is encoded is different. In UTF-8, more than one byte is needed for +characters with code values greater than 127, whereas ISO-8859-1 is a +single-byte encoding (but thereby limited to 256 characters). This makes +translation from UTF-8 to ISO-8859-1 straightforward. + + +*\$\{hash_*<'n'>*_*<'m'>*:*<'string'>*\}*:: +cindex:[hash function,textual] +cindex:[expansion,textual hash] +The %hash% operator is a simpler interface to the hashing function that can be +used when the two parameters are fixed numbers (as opposed to strings that +change when expanded). The effect is the same as + + ${hash{<n>}{<m>}{<string>}} ++ +See the description of the general %hash% item above for details. The +abbreviation %h% can be used when %hash% is used as an operator. + + + +*\$\{hex2b64:*<'hexstring'>*\}*:: +cindex:[base64 encoding,conversion from hex] +cindex:[expansion,hex to base64] +This operator converts a hex string into one that is base64 encoded. This can +be useful for processing the output of the MD5 and SHA-1 hashing functions. + + +*\$\{lc:*<'string'>*\}*:: +cindex:[case forcing in strings] +cindex:[string,case forcing] +cindex:[lower casing] +cindex:[expansion,case forcing] +This forces the letters in the string into lower-case, for example: + + ${lc:$local_part} + + + +*\$\{length_*<'number'>*:*<'string'>*\}*:: +cindex:[expansion,string truncation] +The %length% operator is a simpler interface to the %length% function that can +be used when the parameter is a fixed number (as opposed to a string that +changes when expanded). The effect is the same as + + ${length{<number>}{<string>}} ++ +See the description of the general %length% item above for details. Note that +%length% is not the same as %strlen%. The abbreviation %l% can be used when +%length% is used as an operator. + + +*\$\{local_part:*<'string'>*\}*:: +cindex:[expansion,local part extraction] +The string is interpreted as an RFC 2822 address and the local part is +extracted from it. If the string does not parse successfully, the result is +empty. + + +*\$\{mask:*<'IP~address'>*/*<'bit~count'>*\}*:: +cindex:[masked IP address] +cindex:[IP address,masking] +cindex:[CIDR notation] +cindex:[expansion,IP address masking] +If the form of the string to be operated on is not an IP address followed by a +slash and an integer (that is, a network address in CIDR notation), the +expansion fails. Otherwise, this operator converts the IP address to binary, +masks off the least significant bits according to the bit count, and converts +the result back to text, with mask appended. For example, + + ${mask:10.111.131.206/28} ++ +returns the string ``10.111.131.192/28''. Since this operation is expected to be +mostly used for looking up masked addresses in files, the result for an IPv6 +address uses dots to separate components instead of colons, because colon +terminates a key string in lsearch files. So, for example, + + ${mask:3ffe:ffff:836f:0a00:000a:0800:200a:c031/99} ++ +returns the string + + 3ffe.ffff.836f.0a00.000a.0800.2000.0000/99 ++ +Letters in IPv6 addresses are always output in lower case. + + +*\$\{md5:*<'string'>*\}*:: +cindex:[MD5 hash] +cindex:[expansion,MD5 hash] +The %md5% operator computes the MD5 hash value of the string, and returns it as +a 32-digit hexadecimal number, +in which any letters are in lower case. + + +*\$\{nhash_*<'n'>*_*<'m'>*:*<'string'>*\}*:: +cindex:[expansion,numeric hash] +cindex:[hash function,numeric] +The %nhash% operator is a simpler interface to the numeric hashing function +that can be used when the two parameters are fixed numbers (as opposed to +strings that change when expanded). The effect is the same as + + ${nhash{<n>}{<m>}{<string>}} ++ +See the description of the general %nhash% item above for details. + + +*\$\{quote:*<'string'>*\}*:: +cindex:[quoting,in string expansions] +cindex:[expansion,quoting] +The %quote% operator puts its argument into double quotes if it +is an empty string or +contains anything other than letters, digits, underscores, dots, and hyphens. +Any occurrences of double quotes and backslashes are escaped with a backslash. +Newlines and carriage returns are converted to `\n` and `\r`, +respectively For example, + + ${quote:ab"*"cd} ++ +becomes + + "ab\"*\"cd" ++ +The place where this is useful is when the argument is a substitution from a +variable or a message header. + +*\$\{quote_local_part:*<'string'>*\}*:: +This operator is like %quote%, except that it quotes the string only if +required to do so by the rules of RFC 2822 for quoting local parts. For +example, a plus sign would not cause quoting (but it would for %quote%). +If you are creating a new email address from the contents of $local_part$ +(or any other unknown data), you should always use this operator. + + +*\$\{quote_*<'lookup-type'>*:*<'string'>*\}*:: +cindex:[quoting,lookup-specific] +This operator applies lookup-specific quoting rules to the string. Each +query-style lookup type has its own quoting rules which are described with +the lookups in chapter <<CHAPfdlookup>>. For example, + + ${quote_ldap:two * two} ++ +returns + + two%20%5C2A%20two ++ +For single-key lookup types, no quoting is ever necessary and this operator +yields an unchanged string. + + +*\$\{rxquote:*<'string'>*\}*:: +cindex:[quoting,in regular expressions] +cindex:[regular expressions,quoting] +The %rxquote% operator inserts a backslash before any non-alphanumeric +characters in its argument. This is useful when substituting the values of +variables or headers inside regular expressions. + + +*\$\{rfc2047:*<'string'>*\}*:: +cindex:[expansion,RFC 2047] +This operator encodes text according to the rules of RFC 2047. This is an +encoding that is used in header lines to encode non-ASCII characters. It is +assumed that the input string is in the encoding specified by the +%headers_charset% option, which defaults to ISO-8859-1. If the string contains +only characters in the range 33--126, and no instances of the characters + + ? = ( ) < > @ , ; : \ " . [ ] _ ++ +it is not modified. Otherwise, the result is the RFC 2047 encoding of the +string, using as many ``coded words'' as necessary to encode all the +characters. + + + +*\$\{sha1:*<'string'>*\}*:: +cindex:[SHA-1 hash] +cindex:[expansion,SHA-1 hashing] +The %sha1% operator computes the SHA-1 hash value of the string, and returns it +as a 40-digit hexadecimal number, in which any letters are in upper case. + + +*\$\{stat:*<'string'>*\}*:: +cindex:[expansion,statting a file] +cindex:[file,extracting characteristics] +The string, after expansion, must be a file path. A call to the 'stat()' +function is made for this path. If 'stat()' fails, an error occurs and the +expansion fails. If it succeeds, the data from the stat replaces the item, as a +series of <'name'>=<'value'> pairs, where the values are all numerical, +except for the value of ``smode''. The names are: ``mode'' (giving the mode as a +4-digit octal number), ``smode'' (giving the mode in symbolic format as a +10-character string, as for the 'ls' command), ``inode'', ``device'', ``links'', +``uid'', ``gid'', ``size'', ``atime'', ``mtime'', and ``ctime''. You can extract individual +fields using the %extract% expansion item. *Warning*: The file size may be +incorrect on 32-bit systems for files larger than 2GB. + + +*\$\{str2b64:*<'string'>*\}*:: +cindex:[expansion,base64 encoding] +cindex:[base64 encoding,in string expansion] +This operator converts a string into one that is base64 encoded. + + + +*\$\{strlen:*<'string'>*\}*:: +cindex:[expansion,string length] +cindex:[string,length in expansion] +The item is replace by the length of the expanded string, expressed as a +decimal number. *Note*: Do not confuse %strlen% with %length%. + + +*\$\{substr_*<'start'>*_*<'length'>*:*<'string'>*\}*:: +cindex:[%substr%] +cindex:[substring extraction] +cindex:[expansion,substring expansion] +The %substr% operator is a simpler interface to the %substr% function that can +be used when the two parameters are fixed numbers (as opposed to strings that +change when expanded). The effect is the same as + + ${substr{<start>}{<length>}{<string>}} ++ +See the description of the general %substr% item above for details. The +abbreviation %s% can be used when %substr% is used as an operator. + +*\$\{time_interval:*<'string'>*\}*:: +cindex:[%time_interval%] +cindex:[time interval,formatting] +The argument (after sub-expansion) must be a sequence of decimal digits that +represents an interval of time as a number of seconds. It is converted into a +number of larger units and output in Exim's normal time format, for example, +`1w3d4h2m6s`. + +*\$\{uc:*<'string'>*\}*:: +cindex:[case forcing in strings] +cindex:[string,case forcing] +cindex:[upper casing] +cindex:[expansion,case forcing] +This forces the letters in the string into upper-case. + + + + + + +[[SECTexpcond]] +Expansion conditions +~~~~~~~~~~~~~~~~~~~~ +cindex:[expansion,conditions] +The following conditions are available for testing by the %\$\{if% construct +while expanding strings: + +*!*<'condition'>:: +cindex:[expansion,negating a condition] +Preceding any condition with an exclamation mark negates the result of the +condition. + +<'symbolic~operator'>~*\{*<'string1'>*\}\{*<'string2'>*\}*:: +cindex:[numeric comparison] +cindex:[expansion,numeric comparison] +There are a number of symbolic operators for doing numeric comparisons. They +are: ++ +&&& +`= ` equal +`== ` equal +`> ` greater +`>= ` greater or equal +`< ` less +`<= ` less or equal +&&& ++ +For example, + + ${if >{$message_size}{10M} ... ++ +Note that the general negation operator provides for inequality testing. The +two strings must take the form of optionally signed decimal integers, +optionally followed by one of the letters ``K'' or ``M'' (in either upper or +lower case), signifying multiplication by 1024 or 1024\*1024, respectively. + +*crypteq~\{*<'string1'>*\}\{*<'string2'>*\}*:: +cindex:[expansion,encrypted comparison] +cindex:[encrypted strings, comparing] +This condition is included in the Exim binary if it is built to support any +authentication mechanisms (see chapter <<CHAPSMTPAUTH>>). Otherwise, it is +necessary to define SUPPORT_CRYPTEQ in _Local/Makefile_ to get %crypteq% +included in the binary. ++ +The %crypteq% condition has two arguments. The first is encrypted and compared +against the second, which is already encrypted. The second string may be in the +LDAP form for storing encrypted strings, which starts with the encryption type +in curly brackets, followed by the data. If the second string does not begin +with ``\{'' it is assumed to be encrypted with 'crypt()' or 'crypt16()' (see +below), since such strings cannot begin with ``\{''. Typically this will be a +field from a password file. ++ +An example of an encrypted string in LDAP form is: + + {md5}CY9rzUYh03PK3k6DJie09g== ++ +If such a string appears directly in an expansion, the curly brackets have to +be quoted, because they are part of the expansion syntax. For example: + + ${if crypteq {test}{\{md5\}CY9rzUYh03PK3k6DJie09g==}{yes}{no}} ++ +The following encryption types (whose names are matched case-independently) are +supported: ++ +-- +- cindex:[MD5 hash] +cindex:[base64 encoding,in encrypted password] +%\{md5\}% computes the MD5 digest of the first string, and expresses this as +printable characters to compare with the remainder of the second string. If the +length of the comparison string is 24, Exim assumes that it is base64 encoded +(as in the above example). If the length is 32, Exim assumes that it is a +hexadecimal encoding of the MD5 digest. If the length not 24 or 32, the +comparison fails. + +- cindex:[SHA-1 hash] +%\{sha1\}% computes the SHA-1 digest of the first string, and expresses this as +printable characters to compare with the remainder of the second string. If the +length of the comparison string is 28, Exim assumes that it is base64 encoded. +If the length is 40, Exim assumes that it is a hexadecimal encoding of the +SHA-1 digest. If the length is not 28 or 40, the comparison fails. + +- cindex:['crypt()'] +%\{crypt\}% calls the 'crypt()' function, which traditionally used to use only +the first eight characters of the password. However, in modern operating +systems this is no longer true, and in many cases the entire password is used, +whatever its length. + +- cindex:['crypt16()'] +%\{crypt16\}% calls the 'crypt16()' function (also known as 'bigcrypt()'), +which was orginally created to use up to 16 characters of the password. Again, +in modern operating systems, more characters may be used. +-- ++ +Exim has its own version of 'crypt16()' (which is just a double call to +'crypt()'). For operating systems that have their own version, setting +HAVE_CRYPT16 in _Local/Makefile_ when building Exim causes it to use the +operating system version instead of its own. This option is set by default in +the OS-dependent _Makefile_ for those operating systems that are known to +support 'crypt16()'. ++ +If you do not put any curly bracket encryption type in a %crypteq% comparison, +the default is either `\{crypt\}` or `\{crypt16\}`, as determined by the +setting of DEFAULT_CRYPT in _Local/Makefile_. The default default is +`\{crypt\}`. Whatever the default, you can always use either function by +specifying it explicitly in curly brackets. ++ +Note that if a password is no longer than 8 characters, the results of +encrypting it with 'crypt()' and 'crypt16()' are identical. That means that +'crypt16()' is backwards compatible, as long as nobody feeds it a password +longer than 8 characters. + + +*def:*<'variable~name'>*:: +cindex:[expansion,checking for empty variable] +The %def% condition must be followed by the name of one of the expansion +variables defined in section <<SECTexpvar>>. The condition is true if the named +expansion variable does not contain the empty string, for example + + ${if def:sender_ident {from $sender_ident}} ++ +Note that the variable name is given without a leading %\$% character. If the +variable does not exist, the expansion fails. + +*def:header_*<'header~name'>*:*~~or~~*def:h_*<'header~name'>*:*:: +cindex:[expansion,checking header line existence] +This condition is true if a message is being processed and the named header +exists in the message. For example, + + ${if def:header_reply-to:{$h_reply-to:}{$h_from:}} ++ +Note that no %\$% appears before %header_% or %h_% in the condition, +and that header names must be terminated by colons if white space does not +follow. + +*eq~\{*<'string1'>*\}\{*<'string2'>*\}*:: +cindex:[string,comparison] +cindex:[expansion,string comparison] +The two substrings are first expanded. The condition is true if the two +resulting strings are identical, including the case of letters. + +*eqi~\{*<'string1'>*\}\{*<'string2'>*\}*:: +cindex:[string,comparison] +cindex:[expansion,string comparison] +The two substrings are first expanded. The condition is true if the two +resulting strings are identical when compared in a case-independent way. + +*exists~\{*<'file~name'>*\}*:: +cindex:[expansion,file existence test] +cindex:[file,existence test] +The substring is first expanded and then interpreted as an absolute path. The +condition is true if the named file (or directory) exists. The existence test +is done by calling the 'stat()' function. The use of the %exists% test in +users' filter files may be locked out by the system administrator. + +*first_delivery*:: +cindex:[delivery,first] +cindex:[first delivery] +cindex:[expansion,first delivery test] +This condition, which has no data, is true during a message's first delivery +attempt. It is false during any subsequent delivery attempts. + +*ge~\{*<'string1'>*\}\{*<'string2'>*\}*:: +See *gei*. + +*gei~\{*<'string1'>*\}\{*<'string2'>*\}*:: +cindex:[string,comparison] +cindex:[expansion,string comparison] +The two substrings are first expanded. The condition is true if the first +string is lexically greater than or equal to the second string: for %ge% the +comparison includes the case of letters, whereas for %gei% the comparison is +case-independent. + +*gt~\{*<'string1'>*\}\{*<'string2'>*\}*:: +See *gti*. + +*gti~\{*<'string1'>*\}\{*<'string2'>*\}*:: +cindex:[string,comparison] +cindex:[expansion,string comparison] +The two substrings are first expanded. The condition is true if the first +string is lexically greater than the second string: for %gt% the comparison +includes the case of letters, whereas for %gti% the comparison is +case-independent. + +*isip~\{*<'string'>*\}*:: +See *isip6*. + +*isip4~\{*<'string'>*\}*:: +See *isip6*. + +*isip6~\{*<'string'>*\}*:: +cindex:[IP address,testing string format] +cindex:[string,testing for IP address] +The substring is first expanded, and then tested to see if it has the form of +an IP address. Both IPv4 and IPv6 addresses are valid for %isip%, whereas +%isip4% and %isip6% test just for IPv4 or IPv6 addresses, respectively. For +example, you could use + + ${if isip4{$sender_host_address}... ++ +to test which version of IP an incoming SMTP connection is using. + + +*ldapauth~\{*<'ldap~query'>*\}*:: +cindex:[LDAP,use for authentication] +cindex:[expansion,LDAP authentication test] +This condition supports user authentication using LDAP. See section +<<SECTldap>> for details of how to use LDAP in lookups and the syntax of +queries. For this use, the query must contain a user name and password. The +query itself is not used, and can be empty. The condition is true if the +password is not empty, and the user name and password are accepted by the LDAP +server. An empty password is rejected without calling LDAP because LDAP binds +with an empty password are considered anonymous regardless of the username, and +will succeed in most configurations. See chapter <<CHAPSMTPAUTH>> for details +of SMTP authentication, and chapter <<CHAPplaintext>> for an example of how +this can be used. + + +*le~\{*<'string1'>*\}\{*<'string2'>*\}*:: +See *lei*. + +*lei~\{*<'string1'>*\}\{*<'string2'>*\}*:: +cindex:[string,comparison] +cindex:[expansion,string comparison] +The two substrings are first expanded. The condition is true if the first +string is lexically less than or equal to the second string: for %le% the +comparison includes the case of letters, whereas for %lei% the comparison is +case-independent. + +*lt~\{*<'string1'>*\}\{*<'string2'>*\}*:: +See *lti*. + +*lti~\{*<'string1'>*\}\{*<'string2'>*\}*:: +cindex:[string,comparison] +cindex:[expansion,string comparison] +The two substrings are first expanded. The condition is true if the first +string is lexically less than the second string: for %lt% the comparison +includes the case of letters, whereas for %lti% the comparison is +case-independent. + + +*match~\{*<'string1'>*\}\{*<'string2'>*\}*:: +cindex:[expansion,regular expression comparison] +cindex:[regular expressions,match in expanded string] +The two substrings are first expanded. The second is then treated as a regular +expression and applied to the first. Because of the pre-expansion, if the +regular expression contains dollar, or backslash characters, they must be +escaped. Care must also be taken if the regular expression contains braces +(curly brackets). A closing brace must be escaped so that it is not taken as a +premature termination of <'string2'>. The easiest approach is to use the +`\N` feature to disable expansion of the regular expression. +For example, + + ${if match {$local_part}{\N^\d{3}\N} ... ++ +If the whole expansion string is in double quotes, further escaping of +backslashes is also required. ++ +The condition is true if the regular expression match succeeds. +The regular expression is not required to begin with a circumflex +metacharacter, but if there is no circumflex, the expression is not anchored, +and it may match anywhere in the subject, not just at the start. If you want +the pattern to match at the end of the subject, you must include the `\$` +metacharacter at an appropriate point. ++ +cindex:[numerical variables ($1$ $2$ etc),in %if% expansion] +At the start of an %if% expansion the values of the numeric variable +substitutions $1$ etc. are remembered. Obeying a %match% condition that +succeeds causes them to be reset to the substrings of that condition and they +will have these values during the expansion of the success string. At the end +of the %if% expansion, the previous values are restored. After testing a +combination of conditions using %or%, the subsequent values of the numeric +variables are those of the condition that succeeded. + +*match_domain~\{*<'string1'>*\}\{*<'string2'>*\}*:: +See *match_local_part*. + +*match_address~\{*<'string1'>*\}\{*<'string2'>*\}*:: +See *match_local_part*. + +*match_local_part~\{*<'string1'>*\}\{*<'string2'>*\}*:: +cindex:[domain list,in expansion condition] +cindex:[address list,in expansion condition] +cindex:[local part list,in expansion condition] +These conditions make it possible to test domain, address, and local +part lists within expansions. Each condition requires two arguments: an item +and a list to match. A trivial example is: + + ${if match_domain{a.b.c}{x.y.z:a.b.c:p.q.r}{yes}{no}} ++ +In each case, the second argument may contain any of the allowable items for a +list of the appropriate type. Also, because the second argument (after +expansion) is a standard form of list, it is possible to refer to a named list. +Thus, you can use conditions like this: + + ${if match_domain{$domain}{+local_domains}{... ++ +cindex:[`+caseful`] +For address lists, the matching starts off caselessly, but the `+caseful` +item can be used, as in all address lists, to cause subsequent items to +have their local parts matched casefully. Domains are always matched +caselessly. ++ +*Note*: Host lists are 'not' supported in this way. This is because +hosts have two identities: a name and an IP address, and it is not clear +how to specify cleanly how such a test would work. At least, I haven't come +up with anything yet. + +*pam~\{*<'string1'>*:*<'string2'>*:...\}*:: +cindex:[PAM authentication] +cindex:[AUTH,with PAM] +cindex:[Solaris,PAM support] +cindex:[expansion,PAM authentication test] +'Pluggable Authentication Modules' +(*http://www.kernel.org/pub/linux/libs/pam/[]*) +are a facility that is available in the latest releases of Solaris and in some +GNU/Linux distributions. The Exim support, which is intended for use in +conjunction with the SMTP AUTH command, is available only if Exim is +compiled with + + SUPPORT_PAM=yes ++ +in _Local/Makefile_. You probably need to add %-lpam% to EXTRALIBS, and +in some releases of GNU/Linux %-ldl% is also needed. ++ +The argument string is first expanded, and the result must be a +colon-separated list of strings. Leading and trailing whitespace is ignored. +The PAM module is initialized with the service name ``exim'' and the user name +taken from the first item in the colon-separated data string (<'string1'>). The +remaining items in the data string are passed over in response to requests from +the authentication function. In the simple case there will only be one request, +for a password, so the data consists of just two strings. ++ +There can be problems if any of the strings are permitted to contain colon +characters. In the usual way, these have to be doubled to avoid being taken as +separators. If the data is being inserted from a variable, the %sg% expansion +item can be used to double any existing colons. For example, the configuration +of a LOGIN authenticator might contain this setting: + + server_condition = ${if pam{$1:${sg{$2}{:}{::}}}{yes}{no}} ++ +For a PLAIN authenticator you could use: + + server_condition = ${if pam{$2:${sg{$3}{:}{::}}}{yes}{no}} ++ +In some operating systems, PAM authentication can be done only from a process +running as root. Since Exim is running as the Exim user when receiving +messages, this means that PAM cannot be used directly in those systems. +A patched version of the 'pam_unix' module that comes with the +Linux PAM package is available from *http://www.e-admin.de/pam_exim/[]*. +The patched module allows one special uid/gid combination, in addition to root, +to authenticate. If you build the patched module to allow the Exim user and +group, PAM can then be used from an Exim authenticator. + + +*pwcheck~\{*<'string1'>*:*<'string2'>*\}*:: +cindex:['pwcheck' daemon] +cindex:[Cyrus] +cindex:[expansion,'pwcheck' authentication test] +This condition supports user authentication using the Cyrus 'pwcheck' daemon. +This is one way of making it possible for passwords to be checked by a process +that is not running as root. *Note:* The use of 'pwcheck' is now deprecated. +Its replacement is 'saslauthd' (see below). ++ +The pwcheck support is not included in Exim by default. You need to specify +the location of the pwcheck daemon's socket in _Local/Makefile_ before +building Exim. For example: + + CYRUS_PWCHECK_SOCKET=/var/pwcheck/pwcheck ++ +You do not need to install the full Cyrus software suite in order to use +the pwcheck daemon. You can compile and install just the daemon alone +from the Cyrus SASL library. Ensure that 'exim' is the only user that has +access to the _/var/pwcheck_ directory. ++ +The %pwcheck% condition takes one argument, which must be the user name and +password, separated by a colon. For example, in a LOGIN authenticator +configuration, you might have this: + + server_condition = ${if pwcheck{$1:$2}{1}{0}} + + +*queue_running*:: +cindex:[queue runner,detecting when delivering from] +cindex:[expansion,queue runner test] +This condition, which has no data, is true during delivery attempts that are +initiated by queue runner processes, and false otherwise. + + +*radius~\{*<'authentication~string'>*\}*:: +cindex:[Radius] +cindex:[expansion,Radius authentication] +Radius authentication (RFC 2865) is supported in a similar way to PAM. You must +set RADIUS_CONFIG_FILE in _Local/Makefile_ to specify the location of +the Radius client configuration file in order to build Exim with Radius +support. ++ +With just that one setting, Exim expects to be linked with the %radiusclient% +library. You can also link Exim with the %libradius% library that comes with +FreeBSD. To do this, set + + RADIUS_LIB_TYPE=RADLIB ++ +in _Local/Makefile_, in addition to setting RADIUS_CONFIGURE_FILE. +You may also have to supply a suitable setting in EXTRALIBS so that the +Radius library can be found when Exim is linked. ++ +The string specified by RADIUS_CONFIG_FILE is expanded and passed to the +Radius client library, which calls the Radius server. The condition is true if +the authentication is successful. For example + + server_condition = \$\{if radius\{<arguments>\}\{yes\}\{no\}\} + + + + +*saslauthd~\{\{*<'user'>*\}\{*<'password'>*\}\{*<'service'>*\}\{*<'realm'>*\}\}*:: +cindex:['saslauthd' daemon] +cindex:[Cyrus] +cindex:[expansion,'saslauthd' authentication test] +This condition supports user authentication using the Cyrus 'saslauthd' +daemon. This replaces the older 'pwcheck' daemon, which is now deprecated. +Using this daemon is one way of making it possible for passwords to be checked +by a process that is not running as root. ++ +The saslauthd support is not included in Exim by default. You need to specify +the location of the saslauthd daemon's socket in _Local/Makefile_ before +building Exim. For example: + + CYRUS_SASLAUTHD_SOCKET=/var/state/saslauthd/mux ++ +You do not need to install the full Cyrus software suite in order to use +the saslauthd daemon. You can compile and install just the daemon alone +from the Cyrus SASL library. ++ +Up to four arguments can be supplied to the %saslauthd% condition, but only two +are mandatory. For example: + + server_condition = ${if saslauthd{{$1}{$2}}{1}{0}} ++ +The service and the realm are optional (which is why the arguments are enclosed +in their own set of braces). For details of the meaning of the service and +realm, and how to run the daemon, consult the Cyrus documentation. + + + +Combining expansion conditions +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[expansion,combining conditions] +Several conditions can be tested at once by combining them using the %and% and +%or% combination conditions. Note that %and% and %or% are complete conditions +on their own, and precede their lists of sub-conditions. Each sub-condition +must be enclosed in braces within the overall braces that contain the list. No +repetition of %if% is used. + + +*or~\{\{*<'cond1'>*\}\{*<'cond2'>*\}...\}*:: +cindex:[``or'' expansion condition] +cindex:[expansion,``or'' of conditions] +The sub-conditions are evaluated from left to right. The condition is true if +any one of the sub-conditions is true. +For example, + + ${if or {{eq{$local_part}{spqr}}{eq{$domain}{testing.com}}}... ++ +When a true sub-condition is found, the following ones are parsed but not +evaluated. If there are several ``match'' sub-conditions the values of the +numeric variables afterwards are taken from the first one that succeeds. + +*and~\{\{*<'cond1'>*\}\{*<'cond2'>*\}...\}*:: +cindex:[``and'' expansion condition] +cindex:[expansion,``and'' of conditions] +The sub-conditions are evaluated from left to right. The condition is true if +all of the sub-conditions are true. If there are several ``match'' +sub-conditions, the values of the numeric variables afterwards are taken from +the last one. When a false sub-condition is found, the following ones are +parsed but not evaluated. + + + + +[[SECTexpvar]] +Expansion variables +~~~~~~~~~~~~~~~~~~~ +cindex:[expansion variables, list of] +This section contains an alphabetical list of all the expansion variables. Some +of them are available only when Exim is compiled with specific options such as +support for TLS or the content scanning extension. + +$0$, $1$, etc:: +cindex:[numerical variables ($1$ $2$ etc)] +When a %match% expansion condition succeeds, these variables contain the +captured substrings identified by the regular expression during subsequent +processing of the success string of the containing %if% expansion item. They +may also be set externally by some other matching process which precedes the +expansion of the string. For example, the commands available in Exim filter +files include an %if% command with its own regular expression matching +condition. + +$acl_c0$ -- $acl_c9$:: +Values can be placed in these variables by the %set% modifier in an ACL. The +values persist throughout the lifetime of an SMTP connection. They can be used +to pass information between ACLs and different invocations of the same ACL. +When a message is received, the values of these variables are saved with the +message, and can be accessed by filters, routers, and transports during +subsequent delivery. + +$acl_m0$ -- $acl_m9$:: +Values can be placed in these variables by the %set% modifier in an ACL. They +retain their values while a message is being received, but are reset +afterwards. They are also reset by MAIL, RSET, EHLO, HELO, and after starting a +TLS session. When a message is received, the values of these variables are +saved with the message, and can be accessed by filters, routers, and transports +during subsequent delivery. + +$acl_verify_message$:: +During the expansion of the %message% and %log_message% modifiers in an ACL +statement after an address verification has failed, this variable contains the +original failure message that will be overridden by the expanded string. + +$address_data$:: +This variable is set by means of the %address_data% option in routers. The +value then remains with the address while it is processed by subsequent routers +and eventually a transport. If the transport is handling multiple addresses, +the value from the first address is used. See chapter <<CHAProutergeneric>> for +more details. *Note*: the contents of $address_data$ are visible in user filter +files. ++ +If $address_data$ is set when the routers are called from an ACL to verify +a recipient address, the final value is still in the variable for subsequent +conditions and modifiers of the ACL statement. If routing the address caused it +to be redirected to just one address, the child address is also routed as part +of the verification, and in this case the final value of $address_data$ is +from the child's routing. ++ +If $address_data$ is set when the routers are called from an ACL to verify a +sender address, the final value is also preserved, but this time in +$sender_address_data$, to distinguish it from data from a recipient +address. ++ +In both cases (recipient and sender verification), the value does not persist +after the end of the current ACL statement. If you want to preserve +these values for longer, you can save them in ACL variables. + +$address_file$:: +When, as a result of aliasing, forwarding, or filtering, a message is directed +to a specific file, this variable holds the name of the file when the transport +is running. At other times, the variable is empty. For example, using the +default configuration, if user %r2d2% has a _.forward_ file containing + + /home/r2d2/savemail ++ +then when the ^address_file^ transport is running, $address_file$ +contains ``/home/r2d2/savemail''. ++ +cindex:[Sieve filter,value of $address_file$] +For Sieve filters, the value may be ``inbox'' or a relative folder name. It is +then up to the transport configuration to generate an appropriate absolute path +to the relevant file. + +$address_pipe$:: +When, as a result of aliasing or forwarding, a message is directed to a pipe, +this variable holds the pipe command when the transport is running. + +$authenticated_id$:: +cindex:[authentication,id] +When a server successfully authenticates a client it may be configured to +preserve some of the authentication information in the variable +$authenticated_id$ (see chapter <<CHAPSMTPAUTH>>). For example, a user/password +authenticator configuration might preserve the user name for use in the +routers. When a message is submitted locally (that is, not over a TCP +connection), the value of $authenticated_id$ is the login name of the calling +process. + +$authenticated_sender$:: +cindex:[sender,authenticated] +cindex:[authentication,sender] +cindex:[AUTH,on MAIL command] +When acting as a server, Exim takes note of the AUTH= parameter on an incoming +SMTP MAIL command if it believes the sender is sufficiently trusted, as +described in section <<SECTauthparamail>>. Unless the data is the string +``<>'', it is set as the authenticated sender of the message, and the value is +available during delivery in the $authenticated_sender$ variable. If the sender +is not trusted, Exim accepts the syntax of AUTH=, but ignores the data. ++ +When a message is submitted locally (that is, not over a TCP connection), the +value of $authenticated_sender$ is an address constructed from the login +name of the calling process and $qualify_domain$. + + +$authentication_failed$:: +cindex:[authentication,failure] +This variable is set to ``1'' in an Exim server if a client issues an AUTH +command that does not succeed. Otherwise it is set to ``0''. This makes it +possible to distinguish between ``did not try to authenticate'' +($sender_host_authenticated$ is empty and $authentication_failed$ is set to +``0'') and ``tried to authenticate but failed'' ($sender_host_authenticated$ is +empty and $authentication_failed$ is set to ``1''). Failure includes any +negative response to an AUTH command, including (for example) an attempt to use +an undefined mechanism. + +$body_linecount$:: +cindex:[message body, line count] +cindex:[body of message,line count] +When a message is being received or delivered, this variable contains the +number of lines in the message's body. + +$body_zerocount$:: +cindex:[message body, binary zero count] +cindex:[body of message,binary zero count] +cindex:[binary zero,in message body] +When a message is being received or delivered, this variable contains the +number of binary zero bytes in the message's body. + +$bounce_recipient$:: +This is set to the recipient address of a bounce message while Exim is creating +it. It is useful if a customized bounce message text file is in use (see +chapter <<CHAPemsgcust>>). + +$bounce_return_size_limit$:: +This contains the value set in the %bounce_return_size_limit% option, rounded +up to a multiple of 1000. It is useful when a customized error message text +file is in use (see chapter <<CHAPemsgcust>>). + +$caller_gid$:: +cindex:[gid (group id),caller] +The real group id under which the process that called Exim was running. This is +not the same as the group id of the originator of a message (see +$originator_gid$). If Exim re-execs itself, this variable in the new +incarnation normally contains the Exim gid. + +$caller_uid$:: +cindex:[uid (user id),caller] +The real user id under which the process that called Exim was running. This is +not the same as the user id of the originator of a message (see +$originator_uid$). If Exim re-execs itself, this variable in the new +incarnation normally contains the Exim uid. + +$compile_date$:: +The date on which the Exim binary was compiled. + +$compile_number$:: +The building process for Exim keeps a count of the number +of times it has been compiled. This serves to distinguish different +compilations of the same version of the program. + +$demime_errorlevel$:: +This variable is available when Exim is compiled with +the content-scanning extension and the obsolete %demime% condition. For +details, see section <<SECTdemimecond>>. + +$demime_reason$:: +This variable is available when Exim is compiled with the +content-scanning extension and the obsolete %demime% condition. For details, +see section <<SECTdemimecond>>. + + +$dnslist_domain$:: +cindex:[black list (DNS)] +When a client host is found to be on a DNS (black) list, +the list's domain name is put into this variable so that it can be included in +the rejection message. + +$dnslist_text$:: +When a client host is found to be on a DNS (black) list, the +contents of any associated TXT record are placed in this variable. + +$dnslist_value$:: +When a client host is found to be on a DNS (black) list, +the IP address from the resource record is placed in this variable. +If there are multiple records, all the addresses are included, comma-space +separated. + +$domain$:: +When an address is being routed, or delivered on its own, this +variable contains the domain. Global address rewriting happens when a message +is received, so the value of $domain$ during routing and delivery is the +value after rewriting. $domain$ is set during user filtering, but not during +system filtering, because a message may have many recipients and the system +filter is called just once. ++ +When more than one address is being delivered at once (for example, several +RCPT commands in one SMTP delivery), $domain$ is set only if they all +have the same domain. Transports can be restricted to handling only one domain +at a time if the value of $domain$ is required at transport time -- this is +the default for local transports. For further details of the environment in +which local transports are run, see chapter <<CHAPenvironment>>. ++ +cindex:[%delay_warning_condition%] +At the end of a delivery, if all deferred addresses have the same domain, it is +set in $domain$ during the expansion of %delay_warning_condition%. ++ +The $domain$ variable is also used in some other circumstances: + +- When an ACL is running for a RCPT command, $domain$ contains the domain +of the recipient address. +*Note:* the domain of the sender address is in $sender_address_domain$ +at MAIL time and at RCPT time. $domain$ is not set for the MAIL +ACL. + +- When a rewrite item is being processed (see chapter <<CHAPrewrite>>), $domain$ +contains the domain portion of the address that is being rewritten; it can be +used in the expansion of the replacement address, for example, to rewrite +domains by file lookup. + +- With one important exception, whenever a domain list is being scanned, +$domain$ contains the subject domain. *Exception*: When a domain list in +a %sender_domains% condition in an ACL is being processed, the subject domain +is in $sender_address_domain$ and not in $domain$. It works this way so +that, in a RCPT ACL, the sender domain list can be dependent on the +recipient domain (which is what is in $domain$ at this time). + +- cindex:[ETRN,value of $domain$] +cindex:[%smtp_etrn_command%] +When the %smtp_etrn_command% option is being expanded, $domain$ contains +the complete argument of the ETRN command (see section <<SECTETRN>>). + + +$domain_data$:: +When the %domains% option on a router matches a domain by +means of a lookup, the data read by the lookup is available during the running +of the router as $domain_data$. In addition, if the driver routes the +address to a transport, the value is available in that transport. If the +transport is handling multiple addresses, the value from the first address is +used. ++ +$domain_data$ is also set when the %domains% condition in an ACL matches a +domain by means of a lookup. The data read by the lookup is available during +the rest of the ACL statement. In all other situations, this variable expands +to nothing. + +$exim_gid$:: +This variable contains the numerical value of the Exim group id. + +$exim_path$:: +This variable contains the path to the Exim binary. + +$exim_uid$:: +This variable contains the numerical value of the Exim user id. + +$found_extension$:: +This variable is available when Exim is compiled with the +content-scanning extension and the obsolete %demime% condition. For details, +see section <<SECTdemimecond>>. + +$header_$<'name'>:: +This is not strictly an expansion variable. It is +expansion syntax for inserting the message header line with the given name. +Note that the name must be terminated by colon or white space, because it may +contain a wide variety of characters. +Note also that braces must 'not' be used. + +$home$:: +When the %check_local_user% option is set for a router, the user's home +directory is placed in $home$ when the check succeeds. In particular, this +means it is set during the running of users' filter files. A router may also +explicitly set a home directory for use by a transport; this can be overridden +by a setting on the transport itself. ++ +When running a filter test via the %-bf% option, $home$ is set to the value +of the environment variable HOME. + +$host$:: +When the ^smtp^ transport is expanding its options for encryption using TLS, +$host$ contains the name of the host to which it is connected. Likewise, when +used in the client part of an authenticator configuration (see chapter +<<CHAPSMTPAUTH>>), $host$ contains the name of the server to which the client +is connected. ++ +cindex:[transport,filter] +cindex:[filter,transport filter] +When used in a transport filter (see chapter <<CHAPtransportgeneric>>) $host$ +refers to the host involved in the current connection. When a local transport +is run as a result of a router that sets up a host list, $host$ contains the +name of the first host. + +$host_address$:: +This variable is set to the remote host's IP address whenever $host$ is set for +a remote connection. It is also set to the IP address that is being checked +when the %ignore_target_hosts% option is being processed. + +$host_data$:: +If a %hosts% condition in an ACL is satisfied by means of a lookup, the result +of the lookup is made available in the $host_data$ variable. This +allows you, for example, to do things like this: + + deny hosts = net-lsearch;/some/file + message = $host_data + + +$host_lookup_deferred$:: +cindex:[host name lookup, failure of] +This variable normally contains ``0'', as does $host_lookup_failed$. When a +message comes from a remote host and there is an attempt to look up the host's +name from its IP address, and the attempt is not successful, one of these +variables is set to ``1''. ++ +-- +- If the lookup receives a definite negative response (for example, a DNS lookup +succeeded, but no records were found), $host_lookup_failed$ is set to ``1''. + +- If there is any kind of problem during the lookup, such that Exim cannot +tell whether or not the host name is defined (for example, a timeout for a DNS +lookup), $host_lookup_deferred$ is set to ``1''. +-- ++ +Looking up a host's name from its IP address consists of more than just a +single reverse lookup. Exim checks that a forward lookup of at least one of the +names it receives from a reverse lookup yields the original IP address. If this +is not the case, Exim does not accept the looked up name(s), and +$host_lookup_failed$ is set to ``1''. Thus, being able to find a name from an +IP address (for example, the existence of a PTR record in the DNS) is not +sufficient on its own for the success of a host name lookup. If the reverse +lookup succeeds, but there is a lookup problem such as a timeout when checking +the result, the name is not accepted, and $host_lookup_deferred$ is set to +``1''. See also $sender_host_name$. + +$host_lookup_failed$:: +See $host_lookup_deferred$. + + +$inode$:: +The only time this variable is set is while expanding the %directory_file% +option in the ^appendfile^ transport. The variable contains the inode number +of the temporary file which is about to be renamed. It can be used to construct +a unique name for the file. + +$interface_address$:: +When a message is received over a TCP/IP connection, this variable contains the +address of the local IP interface. See also the %-oMi% command line option. +This variable can be used in ACLs and also, for example, to make the file name +for a TLS certificate depend on which interface is being used. + +$interface_port$:: +When a message is received over a TCP/IP connection, this variable contains the +local port number. See also the %-oMi% command line option. +This variable can be used in ACLs and also, for example, to make the file name +for a TLS certificate depend on which port is being used. + +$ldap_dn$:: +This variable, which is available only when Exim is compiled with LDAP support, +contains the DN from the last entry in the most recently successful LDAP +lookup. + +$load_average$:: +This variable contains the system load average, multiplied by 1000 to that it +is an integer. For example, if the load average is 0.21, the value of the +variable is 210. The value is recomputed every time the variable is referenced. + +$local_part$:: +When an address is being routed, or delivered on its own, this +variable contains the local part. When a number of addresses are being +delivered together (for example, multiple RCPT commands in an SMTP +session), $local_part$ is not set. ++ +Global address rewriting happens when a message is received, so the value of +$local_part$ during routing and delivery is the value after rewriting. +$local_part$ is set during user filtering, but not during system filtering, +because a message may have many recipients and the system filter is called just +once. ++ +If a local part prefix or suffix has been recognized, it is not included in the +value of $local_part$ during routing and subsequent delivery. The values of +any prefix or suffix are in $local_part_prefix$ and +$local_part_suffix$, respectively. ++ +When a message is being delivered to a file, pipe, or autoreply transport as a +result of aliasing or forwarding, $local_part$ is set to the local part of +the parent address, not to the file name or command (see $address_file$ and +$address_pipe$). ++ +When an ACL is running for a RCPT command, $local_part$ contains the +local part of the recipient address. ++ +When a rewrite item is being processed (see chapter <<CHAPrewrite>>), +$local_part$ contains the local part of the address that is being rewritten; +it can be used in the expansion of the replacement address, for example. ++ +In all cases, all quoting is removed from the local part. For example, for both +the addresses + + "abc:xyz"@test.example + abc\:xyz@test.example ++ +the value of $local_part$ is + + abc:xyz ++ +If you use $local_part$ to create another address, you should always wrap it +inside a quoting operator. For example, in a ^redirect^ router you could have: + + data = ${quote_local_part:$local_part}@new.domain.example ++ +*Note*: The value of $local_part$ is normally lower cased. If you want +to process local parts in a case-dependent manner in a router, you can set the +%caseful_local_part% option (see chapter <<CHAProutergeneric>>). + +$local_part_data$:: +When the %local_parts% option on a router matches a local part by means of a +lookup, the data read by the lookup is available during the running of the +router as $local_part_data$. In addition, if the driver routes the address +to a transport, the value is available in that transport. If the transport is +handling multiple addresses, the value from the first address is used. ++ +$local_part_data$ is also set when the %local_parts% condition in an ACL +matches a local part by means of a lookup. The data read by the lookup is +available during the rest of the ACL statement. In all other situations, this +variable expands to nothing. + +$local_part_prefix$:: +When an address is being routed or delivered, and a +specific prefix for the local part was recognized, it is available in this +variable, having been removed from $local_part$. + +$local_part_suffix$:: +When an address is being routed or delivered, and a +specific suffix for the local part was recognized, it is available in this +variable, having been removed from $local_part$. + +$local_scan_data$:: +This variable contains the text returned by the 'local_scan()' function when a +message is received. See chapter <<CHAPlocalscan>> for more details. + +$local_user_gid$:: +See $local_user_uid$. + +$local_user_uid$:: +This variable and $local_user_gid$ are set to +the uid and gid after the %check_local_user% router precondition succeeds. +This means that their values are available for the remaining preconditions +(%senders%, %require_files%, and %condition%), for the %address_data% +expansion, and for any router-specific expansions. At all other times, the +values in these variables are `(uid_t)(-1)` and `(gid_t)(-1)`, +respectively. + +$localhost_number$:: +This contains the expanded value of the +%localhost_number% option. The expansion happens after the main options have +been read. + +$log_inodes$:: +The number of free inodes in the disk partition where Exim's +log files are being written. The value is recalculated whenever the variable is +referenced. If the relevant file system does not have the concept of inodes, +the value of is -1. See also the %check_log_inodes% option. + +$log_space$:: +The amount of free space (as a number of kilobytes) in the disk +partition where Exim's log files are being written. The value is recalculated +whenever the variable is referenced. If the operating system does not have the +ability to find the amount of free space (only true for experimental systems), +the space value is -1. See also the %check_log_space% option. + + +$mailstore_basename$:: +This variable is set only when doing deliveries in +``mailstore'' format in the ^appendfile^ transport. During the expansion of the +%mailstore_prefix%, %mailstore_suffix%, %message_prefix%, and +%message_suffix% options, it contains the basename of the files that are being +written, that is, the name without the ``.tmp'', ``.env'', or ``.msg'' suffix. At all +other times, this variable is empty. + +$malware_name$:: +This variable is available when Exim is compiled with the +content-scanning extension. It is set to the name of the virus that was found +when the ACL %malware% condition is true (see section <<SECTscanvirus>>). + + +$message_age$:: +cindex:[message,age of] +This variable is set at the start of a delivery attempt to +contain the number of seconds since the message was received. It does not +change during a single delivery attempt. + +$message_body$:: +cindex:[body of message,expansion variable] +cindex:[message body, in expansion] +cindex:[binary zero,in message body] +This variable contains the initial portion of a message's +body while it is being delivered, and is intended mainly for use in filter +files. The maximum number of characters of the body that are put into the +variable is set by the %message_body_visible% configuration option; the +default is 500. Newlines are converted into spaces to make it easier to search +for phrases that might be split over a line break. +Binary zeros are also converted into spaces. + +$message_body_end$:: +cindex:[body of message,expansion variable] +cindex:[message body, in expansion] +This variable contains the final portion of a message's +body while it is being delivered. The format and maximum size are as for +$message_body$. + +$message_body_size$:: +cindex:[body of message,size] +cindex:[message body, size] +When a message is being delivered, this variable +contains the size of the body in bytes. The count starts from the character +after the blank line that separates the body from the header. Newlines are +included in the count. See also $message_size$, $body_linecount$, and +$body_zerocount$. + +$message_headers$:: +This variable contains a concatenation of all the header lines when a message +is being processed, except for lines added by routers or transports. The header +lines are separated by newline characters. + +$message_id$:: +When a message is being received or delivered, this variable contains the +unique message id that is used by Exim to identify the message. +An id is not created for a message until after its header has been +successfully received. +*Note*: This is 'not' the contents of the 'Message-ID:' header line; it +is the local id that Exim assigns to the message, for example: +`1BXTIK-0001yO-VA`. + +$message_size$:: +cindex:[size,of message] +cindex:[message,size] +When a message is being processed, this variable contains its size in bytes. In +most cases, the size includes those headers that were received with the +message, but not those (such as 'Envelope-to:') that are added to individual +deliveries as they are written. However, there is one special case: during the +expansion of the %maildir_tag% option in the ^appendfile^ transport while +doing a delivery in maildir format, the value of $message_size$ is the +precise size of the file that has been written. See also +$message_body_size$, $body_linecount$, and $body_zerocount$. ++ +cindex:[RCPT,value of $message_size$] +While running an ACL at the time of an SMTP RCPT command, $message_size$ +contains the size supplied on the MAIL command, or -1 if no size was given. The +value may not, of course, be truthful. + +$mime_$'xxx':: +A number of variables whose names start with $mime$ are +available when Exim is compiled with the content-scanning extension. For +details, see section <<SECTscanmimepart>>. + + +$n0$ -- $n9$:: +These variables are counters that can be incremented by means +of the %add% command in filter files. + +$original_domain$:: +When a top-level address is being processed for delivery, +this contains the same value as $domain$. However, if a ``child'' address (for +example, generated by an alias, forward, or filter file) is being processed, +this variable contains the domain of the original address. This differs from +$parent_domain$ only when there is more than one level of aliasing or +forwarding. When more than one address is being delivered in a single transport +run, $original_domain$ is not set. ++ +If new an address is created by means of a %deliver% command in a system +filter, it is set up with an artificial ``parent'' address. This has the local +part 'system-filter' and the default qualify domain. + +$original_local_part$:: +When a top-level address is being processed for +delivery, this contains the same value as $local_part$, unless a prefix or +suffix was removed from the local part, because $original_local_part$ +always contains the full local part. When a ``child'' address (for example, +generated by an alias, forward, or filter file) is being processed, this +variable contains the full local part of the original address. ++ +If the router that did the redirection processed the local part +case-insensitively, the value in $original_local_part$ is in lower case. +This variable differs from $parent_local_part$ only when there is more than +one level of aliasing or forwarding. When more than one address is being +delivered in a single transport run, $original_local_part$ is not set. ++ +If new an address is created by means of a %deliver% command in a system +filter, it is set up with an artificial ``parent'' address. This has the local +part 'system-filter' and the default qualify domain. + + +$originator_gid$:: +cindex:[gid (group id),of originating user] +cindex:[sender,gid] +The value of $caller_gid$ that was set when the message +was received. For messages received via the command line, this is the gid of +the sending user. For messages received by SMTP over TCP/IP, this is normally +the gid of the Exim user. + +$originator_uid$:: +cindex:[uid (user id),of originating user] +cindex:[sender,uid] +The value of $caller_uid$ that was set when the message +was received. For messages received via the command line, this is the uid of +the sending user. For messages received by SMTP over TCP/IP, this is normally +the uid of the Exim user. + +$parent_domain$:: +This variable is similar to $original_domain$ (see +above), except that it refers to the immediately preceding parent address. + +$parent_local_part$:: +This variable is similar to $original_local_part$ +(see above), except that it refers to the immediately preceding parent address. + +$pid$:: +cindex:[pid (process id),of current process] +This variable contains the current process id. + +$pipe_addresses$:: +cindex:[filter,transport filter] +cindex:[transport,filter] +This is not an expansion variable, but is mentioned here +because the string ``\$pipe_addresses'' is handled specially in the command +specification for the ^pipe^ transport (chapter <<CHAPpipetransport>>) and in +transport filters (described under %transport_filter% in chapter +<<CHAPtransportgeneric>>). It cannot be used in general expansion strings, and +provokes an ``unknown variable'' error if encountered. + +$primary_hostname$:: +The value set in the configuration file, or read by the +'uname()' function. If 'uname()' returns a single-component name, Exim +calls 'gethostbyname()' (or 'getipnodebyname()' where available) in an +attempt to acquire a fully qualified host name. +See also $smtp_active_hostname$. + +$qualify_domain$:: +The value set for this option in the configuration file. + +$qualify_recipient$:: +The value set for this option in the configuration file, +or if not set, the value of $qualify_domain$. + +$rcpt_count$:: +When a message is being received by SMTP, this variable +contains the number of RCPT commands received for the current message. If +this variable is used in a RCPT ACL, its value includes the current +command. + +$rcpt_defer_count$:: +When a message is being received by SMTP, this variable +contains the number of RCPT commands in the current message that have +previously been rejected with a temporary (4##'xx') response. + +$rcpt_fail_count$:: +When a message is being received by SMTP, this variable +contains the number of RCPT commands in the current message that have +previously been rejected with a permanent (5##'xx') response. + +$received_count$:: +This variable contains the number of 'Received:' header +lines in the message, including the one added by Exim (so its value is always +greater than zero). It is available in the DATA ACL, the non-SMTP ACL, and +while routing and delivering. + +$received_for$:: +If there is only a single recipient address in an incoming +message, this variable contains that address when the 'Received:' header line +is being built. +The value is copied after recipient rewriting has happened, but before the +'local_scan()' function is run. + +$received_protocol$:: +When a message is being processed, this variable +contains the name of the protocol by which it was received. +Most of the names used by Exim are defined by RFCs 821, 2821, and 3848. They +start with ``smtp'' (the client used HELO) or ``esmtp'' (the client used +EHLO). This can be followed by ``s'' for secure (encrypted) and/or ``a'' for +authenticated. Thus, for example, if the protocol is set to ``esmtpsa'', the +message was received over an encrypted SMTP connection and the client was +successfully authenticated. ++ +Exim uses the protocol name ``smtps'' for the case when encryption is +automatically set up on connection without the use of STARTTLS (see +%tls_on_connect_ports%), and the client uses HELO to initiate the +encrypted SMTP session. The name ``smtps'' is also used for the rare situation +where the client initially uses EHLO, sets up an encrypted connection using +STARTTLS, and then uses HELO afterwards. ++ +The %-oMr% option provides a way of specifying a custom protocol name for +messages that are injected locally by trusted callers. This is commonly used to +identify messages that are being re-injected after some kind of scanning. + + +$recipient_data$:: +This variable is set after an indexing lookup success in +an ACL %recipients% condition. It contains the data from the lookup, and the +value remains set until the next %recipients% test. Thus, you can do things +like this: ++ +&&& +`require recipients = cdb*@;/some/file` +`deny `'some further test involving' `\$recipient_data` +&&& ++ +*Warning*: This variable is set only when a lookup is used as an indexing +method in the address list, using the semicolon syntax as in the example above. +The variable is not set for a lookup that is used as part of the string +expansion that all such lists undergo before being interpreted. + +$recipient_verify_failure$:: +In an ACL, when a recipient verification fails, +this variable contains information about the failure. It is set to one of the +following words: ++ +-- +- ``qualify'': The address was unqualified (no domain), and the message +was neither local nor came from an exempted host. + +- ``route'': Routing failed. + +- ``mail'': Routing succeeded, and a callout was attempted; rejection occurred at +or before the MAIL command (that is, on initial connection, HELO, or +MAIL). + +- ``recipient'': The RCPT command in a callout was rejected. + +- ``postmaster'': The postmaster check in a callout was rejected. +-- ++ +The main use of this variable is expected to be to distinguish between +rejections of MAIL and rejections of RCPT. + + +$recipients$:: +This variable contains a list of envelope recipients for a +message. A comma and a space separate the addresses in the replacement text. +However, the variable is not generally available, to prevent exposure of Bcc +recipients in unprivileged users' filter files. You can use $recipients$ only +in these two cases: + +. In a system filter file. + +. In the ACLs associated with the DATA command, that is, the ACLs defined by +%acl_smtp_predata% and %acl_smtp_data%. + + +$recipients_count$:: +When a message is being processed, this variable +contains the number of envelope recipients that came with the message. +Duplicates are not excluded from the count. While a message is being received +over SMTP, the number increases for each accepted recipient. It can be +referenced in an ACL. + +$reply_address$:: +When a message is being processed, this variable contains +the contents of the 'Reply-To:' header line if one exists +and it is not empty, +or otherwise the contents of the 'From:' header line. + +$return_path$:: +When a message is being delivered, this variable contains the return path -- +the sender field that will be sent as part of the envelope. It is not enclosed +in <> characters. At the start of routing an address, $return_path$ has the +same value as $sender_address$, but if, for example, an incoming message to a +mailing list has been expanded by a router which specifies a different address +for bounce messages, $return_path$ subsequently contains the new bounce +address, whereas $sender_address$ always contains the original sender address +that was received with the message. In other words, $sender_address$ contains +the incoming envelope sender, and $return_path$ contains the outgoing envelope +sender. + +$return_size_limit$:: +This is an obsolete name for $bounce_return_size_limit$. + +$runrc$:: +cindex:[return code,from %run% expansion] +This variable contains the return code from a command that is run by the +%\$\{run...\}% expansion item. *Warning*: In a router or transport, you cannot +assume the order in which option values are expanded, except for those +pre-conditions whose order of testing is documented. Therefore, you cannot +reliably expect to set $runrc$ by the expansion of one option, and use it in +another. + +$self_hostname$:: +When an address is routed to a supposedly remote host that turns out to be the +local host, what happens is controlled by the +cindex:[%self% option,value of host name] +%self% generic router option. One of its values causes the address to be passed +to another router. When this happens, $self_hostname$ is set to the name of +the local host that the original router encountered. In other circumstances its +contents are null. + +$sender_address$:: +When a message is being processed, this variable contains +the sender's address that was received in the message's envelope. For bounce +messages, the value of this variable is the empty string. +See also $return_path$. + +$sender_address_data$:: +If $address_data$ is set when the routers are called from an ACL to verify a +sender address, the final value is preserved in $sender_address_data$, to +distinguish it from data from a recipient address. The value does not persist +after the end of the current ACL statement. If you want to preserve it for +longer, you can save it in an ACL variable. + + +$sender_address_domain$:: +The domain portion of $sender_address$. + +$sender_address_local_part$:: +The local part portion of $sender_address$. + +$sender_data$:: +This variable is set after a lookup success in an ACL %senders% condition or in +a router %senders% option. It contains the data from the lookup, and the value +remains set until the next %senders% test. Thus, you can do things like this: ++ +&&& +`require senders = cdb*@;/some/file` +`deny `'some further test involving' `\$sender_data` +&&& ++ +*Warning*: This variable is set only when a lookup is used as an indexing +method in the address list, using the semicolon syntax as in the example above. +The variable is not set for a lookup that is used as part of the string +expansion that all such lists undergo before being interpreted. + +$sender_fullhost$:: +When a message is received from a remote host, this variable contains the host +name and IP address in a single string. It ends with the IP address in square +brackets, followed by a colon and a port number if the logging of ports is +enabled. The format of the rest of the string depends on whether the host +issued a HELO or EHLO SMTP command, and whether the host name was verified by +looking up its IP address. (Looking up the IP address can be forced by the +%host_lookup% option, independent of verification.) A plain host name at the +start of the string is a verified host name; if this is not present, +verification either failed or was not requested. A host name in parentheses is +the argument of a HELO or EHLO command. This is omitted if it is identical to +the verified host name or to the host's IP address in square brackets. + +$sender_helo_name$:: +When a message is received from a remote host that has +issued a HELO or EHLO command, the argument of that command is placed +in this variable. It is also set if HELO or EHLO is used when a message +is received using SMTP locally via the %-bs% or %-bS% options. + +$sender_host_address$:: +When a message is received from a remote host, this +variable contains that host's IP address. For locally submitted messages, it is +empty. + +$sender_host_authenticated$:: +This variable contains the name (not the public name) of the authenticator +driver which successfully authenticated the client from which the message was +received. It is empty if there was no successful authentication. + +$sender_host_name$:: +When a message is received from a remote host, this variable contains the +host's name as obtained by looking up its IP address. For messages received by +other means, this variable is empty. ++ +If the host name has not previously been looked up, a reference to +$sender_host_name$ triggers a lookup (for messages from remote hosts). +A looked up name is accepted only if it leads back to the original IP address +via a forward lookup. If either the reverse or the forward lookup fails to find +any data, or if the forward lookup does not yield the original IP address, +$sender_host_name$ remains empty, and $host_lookup_failed$ is set to ``1''. ++ +However, if either of the lookups cannot be completed (for example, there is a +DNS timeout), $host_lookup_deferred$ is set to ``1'', and +$host_lookup_failed$ remains set to ``0''. ++ +Once $host_lookup_failed$ is set to ``1'', Exim does not try to look up the +host name again if there is a subsequent reference to $sender_host_name$ +in the same Exim process, but it does try again if $sender_host_deferred$ +is set to ``1''. ++ +Exim does not automatically look up every calling host's name. If you want +maximum efficiency, you should arrange your configuration so that it avoids +these lookups altogether. The lookup happens only if one or more of the +following are true: + +- A string containing $sender_host_name$ is expanded. + +- The calling host matches the list in %host_lookup%. In the default +configuration, this option is set to \*, so it must be changed if lookups are +to be avoided. (In the code, the default for %host_lookup% is unset.) + +- Exim needs the host name in order to test an item in a host list. The items +that require this are described in sections <<SECThoslispatnam>> and +<<SECThoslispatnamsk>>. + +- The calling host matches %helo_try_verify_hosts% or %helo_verify_hosts%. +In this case, the host name is required to compare with the name quoted in any +EHLO or HELO commands that the client issues. + +- The remote host issues a EHLO or HELO command that quotes one of the +domains in %helo_lookup_domains%. The default value of this option is ++ +.... +helo_lookup_domains = @ : @[] +.... ++ +which causes a lookup if a remote host (incorrectly) gives the server's name or +IP address in an EHLO or HELO command. + + +$sender_host_port$:: +When a message is received from a remote host, this +variable contains the port number that was used on the remote host. + +$sender_ident$:: +When a message is received from a remote host, this variable contains the +identification received in response to an RFC 1413 request. When a message has +been received locally, this variable contains the login name of the user that +called Exim. + +$sender_rcvhost$:: +This is provided specifically for use in 'Received:' headers. It starts with +either the verified host name (as obtained from a +cindex:[DNS,reverse lookup] +cindex:[reverse DNS lookup] +reverse DNS lookup) or, if there is no verified host name, the IP address in +square brackets. After that there may be text in parentheses. When the first +item is a verified host name, the first thing in the parentheses is the IP +address in square brackets, followed by a colon and a port number if port +logging is enabled. When the first item is an IP address, the port is recorded +as ``port='xxxx'##'' inside the parentheses. ++ +There may also be items of the form ``helo='xxxx'##'' if HELO or EHLO +was used and its argument was not identical to the real host name or IP +address, and ``ident='xxxx'##'' if an RFC 1413 ident string is available. If all +three items are present in the parentheses, a newline and tab are inserted into +the string, to improve the formatting of the 'Received:' header. + +$sender_verify_failure$:: +In an ACL, when a sender verification fails, this variable contains information +about the failure. The details are the same as for $recipient_verify_failure$. + +$smtp_active_hostname$:: +During an SMTP session, this variable contains the value of the active host +name, as specified by the %smtp_active_hostname% option. The value of +$smtp_active_hostname$ is saved with any message that is received, so its value +can be consulted during routing and delivery. + + +$smtp_command_argument$:: +cindex:[AUTH,argument] +cindex:[EXPN,argument] +cindex:[ETRN,argument] +cindex:[VRFY,argument] +While an ACL is running to check an AUTH, EHLO, EXPN, ETRN, HELO, or VRFY +command, this variable contains the argument for the SMTP command. + +$sn0$ -- $sn9$:: +These variables are copies of the values of the $n0$ -- $n9$ accumulators that +were current at the end of the system filter file. This allows a system filter +file to set values that can be tested in users' filter files. For example, a +system filter could set a value indicating how likely it is that a message is +junk mail. + +$spam_$'xxx':: +A number of variables whose names start with $spam$ are available when Exim is +compiled with the content-scanning extension. For details, see section +<<SECTscanspamass>>. + + +$spool_directory$:: +The name of Exim's spool directory. + +$spool_inodes$:: +The number of free inodes in the disk partition where Exim's spool files are +being written. The value is recalculated whenever the variable is referenced. +If the relevant file system does not have the concept of inodes, the value of +is -1. See also the %check_spool_inodes% option. + +$spool_space$:: +The amount of free space (as a number of kilobytes) in the disk partition where +Exim's spool files are being written. The value is recalculated whenever the +variable is referenced. If the operating system does not have the ability to +find the amount of free space (only true for experimental systems), the space +value is -1. For example, to check in an ACL that there is at least 50 +megabytes free on the spool, you could write: + + condition = ${if > {$spool_space}{50000}} ++ +See also the %check_spool_space% option. + + +$thisaddress$:: +This variable is set only during the processing of the %foranyaddress% command +in a filter file. Its use is explained in the description of that command. + +$tls_certificate_verified$:: +This variable is set to ``1'' if a TLS certificate was verified when the message +was received, and ``0'' otherwise. + +$tls_cipher$:: +When a message is received from a remote host over an encrypted SMTP +connection, this variable is set to the cipher suite that was negotiated, for +example DES-CBC3-SHA. In other circumstances, in particular, for message +received over unencrypted connections, the variable is empty. See chapter +<<CHAPTLS>> for details of TLS support. + +$tls_peerdn$:: + When a message is received from a remote host over an encrypted SMTP +connection, and Exim is configured to request a certificate from the client, +the value of the Distinguished Name of the certificate is made available in the +$tls_peerdn$ during subsequent processing. + +$tod_bsdinbox$:: +The time of day and date, in the format required for BSD-style mailbox files, +for example: Thu Oct 17 17:14:09 1995. + +$tod_epoch$:: +The time and date as a number of seconds since the start of the Unix epoch. + +$tod_full$:: +A full version of the time and date, for example: Wed, 16 Oct 1995 09:51:40 ++0100. The timezone is always given as a numerical offset from UTC, with +positive values used for timezones that are ahead (east) of UTC, and negative +values for those that are behind (west). + +$tod_log$:: +The time and date in the format used for writing Exim's log files, for example: +1995-10-12 15:32:29, but without a timezone. + +$tod_logfile$:: +This variable contains the date in the format yyyymmdd. This is the format that +is used for datestamping log files when %log_file_path% contains the `%D` +flag. + +$tod_zone$:: +This variable contains the numerical value of the local timezone, for example: +-0500. + +$tod_zulu$:: +This variable contains the UTC date and time in ``Zulu'' format, as specified by +ISO 8601, for example: 20030221154023Z. + +$value$:: +cindex:[$value$] +This variable contains the result of an expansion lookup, extraction operation, +or external command, as described above. + +$version_number$:: +The version number of Exim. + +$warn_message_delay$:: +This variable is set only during the creation of a message warning about a +delivery delay. Details of its use are explained in section <<SECTcustwarn>>. + +$warn_message_recipients$:: +This variable is set only during the creation of a message warning about a +delivery delay. Details of its use are explained in section <<SECTcustwarn>>. + + + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// + +[[CHAPperl]] +Embedded Perl +------------- +cindex:[Perl,calling from Exim] +Exim can be built to include an embedded Perl interpreter. When this is done, +Perl subroutines can be called as part of the string expansion process. To make +use of the Perl support, you need version 5.004 or later of Perl installed on +your system. To include the embedded interpreter in the Exim binary, include +the line + + EXIM_PERL = perl.o + +in your _Local/Makefile_ and then build Exim in the normal way. + + +Setting up so Perl can be used +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[%perl_startup%] +Access to Perl subroutines is via a global configuration option called +%perl_startup% and an expansion string operator %\$\{perl ...\}%. If there is +no %perl_startup% option in the Exim configuration file then no Perl +interpreter is started and there is almost no overhead for Exim (since none of +the Perl library will be paged in unless used). If there is a %perl_startup% +option then the associated value is taken to be Perl code which is executed in +a newly created Perl interpreter. + +The value of %perl_startup% is not expanded in the Exim sense, so you do not +need backslashes before any characters to escape special meanings. The option +should usually be something like + + perl_startup = do '/etc/exim.pl' + +where _/etc/exim.pl_ is Perl code which defines any subroutines you want to +use from Exim. Exim can be configured either to start up a Perl interpreter as +soon as it is entered, or to wait until the first time it is needed. Starting +the interpreter at the beginning ensures that it is done while Exim still has +its setuid privilege, but can impose an unnecessary overhead if Perl is not in +fact used in a particular run. Also, note that this does not mean that Exim is +necessarily running as root when Perl is called at a later time. By default, +the interpreter is started only when it is needed, but this can be changed in +two ways: + +- cindex:[%perl_at_start%] +Setting %perl_at_start% (a boolean option) in the configuration requests +a startup when Exim is entered. + +- The command line option %-ps% also requests a startup when Exim is entered, +overriding the setting of %perl_at_start%. + +There is also a command line option %-pd% (for delay) which suppresses the +initial startup, even if %perl_at_start% is set. + + +Calling Perl subroutines +~~~~~~~~~~~~~~~~~~~~~~~~ +When the configuration file includes a %perl_startup% option you can make use +of the string expansion item to call the Perl subroutines that are defined +by the %perl_startup% code. The operator is used in any of the following +forms: + + ${perl{foo}} + ${perl{foo}{argument}} + ${perl{foo}{argument1}{argument2} ... } + +which calls the subroutine %foo% with the given arguments. A maximum of eight +arguments may be passed. Passing more than this results in an expansion failure +with an error message of the form + + Too many arguments passed to Perl subroutine "foo" (max is 8) + +The return value of the Perl subroutine is evaluated in a scalar context before +it is passed back to Exim to be inserted into the expanded string. If the +return value is 'undef', the expansion is forced to fail in the same way as +an explicit ``fail'' on an %\$\{if ...\}% or %\$\{lookup...\}% item. If the +subroutine aborts by obeying Perl's %die% function, the expansion fails with +the error message that was passed to %die%. + + +Calling Exim functions from Perl +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Within any Perl code called from Exim, the function 'Exim::expand_string' +is available to call back into Exim's string expansion function. For example, +the Perl code + + my $lp = Exim::expand_string('$local_part'); + +makes the current Exim $local_part$ available in the Perl variable $lp$. +Note those are single quotes and not double quotes to protect against +$local_part$ being interpolated as a Perl variable. + +If the string expansion is forced to fail by a ``fail'' item, the result of +'Exim::expand_string' is %undef%. If there is a syntax error in the +expansion string, the Perl call from the original expansion string fails with +an appropriate error message, in the same way as if %die% were used. + +cindex:[debugging,from embedded Perl] +cindex:[log,writing from embedded Perl] +Two other Exim functions are available for use from within Perl code. +'Exim::debug_write(<'string'>)' writes the string to the standard error +stream if Exim's debugging is enabled. If you want a newline at the end, you +must supply it. 'Exim::log_write(<'string'>)' writes the string to Exim's +main log, adding a leading timestamp. In this case, you should not supply a +terminating newline. + + +Use of standard output and error by Perl +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[Perl,standard output and error] +You should not write to the standard error or output streams from within your +Perl code, as it is not defined how these are set up. In versions of Exim +before 4.50, it is possible for the standard output or error to refer to the +SMTP connection during message reception via the daemon. Writing to this stream +is certain to cause chaos. From Exim 4.50 onwards, the standard output and +error streams are connected to _/dev/null_ in the daemon. The chaos is +avoided, but the output is lost. + +cindex:[Perl,use of %warn%] +The Perl %warn% statement writes to the standard error stream by default. Calls +to %warn% may be embedded in Perl modules that you use, but over which you have +no control. When Exim starts up the Perl interpreter, it arranges for output +from the %warn% statement to be written to the Exim main log. You can change +this by including appropriate Perl magic somewhere in your Perl code. For +example, to discard %warn% output completely, you need this: + + $SIG{__WARN__} = sub { }; + +Whenever a %warn% is obeyed, the anonymous subroutine is called. In this +example, the code for the subroutine is empty, so it does nothing, but you can +include any Perl code that you like. The text of the %warn% message is passed +as the first subroutine argument. + + + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// + +[[CHAPinterfaces]] +[titleabbrev="Starting the daemon"] +Starting the daemon and the use of network interfaces +----------------------------------------------------- +cindex:[daemon,starting] +cindex:[interface,listening] +cindex:[network interface] +cindex:[interface,network] +cindex:[IP address,for listening] +cindex:[daemon,listening IP addresses] +cindex:[TCP/IP,setting listening interfaces] +cindex:[TCP/IP,setting listening ports] +A host that is connected to a TCP/IP network may have one or more physical +hardware network interfaces. Each of these interfaces may be configured as one +or more ``logical'' interfaces, which are the entities that a program actually +works with. Each of these logical interfaces is associated with an IP address. +In addition, TCP/IP software supports ``loopback'' interfaces (127.0.0.1 in IPv4 +and ::1 in IPv6), which do not use any physical hardware. Exim requires +knowledge about the host's interfaces for use in three different circumstances: + +. When a listening daemon is started, Exim needs to know which interfaces +and ports to listen on. + +. When Exim is routing an address, it needs to know which IP addresses +are associated with local interfaces. This is required for the correct +processing of MX lists by removing the local host and others with the +same or higher priority values. Also, Exim needs to detect cases +when an address is routed to an IP address that in fact belongs to the +local host. Unless the %self% router option or the %allow_localhost% +option of the smtp transport is set (as appropriate), this is treated +as an error situation. + +. When Exim connects to a remote host, it may need to know which interface to use +for the outgoing connection. + + +Exim's default behaviour is likely to be appropriate in the vast majority +of cases. If your host has only one interface, and you want all its IP +addresses to be treated in the same way, and you are using only the +standard SMTP port, you should not need to take any special action. The +rest of this chapter does not apply to you. + +In a more complicated situation you may want to listen only on certain +interfaces, or on different ports, and for this reason there are a number of +options that can be used to influence Exim's behaviour. The rest of this +chapter describes how they operate. + +When a message is received over TCP/IP, the interface and port that were +actually used are set in $interface_address$ and $interface_port$. + + + +Starting a listening daemon +~~~~~~~~~~~~~~~~~~~~~~~~~~~ +When a listening daemon is started (by means of the %-bd% command line +option), the interfaces and ports on which it listens are controlled by the +following options: + +- %daemon_smtp_ports% contains a list of default ports. (For backward +compatibility, this option can also be specified in the singular.) + +- %local_interfaces% contains list of interface IP addresses on which to +listen. Each item may optionally also specify a port. + +The default list separator in both cases is a colon, but this can be changed as +described in section <<SECTlistconstruct>>. When IPv6 addresses are involved, it +is usually best to change the separator to avoid having to double all the +colons. For example: + +.... +local_interfaces = <; 127.0.0.1 ; \ + 192.168.23.65 ; \ + ::1 ; \ + 3ffe:ffff:836f::fe86:a061 +.... + +There are two different formats for specifying a port along with an IP address +in %local_interfaces%: + +. The port is added onto the address with a dot separator. For example, to listen +on port 1234 on two different IP addresses: ++ +.... +local_interfaces = <; 192.168.23.65.1234 ; \ + 3ffe:ffff:836f::fe86:a061.1234 +.... + +. The IP address is enclosed in square brackets, and the port is added +with a colon separator, for example: ++ +.... +local_interfaces = <; [192.168.23.65]:1234 ; \ + [3ffe:ffff:836f::fe86:a061]:1234 +.... + +When a port is not specified, the value of %daemon_smtp_ports% is used. The +default setting contains just one port: + + daemon_smtp_ports = smtp + +If more than one port is listed, each interface that does not have its own port +specified listens on all of them. Ports that are listed in +%daemon_smtp_ports% can be identified either by name (defined in +_/etc/services_) or by number. However, when ports are given with individual +IP addresses in %local_interfaces%, only numbers (not names) can be used. + + + +Special IP listening addresses +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +The addresses 0.0.0.0 and ::0 are treated specially. They are interpreted +as ``all IPv4 interfaces'' and ``all IPv6 interfaces'', respectively. In each +case, Exim tells the TCP/IP stack to ``listen on all IPv##'x' interfaces'' +instead of setting up separate listening sockets for each interface. The +default value of %local_interfaces% is + + local_interfaces = 0.0.0.0 + +when Exim is built without IPv6 support; otherwise it is: + + local_interfaces = <; ::0 ; 0.0.0.0 + +Thus, by default, Exim listens on all available interfaces, on the SMTP port. + + + +Overriding local_interfaces and daemon_smtp_ports +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +The %-oX% command line option can be used to override the values of +%daemon_smtp_ports% and/or %local_interfaces% for a particular daemon +instance. Another way of doing this would be to use macros and the %-D% +option. However, %-oX% can be used by any admin user, whereas modification of +the runtime configuration by %-D% is allowed only when the caller is root or +exim. + +The value of %-oX% is a list of items. The default colon separator can be +changed in the usual way if required. If there are any items that do not +contain dots or colons (that is, are not IP addresses), the value of +%daemon_smtp_ports% is replaced by the list of those items. If there are any +items that do contain dots or colons, the value of %local_interfaces% is +replaced by those items. Thus, for example, + + -oX 1225 + +overrides %daemon_smtp_ports%, but leaves %local_interfaces% unchanged, +whereas + + -oX 192.168.34.5.1125 + +overrides %local_interfaces%, leaving %daemon_smtp_ports% unchanged. +(However, since %local_interfaces% now contains no items without ports, the +value of %daemon_smtp_ports% is no longer relevant in this example.) + + + +[[SECTsupobssmt]] +Support for the obsolete SSMTP (or SMTPS) protocol +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[ssmtp protocol] +cindex:[smtps protocol] +cindex:[SMTP,ssmtp protocol] +cindex:[SMTP,smtps protocol] +Exim supports the obsolete SSMTP protocol (also known as SMTPS) that was used +before the STARTTLS command was standardized for SMTP. Some legacy clients +still use this protocol. If the %tls_on_connect_ports% option is set to a +list of port numbers, connections to those ports must use SSMTP. The most +common use of this option is expected to be + + tls_on_connect_ports = 465 + +because 465 is the usual port number used by the legacy clients. There is also +a command line option %-tls-on-connect%, which forces all ports to behave in +this way when a daemon is started. + +*Warning*: Setting %tls_on_connect_ports% does not of itself cause the +daemon to listen on those ports. You must still specify them in +%daemon_smtp_ports%, %local_interfaces%, or the %-oX% option. (This is +because %tls_on_connect_ports% applies to %inetd% connections as well as to +connections via the daemon.) + + + + +IPv6 address scopes +~~~~~~~~~~~~~~~~~~~ +IPv6 addresses have ``scopes'', and a host with multiple hardware interfaces +can, in principle, have the same link-local IPv6 address on different +interfaces. Thus, additional information is needed, over and above the IP +address, to distinguish individual interfaces. A convention of using a +percent sign followed by something (often the interface name) has been +adopted in some cases, leading to addresses like this: + + fe80::202:b3ff:fe03:45c1%eth0 + +To accommodate this usage, a percent sign followed by an arbitrary string is +allowed at the end of an IPv6 address. By default, Exim calls 'getaddrinfo()' +to convert a textual IPv6 address for actual use. This function recognizes the +percent convention in operating systems that support it, and it processes the +address appropriately. Unfortunately, some older libraries have problems with +'getaddrinfo()'. If + + IPV6_USE_INET_PTON=yes + +is set in _Local/Makefile_ (or an OS-dependent Makefile) when Exim is built, +Exim uses 'inet_pton()' to convert a textual IPv6 address for actual use, +instead of 'getaddrinfo()'. (Before version 4.14, it always used this +function.) Of course, this means that the additional functionality of +'getaddrinfo()' -- recognizing scoped addresses -- is lost. + + + +Examples of starting a listening daemon +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +The default case in an IPv6 environment is + + daemon_smtp_ports = smtp + local_interfaces = <; ::0 ; 0.0.0.0 + +This specifies listening on the smtp port on all IPv6 and IPv4 interfaces. +Either one or two sockets may be used, depending on the characteristics of +the TCP/IP stack. (This is complicated and messy; for more information, +read the comments in the _daemon.c_ source file.) + +To specify listening on ports 25 and 26 on all interfaces: + + daemon_smtp_ports = 25 : 26 + +(leaving %local_interfaces% at the default setting) or, more explicitly: + +.... +local_interfaces = <; ::0.25 ; ::0.26 \ + 0.0.0.0.25 ; 0.0.0.0.26 +.... + +To listen on the default port on all IPv4 interfaces, and on port 26 on the +IPv4 loopback address only: + + local_interfaces = 0.0.0.0 : 127.0.0.1.26 + +To specify listening on the default port on specific interfaces only: + + local_interfaces = 192.168.34.67 : 192.168.34.67 + +*Warning*: such a setting excludes listening on the loopback interfaces. + + + +[[SECTreclocipadd]] +Recognising the local host +~~~~~~~~~~~~~~~~~~~~~~~~~~ +The %local_interfaces% option is also used when Exim needs to determine +whether or not an IP address refers to the local host. That is, the IP +addresses of all the interfaces on which a daemon is listening are always +treated as local. + +For this usage, port numbers in %local_interfaces% are ignored. If either of +the items 0.0.0.0 or ::0 are encountered, Exim gets a complete list of +available interfaces from the operating system, and extracts the relevant +(that is, IPv4 or IPv6) addresses to use for checking. + +Some systems set up large numbers of virtual interfaces in order to provide +many virtual web servers. In this situation, you may want to listen for +email on only a few of the available interfaces, but nevertheless treat all +interfaces as local when routing. You can do this by setting +%extra_local_interfaces% to a list of IP addresses, possibly including the +``all'' wildcard values. These addresses are recognized as local, but are not +used for listening. Consider this example: + +.... +local_interfaces = <; 127.0.0.1 ; ::1 ; \ + 192.168.53.235 ; \ + 3ffe:2101:12:1:a00:20ff:fe86:a061 + +extra_local_interfaces = <; ::0 ; 0.0.0.0 +.... + +The daemon listens on the loopback interfaces and just one IPv4 and one IPv6 +address, but all available interface addresses are treated as local when +Exim is routing. + +In some environments the local host name may be in an MX list, but with an IP +address that is not assigned to any local interface. In other cases it may be +desirable to treat other host names as if they referred to the local host. Both +these cases can be handled by setting the %hosts_treat_as_local% option. +This contains host names rather than IP addresses. When a host is referenced +during routing, either via an MX record or directly, it is treated as the local +host if its name matches %hosts_treat_as_local%, or if any of its IP +addresses match %local_interfaces% or %extra_local_interfaces%. + + + +Delivering to a remote host +~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Delivery to a remote host is handled by the smtp transport. By default, it +allows the system's TCP/IP functions to choose which interface to use (if +there is more than one) when connecting to a remote host. However, the +%interface% option can be set to specify which interface is used. See the +description of the smtp transport in chapter <<CHAPsmtptrans>> for more details. + + + + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// + +[[CHAPmainconfig]] +Main configuration +------------------ +cindex:[configuration file,main section] +cindex:[main configuration] +The first part of the run time configuration file contains three types of item: + +- Macro definitions: These lines start with an upper case letter. See section +<<SECTmacrodefs>> for details of macro processing. + +- Named list definitions: These lines start with one of the words ``domainlist'', +``hostlist'', ``addresslist'', or ``localpartlist''. Their use is described in +section <<SECTnamedlists>>. + +- Main configuration settings: Each setting occupies one line of the file +(with possible continuations). If any setting is preceded by the word +``hide'', the %-bP% command line option displays its value to admin users only. +See section <<SECTcos>> for a description of the syntax of these option settings. + +This chapter specifies all the main configuration options, along with their +types and default values. For ease of finding a particular option, they appear +in alphabetical order in section <<SECTalomo>> below. However, because there are +now so many options, they are first listed briefly in functional groups, as an +aid to finding the name of the option you are looking for. Some options are +listed in more than one group. + +Miscellaneous +~~~~~~~~~~~~~ +[frame="none"] +`-----------------------------------`------------------------------------- +%bi_command% to run for %-bi% command line option +%keep_malformed% for broken files -- should not happen +%localhost_number% for unique message ids in clusters +%message_body_visible% how much to show in $message_body$ +%mua_wrapper% run in ``MUA wrapper'' mode +%print_topbitchars% top-bit characters are printing +%timezone% force time zone +-------------------------------------------------------------------------- + + +Exim parameters +~~~~~~~~~~~~~~~ +[frame="none"] +`-----------------------------------`------------------------------------- +%exim_group% override compiled-in value +%exim_path% override compiled-in value +%exim_user% override compiled-in value +%primary_hostname% default from 'uname()' +%split_spool_directory% use multiple directories +%spool_directory% override compiled-in value +-------------------------------------------------------------------------- + + + +Privilege controls +~~~~~~~~~~~~~~~~~~ +[frame="none"] +`-----------------------------------`------------------------------------- +%admin_groups% groups that are Exim admin users +%deliver_drop_privilege% drop root for delivery processes +%local_from_check% insert 'Sender:' if necessary +%local_from_prefix% for testing 'From:' for local sender +%local_from_suffix% for testing 'From:' for local sender +%local_sender_retain% keep 'Sender:' from untrusted user +%never_users% do not run deliveries as these +%prod_requires_admin% forced delivery requires admin user +%queue_list_requires_admin% queue listing requires admin user +%trusted_groups% groups that are trusted +%trusted_users% users that are trusted +-------------------------------------------------------------------------- + + + +Logging +~~~~~~~ +[frame="none"] +`-----------------------------------`------------------------------------- +%hosts_connection_nolog% exemption from connect logging +%log_file_path% override compiled-in value +%log_selector% set/unset optional logging +%log_timezone% add timezone to log lines +%message_logs% create per-message logs +%preserve_message_logs% after message completion +%process_log_path% for SIGUSR1 and 'exiwhat' +%syslog_duplication% controls duplicate log lines on syslog +%syslog_facility% set syslog ``facility'' field +%syslog_processname% set syslog ``ident'' field +%syslog_timestamp% timestamp syslog lines +%write_rejectlog% control use of message log +-------------------------------------------------------------------------- + + + +Frozen messages +~~~~~~~~~~~~~~~ +[frame="none"] +`-----------------------------------`------------------------------------- +%auto_thaw% sets time for retrying frozen messages +%freeze_tell% send message when freezing +%move_frozen_messages% to another directory +%timeout_frozen_after% keep frozen messages only so long +-------------------------------------------------------------------------- + + + +Data lookups +~~~~~~~~~~~~ +[frame="none"] +`-----------------------------------`------------------------------------- +%ldap_default_servers% used if no server in query +%ldap_version% set protocol version +%lookup_open_max% lookup files held open +%mysql_servers% as it says +%oracle_servers% as it says +%pgsql_servers% as it says +-------------------------------------------------------------------------- + + + +Message ids +~~~~~~~~~~~ +[frame="none"] +`-----------------------------------`------------------------------------- +%message_id_header_domain% used to build 'Message-ID:' header +%message_id_header_text% ditto +-------------------------------------------------------------------------- + + + +Embedded Perl Startup +~~~~~~~~~~~~~~~~~~~~~ +[frame="none"] +`-----------------------------------`------------------------------------- +%perl_at_start% always start the interpreter +%perl_startup% code to obey when starting Perl +-------------------------------------------------------------------------- + + + +Daemon +~~~~~~ +[frame="none"] +`-----------------------------------`------------------------------------- +%daemon_smtp_ports% default ports +%extra_local_interfaces% not necessarily listened on +%local_interfaces% on which to listen, with optional ports +%pid_file_path% override compiled-in value +%queue_run_max% maximum simultaneous queue runners +-------------------------------------------------------------------------- + + + +Resource control +~~~~~~~~~~~~~~~~ +[frame="none"] +`-----------------------------------`------------------------------------- +%check_log_inodes% before accepting a message +%check_log_space% before accepting a message +%check_spool_inodes% before accepting a message +%check_spool_space% before accepting a message +%deliver_queue_load_max% no queue deliveries if load high +%queue_only_load% queue incoming if load high +%queue_run_max% maximum simultaneous queue runners +%remote_max_parallel% parallel SMTP delivery per message +%smtp_accept_max% simultaneous incoming connections +%smtp_accept_max_nommail% non-mail commands +%smtp_accept_max_nonmail_hosts% hosts to which the limit applies +%smtp_accept_max_per_connection% messages per connection +%smtp_accept_max_per_host% connections from one host +%smtp_accept_queue% queue mail if more connections +%smtp_accept_queue_per_connection% queue if more messages per connection +%smtp_accept_reserve% only reserve hosts if more connections +%smtp_check_spool_space% from SIZE on MAIL command +%smtp_connect_backlog% passed to TCP/IP stack +%smtp_load_reserve% SMTP from reserved hosts if load high +%smtp_reserve_hosts% these are the reserve hosts +-------------------------------------------------------------------------- + + + +Policy controls +~~~~~~~~~~~~~~~ +[frame="none"] +`-----------------------------------`------------------------------------- +%acl_not_smtp% set ACL for non-SMTP messages +%acl_smtp_auth% set ACL for AUTH +%acl_smtp_connect% set ACL for connection +%acl_smtp_data% set ACL for DATA +%acl_smtp_etrn% set ACL for ETRN +%acl_smtp_expn% set ACL for EXPN +%acl_smtp_helo% set ACL for EHLO or HELO +%acl_smtp_mail% set ACL for MAIL +%acl_smtp_mailauth% set ACL for AUTH on MAIL command +%acl_smtp_mime% set ACL for MIME parts +%acl_smtp_predata% set ACL for start of data +%acl_smtp_quit% set ACL for QUIT +%acl_smtp_rcpt% set ACL for RCPT +%acl_smtp_starttls% set ACL for STARTTLS +%acl_smtp_vrfy% set ACL for VRFY +%av_scanner% specify virus scanner +%header_maxsize% total size of message header +%header_line_maxsize% individual header line limit +%helo_accept_junk_hosts% allow syntactic junk from these hosts +%helo_allow_chars% allow illegal chars in HELO names +%helo_lookup_domains% lookup hostname for these HELO names +%helo_try_verify_hosts% HELO soft-checked for these hosts +%helo_verify_hosts% HELO hard-checked for these hosts +%host_lookup% host name looked up for these hosts +%host_lookup_order% order of DNS and local name lookups +%host_reject_connection% reject connection from these hosts +%hosts_treat_as_local% useful in some cluster configurations +%local_scan_timeout% timeout for 'local_scan()' +%message_size_limit% for all messages +%percent_hack_domains% recognize %-hack for these domains +%spamd_address% set interface to SpamAssassin +-------------------------------------------------------------------------- + + + +Callout cache +~~~~~~~~~~~~~ +[frame="none"] +`-----------------------------------`------------------------------------- +%callout_domain_negative_expire% timeout for negative domain cache item +%callout_domain_positive_expire% timeout for positive domain cache item +%callout_negative_expire% timeout for negative address cache item +%callout_positive_expire% timeout for positive address cache item +%callout_random_local_part% string to use for ``random'' testing +-------------------------------------------------------------------------- + + + +TLS +~~~ +[frame="none"] +`-----------------------------------`------------------------------------- +%tls_advertise_hosts% advertise TLS to these hosts +%tls_certificate% location of server certificate +%tls_crl% certificate revocation list +%tls_dhparam% DH parameters for server +%tls_on_connect_ports% specify SSMTP (SMTPS) ports +%tls_privatekey% location of server private key +%tls_remember_esmtp% don't reset after starting TLS +%tls_require_ciphers% specify acceptable cipers +%tls_try_verify_hosts% try to verify client certificate +%tls_verify_certificates% expected client certificates +%tls_verify_hosts% insist on client certificate verify +-------------------------------------------------------------------------- + + + +Local user handling +~~~~~~~~~~~~~~~~~~~ +[frame="none"] +`-----------------------------------`------------------------------------- +%finduser_retries% useful in NIS environments +%gecos_name% used when creating 'Sender:' +%gecos_pattern% ditto +%max_username_length% for systems that truncate +%unknown_login% used when no login name found +%unknown_username% ditto +%uucp_from_pattern% for recognizing ``From '' lines +%uucp_from_sender% ditto +-------------------------------------------------------------------------- + + + +All incoming messages (SMTP and non-SMTP) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +[frame="none"] +`-----------------------------------`------------------------------------- +%header_maxsize% total size of message header +%header_line_maxsize% individual header line limit +%message_size_limit% applies to all messages +%percent_hack_domains% recognize %-hack for these domains +%received_header_text% expanded to make 'Received:' +%received_headers_max% for mail loop detection +%recipients_max% limit per message +%recipients_max_reject% permanently reject excess +-------------------------------------------------------------------------- + + + + +Non-SMTP incoming messages +~~~~~~~~~~~~~~~~~~~~~~~~~~ +[frame="none"] +`-----------------------------------`------------------------------------- +%receive_timeout% for non-SMTP messages +-------------------------------------------------------------------------- + + + + + +Incoming SMTP messages +~~~~~~~~~~~~~~~~~~~~~~ +See also the 'Policy controls' section above. + +[frame="none"] +`-----------------------------------`------------------------------------- +%host_lookup% host name looked up for these hosts +%host_lookup_order% order of DNS and local name lookups +%recipient_unqualified_hosts% may send unqualified recipients +%rfc1413_hosts% make ident calls to these hosts +%rfc1413_query_timeout% zero disables ident calls +%sender_unqualified_hosts% may send unqualified senders +%smtp_accept_keepalive% some TCP/IP magic +%smtp_accept_max% simultaneous incoming connections +%smtp_accept_max_nommail% non-mail commands +%smtp_accept_max_nonmail_hosts% hosts to which the limit applies +%smtp_accept_max_per_connection% messages per connection +%smtp_accept_max_per_host% connections from one host +%smtp_accept_queue% queue mail if more connections +%smtp_accept_queue_per_connection% queue if more messages per connection +%smtp_accept_reserve% only reserve hosts if more connections +%smtp_active_hostname% host name to use in messages +%smtp_banner% text for welcome banner +%smtp_check_spool_space% from SIZE on MAIL command +%smtp_connect_backlog% passed to TCP/IP stack +%smtp_enforce_sync% of SMTP command/responses +%smtp_etrn_command% what to run for ETRN +%smtp_etrn_serialize% only one at once +%smtp_load_reserve% only reserve hosts if this load +%smtp_max_unknown_commands% before dropping connection +%smtp_ratelimit_hosts% apply ratelimiting to these hosts +%smtp_ratelimit_mail% ratelimit for MAIL commands +%smtp_ratelimit_rcpt% ratelimit for RCPT commands +%smtp_receive_timeout% per command or data line +%smtp_reserve_hosts% these are the reserve hosts +%smtp_return_error_details% give detail on rejections +-------------------------------------------------------------------------- + + + +SMTP extensions +~~~~~~~~~~~~~~~ +[frame="none"] +`-----------------------------------`------------------------------------- +%accept_8bitmime% advertise 8BITMIME +%auth_advertise_hosts% advertise AUTH to these hosts +%ignore_fromline_hosts% allow ``From '' from these hosts +%ignore_fromline_local% allow ``From '' from local SMTP +%pipelining_advertise_hosts% advertise pipelining to these hosts +%tls_advertise_hosts% advertise TLS to these hosts +-------------------------------------------------------------------------- + + + +Processing messages +~~~~~~~~~~~~~~~~~~~ +[frame="none"] +`-----------------------------------`------------------------------------- +%allow_domain_literals% recognize domain literal syntax +%allow_mx_to_ip% allow MX to point to IP address +%allow_utf8_domains% in addresses +%delivery_date_remove% from incoming messages +%envelope_to_remote% from incoming messages +%extract_addresses_remove_arguments%affects %-t% processing +%headers_charset% default for translations +%qualify_domain% default for senders +%qualify_recipient% default for recipients +%return_path_remove% from incoming messages +%strip_excess_angle_brackets% in addresses +%strip_trailing_dot% at end of addresses +%untrusted_set_sender% untrusted can set envelope sender +-------------------------------------------------------------------------- + + + +System filter +~~~~~~~~~~~~~ +[frame="none"] +`-----------------------------------`------------------------------------- +%system_filter% locate system filter +%system_filter_directory_transport% transport for delivery to a directory +%system_filter_file_transport% transport for delivery to a file +%system_filter_group% group for filter running +%system_filter_pipe_transport% transport for delivery to a pipe +%system_filter_reply_transport% transport for autoreply delivery +%system_filter_user% user for filter running +-------------------------------------------------------------------------- + + + +Routing and delivery +~~~~~~~~~~~~~~~~~~~~ +[frame="none"] +`-----------------------------------`------------------------------------- +%dns_again_means_nonexist% for broken domains +%dns_check_names_pattern% pre-DNS syntax check +%dns_ipv4_lookup% only v4 lookup for these domains +%dns_retrans% parameter for resolver +%dns_retry% parameter for resolver +%hold_domains% hold delivery for these domains +%local_interfaces% for routing checks +%queue_domains% no immediate delivery for these +%queue_only% no immediate delivery at all +%queue_only_file% no immediate deliveryif file exists +%queue_only_load% no immediate delivery if load is high +%queue_only_override% allow command line to override +%queue_run_in_order% order of arrival +%queue_run_max% of simultaneous queue runners +%queue_smtp_domains% no immediate SMTP delivery for these +%remote_max_parallel% parallel SMTP delivery per message +%remote_sort_domains% order of remote deliveries +%retry_data_expire% timeout for retry data +%retry_interval_max% safety net for retry rules +-------------------------------------------------------------------------- + + + +Bounce and warning messages +~~~~~~~~~~~~~~~~~~~~~~~~~~~ +[frame="none"] +`-----------------------------------`------------------------------------- +%bounce_message_file% content of bounce +%bounce_message_text% content of bounce +%bounce_return_body% include body if returning message +%bounce_return_message% include original message in bounce +%bounce_return_size_limit% limit on returned message +%bounce_sender_authentication% send authenticated sender with bounce +%errors_copy% copy bounce messages +%errors_reply_to% 'Reply-to:' in bounces +%delay_warning% time schedule +%delay_warning_condition% condition for warning messages +%ignore_bounce_errors_after% discard undeliverable bounces +%warn_message_file% content of warning message +-------------------------------------------------------------------------- + + + +[[SECTalomo]] +Alphabetical list of main options +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Those options that undergo string expansion before use are marked with !!. + +oindex:[%accept_8bitmime%] +`..'= +%accept_8bitmime%, Use: 'main', Type: 'boolean', Default: 'false' +=== + +cindex:[8BITMIME] +cindex:[8-bit characters] +This option causes Exim to send 8BITMIME in its response to an SMTP +EHLO command, and to accept the BODY= parameter on MAIL commands. +However, though Exim is 8-bit clean, it is not a protocol converter, and it +takes no steps to do anything special with messages received by this route. +Consequently, this option is turned off by default. + +oindex:[%acl_not_smtp%] +`..'= +%acl_not_smtp%, Use: 'main', Type: 'string'!!, Default: 'unset' +=== + +cindex:[{ACL},for non-SMTP messages] +cindex:[non-SMTP messages, ACL for] +This option defines the ACL that is run when a non-SMTP message is on the point +of being accepted. See chapter <<CHAPACL>> for further details. + +oindex:[%acl_smtp_auth%] +`..'= +%acl_smtp_auth%, Use: 'main', Type: 'string'!!, Default: 'unset' +=== + +cindex:[{ACL},setting up for SMTP commands] +cindex:[AUTH,ACL for] +This option defines the ACL that is run when an SMTP AUTH command is +received. See chapter <<CHAPACL>> for further details. + +oindex:[%acl_smtp_connect%] +`..'= +%acl_smtp_connect%, Use: 'main', Type: 'string'!!, Default: 'unset' +=== + +cindex:[{ACL},on SMTP connection] +This option defines the ACL that is run when an SMTP connection is received. +See chapter <<CHAPACL>> for further details. + +oindex:[%acl_smtp_data%] +`..'= +%acl_smtp_data%, Use: 'main', Type: 'string'!!, Default: 'unset' +=== + +cindex:[DATA, ACL for] +This option defines the ACL that is run after an SMTP DATA command has been +processed and the message itself has been received, but before the final +acknowledgement is sent. See chapter <<CHAPACL>> for further details. + +oindex:[%acl_smtp_etrn%] +`..'= +%acl_smtp_etrn%, Use: 'main', Type: 'string'!!, Default: 'unset' +=== + +cindex:[ETRN,ACL for] +This option defines the ACL that is run when an SMTP ETRN command is +received. See chapter <<CHAPACL>> for further details. + +oindex:[%acl_smtp_expn%] +`..'= +%acl_smtp_expn%, Use: 'main', Type: 'string'!!, Default: 'unset' +=== + +cindex:[EXPN,ACL for] +This option defines the ACL that is run when an SMTP EXPN command is +received. See chapter <<CHAPACL>> for further details. + +oindex:[%acl_smtp_helo%] +`..'= +%acl_smtp_helo%, Use: 'main', Type: 'string'!!, Default: 'unset' +=== + +cindex:[EHLO,ACL for] +cindex:[HELO,ACL for] +This option defines the ACL that is run when an SMTP EHLO or HELO +command is received. See chapter <<CHAPACL>> for further details. + + +oindex:[%acl_smtp_mail%] +`..'= +%acl_smtp_mail%, Use: 'main', Type: 'string'!!, Default: 'unset' +=== + +cindex:[MAIL,ACL for] +This option defines the ACL that is run when an SMTP MAIL command is +received. See chapter <<CHAPACL>> for further details. + +oindex:[%acl_smtp_mailauth%] +`..'= +%acl_smtp_mailauth%, Use: 'main', Type: 'string'!!, Default: 'unset' +=== + +cindex:[AUTH,on MAIL command] +This option defines the ACL that is run when there is an AUTH parameter on +a MAIL command. See chapter <<CHAPACL>> for details of ACLs, and chapter +<<CHAPSMTPAUTH>> for details of authentication. + +oindex:[%acl_smtp_mime%] +`..'= +%acl_smtp_mime%, Use: 'main', Type: 'string'!!, Default: 'unset' +=== + +cindex:[MIME content scanning,ACL for] +This option is available when Exim is built with the content-scanning +extension. It defines the ACL that is run for each MIME part in a message. See +section <<SECTscanmimepart>> for details. + +oindex:[%acl_smtp_predata%] +`..'= +%acl_smtp_predata%, Use: 'main', Type: 'string'!!, Default: 'unset' +=== + +This option defines the ACL that is run when an SMTP DATA command is +received, before the message itself is received. See chapter <<CHAPACL>> for +further details. + +oindex:[%acl_smtp_quit%] +`..'= +%acl_smtp_quit%, Use: 'main', Type: 'string'!!, Default: 'unset' +=== + +cindex:[QUIT,ACL for] +This option defines the ACL that is run when an SMTP QUIT command is +received. See chapter <<CHAPACL>> for further details. + +oindex:[%acl_smtp_rcpt%] +`..'= +%acl_smtp_rcpt%, Use: 'main', Type: 'string'!!, Default: 'unset' +=== + +cindex:[RCPT,ACL for] +This option defines the ACL that is run when an SMTP RCPT command is +received. See chapter <<CHAPACL>> for further details. + +oindex:[%acl_smtp_starttls%] +`..'= +%acl_smtp_starttls%, Use: 'main', Type: 'string'!!, Default: 'unset' +=== + +cindex:[STARTTLS, ACL for] +This option defines the ACL that is run when an SMTP STARTTLS command is +received. See chapter <<CHAPACL>> for further details. + +oindex:[%acl_smtp_vrfy%] +`..'= +%acl_smtp_vrfy%, Use: 'main', Type: 'string'!!, Default: 'unset' +=== + +cindex:[VRFY,ACL for] +This option defines the ACL that is run when an SMTP VRFY command is +received. See chapter <<CHAPACL>> for further details. + +oindex:[%admin_groups%] +`..'= +%admin_groups%, Use: 'main', Type: 'string list', Default: 'unset' +=== + +cindex:[admin user] +If the current group or any of the supplementary groups of the caller is in +this colon-separated list, the caller has admin privileges. If all your system +programmers are in a specific group, for example, you can give them all Exim +admin privileges by putting that group in %admin_groups%. However, this does +not permit them to read Exim's spool files (whose group owner is the Exim gid). +To permit this, you have to add individuals to the Exim group. + + +oindex:[%allow_domain_literals%] +`..'= +%allow_domain_literals%, Use: 'main', Type: 'boolean', Default: 'false' +=== + +cindex:[domain literal] +If this option is set, the RFC 2822 domain literal format is permitted in +email addresses. The option is not set by default, because the domain literal +format is not normally required these days, and few people know about it. It +has, however, been exploited by mail abusers. + +Unfortunately, it seems that some DNS black list maintainers are using this +format to report black listing to postmasters. If you want to accept messages +addressed to your hosts by IP address, you need to set +%allow_domain_literals% true, and also to add `@[]` to the list of local +domains (defined in the named domain list %local_domains% in the default +configuration). This ``magic string'' matches the domain literal form of all the +local host's IP addresses. + + +oindex:[%allow_mx_to_ip%] +`..'= +%allow_mx_to_ip%, Use: 'main', Type: 'boolean', Default: 'false' +=== + +cindex:[MX record,pointing to IP address] +It appears that more and more DNS zone administrators are breaking the rules +and putting domain names that look like IP addresses on the right hand side of +MX records. Exim follows the rules and rejects this, giving an error message +that explains the mis-configuration. However, some other MTAs support this +practice, so to avoid ``Why can''t Exim do this?' complaints, %allow_mx_to_ip% +exists, in order to enable this heinous activity. It is not recommended, except +when you have no other choice. + +oindex:[%allow_utf8_domains%] +`..'= +%allow_utf8_domains%, Use: 'main', Type: 'boolean', Default: 'false' +=== + +cindex:[domain,UTF-8 characters in] +cindex:[UTF-8,in domain name] +Lots of discussion is going on about internationalized domain names. One +camp is strongly in favour of just using UTF-8 characters, and it seems +that at least two other MTAs permit this. This option allows Exim users to +experiment if they wish. + +If it is set true, Exim's domain parsing function allows valid +UTF-8 multicharacters to appear in domain name components, in addition to +letters, digits, and hyphens. However, just setting this option is not +enough; if you want to look up these domain names in the DNS, you must also +adjust the value of %dns_check_names_pattern% to match the extended form. A +suitable setting is: + +.... +dns_check_names_pattern = (?i)^(?>(?(1)\.|())[a-z0-9\xc0-\xff]\ + (?>[-a-z0-9\x80-\xff]*[a-z0-9\x80-\xbf])?)+$ +.... + +Alternatively, you can just disable this feature by setting + + dns_check_names_pattern = + +That is, set the option to an empty string so that no check is done. + + +oindex:[%auth_advertise_hosts%] +`..'= +%auth_advertise_hosts%, Use: 'main', Type: 'host list'!!, Default: '\*' +=== + +cindex:[authentication,advertising] +cindex:[AUTH,advertising] +If any server authentication mechanisms are configured, Exim advertises them in +response to an EHLO command only if the calling host matches this list. +Otherwise, Exim does not advertise AUTH. +Exim does not accept AUTH commands from clients to which it has not +advertised the availability of AUTH. The advertising of individual +authentication mechanisms can be controlled by the use of the +%server_advertise_condition% generic authenticator option on the individual +authenticators. See chapter <<CHAPSMTPAUTH>> for further details. + +Certain mail clients (for example, Netscape) require the user to provide a name +and password for authentication if AUTH is advertised, even though it may +not be needed (the host may accept messages from hosts on its local LAN without +authentication, for example). The %auth_advertise_hosts% option can be used +to make these clients more friendly by excluding them from the set of hosts to +which Exim advertises AUTH. + +cindex:[AUTH,advertising when encrypted] +If you want to advertise the availability of AUTH only when the connection +is encrypted using TLS, you can make use of the fact that the value of this +option is expanded, with a setting like this: + + auth_advertise_hosts = ${if eq{$tls_cipher}{}{}{*}} + +If $tls_cipher$ is empty, the session is not encrypted, and the result of +the expansion is empty, thus matching no hosts. Otherwise, the result of the +expansion is \*, which matches all hosts. + + +oindex:[%auto_thaw%] +`..'= +%auto_thaw%, Use: 'main', Type: 'time', Default: '0s' +=== + +cindex:[thawing messages] +cindex:[unfreezing messages] +If this option is set to a time greater than zero, a queue runner will try a +new delivery attempt on any frozen message if this much time has passed since +it was frozen. This may result in the message being re-frozen if nothing has +changed since the last attempt. It is a way of saying ``keep on trying, even +though there are big problems''. See also %timeout_frozen_after% and +%ignore_bounce_errors_after%. + + +oindex:[%av_scanner%] +`..'= +%av_scanner%, Use: 'main', Type: 'string', Default: 'see below' +=== + +This option is available if Exim is built with the content-scanning extension. +It specifies which anti-virus scanner to use. The default value is: + + sophie:/var/run/sophie + +If the value of %av_scanner% starts with dollar character, it is expanded +before use. See section <<SECTscanvirus>> for further details. + + + +oindex:[%bi_command%] +`..'= +%bi_command%, Use: 'main', Type: 'string', Default: 'unset' +=== + +cindex:[%-bi% option] +This option supplies the name of a command that is run when Exim is called with +the %-bi% option (see chapter <<CHAPcommandline>>). The string value is just the +command name, it is not a complete command line. If an argument is required, it +must come from the %-oA% command line option. + + +oindex:[%bounce_message_file%] +`..'= +%bounce_message_file%, Use: 'main', Type: 'string', Default: 'unset' +=== + +cindex:[bounce message,customizing] +cindex:[customizing,bounce message] +This option defines a template file containing paragraphs of text to be used +for constructing bounce messages. Details of the file's contents are given in +chapter <<CHAPemsgcust>>. See also %warn_message_file%. + + +oindex:[%bounce_message_text%] +`..'= +%bounce_message_text%, Use: 'main', Type: 'string', Default: 'unset' +=== + +When this option is set, its contents are included in the default bounce +message immediately after ``This message was created automatically by mail +delivery software.'' It is not used if %bounce_message_file% is set. + +oindex:[%bounce_return_body%] +`..'= +%bounce_return_body%, Use: 'main', Type: 'boolean', Default: 'true' +=== + +cindex:[bounce message,including body] +This option controls whether the body of an incoming message is included in a +bounce message when %bounce_return_message% is true. If it is not set, only +the message header is included. +cindex:[bounce message,including original] + +oindex:[%bounce_return_message%] +`..'= +%bounce_return_message%, Use: 'main', Type: 'boolean', Default: 'true' +=== + +If this option is set false, the original message is not included in bounce +messages generated by Exim. See also %bounce_return_size_limit%. + + +oindex:[%bounce_return_size_limit%] +`..'= +%bounce_return_size_limit%, Use: 'main', Type: 'integer', Default: '100K' +=== + +cindex:[size limit, of bounce] +cindex:[bounce message,size limit] +cindex:[limit,bounce message size] +This option sets a limit in bytes on the size of messages that are returned to +senders as part of bounce messages when %bounce_return_message% is true. The +limit should be less than the value of the global %message_size_limit% and of +any %message_size_limit% settings on transports, to allow for the bounce text +that Exim generates. If this option is set to zero there is no limit. + +When the body of any message that is to be included in a bounce message is +greater than the limit, it is truncated, and a comment pointing this out is +added at the top. The actual cutoff may be greater than the value given, owing +to the use of buffering for transferring the message in chunks (typically 8K in +size). The idea is to save bandwidth on those undeliverable 15-megabyte +messages. + +oindex:[%bounce_sender_authentication%] +`..'= +%bounce_sender_authentication%, Use: 'main', Type: 'string', Default: 'unset' +=== + +cindex:[bounce message,sender authentication] +cindex:[authentication,bounce message] +cindex:[AUTH,on bounce message] +This option provides an authenticated sender address that is sent with any +bounce messages generated by Exim that are sent over an authenticated SMTP +connection. A typical setting might be: + + bounce_sender_authentication = mailer-daemon@my.domain.example + +which would cause bounce messages to be sent using the SMTP command: + + MAIL FROM:<> AUTH=mailer-daemon@my.domain.example + +The value of %bounce_sender_authentication% must always be a complete email +address. + +oindex:[%callout_domain_negative_expire%] +`..'= +%callout_domain_negative_expire%, Use: 'main', Type: 'time', Default: '3h' +=== + +cindex:[caching,callout timeouts] +cindex:[callout,caching timeouts] +This option specifies the expiry time for negative callout cache data for a +domain. See section <<SECTcallver>> for details of callout verification, and +section <<SECTcallvercache>> for details of the caching. + + +oindex:[%callout_domain_positive_expire%] +`..'= +%callout_domain_positive_expire%, Use: 'main', Type: 'time', Default: '7d' +=== + +This option specifies the expiry time for positive callout cache data for a +domain. See section <<SECTcallver>> for details of callout verification, and +section <<SECTcallvercache>> for details of the caching. + + +oindex:[%callout_negative_expire%] +`..'= +%callout_negative_expire%, Use: 'main', Type: 'time', Default: '2h' +=== + +This option specifies the expiry time for negative callout cache data for an +address. See section <<SECTcallver>> for details of callout verification, and +section <<SECTcallvercache>> for details of the caching. + + +oindex:[%callout_positive_expire%] +`..'= +%callout_positive_expire%, Use: 'main', Type: 'time', Default: '24h' +=== + +This option specifies the expiry time for positive callout cache data for an +address. See section <<SECTcallver>> for details of callout verification, and +section <<SECTcallvercache>> for details of the caching. + + +oindex:[%callout_random_local_part%] +`..'= +%callout_random_local_part%, Use: 'main', Type: 'string'!!, Default: 'see below' +=== + +This option defines the ``random'' local part that can be used as part of callout +verification. The default value is + + $primary_host_name-$tod_epoch-testing + +See section <<CALLaddparcall>> for details of how this value is used. + + +oindex:[%check_log_inodes%] +`..'= +%check_log_inodes%, Use: 'main', Type: 'integer', Default: '0' +=== + +See %check_spool_space% below. + + +oindex:[%check_log_space%] +`..'= +%check_log_space%, Use: 'main', Type: 'integer', Default: '0' +=== + +See %check_spool_space% below. + + +oindex:[%check_spool_inodes%] +`..'= +%check_spool_inodes%, Use: 'main', Type: 'integer', Default: '0' +=== + +See %check_spool_space% below. + + +oindex:[%check_spool_space%] +`..'= +%check_spool_space%, Use: 'main', Type: 'integer', Default: '0' +=== + +cindex:[checking disk space] +cindex:[disk space, checking] +cindex:[spool directory,checking space] +The four %check_...% options allow for checking of disk resources before a +message is accepted. + +When any of these options are set, they apply to all incoming messages. If you +want to apply different checks to different kinds of message, you can do so +by testing the the variables $log_inodes$, $log_space$, +$spool_inodes$, and $spool_space$ in an ACL with appropriate additional +conditions. + + +%check_spool_space% and %check_spool_inodes% check the spool partition if +either value is greater than zero, for example: + + check_spool_space = 10M + check_spool_inodes = 100 + +The spool partition is the one that contains the directory defined by +SPOOL_DIRECTORY in _Local/Makefile_. It is used for holding messages in +transit. + +%check_log_space% and %check_log_inodes% check the partition in which log +files are written if either is greater than zero. These should be set only if +%log_file_path% and %spool_directory% refer to different partitions. + +If there is less space or fewer inodes than requested, Exim refuses to accept +incoming mail. In the case of SMTP input this is done by giving a 452 temporary +error response to the MAIL command. If ESMTP is in use and there was a +SIZE parameter on the MAIL command, its value is added to the +%check_spool_space% value, and the check is performed even if +%check_spool_space% is zero, unless %no_smtp_check_spool_space% is set. + +The values for %check_spool_space% and %check_log_space% are held as a +number of kilobytes. If a non-multiple of 1024 is specified, it is rounded up. + +For non-SMTP input and for batched SMTP input, the test is done at start-up; on +failure a message is written to stderr and Exim exits with a non-zero code, as +it obviously cannot send an error message of any kind. + +oindex:[%daemon_smtp_ports%] +`..'= +%daemon_smtp_ports%, Use: 'main', Type: 'string', Default: `smtp` +=== + +cindex:[port,for daemon] +cindex:[TCP/IP,setting listening ports] +This option specifies one or more default SMTP ports on which the Exim daemon +listens. See chapter <<CHAPinterfaces>> for details of how it is used. For +backward compatibility, %daemon_smtp_port% (singular) is a synonym. + + +oindex:[%delay_warning%] +`..'= +%delay_warning%, Use: 'main', Type: 'time list', Default: '24h' +=== + +cindex:[warning of delay] +cindex:[delay warning, specifying] +When a message is delayed, Exim sends a warning message to the sender at +intervals specified by this option. The data is a colon-separated list of times +after which to send warning messages. + +If the value of the option is an empty string or a zero time, no warnings are +sent. + +Up to 10 times may be given. If a message has been on the queue for longer than +the last time, the last interval between the times is used to compute +subsequent warning times. For example, with + + delay_warning = 4h:8h:24h + +the first message is sent after 4 hours, the second after 8 hours, and +the third one after 24 hours. After that, messages are sent every 16 hours, +because that is the interval between the last two times on the list. If you set +just one time, it specifies the repeat interval. For example, with: + + delay_warning = 6h + +messages are repeated every six hours. To stop warnings after a given time, set +a very large time at the end of the list. For example: + + delay_warning = 2h:12h:99d + + + +oindex:[%delay_warning_condition%] +`..'= +%delay_warning_condition%, Use: 'main', Type: 'string'!!, Default: 'see below' +=== + +The string is expanded at the time a warning message might be sent. If all the +deferred addresses have the same domain, it is set in $domain$ during the +expansion. Otherwise $domain$ is empty. If the result of the expansion is a +forced failure, an empty string, or a string matching any of ``0'', ``no'' or +``false'' (the comparison being done caselessly) then the warning message is not +sent. The default is + +.... +delay_warning_condition = \ + ${if match{$h_precedence:}{(?i)bulk|list|junk}{no}{yes}} +.... + +which suppresses the sending of warnings about messages that have ``bulk'', +``list'' or ``junk'' in a 'Precedence:' header. + +oindex:[%deliver_drop_privilege%] +`..'= +%deliver_drop_privilege%, Use: 'main', Type: 'boolean', Default: 'false' +=== + +cindex:[unprivileged delivery] +cindex:[delivery,unprivileged] +If this option is set true, Exim drops its root privilege at the start of a +delivery process, and runs as the Exim user throughout. This severely restricts +the kinds of local delivery that are possible, but is viable in certain types +of configuration. There is a discussion about the use of root privilege in +chapter <<CHAPsecurity>>. + +oindex:[%deliver_queue_load_max%] +`..'= +%deliver_queue_load_max%, Use: 'main', Type: 'fixed-point', Default: 'unset' +=== + +cindex:[load average] +cindex:[queue runner,abandoning] +When this option is set, a queue run is abandoned if the system load average +becomes greater than the value of the option. The option has no effect on +ancient operating systems on which Exim cannot determine the load average. +See also %queue_only_load% and %smtp_load_reserve%. + + +oindex:[%delivery_date_remove%] +`..'= +%delivery_date_remove%, Use: 'main', Type: 'boolean', Default: 'true' +=== + +cindex:['Delivery-date:' header line] +Exim's transports have an option for adding a 'Delivery-date:' header to a +message when it is delivered -- in exactly the same way as 'Return-path:' is +handled. 'Delivery-date:' records the actual time of delivery. Such headers +should not be present in incoming messages, and this option causes them to be +removed at the time the message is received, to avoid any problems that might +occur when a delivered message is subsequently sent on to some other recipient. + +oindex:[%dns_again_means_nonexist%] +`..'= +%dns_again_means_nonexist%, Use: 'main', Type: 'domain list'!!, Default: 'unset' +=== + +cindex:[DNS,``try again'' response; overriding] +DNS lookups give a ``try again'' response for the DNS errors ``non-authoritative +host not found'' and ``SERVERFAIL''. This can cause Exim to keep trying to +deliver a message, or to give repeated temporary errors to incoming mail. +Sometimes the effect is caused by a badly set up name server and may persist +for a long time. If a domain which exhibits this problem matches anything in +%dns_again_means_nonexist%, it is treated as if it did not exist. This +option should be used with care. +You can make it apply to reverse lookups by a setting such as this: + + dns_again_means_nonexist = *.in-addr.arpa + +This option applies to all DNS lookups that Exim does. The ^dnslookup^ router +has some options of its own for controlling what happens when lookups for MX or +SRV records give temporary errors. These more specific options are applied +after the global option. + +oindex:[%dns_check_names_pattern%] +`..'= +%dns_check_names_pattern%, Use: 'main', Type: 'string', Default: 'see below' +=== + +cindex:[DNS,pre-check of name syntax] +When this option is set to a non-empty string, it causes Exim to check domain +names for illegal characters before handing them to the DNS resolver, because +some resolvers give temporary errors for malformed names. If a domain name +contains any illegal characters, a ``not found'' result is forced, and the +resolver is not called. The check is done by matching the domain name against a +regular expression, which is the value of this option. The default pattern is + +.... +dns_check_names_pattern = \ + (?i)^(?>(?(1)\.|())[^\W_](?>[a-z0-9-]*[^\W_])?)+$ +.... + +which permits only letters, digits, and hyphens in components, but they may not +start or end with a hyphen. +If you set %allow_utf8_domains%, you must modify this pattern, or set the +option to an empty string. + + +oindex:[%dns_ipv4_lookup%] +`..'= +%dns_ipv4_lookup%, Use: 'main', Type: 'domain list'!!, Default: 'unset' +=== + +cindex:[IPv6,DNS lookup for AAAA records] +cindex:[DNS,IPv6 lookup for AAAA records] +When Exim is compiled with IPv6 support, it looks for IPv6 address records +(AAAA and, if configured, A6) as well as IPv4 address records when trying to +find IP addresses for hosts, unless the host's domain matches this list. + +This is a fudge to help with name servers that give big delays or otherwise do +not work for the new IPv6 record types. If Exim is handed an IPv6 address +record as a result of an MX lookup, it always recognizes it, and may as a +result make an outgoing IPv6 connection. All this option does is to make Exim +look only for IPv4-style A records when it needs to find an IP address for a +host name. In due course, when the world's name servers have all been upgraded, +there should be no need for this option. + + +oindex:[%dns_retrans%] +`..'= +%dns_retrans%, Use: 'main', Type: 'time', Default: '0s' +=== + +cindex:[DNS,resolver options] +The options %dns_retrans% and %dns_retry% can be used to set the +retransmission and retry parameters for DNS lookups. Values of zero (the +defaults) leave the system default settings unchanged. The first value is the +time between retries, and the second is the number of retries. It isn't +totally clear exactly how these settings affect the total time a DNS lookup may +take. I haven't found any documentation about timeouts on DNS lookups; these +parameter values are available in the external resolver interface structure, +but nowhere does it seem to describe how they are used or what you might want +to set in them. + + +oindex:[%dns_retry%] +`..'= +%dns_retry%, Use: 'main', Type: 'integer', Default: '0' +=== + +See %dns_retrans% above. + + +oindex:[%drop_cr%] +`..'= +%drop_cr%, Use: 'main', Type: 'boolean', Default: 'false' +=== + +This is an obsolete option that is now a no-op. It used to affect the way Exim +handled CR and LF characters in incoming messages. What happens now is +described in section <<SECTlineendings>>. + + +oindex:[%envelope_to_remove%] +`..'= +%envelope_to_remove%, Use: 'main', Type: 'boolean', Default: 'true' +=== + +cindex:['Envelope-to:' header line] +Exim's transports have an option for adding an 'Envelope-to:' header to a +message when it is delivered -- in exactly the same way as 'Return-path:' is +handled. 'Envelope-to:' records the original recipient address from the +messages's envelope that caused the delivery to happen. Such headers should not +be present in incoming messages, and this option causes them to be removed at +the time the message is received, to avoid any problems that might occur when a +delivered message is subsequently sent on to some other recipient. + + +oindex:[%errors_copy%] +`..'= +%errors_copy%, Use: 'main', Type: 'string list'!!, Default: 'unset' +=== + +cindex:[bounce message,copy to other address] +cindex:[copy of bounce message] +Setting this option causes Exim to send bcc copies of bounce messages that it +generates to other addresses. *Note*: this does not apply to bounce messages +coming from elsewhere. The value of the option is a colon-separated list of +items. Each item consists of a pattern, terminated by white space, followed by +a comma-separated list of email addresses. If a pattern contains spaces, it +must be enclosed in double quotes. + +Each pattern is processed in the same way as a single item in an address list +(see section <<SECTaddresslist>>). When a pattern matches the recipient of the +bounce message, the message is copied to the addresses on the list. The items +are scanned in order, and once a matching one is found, no further items are +examined. For example: + +.... +errors_copy = spqr@mydomain postmaster@mydomain.example :\ + rqps@mydomain hostmaster@mydomain.example,\ + postmaster@mydomain.example +.... + +The address list is expanded before use. The expansion variables +$local_part$ and $domain$ are set from the original recipient of the error +message, and if there was any wildcard matching in the pattern, the expansion + +cindex:[numerical variables ($1$ $2$ etc),in %errors_copy%] +variables $0$, $1$, etc. are set in the normal way. + + +oindex:[%errors_reply_to%] +`..'= +%errors_reply_to%, Use: 'main', Type: 'string', Default: 'unset' +=== + +cindex:[bounce message,'Reply-to:' in] +Exim's bounce and delivery warning messages contain the header line + + From: Mail Delivery System <Mailer-Daemon@<qualify-domain>> + +where <'qualify-domain'> is the value of the %qualify_domain% option. +Experience shows that people reply to bounce messages. If the +%errors_reply_to% option is set, a 'Reply-To:' header is added to bounce and +warning messages. For example: + + errors_reply_to = postmaster@my.domain.example + +The value of the option is not expanded. It must specify a valid RFC 2822 +address. + + +oindex:[%exim_group%] +`..'= +%exim_group%, Use: 'main', Type: 'string', Default: 'compile-time configured' +=== + +cindex:[gid (group id),Exim's own] +cindex:[Exim group] +This option changes the gid under which Exim runs when it gives up root +privilege. The default value is compiled into the binary. The value of this +option is used only when %exim_user% is also set. Unless it consists entirely +of digits, the string is looked up using 'getgrnam()', and failure causes a +configuration error. See chapter <<CHAPsecurity>> for a discussion of security +issues. + + +oindex:[%exim_path%] +`..'= +%exim_path%, Use: 'main', Type: 'string', Default: 'see below' +=== + +cindex:[Exim binary, path name] +This option specifies the path name of the Exim binary, which is used when Exim +needs to re-exec itself. The default is set up to point to the file 'exim' in +the directory configured at compile time by the BIN_DIRECTORY setting. It +is necessary to change %exim_path% if, exceptionally, Exim is run from some +other place. +*Warning*: Do not use a macro to define the value of this option, because +you will break those Exim utilities that scan the configuration file to find +where the binary is. (They then use the %-bP% option to extract option +settings such as the value of %spool_directory%.) + + +oindex:[%exim_user%] +`..'= +%exim_user%, Use: 'main', Type: 'string', Default: 'compile-time configured' +=== + +cindex:[uid (user id),Exim's own] +cindex:[Exim user] +This option changes the uid under which Exim runs when it gives up root +privilege. The default value is compiled into the binary. Ownership of the run +time configuration file and the use of the %-C% and %-D% command line options +is checked against the values in the binary, not what is set here. + +Unless it consists entirely of digits, the string is looked up using +'getpwnam()', and failure causes a configuration error. If %exim_group% is +not also supplied, the gid is taken from the result of 'getpwnam()' if it is +used. See chapter <<CHAPsecurity>> for a discussion of security issues. + + +oindex:[%extra_local_interfaces%] +`..'= +%extra_local_interfaces%, Use: 'main', Type: 'string list', Default: 'unset' +=== + +This option defines network interfaces that are to be considered local when +routing, but which are not used for listening by the daemon. See section +<<SECTreclocipadd>> for details. + + +oindex:[%extract_addresses_remove_arguments%] +`..'= +%extract_addresses_remove_ ~arguments%, Use: 'main', Type: 'boolean', Default: 'true' +=== + +cindex:[%-t% option] +cindex:[command line,addresses with %-t%] +cindex:[Sendmail compatibility,%-t% option] +According to some Sendmail documentation (Sun, IRIX, HP-UX), if any addresses +are present on the command line when the %-t% option is used to build an +envelope from a message's 'To:', 'Cc:' and 'Bcc:' headers, the command line +addresses are removed from the recipients list. This is also how Smail behaves. +However, other Sendmail documentation (the O'Reilly book) states that command +line addresses are added to those obtained from the header lines. When +%extract_addresses_remove_arguments% is true (the default), Exim subtracts +argument headers. If it is set false, Exim adds rather than removes argument +addresses. + + +oindex:[%finduser_retries%] +`..'= +%finduser_retries%, Use: 'main', Type: 'integer', Default: '0' +=== + +cindex:[NIS, looking up users; retrying] +On systems running NIS or other schemes in which user and group information is +distributed from a remote system, there can be times when 'getpwnam()' and +related functions fail, even when given valid data, because things time out. +Unfortunately these failures cannot be distinguished from genuine ``not found'' +errors. If %finduser_retries% is set greater than zero, Exim will try that +many extra times to find a user or a group, waiting for one second between +retries. + +cindex:[_/etc/passwd_, multiple reading of] +You should not set this option greater than zero if your user information is in +a traditional _/etc/passwd_ file, because it will cause Exim needlessly to +search the file multiple times for non-existent users, and also cause delay. + + + +oindex:[%freeze_tell%] +`..'= +%freeze_tell%, Use: 'main', "Type: 'string list, comma separated'", Default: 'unset' +=== + +cindex:[freezing messages,sending a message when freezing] +On encountering certain errors, or when configured to do so in a system filter, +or in an ACL, +Exim freezes a message. This means that no further delivery attempts take place +until an administrator (or the %auto_thaw% feature) thaws the message. If +%freeze_tell% is set, Exim generates a warning message whenever it freezes +something, unless the message it is freezing is a +locally-generated +bounce message. (Without this exception there is the possibility of looping.) +The warning message is sent to the addresses supplied as the comma-separated +value of this option. If several of the message's addresses cause freezing, +only a single message is sent. +If the freezing was automatic, the reason(s) for freezing can be found in the +message log. If you configure freezing in a filter or ACL, you must arrange for +any logging that you require. + + +oindex:[%gecos_name%] +`..'= +%gecos_name%, Use: 'main', Type: 'string'!!, Default: 'unset' +=== + +cindex:[HP-UX] +cindex:[``gecos'' field, parsing] +Some operating systems, notably HP-UX, use the ``gecos'' field in the system +password file to hold other information in addition to users' real names. Exim +looks up this field for use when it is creating 'Sender:' or 'From:' headers. +If either %gecos_pattern% or %gecos_name% are unset, the contents of the +field are used unchanged, except that, if an ampersand is encountered, it is +replaced by the user's login name with the first character forced to +upper case, since this is a convention that is observed on many systems. + +When these options are set, %gecos_pattern% is treated as a regular expression +that is to be applied to the field (again with & replaced by the login name), +and if it matches, %gecos_name% is expanded and used as the user's name. + +cindex:[numerical variables ($1$ $2$ etc),in %gecos_name%] +Numeric variables such as $1$, $2$, etc. can be used in the expansion to +pick up sub-fields that were matched by the pattern. In HP-UX, where the user's +name terminates at the first comma, the following can be used: + + gecos_pattern = ([^,]*) + gecos_name = $1 + + + +oindex:[%gecos_pattern%] +`..'= +%gecos_pattern%, Use: 'main', Type: 'string', Default: 'unset' +=== + +See %gecos_name% above. + + +oindex:[%headers_charset%] +`..'= +%headers_charset%, Use: 'main', Type: 'string', Default: 'see below' +=== + +This option sets a default character set for translating from encoded MIME +``words'' in header lines, when referenced by an $h_xxx$ expansion item. The +default is the value of HEADERS_CHARSET in _Local/Makefile_. The +ultimate default is ISO-8859-1. For more details see the description of header +insertions in section <<SECTexpansionitems>>. + + + +oindex:[%header_maxsize%] +`..'= +%header_maxsize%, Use: 'main', Type: 'integer', Default: 'see below' +=== + +cindex:[header section,maximum size of] +cindex:[limit,size of message header section] +This option controls the overall maximum size of a message's header +section. The default is the value of HEADER_MAXSIZE in +_Local/Makefile_; the default for that is 1M. Messages with larger header +sections are rejected. + + +oindex:[%header_line_maxsize%] +`..'= +%header_line_maxsize%, Use: 'main', Type: 'integer', Default: '0' +=== + +cindex:[header lines,maximum size of] +cindex:[limit,size of one header line] +This option limits the length of any individual header line in a message, after +all the continuations have been joined together. Messages with individual +header lines that are longer than the limit are rejected. The default value of +zero means ``no limit''. + + + + +oindex:[%helo_accept_junk_hosts%] +`..'= +%helo_accept_junk_hosts%, Use: 'main', Type: 'host list'!!, Default: 'unset' +=== + +cindex:[HELO,accepting junk data] +cindex:[EHLO,accepting junk data] +Exim checks the syntax of HELO and EHLO commands for incoming SMTP +mail, and gives an error response for invalid data. Unfortunately, there are +some SMTP clients that send syntactic junk. They can be accommodated by setting +this option. Note that this is a syntax check only. See %helo_verify_hosts% +if you want to do semantic checking. +See also %helo_allow_chars% for a way of extending the permitted character +set. + + +oindex:[%helo_allow_chars%] +`..'= +%helo_allow_chars%, Use: 'main', Type: 'string', Default: 'unset' +=== + +cindex:[HELO,underscores in] +cindex:[EHLO,underscores in] +cindex:[underscore in EHLO/HELO] +This option can be set to a string of rogue characters that are permitted in +all EHLO and HELO names in addition to the standard letters, digits, +hyphens, and dots. If you really must allow underscores, you can set + + helo_allow_chars = _ + +Note that the value is one string, not a list. + + +oindex:[%helo_lookup_domains%] +`..'= +%helo_lookup_domains%, Use: 'main', Type: 'domain list'!!, Default: `@:@[]` +=== + +cindex:[HELO,forcing reverse lookup] +cindex:[EHLO,forcing reverse lookup] +If the domain given by a client in a HELO or EHLO command matches this +list, a reverse lookup is done in order to establish the host's true name. The +default forces a lookup if the client host gives the server's name or any of +its IP addresses (in brackets), something that broken clients have been seen to +do. + + +oindex:[%helo_try_verify_hosts%] +`..'= +%helo_try_verify_hosts%, Use: 'main', Type: 'host list'!!, Default: 'unset' +=== + +cindex:[HELO verifying, optional] +cindex:[EHLO verifying, optional] +The RFCs mandate that a server must not reject a message because it doesn't +like the HELO or EHLO command. By default, Exim just checks the syntax +of these commands (see %helo_accept_junk_hosts% and %helo_allow_chars% +above). However, some sites like to be stricter. If the calling host matches +%helo_try_verify_hosts%, Exim checks that the host name given in the HELO +or EHLO command either: + +- is an IP literal matching the calling address of the host (the RFCs +specifically allow this), or + +- cindex:[DNS,reverse lookup] +cindex:[reverse DNS lookup] +matches the host name that Exim obtains by doing a reverse lookup of the +calling host address, or + +- when looked up using 'gethostbyname()' (or 'getipnodebyname()' when +available) yields the calling host address. + +However, the EHLO or HELO command is not rejected if any of the checks +fail. Processing continues, but the result of the check is remembered, and can +be detected later in an ACL by the `verify = helo` condition. If you want +verification failure to cause rejection of EHLO or HELO, use +%helo_verify_hosts% instead. + + + +oindex:[%helo_verify_hosts%] +`..'= +%helo_verify_hosts%, Use: 'main', Type: 'host list'!!, Default: 'unset' +=== + +cindex:[HELO verifying, mandatory] +cindex:[EHLO verifying, mandatory] +For hosts that match this option, Exim checks the host name given in the +HELO or EHLO in the same way as for %helo_try_verify_hosts%. If the +check fails, the HELO or EHLO command is rejected with a 550 error, and +entries are written to the main and reject logs. If a MAIL command is +received before EHLO or HELO, it is rejected with a +503 +error. + + +oindex:[%hold_domains%] +`..'= +%hold_domains%, Use: 'main', Type: 'domain list'!!, Default: 'unset' +=== + +cindex:[domain,delaying delivery] +cindex:[delivery,delaying certain domains] +This option allows mail for particular domains to be held on the queue +manually. The option is overridden if a message delivery is forced with the +%-M%, %-qf%, %-Rf% or %-Sf% options, and also while testing or verifying +addresses using %-bt% or %-bv%. Otherwise, if a domain matches an item in +%hold_domains%, no routing or delivery for that address is done, and it is +deferred every time the message is looked at. + +This option is intended as a temporary operational measure for delaying the +delivery of mail while some problem is being sorted out, or some new +configuration tested. If you just want to delay the processing of some +domains until a queue run occurs, you should use %queue_domains% or +%queue_smtp_domains%, not %hold_domains%. + +A setting of %hold_domains% does not override Exim's code for removing +messages from the queue if they have been there longer than the longest retry +time in any retry rule. If you want to hold messages for longer than the normal +retry times, insert a dummy retry rule with a long retry time. + + +oindex:[%host_lookup%] +`..'= +%host_lookup%, Use: 'main', Type: 'host list'!!, Default: 'unset' +=== + +cindex:[host name lookup, forcing] +Exim does not look up the name of a calling host from its IP address unless it +is required to compare against some host list, or the host matches +%helo_try_verify_hosts% or %helo_verify_hosts%, or the host matches this +option (which normally contains IP addresses rather than host names). The +default configuration file contains + + host_lookup = * + +which causes a lookup to happen for all hosts. If the expense of these lookups +is felt to be too great, the setting can be changed or removed. + +After a successful reverse lookup, Exim does a forward lookup on the name it +has obtained, to verify that it yields the IP address that it started with. If +this check fails, Exim behaves as if the name lookup failed. + +After any kind of failure, the host name (in $sender_host_name$) remains +unset, and $host_lookup_failed$ is set to the string ``1''. See also +%dns_again_means_nonexist%, %helo_lookup_domains%, and `verify = +reverse_host_lookup` in ACLs. + + +oindex:[%host_lookup_order%] +`..'= +%host_lookup_order%, Use: 'main', Type: 'string list', Default: `bydns:byaddr` +=== + +This option specifies the order of different lookup methods when Exim is trying +to find a host name from an IP address. The default is to do a DNS lookup +first, and then to try a local lookup (using 'gethostbyaddr()' or equivalent) +if that fails. You can change the order of these lookups, or omit one entirely, +if you want. + +*Warning*: the ``byaddr'' method does not always yield aliases when there are +multiple PTR records in the DNS and the IP address is not listed in +_/etc/hosts_. Different operating systems give different results in this +case. That is why the default tries a DNS lookup first. + + + +oindex:[%host_reject_connection%] +`..'= +%host_reject_connection%, Use: 'main', Type: 'host list'!!, Default: 'unset' +=== + +cindex:[host,rejecting connections from] +If this option is set, incoming SMTP calls from the hosts listed are rejected +as soon as the connection is made. +This option is obsolete, and retained only for backward compatibility, because +nowadays the ACL specified by %acl_smtp_connect% can also reject incoming +connections immediately. + +The ability to give an immediate rejection (either by this option or using an +ACL) is provided for use in unusual cases. Many hosts will just try again, +sometimes without much delay. Normally, it is better to use an ACL to reject +incoming messages at a later stage, such as after RCPT commands. See +chapter <<CHAPACL>>. + + +oindex:[%hosts_connection_nolog%] +`..'= +%hosts_connection_nolog%, Use: 'main', Type: 'host list'!!, Default: 'unset' +=== + +cindex:[host,not logging connections from] +This option defines a list of hosts for which connection logging does not +happen, even though the %smtp_connection% log selector is set. For example, +you might want not to log SMTP connections from local processes, or from +127.0.0.1, or from your local LAN. This option is consulted in the main loop of +the daemon; you should therefore strive to restrict its value to a short inline +list of IP addresses and networks. To disable logging SMTP connections from +local processes, you must create a host list with an empty item. For example: + + hosts_connection_nolog = : + +If the %smtp_connection% log selector is not set, this option has no effect. + + + +oindex:[%hosts_treat_as_local%] +`..'= +%hosts_treat_as_local%, Use: 'main', Type: 'domain list'!!, Default: 'unset' +=== + +cindex:[local host,domains treated as] +cindex:[host,treated as local] +If this option is set, any host names that match the domain list are treated as +if they were the local host when Exim is scanning host lists obtained from MX +records +or other sources. Note that the value of this option is a domain list, not a +host list, because it is always used to check host names, not IP addresses. + +This option also applies when Exim is matching the special items +`@mx_any`, `@mx_primary`, and `@mx_secondary` in a domain list (see +section <<SECTdomainlist>>), and when checking the %hosts% option in the ^smtp^ +transport for the local host (see the %allow_localhost% option in that +transport). +See also %local_interfaces%, %extra_local_interfaces%, and chapter +<<CHAPinterfaces>>, which contains a discussion about local network interfaces +and recognising the local host. + + +oindex:[%ignore_bounce_errors_after%] +`..'= +%ignore_bounce_errors_after%, Use: 'main', Type: 'time', Default: '10w' +=== + +cindex:[bounce message,discarding] +cindex:[discarding bounce message] +This option affects the processing of bounce messages that cannot be delivered, +that is, those that suffer a permanent delivery failure. (Bounce messages that +suffer temporary delivery failures are of course retried in the usual way.) + +After a permanent delivery failure, bounce messages are frozen, +because there is no sender to whom they can be returned. When a frozen bounce +message has been on the queue for more than the given time, it is unfrozen at +the next queue run, and a further delivery is attempted. If delivery fails +again, the bounce message is discarded. This makes it possible to keep failed +bounce messages around for a shorter time than the normal maximum retry time +for frozen messages. For example, + + ignore_bounce_errors_after = 12h + +retries failed bounce message deliveries after 12 hours, discarding any further +failures. If the value of this option is set to a zero time period, bounce +failures are discarded immediately. Setting a very long time (as in the default +value) has the effect of disabling this option. For ways of automatically +dealing with other kinds of frozen message, see %auto_thaw% and +%timeout_frozen_after%. + + +oindex:[%ignore_fromline_hosts%] +`..'= +%ignore_fromline_hosts%, Use: 'main', Type: 'host list'!!, Default: 'unset' +=== + +cindex:[``From'' line] +cindex:[UUCP,``From'' line] +Some broken SMTP clients insist on sending a UUCP-like ``From'' line before the +headers of a message. By default this is treated as the start of the message's +body, which means that any following headers are not recognized as such. Exim +can be made to ignore it by setting %ignore_fromline_hosts% to match those +hosts that insist on sending it. If the sender is actually a local process +rather than a remote host, and is using %-bs% to inject the messages, +%ignore_fromline_local% must be set to achieve this effect. + + +oindex:[%ignore_fromline_local%] +`..'= +%ignore_fromline_local%, Use: 'main', Type: 'boolean', Default: 'false' +=== + +See %ignore_fromline_hosts% above. + + +oindex:[%keep_malformed%] +`..'= +%keep_malformed%, Use: 'main', Type: 'time', Default: '4d' +=== + +This option specifies the length of time to keep messages whose spool files +have been corrupted in some way. This should, of course, never happen. At the +next attempt to deliver such a message, it gets removed. The incident is +logged. + + +oindex:[%ldap_default_servers%] +`..'= +%ldap_default_servers%, Use: 'main', Type: 'string list', Default: 'unset' +=== + +cindex:[LDAP,default servers] +This option provides a list of LDAP servers which are tried in turn when an +LDAP query does not contain a server. See section <<SECTforldaque>> for details +of LDAP queries. This option is available only when Exim has been built with +LDAP support. + + +oindex:[%ldap_version%] +`..'= +%ldap_version%, Use: 'main', Type: 'integer', Default: 'unset' +=== + +cindex:[LDAP protocol version, forcing] +This option can be used to force Exim to set a specific protocol version for +LDAP. If it option is unset, it is shown by the %-bP% command line option as +-1. When this is the case, the default is 3 if LDAP_VERSION3 is defined in +the LDAP headers; otherwise it is 2. This option is available only when Exim +has been built with LDAP support. + + + +oindex:[%local_from_check%] +`..'= +%local_from_check%, Use: 'main', Type: 'boolean', Default: 'true' +=== + +cindex:['Sender:' header line,disabling addition of] +cindex:['From:' header line,disabling checking of] +When a message is submitted locally (that is, not over a TCP/IP connection) by +an untrusted user, Exim removes any existing 'Sender:' header line, and checks +that the 'From:' header line matches the login of the calling user and the +domain specified by %qualify_domain%. + +*Note*: An unqualified address (no domain) in the 'From:' header in a +locally submitted message is automatically qualified by Exim, unless the +%-bnq% command line option is used. + +You can use %local_from_prefix% and %local_from_suffix% to permit affixes +on the local part. If the 'From:' header line does not match, Exim adds a +'Sender:' header with an address constructed from the calling user's login and +the default qualify domain. + +If %local_from_check% is set false, the 'From:' header check is disabled, +and no 'Sender:' header is ever added. If, in addition, you want to retain +'Sender:' header lines supplied by untrusted users, you must also set +%local_sender_retain% to be true. + +cindex:[envelope sender] +These options affect only the header lines in the message. The envelope sender +is still forced to be the login id at the qualify domain unless +%untrusted_set_sender% permits the user to supply an envelope sender. + +For messages received over TCP/IP, an ACL can specify ``submission mode'' to +request similar header line checking. See section <<SECTthesenhea>>, which has +more details about 'Sender:' processing. + + + + +oindex:[%local_from_prefix%] +`..'= +%local_from_prefix%, Use: 'main', Type: 'string', Default: 'unset' +=== + +When Exim checks the 'From:' header line of locally submitted messages for +matching the login id (see %local_from_check% above), it can be configured to +ignore certain prefixes and suffixes in the local part of the address. This is +done by setting %local_from_prefix% and/or %local_from_suffix% to +appropriate lists, in the same form as the %local_part_prefix% and +%local_part_suffix% router options (see chapter <<CHAProutergeneric>>). For +example, if + + local_from_prefix = *- + +is set, a 'From:' line containing + + From: anything-user@your.domain.example + +will not cause a 'Sender:' header to be added if 'user@your.domain.example' +matches the actual sender address that is constructed from the login name and +qualify domain. + + +oindex:[%local_from_suffix%] +`..'= +%local_from_suffix%, Use: 'main', Type: 'string', Default: 'unset' +=== + +See %local_from_prefix% above. + + +oindex:[%local_interfaces%] +`..'= +%local_interfaces%, Use: 'main', Type: 'string list', Default: 'see below' +=== + +This option controls which network interfaces are used by the daemon for +listening; they are also used to identify the local host when routing. Chapter +<<CHAPinterfaces>> contains a full description of this option and the related +options + +%daemon_smtp_ports%, %extra_local_interfaces%, %hosts_treat_as_local%, +and %tls_on_connect_ports%. + +The default value for %local_interfaces% is + + local_interfaces = 0.0.0.0 + +when Exim is built without IPv6 support; otherwise it is + + local_interfaces = <; ::0 ; 0.0.0.0 + + + +oindex:[%local_scan_timeout%] +`..'= +%local_scan_timeout%, Use: 'main', Type: 'time', Default: '5m' +=== + +cindex:[timeout,for 'local_scan()' function] +cindex:['local_scan()' function,timeout] +This timeout applies to the 'local_scan()' function (see chapter +<<CHAPlocalscan>>). Zero means ``no timeout''. If the timeout is exceeded, the +incoming message is rejected with a temporary error if it is an SMTP message. +For a non-SMTP message, the message is dropped and Exim ends with a non-zero +code. The incident is logged on the main and reject logs. + + + +oindex:[%local_sender_retain%] +`..'= +%local_sender_retain%, Use: 'main', Type: 'boolean', Default: 'false' +=== + +cindex:['Sender:' header line,retaining from local submission] +When a message is submitted locally (that is, not over a TCP/IP connection) by +an untrusted user, Exim removes any existing 'Sender:' header line. If you +do not want this to happen, you must set %local_sender_retain%, and you must +also set %local_from_check% to be false (Exim will complain if you do not). +Section <<SECTthesenhea>> has more details about 'Sender:' processing. + + + + +oindex:[%localhost_number%] +`..'= +%localhost_number%, Use: 'main', Type: 'string'!!, Default: 'unset' +=== + +cindex:[host,locally unique number for] +cindex:[message ids, with multiple hosts] +Exim's message ids are normally unique only within the local host. If +uniqueness among a set of hosts is required, each host must set a different +value for the %localhost_number% option. The string is expanded immediately +after reading the configuration file (so that a number can be computed from the +host name, for example) and the result of the expansion must be a number in the +range 0--16 (or 0--10 on operating systems with case-insensitive file systems). +This is available in subsequent string expansions via the variable +$localhost_number$. When %localhost_number is set%, the final two +characters of the message id, instead of just being a fractional part of the +time, are computed from the time and the local host number as described in +section <<SECTmessiden>>. + + + +oindex:[%log_file_path%] +`..'= +%log_file_path%, Use: 'main', Type: 'string list'!!, Default: 'set at compile time' +=== + +cindex:[log,file path for] +This option sets the path which is used to determine the names of Exim's log +files, or indicates that logging is to be to syslog, or both. It is expanded +when Exim is entered, so it can, for example, contain a reference to the host +name. If no specific path is set for the log files at compile or run time, they +are written in a sub-directory called _log_ in Exim's spool directory. +Chapter <<CHAPlog>> contains further details about Exim's logging, and section +<<SECTwhelogwri>> describes how the contents of %log_file_path% are used. If +this string is fixed at your installation (contains no expansion variables) it +is recommended that you do not set this option in the configuration file, but +instead supply the path using LOG_FILE_PATH in _Local/Makefile_ so that +it is available to Exim for logging errors detected early on -- in particular, +failure to read the configuration file. + + +oindex:[%log_selector%] +`..'= +%log_selector%, Use: 'main', Type: 'string', Default: 'unset' +=== + +cindex:[log,selectors] +This option can be used to reduce or increase the number of things that Exim +writes to its log files. Its argument is made up of names preceded by plus or +minus characters. For example: + + log_selector = +arguments -retry_defer + +A list of possible names and what they control is given in the chapter on +logging, in section <<SECTlogselector>>. + + +oindex:[%log_timezone%] +`..'= +%log_timezone%, Use: 'main', Type: 'boolean', Default: 'false' +=== + +cindex:[log,timezone for entries] +By default, the timestamps on log lines are in local time without the +timezone. This means that if your timezone changes twice a year, the timestamps +in log lines are ambiguous for an hour when the clocks go back. One way of +avoiding this problem is to set the timezone to UTC. An alternative is to set +%log_timezone% true. This turns on the addition of the timezone offset to +timestamps in log lines. Turning on this option can add quite a lot to the size +of log files because each line is extended by 6 characters. Note that the +$tod_log$ variable contains the log timestamp without the zone, but there is +another variable called $tod_zone$ that contains just the timezone offset. + + +oindex:[%lookup_open_max%] +`..'= +%lookup_open_max%, Use: 'main', Type: 'integer', Default: '25' +=== + +cindex:[too many open files] +cindex:[open files, too many] +cindex:[file,too many open] +cindex:[lookup,maximum open files] +cindex:[limit,open files for lookups] +This option limits the number of simultaneously open files for single-key +lookups that use regular files (that is, ^lsearch^, ^dbm^, and ^cdb^). Exim +normally keeps these files open during routing, because often the same file is +required several times. If the limit is reached, Exim closes the least recently +used file. Note that if you are using the 'ndbm' library, it actually opens +two files for each logical DBM database, though it still counts as one for the +purposes of %lookup_open_max%. If you are getting ``too many open files'' +errors with NDBM, you need to reduce the value of %lookup_open_max%. + + +oindex:[%max_username_length%] +`..'= +%max_username_length%, Use: 'main', Type: 'integer', Default: '0' +=== + +cindex:[length of login name] +cindex:[user name,maximum length] +cindex:[limit,user name length] +Some operating systems are broken in that they truncate long arguments to +'getpwnam()' to eight characters, instead of returning ``no such user''. If +this option is set greater than zero, any attempt to call 'getpwnam()' with +an argument that is longer behaves as if 'getpwnam()' failed. + + + +oindex:[%message_body_visible%] +`..'= +%message_body_visible%, Use: 'main', Type: 'integer', Default: '500' +=== + +cindex:[body of message,visible size] +cindex:[message body, visible size] +This option specifies how much of a message's body is to be included in the +$message_body$ and $message_body_end$ expansion variables. + + +oindex:[%message_id_header_domain%] +`..'= +%message_id_header_domain%, Use: 'main', Type: 'string'!!, Default: 'unset' +=== + +cindex:['Message-ID:' header line] +If this option is set, the string is expanded and used as the right hand side +(domain) of the 'Message-ID:' header that Exim creates if a +locally-originated incoming message does not have one. ``Locally-originated'' +means ``not received over TCP/IP.'' +Otherwise, the primary host name is used. +Only letters, digits, dot and hyphen are accepted; any other characters are +replaced by hyphens. If the expansion is forced to fail, or if the result is an +empty string, the option is ignored. + + +oindex:[%message_id_header_text%] +`..'= +%message_id_header_text%, Use: 'main', Type: 'string'!!, Default: 'unset' +=== + +If this variable is set, the string is expanded and used to augment the text of +the 'Message-id:' header that Exim creates if a +locally-originated +incoming message does not have one. The text of this header is required by RFC +2822 to take the form of an address. By default, Exim uses its internal message +id as the local part, and the primary host name as the domain. If this option +is set, it is expanded, and provided the expansion is not forced to fail, and +does not yield an empty string, the result is inserted into the header +immediately before the @, separated from the internal message id by a dot. Any +characters that are illegal in an address are automatically converted into +hyphens. This means that variables such as $tod_log$ can be used, because +the spaces and colons will become hyphens. + + +oindex:[%message_logs%] +`..'= +%message_logs%, Use: 'main', Type: 'boolean', Default: 'true' +=== + +cindex:[message log, disabling] +cindex:[log,message log; disabling] +If this option is turned off, per-message log files are not created in the +_msglog_ spool sub-directory. This reduces the amount of disk I/O required by +Exim, by reducing the number of files involved in handling a message from a +minimum of four (header spool file, body spool file, delivery journal, and +per-message log) to three. The other major I/O activity is Exim's main log, +which is not affected by this option. + + +oindex:[%message_size_limit%] +`..'= +%message_size_limit%, Use: 'main', Type: 'string'!!, Default: '50M' +=== + +cindex:[message,size limit] +cindex:[limit,message size] +cindex:[size of message, limit] +This option limits the maximum size of message that Exim will process. The +value is expanded for each incoming +connection so, for example, it can be made to depend on the IP address of the +remote host for messages arriving via TCP/IP. *Note*: This limit cannot be +made to depend on a message's sender or any other properties of an individual +message, because it has to be advertised in the server's response to EHLO. +String expansion failure causes a temporary error. A value of zero means no +limit, but its use is not recommended. See also %bounce_return_size_limit%. + +Incoming SMTP messages are failed with a 552 error if the limit is +exceeded; locally-generated messages either get a stderr message or a delivery +failure message to the sender, depending on the %-oe% setting. Rejection of an +oversized message is logged in both the main and the reject logs. See also the +generic transport option %message_size_limit%, which limits the size of +message that an individual transport can process. + + +oindex:[%move_frozen_messages%] +`..'= +%move_frozen_messages%, Use: 'main', Type: 'boolean', Default: 'false' +=== + +cindex:[frozen messages,moving] +This option, which is available only if Exim has been built with the setting + + SUPPORT_MOVE_FROZEN_MESSAGES=yes + +in _Local/Makefile_, causes frozen messages and their message logs to be +moved from the _input_ and _msglog_ directories on the spool to _Finput_ +and _Fmsglog_, respectively. There is currently no support in Exim or the +standard utilities for handling such moved messages, and they do not show up in +lists generated by %-bp% or by the Exim monitor. + + +oindex:[%mua_wrapper%] +`..'= +%mua_wrapper%, Use: 'main', Type: 'boolean', Default: 'false' +=== + +Setting this option true causes Exim to run in a very restrictive mode in which +it passes messages synchronously to a smart host. Chapter <<CHAPnonqueueing>> +contains a full description of this facility. + + + +oindex:[%mysql_servers%] +`..'= +%mysql_servers%, Use: 'main', Type: 'string list', Default: 'unset' +=== + +cindex:[MySQL,server list] +This option provides a list of MySQL servers and associated connection data, to +be used in conjunction with ^mysql^ lookups (see section <<SECTsql>>). The +option is available only if Exim has been built with MySQL support. + + +oindex:[%never_users%] +`..'= +%never_users%, Use: 'main', Type: 'string list', Default: 'unset' +=== + +Local message deliveries are normally run in processes that are setuid to the +recipient, and remote deliveries are normally run under Exim's own uid and gid. +It is usually desirable to prevent any deliveries from running as root, as a +safety precaution. + +When Exim is built, an option called FIXED_NEVER_USERS can be set to a +list of users that must not be used for local deliveries. This list is fixed in +the binary and cannot be overridden by the configuration file. By default, it +contains just the single user name ``root''. The %never_users% runtime option +can be used to add more users to the fixed list. + +If a message is to be delivered as one of the users on the fixed list or the +%never_users% list, an error occurs, and delivery is deferred. A common +example is + + never_users = root:daemon:bin + +Including root is redundant if it is also on the fixed list, but it does no +harm. This option overrides the %pipe_as_creator% option of the ^pipe^ +transport driver. + + +oindex:[%oracle_servers%] +`..'= +%oracle_servers%, Use: 'main', Type: 'string list', Default: 'unset' +=== + +cindex:[Oracle,server list] +This option provides a list of Oracle servers and associated connection data, +to be used in conjunction with ^oracle^ lookups (see section <<SECTsql>>). The +option is available only if Exim has been built with Oracle support. + + +oindex:[%percent_hack_domains%] +`..'= +%percent_hack_domains%, Use: 'main', Type: 'domain list'!!, Default: 'unset' +=== + +cindex:[``percent hack''] +cindex:[source routing,in email address] +cindex:[address,source-routed] +The ``percent hack'' is the convention whereby a local part containing a percent +sign is re-interpreted as a new email address, with the percent replaced by @. +This is sometimes called ``source routing'', though that term is also applied to +RFC 2822 addresses that begin with an @ character. If this option is set, Exim +implements the percent facility for those domains listed, but no others. This +happens before an incoming SMTP address is tested against an ACL. + +*Warning*: The ``percent hack'' has often been abused by people who are +trying to get round relaying restrictions. For this reason, it is best avoided +if at all possible. Unfortunately, a number of less security-conscious MTAs +implement it unconditionally. If you are running Exim on a gateway host, and +routing mail through to internal MTAs without processing the local parts, it is +a good idea to reject recipient addresses with percent characters in their +local parts. Exim's default configuration does this. + + +oindex:[%perl_at_start%] +`..'= +%perl_at_start%, Use: 'main', Type: 'boolean', Default: 'false' +=== + +This option is available only when Exim is built with an embedded Perl +interpreter. See chapter <<CHAPperl>> for details of its use. + + +oindex:[%perl_startup%] +`..'= +%perl_startup%, Use: 'main', Type: 'string', Default: 'unset' +=== + +This option is available only when Exim is built with an embedded Perl +interpreter. See chapter <<CHAPperl>> for details of its use. + + +oindex:[%pgsql_servers%] +`..'= +%pgsql_servers%, Use: 'main', Type: 'string list', Default: 'unset' +=== + +cindex:[PostgreSQL lookup type,server list] +This option provides a list of PostgreSQL servers and associated connection +data, to be used in conjunction with ^pgsql^ lookups (see section <<SECTsql>>). +The option is available only if Exim has been built with PostgreSQL support. + + +oindex:[%pid_file_path%] +`..'= +%pid_file_path%, Use: 'main', Type: 'string'!!, Default: 'set at compile time' +=== + +cindex:[daemon,pid file path] +cindex:[pid file, path for] +This option sets the name of the file to which the Exim daemon writes its +process id. The string is expanded, so it can contain, for example, references +to the host name: + + pid_file_path = /var/log/$primary_hostname/exim.pid + +If no path is set, the pid is written to the file _exim-daemon.pid_ in Exim's +spool directory. +The value set by the option can be overridden by the %-oP% command line +option. A pid file is not written if a ``non-standard'' daemon is run by means of +the %-oX% option, unless a path is explicitly supplied by %-oP%. + + +oindex:[%pipelining_advertise_hosts%] +`..'= +%pipelining_advertise_hosts%, Use: 'main', Type: 'host list'!!, Default: '\*' +=== + +cindex:[PIPELINING advertising, suppressing] +This option can be used to suppress the advertisement of the SMTP +PIPELINING extension to specific hosts. When PIPELINING is not +advertised and %smtp_enforce_sync% is true, an Exim server enforces strict +synchronization for each SMTP command and response. +When PIPELINING is advertised, Exim assumes that clients will use it; ``out +of order'' commands that are ``expected'' do not count as protocol errors (see +%smtp_max_synprot_errors%). + + +oindex:[%preserve_message_logs%] +`..'= +%preserve_message_logs%, Use: 'main', Type: 'boolean', Default: 'false' +=== + +cindex:[message logs, preserving] +If this option is set, message log files are not deleted when messages are +completed. Instead, they are moved to a sub-directory of the spool directory +called _msglog.OLD_, where they remain available for statistical or debugging +purposes. This is a dangerous option to set on systems with any appreciable +volume of mail. Use with care! + + +oindex:[%primary_hostname%] +`..'= +%primary_hostname%, Use: 'main', Type: 'string', Default: 'see below' +=== + +cindex:[name,of local host] +cindex:[host,name of local] +cindex:[local host,name of] +This specifies the name of the current host. It is used in the default EHLO +or HELO command for outgoing SMTP messages (changeable via the %helo_data% +option in the ^smtp^ transport), +and as the default for %qualify_domain%. If it is not set, Exim calls +'uname()' to find it. If this fails, Exim panics and dies. If the name +returned by 'uname()' contains only one component, Exim passes it to +'gethostbyname()' (or 'getipnodebyname()' when available) in order to +obtain the fully qualified version. + +The value of $primary_hostname$ is also used by default in some SMTP +response messages from an Exim server. This can be changed dynamically by +setting %smtp_active_hostname%. + + +oindex:[%print_topbitchars%] +`..'= +%print_topbitchars%, Use: 'main', Type: 'boolean', Default: 'false' +=== + +cindex:[printing characters] +cindex:[8-bit characters] +By default, Exim considers only those characters whose codes lie in the range +32--126 to be printing characters. In a number of circumstances (for example, +when writing log entries) non-printing characters are converted into escape +sequences, primarily to avoid messing up the layout. If %print_topbitchars% is +set, code values of 128 and above are also considered to be printing +characters. + + +oindex:[%process_log_path%] +`..'= +%process_log_path%, Use: 'main', Type: 'string', Default: 'unset' +=== + +cindex:[process log path] +cindex:[log,process log] +cindex:['exiwhat'] +This option sets the name of the file to which an Exim process writes its +``process log'' when sent a USR1 signal. This is used by the 'exiwhat' utility +script. If this option is unset, the file called _exim-process.info_ in +Exim's spool directory is used. The ability to specify the name explicitly can +be useful in environments where two different Exims are running, using +different spool directories. + + +oindex:[%prod_requires_admin%] +`..'= +%prod_requires_admin%, Use: 'main', Type: 'boolean', Default: 'true' +=== + +cindex:[%-M% option] +cindex:[%-R% option] +cindex:[%-q% option] +The %-M%, %-R%, and %-q% command-line options require the caller to be an +admin user unless %prod_requires_admin% is set false. See also +%queue_list_requires_admin%. + + +oindex:[%qualify_domain%] +`..'= +%qualify_domain%, Use: 'main', Type: 'string', Default: 'see below' +=== + +cindex:[domain,for qualifying addresses] +cindex:[address,qualification] +This option specifies the domain name that is added to any envelope sender +addresses that do not have a domain qualification. It also applies to +recipient addresses if %qualify_recipient% is not set. + +Unqualified addresses are accepted by default only for locally-generated +messages. + +Qualification is also applied to addresses in header lines such as 'From:' and +'To:' for locally-generated messages, unless the %-bnq% command line option +is used. + + +Messages from external sources must always contain fully qualified addresses, +unless the sending host matches %sender_unqualified_hosts% or +%recipient_unqualified_hosts% (as appropriate), in which case incoming +addresses are qualified with %qualify_domain% or %qualify_recipient% as +necessary. Internally, Exim always works with fully qualified envelope +addresses. If %qualify_domain% is not set, it defaults to the +%primary_hostname% value. + + +oindex:[%qualify_recipient%] +`..'= +%qualify_recipient%, Use: 'main', Type: 'string', Default: 'see below' +=== + +This option allows you to specify a different domain for qualifying recipient +addresses to the one that is used for senders. See %qualify_domain% above. + + + +oindex:[%queue_domains%] +`..'= +%queue_domains%, Use: 'main', Type: 'domain list'!!, Default: 'unset' +=== + +cindex:[domain,specifying non-immediate delivery] +cindex:[queueing incoming messages] +cindex:[message,queueing certain domains] +This option lists domains for which immediate delivery is not required. +A delivery process is started whenever a message is received, but only those +domains that do not match are processed. All other deliveries wait until the +next queue run. See also %hold_domains% and %queue_smtp_domains%. + + +oindex:[%queue_list_requires_admin%] +`..'= +%queue_list_requires_admin%, Use: 'main', Type: 'boolean', Default: 'true' +=== + +cindex:[%-bp% option] +The %-bp% command-line option, which lists the messages that are on the queue, +requires the caller to be an admin user unless %queue_list_requires_admin% +is set false. See also %prod_requires_admin%. + + +oindex:[%queue_only%] +`..'= +%queue_only%, Use: 'main', Type: 'boolean', Default: 'false' +=== + +cindex:[queueing incoming messages] +cindex:[message,queueing unconditionally] +If %queue_only% is set, a delivery process is not automatically started +whenever a message is received. Instead, the message waits on the queue for the +next queue run. Even if %queue_only% is false, incoming messages may not get +delivered immediately when certain conditions (such as heavy load) occur. + +The %-odq% command line has the same effect as %queue_only%. The %-odb% and +%-odi% command line options override %queue_only% unless +%queue_only_override% is set false. See also %queue_only_file%, +%queue_only_load%, and %smtp_accept_queue%. + + +oindex:[%queue_only_file%] +`..'= +%queue_only_file%, Use: 'main', Type: 'string', Default: 'unset' +=== + +cindex:[queueing incoming messages] +cindex:[message,queueing by file existence] +This option can be set to a colon-separated list of absolute path names, each +one optionally preceded by ``smtp''. When Exim is receiving a message, +it tests for the existence of each listed path using a call to 'stat()'. For +each path that exists, the corresponding queuing option is set. +For paths with no prefix, %queue_only% is set; for paths prefixed by ``smtp'', +%queue_smtp_domains% is set to match all domains. So, for example, + + queue_only_file = smtp/some/file + +causes Exim to behave as if %queue_smtp_domains% were set to ``\*'' whenever +_/some/file_ exists. + + +oindex:[%queue_only_load%] +`..'= +%queue_only_load%, Use: 'main', Type: 'fixed-point', Default: 'unset' +=== + +cindex:[load average] +cindex:[queueing incoming messages] +cindex:[message,queueing by load] +If the system load average is higher than this value, incoming messages from +all sources are queued, and no automatic deliveries are started. If this +happens during local or remote SMTP input, all subsequent messages on the same +connection are queued. Deliveries will subsequently be performed by queue +runner processes. This option has no effect on ancient operating systems on +which Exim cannot determine the load average. See also +%deliver_queue_load_max% and %smtp_load_reserve%. + + +oindex:[%queue_only_override%] +`..'= +%queue_only_override%, Use: 'main', Type: 'boolean', Default: 'true' +=== + +cindex:[queueing incoming messages] +When this option is true, the %-od'x'% command line options override the +setting of %queue_only% or %queue_only_file% in the configuration file. If +%queue_only_override% is set false, the %-od'x'% options cannot be used to +override; they are accepted, but ignored. + + +oindex:[%queue_run_in_order%] +`..'= +%queue_run_in_order%, Use: 'main', Type: 'boolean', Default: 'false' +=== + +cindex:[queue runner,processing messages in order] +If this option is set, queue runs happen in order of message arrival instead of +in an arbitrary order. For this to happen, a complete list of the entire queue +must be set up before the deliveries start. When the queue is all held in a +single directory (the default), + +a single list is created for both the ordered and the non-ordered cases. +However, if %split_spool_directory% is set, a single list is not created when +%queue_run_in_order% is false. In this case, the sub-directories are +processed one at a time (in a random order), and this avoids setting up one +huge list for the whole queue. Thus, setting %queue_run_in_order% with +%split_spool_directory% may degrade performance when the queue is large, +because of the extra work in setting up the single, large list. In most +situations, %queue_run_in_order% should not be set. + + + +oindex:[%queue_run_max%] +`..'= +%queue_run_max%, Use: 'main', Type: 'integer', Default: '5' +=== + +cindex:[queue runner,maximum number of] +This controls the maximum number of queue runner processes that an Exim daemon +can run simultaneously. This does not mean that it starts them all at once, +but rather that if the maximum number are still running when the time comes to +start another one, it refrains from starting another one. This can happen with +very large queues and/or very sluggish deliveries. This option does not, +however, interlock with other processes, so additional queue runners can be +started by other means, or by killing and restarting the daemon. + + +oindex:[%queue_smtp_domains%] +`..'= +%queue_smtp_domains%, Use: 'main', Type: 'domain list'!!, Default: 'unset' +=== + +cindex:[queueing incoming messages] +cindex:[message,queueing remote deliveries] +When this option is set, a delivery process is started whenever a message is +received, routing is performed, and local deliveries take place. +However, if any SMTP deliveries are required for domains that match +%queue_smtp_domains%, they are not immediately delivered, but instead the +message waits on the queue for the next queue run. Since routing of the message +has taken place, Exim knows to which remote hosts it must be delivered, and so +when the queue run happens, multiple messages for the same host are delivered +over a single SMTP connection. The %-odqs% command line option causes all SMTP +deliveries to be queued in this way, and is equivalent to setting +%queue_smtp_domains% to ``\*''. See also %hold_domains% and %queue_domains%. + + +oindex:[%receive_timeout%] +`..'= +%receive_timeout%, Use: 'main', Type: 'time', Default: '0s' +=== + +cindex:[timeout,for non-SMTP input] +This option sets the timeout for accepting a non-SMTP message, that is, the +maximum time that Exim waits when reading a message on the standard input. If +the value is zero, it will wait for ever. This setting is overridden by the +%-or% command line option. The timeout for incoming SMTP messages is +controlled by %smtp_receive_timeout%. + +oindex:[%received_header_text%] +`..'= +%received_header_text%, Use: 'main', Type: 'string'!!, Default: 'see below' +=== + +cindex:[customizing, 'Received:' header] +cindex:['Received:' header line,customizing] +This string defines the contents of the 'Received:' message header that is +added to each message, except for the timestamp, which is automatically added +on at the end (preceded by a semicolon). The string is expanded each time it is +used. If the expansion yields an empty string, no 'Received:' header line is +added to the message. Otherwise, the string should start with the text +``Received:'' and conform to the RFC 2822 specification for 'Received:' header +lines. The default setting is: + +.... +received_header_text = Received: \ + ${if def:sender_rcvhost {from $sender_rcvhost\n\t}\ + {${if def:sender_ident {from $sender_ident }}\ + ${if def:sender_helo_name {(helo=$sender_helo_name)\n\t}}}}\ + by $primary_hostname \ + ${if def:received_protocol {with $received_protocol}} \ + ${if def:tls_cipher {($tls_cipher)\n\t}}\ + (Exim $version_number)\n\t\ + id $message_id\ + ${if def:received_for {\n\tfor $received_for}} +.... + +Note the use of quotes, to allow the sequences `\n` and `\t` to be used +for newlines and tabs, respectively. The reference to the TLS cipher is omitted +when Exim is built without TLS support. The use of conditional expansions +ensures that this works for both locally generated messages and messages +received from remote hosts, giving header lines such as the following: + + Received: from scrooge.carol.example ([192.168.12.25] ident=root) + by marley.carol.example with esmtp (Exim 4.00) + id 16IOWa-00019l-00 + for chas@dickens.example; Tue, 25 Dec 2001 14:43:44 +0000 + Received: by scrooge.carol.example with local (Exim 4.00) + id 16IOWW-000083-00; Tue, 25 Dec 2001 14:43:41 +0000 + +Until the body of the message has been received, the timestamp is the time when +the message started to be received. Once the body has arrived, and all policy +checks have taken place, the timestamp is updated to the time at which the +message was accepted. + + +oindex:[%received_headers_max%] +`..'= +%received_headers_max%, Use: 'main', Type: 'integer', Default: '30' +=== + +cindex:[loop,prevention] +cindex:[mail loop prevention] +cindex:['Received:' header line,counting] +When a message is to be delivered, the number of 'Received:' headers is +counted, and if it is greater than this parameter, a mail loop is assumed to +have occurred, the delivery is abandoned, and an error message is generated. +This applies to both local and remote deliveries. + + +oindex:[%recipient_unqualified_hosts%] +`..'= +%recipient_unqualified_hosts%, Use: 'main', Type: 'host list'!!, Default: 'unset' +=== + +cindex:[unqualified addresses] +cindex:[host,unqualified addresses from] +This option lists those hosts from which Exim is prepared to accept unqualified +recipient addresses in message envelopes. The addresses are made fully +qualified by the addition of the %qualify_recipient% value. This option also +affects message header lines. Exim does not reject unqualified recipient +addresses in headers, but it qualifies them only if the message came from a +host that matches %recipient_unqualified_hosts%, +or if the message was submitted locally (not using TCP/IP), and the %-bnq% +option was not set. + + +oindex:[%recipients_max%] +`..'= +%recipients_max%, Use: 'main', Type: 'integer', Default: '0' +=== + +cindex:[limit,number of recipients] +cindex:[recipient,maximum number] +If this option is set greater than zero, it specifies the maximum number of +original recipients for any message. Additional recipients that are generated +by aliasing or forwarding do not count. SMTP messages get a 452 response for +all recipients over the limit; earlier recipients are delivered as normal. +Non-SMTP messages with too many recipients are failed, and no deliveries are +done. + +cindex:[RCPT,maximum number of incoming] +Note that the RFCs specify that an SMTP server should accept at least 100 +RCPT commands in a single message. + + +oindex:[%recipients_max_reject%] +`..'= +%recipients_max_reject%, Use: 'main', Type: 'boolean', Default: 'false' +=== + +If this option is set true, Exim rejects SMTP messages containing too many +recipients by giving 552 errors to the surplus RCPT commands, and a 554 +error to the eventual DATA command. Otherwise (the default) it gives a 452 +error to the surplus RCPT commands and accepts the message on behalf of the +initial set of recipients. The remote server should then re-send the message +for the remaining recipients at a later time. + + +oindex:[%remote_max_parallel%] +`..'= +%remote_max_parallel%, Use: 'main', Type: 'integer', Default: '2' +=== + +cindex:[delivery,parallelism for remote] +This option controls parallel delivery of one message to a number of remote +hosts. If the value is less than 2, parallel delivery is disabled, and Exim +does all the remote deliveries for a message one by one. Otherwise, if a single +message has to be delivered to more than one remote host, or if several copies +have to be sent to the same remote host, up to %remote_max_parallel% +deliveries are done simultaneously. If more than %remote_max_parallel% +deliveries are required, the maximum number of processes are started, and as +each one finishes, another is begun. The order of starting processes is the +same as if sequential delivery were being done, and can be controlled by the +%remote_sort_domains% option. If parallel delivery takes place while running +with debugging turned on, the debugging output from each delivery process is +tagged with its process id. + +This option controls only the maximum number of parallel deliveries for one +message in one Exim delivery process. Because Exim has no central queue +manager, there is no way of controlling the total number of simultaneous +deliveries if the configuration allows a delivery attempt as soon as a message +is received. + +cindex:[number of deliveries] +cindex:[delivery,maximum number of] +If you want to control the total number of deliveries on the system, you +need to set the %queue_only% option. This ensures that all incoming messages +are added to the queue without starting a delivery process. Then set up an Exim +daemon to start queue runner processes at appropriate intervals (probably +fairly often, for example, every minute), and limit the total number of queue +runners by setting the %queue_run_max% parameter. Because each queue runner +delivers only one message at a time, the maximum number of deliveries that can +then take place at once is %queue_run_max% multiplied by +%remote_max_parallel%. + +If it is purely remote deliveries you want to control, use +%queue_smtp_domains% instead of %queue_only%. This has the added benefit of +doing the SMTP routing before queuing, so that several messages for the same +host will eventually get delivered down the same connection. + + +oindex:[%remote_sort_domains%] +`..'= +%remote_sort_domains%, Use: 'main', Type: 'domain list'!!, Default: 'unset' +=== + +cindex:[sorting remote deliveries] +cindex:[delivery,sorting remote] +When there are a number of remote deliveries for a message, they are sorted by +domain into the order given by this list. For example, + + remote_sort_domains = *.cam.ac.uk:*.uk + +would attempt to deliver to all addresses in the 'cam.ac.uk' domain first, then +to those in the %uk% domain, then to any others. + + +oindex:[%retry_data_expire%] +`..'= +%retry_data_expire%, Use: 'main', Type: 'time', Default: '7d' +=== + +cindex:[hints database,data expiry] +This option sets a ``use before'' time on retry information in Exim's hints +database. Any older retry data is ignored. This means that, for example, once a +host has not been tried for 7 days, Exim behaves as if it has no knowledge of +past failures. + + +oindex:[%retry_interval_max%] +`..'= +%retry_interval_max%, Use: 'main', Type: 'time', Default: '24h' +=== + +cindex:[retry,limit on interval] +cindex:[limit,on retry interval] +Chapter <<CHAPretry>> describes Exim's mechanisms for controlling the intervals +between delivery attempts for messages that cannot be delivered straight away. +This option sets an overall limit to the length of time between retries. + + +oindex:[%return_path_remove%] +`..'= +%return_path_remove%, Use: 'main', Type: 'boolean', Default: 'true' +=== + +cindex:['Return-path:' header line,removing] +RFC 2821, section 4.4, states that an SMTP server must insert a 'Return-path:' +header line into a message when it makes a ``final delivery''. The 'Return-path:' +header preserves the sender address as received in the MAIL command. This +description implies that this header should not be present in an incoming +message. If %return_path_remove% is true, any existing 'Return-path:' +headers are removed from messages at the time they are received. Exim's +transports have options for adding 'Return-path:' headers at the time of +delivery. They are normally used only for final local deliveries. + + +oindex:[%return_size_limit%] +`..'= +%return_size_limit%, Use: 'main', Type: 'integer', Default: '100K' +=== + +This option is an obsolete synonym for %bounce_return_size_limit%. + + +oindex:[%rfc1413_hosts%] +`..'= +%rfc1413_hosts%, Use: 'main', Type: 'host list'!!, Default: '\*' +=== + +cindex:[RFC 1413] +cindex:[host,for RFC 1413 calls] +RFC 1413 identification calls are made to any client host which matches an item +in the list. + + +oindex:[%rfc1413_query_timeout%] +`..'= +%rfc1413_query_timeout%, Use: 'main', Type: 'time', Default: '30s' +=== + +cindex:[RFC 1413,query timeout] +cindex:[timeout,for RFC 1413 call] +This sets the timeout on RFC 1413 identification calls. If it is set to zero, +no RFC 1413 calls are ever made. + + +oindex:[%sender_unqualified_hosts%] +`..'= +%sender_unqualified_hosts%, Use: 'main', Type: 'host list'!!, Default: 'unset' +=== + +cindex:[unqualified addresses] +cindex:[host,unqualified addresses from] +This option lists those hosts from which Exim is prepared to accept unqualified +sender addresses. The addresses are made fully qualified by the addition of +%qualify_domain%. This option also affects message header lines. Exim does not +reject unqualified addresses in headers that contain sender addresses, but it +qualifies them only if the message came from a host that matches +%sender_unqualified_hosts%, +or if the message was submitted locally (not using TCP/IP), and the %-bnq% +option was not set. + + +oindex:[%smtp_accept_keepalive%] +`..'= +%smtp_accept_keepalive%, Use: 'main', Type: 'boolean', Default: 'true' +=== + +cindex:[keepalive,on incoming connection] +This option controls the setting of the SO_KEEPALIVE option on incoming +TCP/IP socket connections. When set, it causes the kernel to probe idle +connections periodically, by sending packets with ``old'' sequence numbers. The +other end of the connection should send an acknowledgement if the connection is +still okay or a reset if the connection has been aborted. The reason for doing +this is that it has the beneficial effect of freeing up certain types of +connection that can get stuck when the remote host is disconnected without +tidying up the TCP/IP call properly. The keepalive mechanism takes several +hours to detect unreachable hosts. + + + +oindex:[%smtp_accept_max%] +`..'= +%smtp_accept_max%, Use: 'main', Type: 'integer', Default: '20' +=== + +cindex:[limit,incoming SMTP connections] +cindex:[SMTP,incoming connection count] +cindex:[inetd] +This option specifies the maximum number of simultaneous incoming SMTP calls +that Exim will accept. It applies only to the listening daemon; there is no +control (in Exim) when incoming SMTP is being handled by 'inetd'. If the value +is set to zero, no limit is applied. However, it is required to be non-zero if +either %smtp_accept_max_per_host% or %smtp_accept_queue% is set. See also +%smtp_accept_reserve%. + + + +oindex:[%smtp_accept_max_nonmail%] +`..'= +%smtp_accept_max_nonmail%, Use: 'main', Type: 'integer', Default: '10' +=== + +cindex:[limit,non-mail SMTP commands] +cindex:[SMTP,limiting non-mail commands] +Exim counts the number of ``non-mail'' commands in an SMTP session, and drops the +connection if there are too many. This option defines ``too many''. The check +catches some denial-of-service attacks, repeated failing AUTHs, or a mad +client looping sending EHLO, for example. The check is applied only if the +client host matches %smtp_accept_max_nonmail_hosts%. + +When a new message is expected, one occurrence of RSET is not counted. This +allows a client to send one RSET between messages (this is not necessary, +but some clients do it). Exim also allows one uncounted occurence of HELO +or EHLO, and one occurrence of STARTTLS between messages. After +starting up a TLS session, another EHLO is expected, and so it too is not +counted. The first occurrence of AUTH in a connection, or immediately +following STARTTLS is not counted. Otherwise, all commands other than +MAIL, RCPT, DATA, and QUIT are counted. + + +oindex:[%smtp_accept_max_nonmail_hosts%] +`..'= +%smtp_accept_max_nonmail_hosts%, Use: 'main', Type: 'host list'!!, Default: '\*' +=== + +You can control which hosts are subject to the %smtp_accept_max_nonmail% +check by setting this option. The default value makes it apply to all hosts. By +changing the value, you can exclude any badly-behaved hosts that you have to +live with. + + + +oindex:[%smtp_accept_max_per_connection%] +`..'= +%smtp_accept_max_per_connection%, Use: 'main', Type: 'integer', Default: '1000' +=== + +cindex:[SMTP incoming message count, limiting] +cindex:[limit,messages per SMTP connection] +The value of this option limits the number of MAIL commands that Exim is +prepared to accept over a single SMTP connection, whether or not each command +results in the transfer of a message. After the limit is reached, a 421 +response is given to subsequent MAIL commands. This limit is a safety +precaution against a client that goes mad (incidents of this type have been +seen). + + +oindex:[%smtp_accept_max_per_host%] +`..'= +%smtp_accept_max_per_host%, Use: 'main', Type: 'string'!!, Default: 'unset' +=== + +cindex:[limit,SMTP connections from one host] +cindex:[host,limiting SMTP connections from] +This option restricts the number of simultaneous IP connections from a single +host (strictly, from a single IP address) to the Exim daemon. The option is +expanded, to enable different limits to be applied to different hosts by +reference to $sender_host_address$. Once the limit is reached, additional +connection attempts from the same host are rejected with error code 421. The +default value of zero imposes no limit. If this option is set, it is required +that %smtp_accept_max% be non-zero. + +*Warning*: When setting this option you should not use any expansion +constructions that take an appreciable amount of time. The expansion and test +happen in the main daemon loop, in order to reject additional connections +without forking additional processes (otherwise a denial-of-service attack +could cause a vast number or processes to be created). While the daemon is +doing this processing, it cannot accept any other incoming connections. + + + +oindex:[%smtp_accept_queue%] +`..'= +%smtp_accept_queue%, Use: 'main', Type: 'integer', Default: '0' +=== + +cindex:[SMTP,incoming connection count] +cindex:[queueing incoming messages] +cindex:[message,queueing by SMTP connection count] +If the number of simultaneous incoming SMTP calls handled via the listening +daemon exceeds this value, messages received by SMTP are just placed on the +queue; no delivery processes are started automatically. A value of zero implies +no limit, and clearly any non-zero value is useful only if it is less than the +%smtp_accept_max% value (unless that is zero). See also %queue_only%, +%queue_only_load%, %queue_smtp_domains%, and the various %-od% command +line options. + + +oindex:[%smtp_accept_queue_per_connection%] +`..'= +%smtp_accept_queue_per_connection%, Use: 'main', Type: 'integer', Default: '10' +=== + +cindex:[queueing incoming messages] +cindex:[message,queueing by message count] +This option limits the number of delivery processes that Exim starts +automatically when receiving messages via SMTP, whether via the daemon or by +the use of %-bs% or %-bS%. If the value of the option is greater than zero, +and the number of messages received in a single SMTP session exceeds this +number, subsequent messages are placed on the queue, but no delivery processes +are started. This helps to limit the number of Exim processes when a server +restarts after downtime and there is a lot of mail waiting for it on other +systems. On large systems, the default should probably be increased, and on +dial-in client systems it should probably be set to zero (that is, disabled). + + +oindex:[%smtp_accept_reserve%] +`..'= +%smtp_accept_reserve%, Use: 'main', Type: 'integer', Default: '0' +=== + +cindex:[SMTP,incoming call count] +cindex:[host,reserved] +When %smtp_accept_max% is set greater than zero, this option specifies a +number of SMTP connections that are reserved for connections from the hosts +that are specified in %smtp_reserve_hosts%. The value set in +%smtp_accept_max% includes this reserve pool. The specified hosts are not +restricted to this number of connections; the option specifies a minimum number +of connection slots for them, not a maximum. It is a guarantee that that group +of hosts can always get at least %smtp_accept_reserve% connections. + +For example, if %smtp_accept_max% is set to 50 and %smtp_accept_reserve% is +set to 5, once there are 45 active connections (from any hosts), new +connections are accepted only from hosts listed in %smtp_reserve_hosts%. +See also %smtp_accept_max_per_host%. + + +oindex:[%smtp_active_hostname%] +`..'= +%smtp_active_hostname%, Use: 'main', Type: 'string'!!, Default: 'unset' +=== + +cindex:[host,name in SMTP responses] +cindex:[SMTP,host name in responses] +This option is provided for multi-homed servers that want to masquerade as +several different hosts. At the start of an SMTP connection, its value is +expanded and used instead of the value of $primary_hostname$ in SMTP +responses. For example, it is used as domain name in the response to an +incoming HELO or EHLO command. + +It is also used in HELO commands for callout verification. +The active hostname is placed in the $smtp_active_hostname$ variable, which +is saved with any messages that are received. It is therefore available for use +in routers and transports when the message is later delivered. + + +If this option is unset, or if its expansion is forced to fail, or if the +expansion results in an empty string, the value of $primary_hostname$ is +used. Other expansion failures cause a message to be written to the main and +panic logs, and the SMTP command receives a temporary error. Typically, the +value of %smtp_active_hostname% depends on the incoming interface address. +For example: + +.... +smtp_active_hostname = ${if eq{$interface_address}{10.0.0.1}\ + {cox.mydomain}{box.mydomain}} +.... + + +oindex:[%smtp_banner%] +`..'= +%smtp_banner%, Use: 'main', Type: 'string'!!, Default: 'see below' +=== + +cindex:[SMTP,welcome banner] +cindex:[banner for SMTP] +cindex:[welcome banner for SMTP] +cindex:[customizing,SMTP banner] +This string, which is expanded every time it is used, is output as the initial +positive response to an SMTP connection. The default setting is: + +.... +smtp_banner = $smtp_active_hostname ESMTP Exim \ + $version_number $tod_full +.... + +Failure to expand the string causes a panic error. If you want to create a +multiline response to the initial SMTP connection, use ``\n'' in the string at +appropriate points, but not at the end. Note that the 220 code is not included +in this string. Exim adds it automatically (several times in the case of a +multiline response). + + +oindex:[%smtp_check_spool_space%] +`..'= +%smtp_check_spool_space%, Use: 'main', Type: 'boolean', Default: 'true' +=== + +cindex:[checking disk space] +cindex:[disk space, checking] +cindex:[spool directory,checking space] +When this option is set, if an incoming SMTP session encounters the SIZE +option on a MAIL command, it checks that there is enough space in the +spool directory's partition to accept a message of that size, while still +leaving free the amount specified by %check_spool_space% (even if that value +is zero). If there isn't enough space, a temporary error code is returned. + + +oindex:[%smtp_connect_backlog%] +`..'= +%smtp_connect_backlog%, Use: 'main', Type: 'integer', Default: '20' +=== + +cindex:[connection backlog] +cindex:[SMTP,connection backlog] +cindex:[backlog of connections] +This option specifies a maximum number of waiting SMTP connections. Exim passes +this value to the TCP/IP system when it sets up its listener. Once this number +of connections are waiting for the daemon's attention, subsequent connection +attempts are refused at the TCP/IP level. At least, that is what the manuals +say; in some circumstances such connection attempts have been observed to time +out instead. For large systems it is probably a good idea to increase the +value (to 50, say). It also gives some protection against denial-of-service +attacks by SYN flooding. + + +oindex:[%smtp_enforce_sync%] +`..'= +%smtp_enforce_sync%, Use: 'main', Type: 'boolean', Default: 'true' +=== + +cindex:[SMTP,synchronization checking] +cindex:[synchronization checking in SMTP] +The SMTP protocol specification requires the client to wait for a response from +the server at certain points in the dialogue. Without PIPELINING these +synchronization points are after every command; with PIPELINING they are +fewer, but they still exist. + +Some spamming sites send out a complete set of SMTP commands without waiting +for any response. Exim protects against this by rejecting a message if the +client has sent further input when it should not have. The error response ``554 +SMTP synchronization error'' is sent, and the connection is dropped. Testing for +this error cannot be perfect because of transmission delays (unexpected input +may be on its way but not yet received when Exim checks). However, it does +detect many instances. + +The check can be globally disabled by setting %smtp_enforce_sync% false. +If you want to disable the check selectively (for example, only for certain +hosts), you can do so by an appropriate use of a %control% modifier in an ACL +(see section <<SECTcontrols>>). See also %pipelining_advertise_hosts%. + + + +oindex:[%smtp_etrn_command%] +`..'= +%smtp_etrn_command%, Use: 'main', Type: 'string'!!, Default: 'unset' +=== + +cindex:[ETRN,command to be run] +If this option is set, the given command is run whenever an SMTP ETRN +command is received from a host that is permitted to issue such commands (see +chapter <<CHAPACL>>). The string is split up into separate arguments which are +independently expanded. The expansion variable $domain$ is set to the +argument of the ETRN command, and no syntax checking is done on it. For +example: + + smtp_etrn_command = /etc/etrn_command $domain $sender_host_address + +A new process is created to run the command, but Exim does not wait for it to +complete. Consequently, its status cannot be checked. If the command cannot be +run, a line is written to the panic log, but the ETRN caller still receives +a 250 success response. Exim is normally running under its own uid when +receiving SMTP, so it is not possible for it to change the uid before running +the command. + + +oindex:[%smtp_etrn_serialize%] +`..'= +%smtp_etrn_serialize%, Use: 'main', Type: 'boolean', Default: 'true' +=== + +cindex:[ETRN,serializing] +When this option is set, it prevents the simultaneous execution of more than +one identical command as a result of ETRN in an SMTP connection. See +section <<SECTETRN>> for details. + + +oindex:[%smtp_load_reserve%] +`..'= +%smtp_load_reserve%, Use: 'main', Type: 'fixed-point', Default: 'unset' +=== + +cindex:[load average] +If the system load average ever gets higher than this, incoming SMTP calls are +accepted only from those hosts that match an entry in %smtp_reserve_hosts%. +If %smtp_reserve_hosts% is not set, no incoming SMTP calls are accepted when +the load is over the limit. The option has no effect on ancient operating +systems on which Exim cannot determine the load average. See also +%deliver_queue_load_max% and %queue_only_load%. + + + +oindex:[%smtp_max_synprot_errors%] +`..'= +%smtp_max_synprot_errors%, Use: 'main', Type: 'integer', Default: '3' +=== + +cindex:[SMTP,limiting syntax and protocol errors] +cindex:[limit,SMTP syntax and protocol errors] +Exim rejects SMTP commands that contain syntax or protocol errors. In +particular, a syntactically invalid email address, as in this command: + + RCPT TO:<abc xyz@a.b.c> + +causes immediate rejection of the command, before any other tests are done. +(The ACL cannot be run if there is no valid address to set up for it.) An +example of a protocol error is receiving RCPT before MAIL. If there are +too many syntax or protocol errors in one SMTP session, the connection is +dropped. The limit is set by this option. + +cindex:[PIPELINING,expected errors] +When the PIPELINING extension to SMTP is in use, some protocol errors are +``expected'', for instance, a RCPT command after a rejected MAIL command. +Exim assumes that PIPELINING will be used if it advertises it (see +%pipelining_advertise_hosts%), and in this situation, ``expected'' errors do +not count towards the limit. + + + +oindex:[%smtp_max_unknown_commands%] +`..'= +%smtp_max_unknown_commands%, Use: 'main', Type: 'integer', Default: '3' +=== + +cindex:[SMTP,limiting unknown commands] +cindex:[limit,unknown SMTP commands] +If there are too many unrecognized commands in an incoming SMTP session, an +Exim server drops the connection. This is a defence against some kinds of abuse +that subvert web +clients +into making connections to SMTP ports; in these circumstances, a number of +non-SMTP command lines are sent first. + + + +oindex:[%smtp_ratelimit_hosts%] +`..'= +%smtp_ratelimit_hosts%, Use: 'main', Type: 'host list'!!, Default: 'unset' +=== + +cindex:[SMTP,rate limiting] +cindex:[limit,rate of message arrival] +cindex:[RCPT,rate limiting] +Some sites find it helpful to be able to limit the rate at which certain hosts +can send them messages, and the rate at which an individual message can specify +recipients. When a host matches %smtp_ratelimit_hosts%, the values of +%smtp_ratelimit_mail% and %smtp_ratelimit_rcpt% are used to control the +rate of acceptance of MAIL and RCPT commands in a single SMTP session, +respectively. Each option, if set, must contain a set of four comma-separated +values: + +- A threshold, before which there is no rate limiting. + +- An initial time delay. Unlike other times in Exim, numbers with decimal +fractional parts are allowed here. + +- A factor by which to increase the delay each time. + +- A maximum value for the delay. This should normally be less than 5 minutes, +because after that time, the client is liable to timeout the SMTP command. + +For example, these settings have been used successfully at the site which +first suggested this feature, for controlling mail from their customers: + + smtp_ratelimit_mail = 2,0.5s,1.05,4m + smtp_ratelimit_rcpt = 4,0.25s,1.015,4m + +The first setting specifies delays that are applied to MAIL commands after +two have been received over a single connection. The initial delay is 0.5 +seconds, increasing by a factor of 1.05 each time. The second setting applies +delays to RCPT commands when more than four occur in a single message. + +It is also possible to configure delays explicitly in ACLs. See section +<<SECTACLmodi>> for details. + + + +oindex:[%smtp_ratelimit_mail%] +`..'= +%smtp_ratelimit_mail%, Use: 'main', Type: 'string', Default: 'unset' +=== + +See %smtp_ratelimit_hosts% above. + + +oindex:[%smtp_ratelimit_rcpt%] +`..'= +%smtp_ratelimit_rcpt%, Use: 'main', Type: 'string', Default: 'unset' +=== + +See %smtp_ratelimit_hosts% above. + + +oindex:[%smtp_receive_timeout%] +`..'= +%smtp_receive_timeout%, Use: 'main', Type: 'time', Default: '5m' +=== + +cindex:[timeout,for SMTP input] +cindex:[SMTP timeout, input] +This sets a timeout value for SMTP reception. It applies to all forms of SMTP +input, including batch SMTP. If a line of input (either an SMTP command or a +data line) is not received within this time, the SMTP connection is dropped and +the message is abandoned. +A line is written to the log containing one of the following messages: + + SMTP command timeout on connection from... + SMTP data timeout on connection from... + +The former means that Exim was expecting to read an SMTP command; the latter +means that it was in the DATA phase, reading the contents of a message. + + +cindex:[%-os% option] +The value set by this option can be overridden by the +%-os% command-line option. A setting of zero time disables the timeout, but +this should never be used for SMTP over TCP/IP. (It can be useful in some cases +of local input using %-bs% or %-bS%.) For non-SMTP input, the reception +timeout is controlled by %receive_timeout% and %-or%. + + +oindex:[%smtp_reserve_hosts%] +`..'= +%smtp_reserve_hosts%, Use: 'main', Type: 'host list'!!, Default: 'unset' +=== + +This option defines hosts for which SMTP connections are reserved; see +%smtp_accept_reserve% and %smtp_load_reserve% above. + + +oindex:[%smtp_return_error_details%] +`..'= +%smtp_return_error_details%, Use: 'main', Type: 'boolean', Default: 'false' +=== + +cindex:[SMTP,details policy failures] +cindex:[policy control rejection, returning details] +In the default state, Exim uses bland messages such as +``Administrative prohibition'' when it rejects SMTP commands for policy +reasons. Many sysadmins like this because it gives away little information +to spammers. However, some other syadmins who are applying strict checking +policies want to give out much fuller information about failures. Setting +%smtp_return_error_details% true causes Exim to be more forthcoming. For +example, instead of ``Administrative prohibition'', it might give: + + 550-Rejected after DATA: '>' missing at end of address: + 550 failing address in "From" header is: <user@dom.ain + + + +oindex:[%spamd_address%] +`..'= +%spamd_address%, Use: 'main', Type: 'string', Default: `127.0.0.1 783` +=== + +This option is available when Exim is compiled with the content-scanning +extension. It specifies how Exim connects to SpamAssassin's %spamd% daemon. See +section <<SECTscanspamass>> for more details. + + + +oindex:[%split_spool_directory%] +`..'= +%split_spool_directory%, Use: 'main', Type: 'boolean', Default: 'false' +=== + +cindex:[multiple spool directories] +cindex:[spool directory,split] +cindex:[directories, multiple] +If this option is set, it causes Exim to split its input directory into 62 +subdirectories, each with a single alphanumeric character as its name. The +sixth character of the message id is used to allocate messages to +subdirectories; this is the least significant base-62 digit of the time of +arrival of the message. + +Splitting up the spool in this way may provide better performance on systems +where there are long mail queues, by reducing the number of files in any one +directory. The msglog directory is also split up in a similar way to the input +directory; however, if %preserve_message_logs% is set, all old msglog files +are still placed in the single directory _msglog.OLD_. + +It is not necessary to take any special action for existing messages when +changing %split_spool_directory%. Exim notices messages that are in the +``wrong'' place, and continues to process them. If the option is turned off after +a period of being on, the subdirectories will eventually empty and be +automatically deleted. + +When %split_spool_directory% is set, the behaviour of queue runner processes +changes. Instead of creating a list of all messages in the queue, and then +trying to deliver each one in turn, it constructs a list of those in one +sub-directory and tries to deliver them, before moving on to the next +sub-directory. The sub-directories are processed in a random order. This +spreads out the scanning of the input directories, and uses less memory. It is +particularly beneficial when there are lots of messages on the queue. However, +if %queue_run_in_order% is set, none of this new processing happens. The +entire queue has to be scanned and sorted before any deliveries can start. + + +oindex:[%spool_directory%] +`..'= +%spool_directory%, Use: 'main', Type: 'string'!!, Default: 'set at compile time' +=== + +cindex:[spool directory,path to] +This defines the directory in which Exim keeps its spool, that is, the messages +it is waiting to deliver. The default value is taken from the compile-time +configuration setting, if there is one. If not, this option must be set. The +string is expanded, so it can contain, for example, a reference to +$primary_hostname$. + +If the spool directory name is fixed on your installation, it is recommended +that you set it at build time rather than from this option, particularly if the +log files are being written to the spool directory (see %log_file_path%). +Otherwise log files cannot be used for errors that are detected early on, such +as failures in the configuration file. + +By using this option to override the compiled-in path, it is possible to run +tests of Exim without using the standard spool. + + +oindex:[%strip_excess_angle_brackets%] +`..'= +%strip_excess_angle_brackets%, Use: 'main', Type: 'boolean', Default: 'false' +=== + +cindex:[angle brackets, excess] +If this option is set, redundant pairs of angle brackets round ``route-addr'' +items in addresses are stripped. For example, `\<\<xxx@a.b.c.d\>\>` is treated +as `<xxx@a.b.c.d>`. If this is in the envelope and the message is passed on +to another MTA, the excess angle brackets are not passed on. If this option is +not set, multiple pairs of angle brackets cause a syntax error. + + +oindex:[%strip_trailing_dot%] +`..'= +%strip_trailing_dot%, Use: 'main', Type: 'boolean', Default: 'false' +=== + +cindex:[trailing dot on domain] +cindex:[dot,trailing on domain] +If this option is set, a trailing dot at the end of a domain in an address is +ignored. If this is in the envelope and the message is passed on to another +MTA, the dot is not passed on. If this option is not set, a dot at the end of a +domain causes a syntax error. +However, addresses in header lines are checked only when an ACL requests header +syntax checking. + + +oindex:[%syslog_duplication%] +`..'= +%syslog_duplication%, Use: 'main', Type: 'boolean', Default: 'true' +=== + +cindex:[syslog,duplicate log lines; suppressing] +When Exim is logging to syslog, it writes the log lines for its three +separate logs at different syslog priorities so that they can in principle +be separated on the logging hosts. Some installations do not require this +separation, and in those cases, the duplication of certain log lines is a +nuisance. If %syslog_duplication% is set false, only one copy of any +particular log line is written to syslog. For lines that normally go to +both the main log and the reject log, the reject log version (possibly +containing message header lines) is written, at LOG_NOTICE priority. +Lines that normally go to both the main and the panic log are written at +the LOG_ALERT priority. + + +oindex:[%syslog_facility%] +`..'= +%syslog_facility%, Use: 'main', Type: 'string', Default: 'unset' +=== + +cindex:[syslog,facility; setting] +This option sets the syslog ``facility'' name, used when Exim is logging to +syslog. The value must be one of the strings ``mail'', ``user'', ``news'', ``uucp'', +``daemon'', or ``local'x'##'' where 'x' is a digit between 0 and 7. If this +option is unset, ``mail'' is used. See chapter <<CHAPlog>> for details of Exim's +logging. + + + +oindex:[%syslog_processname%] +`..'= +%syslog_processname%, Use: 'main', Type: 'string', Default: `exim` +=== + +cindex:[syslog,process name; setting] +This option sets the syslog ``ident'' name, used when Exim is logging to syslog. +The value must be no longer than 32 characters. See chapter <<CHAPlog>> for +details of Exim's logging. + + + +oindex:[%syslog_timestamp%] +`..'= +%syslog_timestamp%, Use: 'main', Type: 'boolean', Default: 'true' +=== + +cindex:[syslog,timestamps] +If %syslog_timestamp% is set false, the timestamps on Exim's log lines are +omitted when these lines are sent to syslog. See chapter <<CHAPlog>> for +details of Exim's logging. + + +oindex:[%system_filter%] +`..'= +%system_filter%, Use: 'main', Type: 'string'!!, Default: 'unset' +=== + +cindex:[filter,system filter] +cindex:[system filter,specifying] +cindex:[Sieve filter,not available for system filter] +This option specifies an Exim filter file that is applied to all messages at +the start of each delivery attempt, before any routing is done. System filters +must be Exim filters; they cannot be Sieve filters. If the system filter +generates any deliveries to files or pipes, or any new mail messages, the +appropriate %system_filter_..._transport% option(s) must be set, to define +which transports are to be used. Details of this facility are given in chapter +<<CHAPsystemfilter>>. + + +oindex:[%system_filter_directory_transport%] +`..'= +%system_filter_directory_transport%, Use: 'main', Type: 'string'!!, Default: 'unset' +=== + +This sets the name of the transport driver that is to be used when the +%save% command in a system message filter specifies a path ending in ``/'', +implying delivery of each message into a separate file in some directory. +During the delivery, the variable $address_file$ contains the path name. + + +oindex:[%system_filter_file_transport%] +`..'= +%system_filter_file_transport%, Use: 'main', Type: 'string'!!, Default: 'unset' +=== + +cindex:[file,transport for system filter] +This sets the name of the transport driver that is to be used when the %save% +command in a system message filter specifies a path not ending in ``/''. During +the delivery, the variable $address_file$ contains the path name. + +oindex:[%system_filter_group%] +`..'= +%system_filter_group%, Use: 'main', Type: 'string', Default: 'unset' +=== + +cindex:[gid (group id),system filter] +This option is used only when %system_filter_user% is also set. It sets the +gid under which the system filter is run, overriding any gid that is associated +with the user. The value may be numerical or symbolic. + +oindex:[%system_filter_pipe_transport%] +`..'= +%system_filter_pipe_transport%, Use: 'main', Type: 'string'!!, Default: 'unset' +=== + +cindex:[^pipe^ transport,for system filter] +This specifies the transport driver that is to be used when a %pipe% command is +used in a system filter. During the delivery, the variable $address_pipe$ +contains the pipe command. + + +oindex:[%system_filter_reply_transport%] +`..'= +%system_filter_reply_transport%, Use: 'main', Type: 'string'!!, Default: 'unset' +=== + +cindex:[^autoreply^ transport,for system filter] +This specifies the transport driver that is to be used when a %mail% command is +used in a system filter. + +oindex:[%system_filter_user%] +`..'= +%system_filter_user%, Use: 'main', Type: 'string', Default: 'unset' +=== + +cindex:[uid (user id),system filter] +If this option is not set, the system filter is run in the main Exim delivery +process, as root. When the option is set, the system filter runs in a separate +process, as the given user. Unless the string consists entirely of digits, it +is looked up in the password data. Failure to find the named user causes a +configuration error. The gid is either taken from the password data, or +specified by %system_filter_group%. When the uid is specified numerically, +%system_filter_group% is required to be set. + +If the system filter generates any pipe, file, or reply deliveries, the uid +under which the filter is run is used when transporting them, unless a +transport option overrides. Normally you should set %system_filter_user% if +your system filter generates these kinds of delivery. + + +oindex:[%tcp_nodelay%] +`..'= +%tcp_nodelay%, Use: 'main', Type: 'boolean', Default: 'true' +=== + +cindex:[daemon,TCP_NODELAY on sockets] +cindex:[Nagle algorithm] +cindex:[TCP_NODELAY on listening sockets] +If this option is set false, it stops the Exim daemon setting the +TCP_NODELAY option on its listening sockets. Setting TCP_NODELAY +turns off the ``Nagle algorithm'', which is a way of improving network +performance in interactive (character-by-character) situations. Turning it off +should improve Exim's performance a bit, so that is what happens by default. +However, it appears that some broken clients cannot cope, and time out. Hence +this option. It affects only those sockets that are set up for listening by the +daemon. Sockets created by the smtp transport for delivering mail always set +TCP_NODELAY. + + +oindex:[%timeout_frozen_after%] +`..'= +%timeout_frozen_after%, Use: 'main', Type: 'time', Default: '0s' +=== + +cindex:[frozen messages,timing out] +cindex:[timeout,frozen messages] +If %timeout_frozen_after% is set to a time greater than zero, a frozen +message of any kind that has been on the queue for longer than the given +time is automatically cancelled at the next queue run. If it is a bounce +message, it is just discarded; otherwise, a bounce is sent to the sender, in a +similar manner to cancellation by the %-Mg% command line option. If you want +to timeout frozen bounce messages earlier than other kinds of frozen message, +see %ignore_bounce_errors_after%. + + +oindex:[%timezone%] +`..'= +%timezone%, Use: 'main', Type: 'string', Default: 'unset' +=== + +cindex:[timezone, setting] +The value of %timezone% is used to set the environment variable TZ while +running Exim (if it is different on entry). This ensures that all timestamps +created by Exim are in the required timezone. If you want all your timestamps +to be in UTC (aka GMT) you should set + + timezone = UTC + +The default value is taken from TIMEZONE_DEFAULT in _Local/Makefile_, +or, if that is not set, from the value of the TZ environment variable when Exim +is built. If %timezone% is set to the empty string, either at build or run +time, any existing TZ variable is removed from the environment when Exim +runs. This is appropriate behaviour for obtaining wall-clock time on some, but +unfortunately not all, operating systems. + + +oindex:[%tls_advertise_hosts%] +`..'= +%tls_advertise_hosts%, Use: 'main', Type: 'host list'!!, Default: 'unset' +=== + +cindex:[TLS,advertising] +cindex:[encryption,on SMTP connection] +cindex:[SMTP,encrypted connection] +When Exim is built with support for TLS encrypted connections, the availability +of the STARTTLS command to set up an encrypted session is advertised in +response to EHLO only to those client hosts that match this option. See +chapter <<CHAPTLS>> for details of Exim's support for TLS. + + +oindex:[%tls_certificate%] +`..'= +%tls_certificate%, Use: 'main', Type: 'string'!!, Default: 'unset' +=== + +cindex:[TLS,server certificate; location of] +cindex:[certificate for server, location of] +The value of this option is expanded, and must then be the absolute path to a +file which contains the server's certificates. The server's private key is also +assumed to be in this file if %tls_privatekey% is unset. See chapter <<CHAPTLS>> +for further details. + +*Note*: The certificates defined by this option are used only when Exim is +receiving incoming messages as a server. If you want to supply certificates for +use when sending messages as a client, you must set the %tls_certificate% +option in the relevant ^smtp^ transport. + + +oindex:[%tls_crl%] +`..'= +%tls_crl%, Use: 'main', Type: 'string'!!, Default: 'unset' +=== + +cindex:[TLS,server certificate revocation list] +cindex:[certificate,revocation list for server] +This option specifies a certificate revocation list. The expanded value must +be the name of a file that contains a CRL in PEM format. + + +oindex:[%tls_dhparam%] +`..'= +%tls_dhparam%, Use: 'main', Type: 'string'!!, Default: 'unset' +=== + +cindex:[TLS,D-H parameters for server] +The value of this option is expanded, and must then be the absolute path to +a file which contains the server's DH parameter values. +This is used only for OpenSSL. When Exim is linked with GnuTLS, this option is +ignored. See section <<SECTopenvsgnu>> for further details. + + +oindex:[%tls_on_connect_ports%] +`..'= +%tls_on_connect_ports%, Use: 'main', Type: 'string list', Default: 'unset' +=== + +This option specifies a list of incoming SSMTP (aka SMTPS) ports that should +operate the obsolete SSMTP (SMTPS) protocol, where a TLS session is immediately +set up without waiting for the client to issue a STARTTLS command. For +further details, see section <<SECTsupobssmt>>. + + + +oindex:[%tls_privatekey%] +`..'= +%tls_privatekey%, Use: 'main', Type: 'string'!!, Default: 'unset' +=== + +cindex:[TLS,server private key; location of] +The value of this option is expanded, and must then be the absolute path to a +file which contains the server's private key. If this option is unset, the +private key is assumed to be in the same file as the server's certificates. See +chapter <<CHAPTLS>> for further details. + + +oindex:[%tls_remember_esmtp%] +`..'= +%tls_remember_esmtp%, Use: 'main', Type: 'boolean', Default: 'false' +=== + +cindex:[TLS,esmtp state; remembering] +cindex:[TLS,broken clients] +If this option is set true, Exim violates the RFCs by remembering that it is in +``esmtp'' state after successfully negotiating a TLS session. This provides +support for broken clients that fail to send a new EHLO after starting a +TLS session. + + +oindex:[%tls_require_ciphers%] +`..'= +%tls_require_ciphers%, Use: 'main', Type: 'string'!!, Default: 'unset' +=== + +cindex:[TLS,requiring specific ciphers] +cindex:[cipher,requiring specific] +This option controls which ciphers can be used for incoming TLS connections. +The ^smtp^ transport has an option of the same name for controlling outgoing +connections. This option is expanded for each connection, so can be varied for +different clients if required. The value of this option must be a list of +permitted cipher suites. The OpenSSL and GnuTLS libraries handle cipher control +in somewhat different ways. + +If GnuTLS is being used, the client controls the preference order of the +available ciphers. + +Details are given in sections <<SECTreqciphssl>> and <<SECTreqciphgnu>>. + + +oindex:[%tls_try_verify_hosts%] +`..'= +%tls_try_verify_hosts%, Use: 'main', Type: 'host list'!!, Default: 'unset' +=== + +cindex:[TLS,client certificate verification] +cindex:[certificate,verification of client] +See %tls_verify_hosts% below. + + +oindex:[%tls_verify_certificates%] +`..'= +%tls_verify_certificates%, Use: 'main', Type: 'string'!!, Default: 'unset' +=== + +cindex:[TLS,client certificate verification] +cindex:[certificate,verification of client] +The value of this option is expanded, and must then be the absolute path to +a file containing permitted certificates for clients that +match %tls_verify_hosts% or %tls_try_verify_hosts%. Alternatively, if you +are using OpenSSL, you can set %tls_verify_certificates% to the name of a +directory containing certificate files. This does not work with GnuTLS; the +option must be set to the name of a single file if you are using GnuTLS. + + +oindex:[%tls_verify_hosts%] +`..'= +%tls_verify_hosts%, Use: 'main', Type: 'host list'!!, Default: 'unset' +=== + +cindex:[TLS,client certificate verification] +cindex:[certificate,verification of client] +This option, along with %tls_try_verify_hosts%, controls the checking of +certificates from clients. +The expected certificates are defined by %tls_verify_certificates%, which +must be set. A configuration error occurs if either %tls_verify_hosts% or +%tls_try_verify_hosts% is set and %tls_verify_certificates% is not set. + +Any client that matches %tls_verify_hosts% is constrained by +%tls_verify_certificates%. The client must present one of the listed +certificates. If it does not, the connection is aborted. + +A weaker form of checking is provided by %tls_try_verify_hosts%. If a client +matches this option (but not %tls_verify_hosts%), Exim requests a +certificate and checks it against %tls_verify_certificates%, but does not +abort the connection if there is no certificate or if it does not match. This +state can be detected in an ACL, which makes it possible to implement policies +such as ``accept for relay only if a verified certificate has been received, but +accept for local delivery if encrypted, even without a verified certificate''. + +Client hosts that match neither of these lists are not asked to present +certificates. + + +oindex:[%trusted_groups%] +`..'= +%trusted_groups%, Use: 'main', Type: 'string list', Default: 'unset' +=== + +cindex:[trusted group] +cindex:[group,trusted] +If this option is set, any process that is running in one of the listed groups, +or which has one of them as a supplementary group, is trusted. +The groups can be specified numerically or by name. +See section <<SECTtrustedadmin>> for details of what trusted callers are +permitted to do. If neither %trusted_groups% nor %trusted_users% is set, only +root and the Exim user are trusted. + + +oindex:[%trusted_users%] +`..'= +%trusted_users%, Use: 'main', Type: 'string list', Default: 'unset' +=== + +cindex:[trusted user] +cindex:[user,trusted] +If this option is set, any process that is running as one of the listed users +is trusted. +The users can be specified numerically or by name. +See section <<SECTtrustedadmin>> for details of what trusted callers are +permitted to do. If neither %trusted_groups% nor %trusted_users% is set, only +root and the Exim user are trusted. + +oindex:[%unknown_login%] +`..'= +%unknown_login%, Use: 'main', Type: 'string'!!, Default: 'unset' +=== + +cindex:[uid (user id),unknown caller] +This is a specialized feature for use in unusual configurations. By default, if +the uid of the caller of Exim cannot be looked up using 'getpwuid()', Exim +gives up. The %unknown_login% option can be used to set a login name to be +used in this circumstance. It is expanded, so values like %user\$caller_uid% +can be set. When %unknown_login% is used, the value of %unknown_username% is +used for the user's real name (gecos field), unless this has been set by the +%-F% option. + + +oindex:[%unknown_username%] +`..'= +%unknown_username%, Use: 'main', Type: 'string', Default: 'unset' +=== + +See %unknown_login%. + + +oindex:[%untrusted_set_sender%] +`..'= +%untrusted_set_sender%, Use: 'main', Type: 'address list'!!, Default: 'unset' +=== + +cindex:[trusted user] +cindex:[sender,setting by untrusted user] +cindex:[untrusted user, setting sender] +cindex:[user,untrusted setting sender] +cindex:[envelope sender] +When an untrusted user submits a message to Exim using the standard input, Exim +normally creates an envelope sender address from the user's login and the +default qualification domain. Data from the %-f% option (for setting envelope +senders on non-SMTP messages) or the SMTP MAIL command (if %-bs% or %-bS% +is used) is ignored. + +However, untrusted users are permitted to set an empty envelope sender address, +to declare that a message should never generate any bounces. For example: + + exim -f '<>' user@domain.example + +The %untrusted_set_sender% option allows you to permit untrusted users to set +other envelope sender addresses in a controlled way. When it is set, untrusted +users are allowed to set envelope sender addresses that match any of the +patterns in the list. Like all address lists, the string is expanded. The +identity of the user is in $sender_ident$, so you can, for example, restrict +users to setting senders that start with their login ids +followed by a hyphen +by a setting like this: + + untrusted_set_sender = ^$sender_ident- + +If you want to allow untrusted users to set envelope sender addresses without +restriction, you can use + + untrusted_set_sender = * + +The %untrusted_set_sender% option applies to all forms of local input, but +only to the setting of the envelope sender. It does not permit untrusted users +to use the other options which trusted user can use to override message +parameters. Furthermore, it does not stop Exim from removing an existing +'Sender:' header in the message, or from adding a 'Sender:' header if +necessary. See %local_sender_retain% and %local_from_check% for ways of +overriding these actions. The handling of the 'Sender:' header is also +described in section <<SECTthesenhea>>. + +The log line for a message's arrival shows the envelope sender following ``<=''. +For local messages, the user's login always follows, after ``U=''. In %-bp% +displays, and in the Exim monitor, if an untrusted user sets an envelope sender +address, the user's login is shown in parentheses after the sender address. + + +oindex:[%uucp_from_pattern%] +`..'= +%uucp_from_pattern%, Use: 'main', Type: 'string', Default: 'see below' +=== + +cindex:[``From'' line] +cindex:[UUCP,``From'' line] +Some applications that pass messages to an MTA via a command line interface use +an initial line starting with ``From'' to pass the envelope sender. In +particular, this is used by UUCP software. Exim recognizes such a line by means +of a regular expression that is set in %uucp_from_pattern%. When the pattern +matches, the sender address is constructed by expanding the contents of +%uucp_from_sender%, provided that the caller of Exim is a trusted user. The +default pattern recognizes lines in the following two forms: + + From ph10 Fri Jan 5 12:35 GMT 1996 + From ph10 Fri, 7 Jan 97 14:00:00 GMT + +The pattern can be seen by running + + exim -bP uucp_from_pattern + +It checks only up to the hours and minutes, and allows for a 2-digit or 4-digit +year in the second case. The first word after ``From'' is matched in the regular +expression by a parenthesized subpattern. The default value for +%uucp_from_sender% is ``$1'', which therefore just uses this first word (``ph10'' +in the example above) as the message's sender. See also +%ignore_fromline_hosts%. + + +oindex:[%uucp_from_sender%] +`..'= +%uucp_from_sender%, Use: 'main', Type: 'string'!!, Default: `\$1` +=== + +See %uucp_from_pattern% above. + + +oindex:[%warn_message_file%] +`..'= +%warn_message_file%, Use: 'main', Type: 'string', Default: 'unset' +=== + +cindex:[warning of delay,customizing the message] +cindex:[customizing,warning message] +This option defines a template file containing paragraphs of text to be used +for constructing the warning message which is sent by Exim when a message has +been on the queue for a specified amount of time, as specified by +%delay_warning%. Details of the file's contents are given in chapter +<<CHAPemsgcust>>. See also %bounce_message_file%. + + +oindex:[%write_rejectlog%] +`..'= +%write_rejectlog%, Use: 'main', Type: 'boolean', Default: 'true' +=== + +cindex:[reject log,disabling] +If this option is set false, Exim no longer writes anything to the reject log. +See chapter <<CHAPlog>> for details of what Exim writes to its logs. + + + + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// + +[[CHAProutergeneric]] +Generic options for routers +--------------------------- +cindex:[options,generic; for routers] +cindex:[generic options,router] +This chapter describes the generic options that apply to all routers. +Those that are preconditions are marked with !? in the ``use'' field. + +For a general description of how a router operates, see sections +<<SECTrunindrou>> and <<SECTrouprecon>>. The latter specifies the order in +which the preconditions are tested. The order of expansion of the options that +provide data for a transport is: %errors_to%, %headers_add%, %headers_remove%, +%transport%. + + + +oindex:[%address_data%] +`..'= +%address_data%, Use: 'routers', Type: 'string'!!, Default: 'unset' +=== + +cindex:[router,data attached to address] +The string is expanded just before the router is run, that is, after all the +precondition tests have succeeded. If the expansion is forced to fail, the +router declines. Other expansion failures cause delivery of the address to be +deferred. + +When the expansion succeeds, the value is retained with the address, and can be +accessed using the variable $address_data$ in the current router, subsequent +routers, and the eventual transport. + +*Warning*: if the current or any subsequent router is a ^redirect^ router +that runs a user's filter file, the contents of $address_data$ are +accessible in the filter. This is not normally a problem, because such data is +usually either not confidential or it ``belongs'' to the current user, but if you +do put confidential data into $address_data$ you need to remember this +point. + +Even if the router declines or passes, the value of $address_data$ remains +with the address, though it can be changed by another %address_data% setting +on a subsequent router. If a router generates child addresses, the value of +$address_data$ propagates to them. This also applies to the special kind of +``child'' that is generated by a router with the %unseen% option. + +The idea of %address_data% is that you can use it to look up a lot of data for +the address once, and then pick out parts of the data later. For example, you +could use a single LDAP lookup to return a string of the form + + uid=1234 gid=5678 mailbox=/mail/xyz forward=/home/xyz/.forward + +In the transport you could pick out the mailbox by a setting such as + + file = ${extract{mailbox}{$address_data}} + +This makes the configuration file less messy, and also reduces the number of +lookups (though Exim does cache lookups). + +The %address_data% facility is also useful as a means of passing information +from one router to another, and from a router to a transport. In addition, if + +$address_data$ is set by a router when verifying a recipient address from an +ACL, it remains available for use in the rest of the ACL statement. After +verifying a sender, the value is transferred to $sender_address_data$. + + + + +oindex:[%address_test%] +`..'= +%address_test%, Use: 'routers'!?, Type: 'boolean', Default: 'true' +=== + +cindex:[%-bt% option] +cindex:[router,skipping when address testing] +If this option is set false, the router is skipped when routing is being tested +by means of the %-bt% command line option. This can be a convenience when your +first router sends messages to an external scanner, because it saves you +having to set the ``already scanned'' indicator when testing real address +routing. + + + +oindex:[%cannot_route_message%] +`..'= +%cannot_route_message%, Use: 'routers', Type: 'string'!!, Default: 'unset' +=== + +cindex:[router,customizing ``cannot route'' message] +cindex:[customizing,``cannot route'' message] +This option specifies a text message that is used when an address cannot be +routed because Exim has run out of routers. The default message is ``Unrouteable +address''. This option is useful only on routers that have %more% set false, or +on the very last router in a configuration, because the value that is used is +taken from the last router that inspects an address. For example, using the +default configuration, you could put: + + cannot_route_message = Remote domain not found in DNS + +on the first (^dnslookup^) router, and + + cannot_route_message = Unknown local user + +on the final router that checks for local users. If string expansion fails, the +default message is used. +Unless the expansion failure was explicitly forced, a message about the failure +is written to the main and panic logs, in addition to the normal message about +the routing failure. + + +oindex:[%caseful_local_part%] +`..'= +%caseful_local_part%, Use: 'routers', Type: 'boolean', Default: 'false' +=== + +cindex:[case of local parts] +cindex:[router,case of local parts] +By default, routers handle the local parts of addresses in a case-insensitive +manner, though the actual case is preserved for transmission with the message. +If you want the case of letters to be significant in a router, you must set +this option true. For individual router options that contain address or local +part lists (for example, %local_parts%), case-sensitive matching can be turned +on by ``+caseful'' as a list item. See section <<SECTcasletadd>> for more details. + +The value of the $local_part$ variable is forced to lower case while a +router is running unless %caseful_local_part% is set. When a router assigns +an address to a transport, the value of $local_part$ when the transport runs +is the same as it was in the router. Similarly, when a router generates child +addresses by aliasing or forwarding, the values of $original_local_part$ +and $parent_local_part$ are those that were used by the redirecting router. + +This option applies to the processing of an address by a router. When a +recipient address is being processed in an ACL, there is a separate %control% +modifier that can be used to specify case-sensitive processing within the ACL +(see section <<SECTcontrols>>). + + + +oindex:[%check_local_user%] +`..'= +%check_local_user%, Use: 'routers'!?, Type: 'boolean', Default: 'false' +=== + +cindex:[local user, checking in router] +cindex:[router,checking for local user] +cindex:[_/etc/passwd_] +When this option is true, Exim checks that the local part of the recipient +address (with affixes removed if relevant) is the name of an account on the +local system. The check is done by calling the 'getpwnam()' function rather +than trying to read _/etc/passwd_ directly. This means that other methods of +holding password data (such as NIS) are supported. If the local part is a local +user, $home$ is set from the password data, and can be tested in other +preconditions that are evaluated after this one (the order of evaluation is +given in section <<SECTrouprecon>>). However, the value of $home$ can be +overridden by %router_home_directory%. If the local part is not a local user, +the router is skipped. + +If you want to check that the local part is either the name of a local user +or matches something else, you cannot combine %check_local_user% with a +setting of %local_parts%, because that specifies the logical 'and' of the +two conditions. However, you can use a ^passwd^ lookup in a %local_parts% +setting to achieve this. For example: + + local_parts = passwd;$local_part : lsearch;/etc/other/users + +Note, however, that the side effects of %check_local_user% (such as setting +up a home directory) do not occur when a ^passwd^ lookup is used in a +%local_parts% (or any other) precondition. + + + +oindex:[%condition%] +`..'= +%condition%, Use: 'routers'!?, Type: 'string'!!, Default: 'unset' +=== + +cindex:[router,customized precondition] +This option specifies a general precondition test that has to succeed for the +router to be called. The %condition% option is the last precondition to be +evaluated (see section <<SECTrouprecon>>). The string is expanded, and if the +result is a forced failure, or an empty string, or one of the strings ``0'' or +``no'' or ``false'' (checked without regard to the case of the letters), the router +is skipped, and the address is offered to the next one. + +If the result is any other value, the router is run (as this is the last +precondition to be evaluated, all the other preconditions must be true). + +The %condition% option provides a means of applying custom conditions to the +running of routers. Note that in the case of a simple conditional expansion, +the default expansion values are exactly what is wanted. For example: + + condition = ${if >{$message_age}{600}} + +Because of the default behaviour of the string expansion, this is equivalent to + + condition = ${if >{$message_age}{600}{true}{}} + + +If the expansion fails (other than forced failure) delivery is deferred. Some +of the other precondition options are common special cases that could in fact +be specified using %condition%. + + + +oindex:[%debug_print%] +`..'= +%debug_print%, Use: 'routers', Type: 'string'!!, Default: 'unset' +=== + +cindex:[testing,variables in drivers] +If this option is set and debugging is enabled (see the %-d% command line +option), the string is expanded and included in the debugging output. +If expansion of the string fails, the error message is written to the debugging +output, and Exim carries on processing. +This option is provided to help with checking out the values of variables and +so on when debugging router configurations. For example, if a %condition% +option appears not to be working, %debug_print% can be used to output the +variables it references. The output happens after checks for %domains%, +%local_parts%, and %check_local_user% but before any other preconditions are +tested. A newline is added to the text if it does not end with one. + + + +oindex:[%disable_logging%] +`..'= +%disable_logging%, Use: 'routers', Type: 'boolean', Default: 'false' +=== + +If this option is set true, nothing is logged for any routing errors +or for any deliveries caused by this router. You should not set this option +unless you really, really know what you are doing. See also the generic +transport option of the same name. + + +oindex:[%domains%] +`..'= +%domains%, Use: 'routers'!?, Type: 'domain list'!!, Default: 'unset' +=== + +cindex:[router,restricting to specific domains] +If this option is set, the router is skipped unless the current domain matches +the list. If the match is achieved by means of a file lookup, the data that the +lookup returned for the domain is placed in $domain_data$ for use in string +expansions of the driver's private options. +See section <<SECTrouprecon>> for a list of the order in which preconditions +are evaluated. + + + +oindex:[%driver%] +`..'= +%driver%, Use: 'routers', Type: 'string', Default: 'unset' +=== + +This option must always be set. It specifies which of the available routers is +to be used. + + + +oindex:[%errors_to%] +`..'= +%errors_to%, Use: 'routers', Type: 'string'!!, Default: 'unset' +=== + +cindex:[envelope sender] +cindex:[router,changing address for errors] +If a router successfully handles an address, it may queue the address for +delivery or it may generate child addresses. In both cases, if there is a +delivery problem during later processing, the resulting bounce message is sent +to the address that results from expanding this string, provided that the +address verifies successfully. +%errors_to% is expanded before %headers_add%, %headers_remove%, and +%transport%. + +If the option is unset, or the expansion is forced to fail, or the result of +the expansion fails to verify, the errors address associated with the incoming +address is used. At top level, this is the envelope sender. A non-forced +expansion failure causes delivery to be deferred. + +If an address for which %errors_to% has been set ends up being delivered over +SMTP, the envelope sender for that delivery is the %errors_to% value, so that +any bounces that are generated by other MTAs on the delivery route are also +sent there. The most common use of %errors_to% is probably to direct mailing +list bounces to the manager of the list, as described in section +<<SECTmailinglists>>. + +The %errors_to% setting associated with an address can be overridden if it +subsequently passes through other routers that have their own %errors_to% +settings, +or if it is delivered by a transport with a %return_path% setting. + +You can set %errors_to% to the empty string by either of these settings: + + errors_to = + errors_to = "" + +An expansion item that yields an empty string has the same effect. If you do +this, a locally detected delivery error for addresses processed by this router +no longer gives rise to a bounce message; the error is discarded. If the +address is delivered to a remote host, the return path is set to `<>`, unless +overridden by the %return_path% option on the transport. + +If for some reason you want to discard local errors, but use a non-empty +MAIL command for remote delivery, you can preserve the original return +path in $address_data$ in the router, and reinstate it in the transport by +setting %return_path%. + + + +oindex:[%expn%] +`..'= +%expn%, Use: 'routers'!?, Type: 'boolean', Default: 'true' +=== + +cindex:[address,testing] +cindex:[testing,addresses] +cindex:[EXPN,router skipping] +cindex:[router,skipping for EXPN] +If this option is turned off, the router is skipped when testing an address +as a result of processing an SMTP EXPN command. You might, for example, +want to turn it off on a router for users' _.forward_ files, while leaving it +on for the system alias file. +See section <<SECTrouprecon>> for a list of the order in which preconditions +are evaluated. + +The use of the SMTP EXPN command is controlled by an ACL (see chapter +<<CHAPACL>>). When Exim is running an EXPN command, it is similar to testing +an address with %-bt%. Compare VRFY, whose counterpart is %-bv%. + + + +oindex:[%fail_verify%] +`..'= +%fail_verify%, Use: 'routers', Type: 'boolean', Default: 'false' +=== + +cindex:[router,forcing verification failure] +Setting this option has the effect of setting both %fail_verify_sender% and +%fail_verify_recipient% to the same value. + + + +oindex:[%fail_verify_recipient%] +`..'= +%fail_verify_recipient%, Use: 'routers', Type: 'boolean', Default: 'false' +=== + +If this option is true and an address is accepted by this router when +verifying a recipient, verification fails. + + + +oindex:[%fail_verify_sender%] +`..'= +%fail_verify_sender%, Use: 'routers', Type: 'boolean', Default: 'false' +=== + +If this option is true and an address is accepted by this router when +verifying a sender, verification fails. + + + +oindex:[%fallback_hosts%] +`..'= +%fallback_hosts%, Use: 'routers', Type: 'string list', Default: 'unset' +=== + +cindex:[router,fallback hosts] +cindex:[fallback,hosts specified on router] +String expansion is not applied to this option. The argument must be a +colon-separated list of host names or IP addresses. If a router queues an +address for a remote transport, this host list is associated with the address, +and used instead of the transport's fallback host list. If %hosts_randomize% +is set on the transport, the order of the list is randomized for each use. See +the %fallback_hosts% option of the ^smtp^ transport for further details. + + +oindex:[%group%] +`..'= +%group%, Use: 'routers', Type: 'string'!!, Default: 'see below' +=== + +cindex:[gid (group id),local delivery] +cindex:[local transports,uid and gid] +cindex:[transport,local] +cindex:[router,setting group] +When a router queues an address for a transport, and the transport does not +specify a group, the group given here is used when running the delivery +process. +The group may be specified numerically or by name. If expansion fails, the +error is logged and delivery is deferred. +The default is unset, unless %check_local_user% is set, when the default +is taken from the password information. See also %initgroups% and %user% and +the discussion in chapter <<CHAPenvironment>>. + + + +oindex:[%headers_add%] +`..'= +%headers_add%, Use: 'routers', Type: 'string'!!, Default: 'unset' +=== + +cindex:[header lines,adding] +cindex:[router,adding header lines] +This option specifies a string of text that is expanded at routing time, and +associated with any addresses that are accepted by the router. However, this +option has no effect when an address is just being verified. The way in which +the text is used to add header lines at transport time is described in section +<<SECTheadersaddrem>>. + +The %headers_add% option is expanded after %errors_to%, but before +%headers_remove% and %transport%. If the expanded string is empty, or if the +expansion is forced to fail, the option has no effect. Other expansion failures +are treated as configuration errors. + +*Warning*: The %headers_add% option cannot be used for a ^redirect^ +router that has the %one_time% option set. + + + + +oindex:[%headers_remove%] +`..'= +%headers_remove%, Use: 'routers', Type: 'string'!!, Default: 'unset' +=== + +cindex:[header lines,removing] +cindex:[router,removing header lines] +This option specifies a string of text that is expanded at routing time, and +associated with any addresses that are accepted by the router. However, this +option has no effect when an address is just being verified. The way in which +the text is used to remove header lines at transport time is described in +section <<SECTheadersaddrem>>. + +The %headers_remove% option is expanded after %errors_to% and %headers_add%, +but before %transport%. If the expansion is forced to fail, the option has no +effect. Other expansion failures are treated as configuration errors. + +*Warning*: The %headers_remove% option cannot be used for a ^redirect^ +router that has the %one_time% option set. + + + + +oindex:[%ignore_target_hosts%] +`..'= +%ignore_target_hosts%, Use: 'routers', Type: 'host list'!!, Default: 'unset' +=== + +cindex:[IP address,discarding] +cindex:[router,discarding IP addresses] +Although this option is a host list, it should normally contain IP address +entries rather than names. If any host that is looked up by the router has an +IP address that matches an item in this list, Exim behaves as if that IP +address did not exist. This option allows you to cope with rogue DNS entries +like + + remote.domain.example. A 127.0.0.1 + +by setting + + ignore_target_hosts = 127.0.0.1 + +on the relevant router. If all the hosts found by a ^dnslookup^ router are +discarded in this way, the router declines. In a conventional configuration, an +attempt to mail to such a domain would normally provoke the ``unrouteable +domain'' error, and an attempt to verify an address in the domain would fail. + +Similarly, if %ignore_target_hosts% is set on an ^ipliteral^ router, the +router declines if presented with one of the listed addresses. + +This option may also be useful for ignoring link-local and site-local IPv6 +addresses. Because, like all host lists, the value of %ignore_target_hosts% +is expanded before use as a list, it is possible to make it dependent on the +domain that is being routed. + +During its expansion, $host_address$ is set to the IP address that is being +checked. + +oindex:[%initgroups%] +`..'= +%initgroups%, Use: 'routers', Type: 'boolean', Default: 'false' +=== + +cindex:[additional groups] +cindex:[groups, additional] +cindex:[local transports,uid and gid] +cindex:[transport,local] +If the router queues an address for a transport, and this option is true, and +the uid supplied by the router is not overridden by the transport, the +'initgroups()' function is called when running the transport to ensure that +any additional groups associated with the uid are set up. See also %group% and +%user% and the discussion in chapter <<CHAPenvironment>>. + + + +oindex:[%local_part_prefix%] +`..'= +%local_part_prefix%, Use: 'routers'!?, Type: 'string list', Default: 'unset' +=== + +cindex:[router,prefix for local part] +cindex:[prefix,for local part; used in router] +If this option is set, the router is skipped unless the local part +starts with one of the given strings, or %local_part_prefix_optional% is +true. +See section <<SECTrouprecon>> for a list of the order in which preconditions +are evaluated. + +The list is scanned from left to right, and the first prefix that matches is +used. A limited form of wildcard is available; if the prefix begins with an +asterisk, it matches the longest possible sequence of arbitrary characters at +the start of the local part. An asterisk should therefore always be followed by +some character that does not occur in normal local parts. + +cindex:[multiple mailboxes] +cindex:[mailbox,multiple] +Wildcarding can be used to set up multiple user mailboxes, as described in +section <<SECTmulbox>>. + +During the testing of the %local_parts% option, and while the router is +running, the prefix is removed from the local part, and is available in the +expansion variable $local_part_prefix$. If the router accepts the address, +this remains true during subsequent delivery. +In particular, the local part that is transmitted in the RCPT command +for LMTP, SMTP, and BSMTP deliveries has the prefix removed by default. This +behaviour can be overridden by setting %rcpt_include_affixes% true on the +relevant transport. + +The prefix facility is commonly used to handle local parts of the form +%owner-something%. Another common use is to support local parts of the form +%real-username% to bypass a user's _.forward_ file -- helpful when trying to +tell a user their forwarding is broken -- by placing a router like this one +immediately before the router that handles _.forward_ files: + + real_localuser: + driver = accept + local_part_prefix = real- + check_local_user + transport = local_delivery + +If both %local_part_prefix% and %local_part_suffix% are set for a router, +both conditions must be met if not optional. Care must be taken if wildcards +are used in both a prefix and a suffix on the same router. Different +separator characters must be used to avoid ambiguity. + + +oindex:[%local_part_prefix_optional%] +`..'= +%local_part_prefix_optional%, Use: 'routers', Type: 'boolean', Default: 'false' +=== + +See %local_part_prefix% above. + + + +oindex:[%local_part_suffix%] +`..'= +%local_part_suffix%, Use: 'routers'!?, Type: 'string list', Default: 'unset' +=== + +cindex:[router,suffix for local part] +cindex:[suffix for local part, used in router] +This option operates in the same way as %local_part_prefix%, except that the +local part must end (rather than start) with the given string, the +%local_part_suffix_optional% option determines whether the suffix is +mandatory, and the wildcard \* character, if present, must be the last +character of the suffix. This option facility is commonly used to handle local +parts of the form %something-request% and multiple user mailboxes of the form +%username-foo%. + + +oindex:[%local_part_suffix_optional%] +`..'= +%local_part_suffix_optional%, Use: 'routers', Type: 'boolean', Default: 'false' +=== + +See %local_part_suffix% above. + + + +oindex:[%local_parts%] +`..'= +%local_parts%, Use: 'routers'!?, Type: 'local part list'!!, Default: 'unset' +=== + +cindex:[router,restricting to specific local parts] +cindex:[local part,checking in router] +The router is run only if the local part of the address matches the list. +See section <<SECTrouprecon>> for a list of the order in which preconditions +are evaluated, and +section <<SECTlocparlis>> for a discussion of local part lists. Because the +string is expanded, it is possible to make it depend on the domain, for +example: + + local_parts = dbm;/usr/local/specials/$domain + +If the match is achieved by a lookup, the data that the lookup returned +for the local part is placed in the variable $local_part_data$ for use in +expansions of the router's private options. You might use this option, for +example, if you have a large number of local virtual domains, and you want to +send all postmaster mail to the same place without having to set up an alias in +each virtual domain: + + postmaster: + driver = redirect + local_parts = postmaster + data = postmaster@real.domain.example + + + + +oindex:[%log_as_local%] +`..'= +%log_as_local%, Use: 'routers', Type: 'boolean', Default: 'see below' +=== + +cindex:[log,delivery line] +cindex:[delivery,log line format] +Exim has two logging styles for delivery, the idea being to make local +deliveries stand out more visibly from remote ones. In the ``local'' style, the +recipient address is given just as the local part, without a domain. The use of +this style is controlled by this option. It defaults to true for the ^accept^ +router, and false for all the others. + + + +oindex:[%more%] +`..'= +%more%, Use: 'routers', Type: 'boolean'!!, Default: 'true' +=== + +The result of string expansion for this option must be a valid boolean value, +that is, one of the strings ``yes'', ``no'', ``true'', or ``false''. Any other +result causes an error, and delivery is deferred. If the expansion is forced to +fail, the default value for the option (true) is used. Other failures cause +delivery to be deferred. + +If this option is set false, and the router is run, but declines to handle the +address, no further routers are tried, routing fails, and the address is +bounced. +cindex:[%self% option] +However, if the router explicitly passes an address to the following router by +means of the setting + + self = pass + +or otherwise, the setting of %more% is ignored. Also, the setting of %more% +does not affect the behaviour if one of the precondition tests fails. In that +case, the address is always passed to the next router. + + + +oindex:[%pass_on_timeout%] +`..'= +%pass_on_timeout%, Use: 'routers', Type: 'boolean', Default: 'false' +=== + +cindex:[timeout,of router] +cindex:[router,timeout] +If a router times out during a host lookup, it normally causes deferral of the +address. If %pass_on_timeout% is set, the address is passed on to the next +router, overriding %no_more%. This may be helpful for systems that are +intermittently connected to the Internet, or those that want to pass to a smart +host any messages that cannot immediately be delivered. + +There are occasional other temporary errors that can occur while doing DNS +lookups. They are treated in the same way as a timeout, and this option +applies to all of them. + + + +oindex:[%pass_router%] +`..'= +%pass_router%, Use: 'routers', Type: 'string', Default: 'unset' +=== + +cindex:[router,go to after ``pass''] +When a router returns ``pass'', the address is normally handed on to the next +router in sequence. This can be changed by setting %pass_router% to the name +of another router. However (unlike %redirect_router%) the named router must be +below the current router, to avoid loops. Note that this option applies only to +the special case of ``pass''. It does not apply when a router returns ``decline''. + + + +oindex:[%redirect_router%] +`..'= +%redirect_router%, Use: 'routers', Type: 'string', Default: 'unset' +=== + +cindex:[router,start at after redirection] +Sometimes an administrator knows that it is pointless to reprocess addresses +generated from alias or forward files with the same router again. For +example, if an alias file translates real names into login ids there is no +point searching the alias file a second time, especially if it is a large file. + +The %redirect_router% option can be set to the name of any router instance. It +causes the routing of any generated addresses to start at the named router +instead of at the first router. This option has no effect if the router in +which it is set does not generate new addresses. + + + +oindex:[%require_files%] +`..'= +%require_files%, Use: 'routers'!?, Type: 'string list'!!, Default: 'unset' +=== + +cindex:[file,requiring for router] +cindex:[router,requiring file existence] +This option provides a general mechanism for predicating the running of a +router on the existence or non-existence of certain files or directories. +Before running a router, as one of its precondition tests, Exim works its way +through the %require_files% list, expanding each item separately. + +Because the list is split before expansion, any colons in expansion items must +be doubled, or the facility for using a different list separator must be used. +If any expansion is forced to fail, the item is ignored. Other expansion +failures cause routing of the address to be deferred. + +If any expanded string is empty, it is ignored. Otherwise, except as described +below, each string must be a fully qualified file path, optionally preceded by +``!''. The paths are passed to the 'stat()' function to test for the existence +of the files or directories. The router is skipped if any paths not preceded by +``!'' do not exist, or if any paths preceded by ``!'' do exist. + +cindex:[NFS] +If 'stat()' cannot determine whether a file exists or not, delivery of +the message is deferred. This can happen when NFS-mounted filesystems are +unavailable. + +This option is checked after the %domains%, %local_parts%, and %senders% +options, so you cannot use it to check for the existence of a file in which to +look up a domain, local part, or sender. (See section <<SECTrouprecon>> for a +full list of the order in which preconditions are evaluated.) However, as +these options are all expanded, you can use the %exists% expansion condition to +make such tests. The %require_files% option is intended for checking files +that the router may be going to use internally, or which are needed by a +transport (for example _.procmailrc_). + +During delivery, the 'stat()' function is run as root, but there is a +facility for some checking of the accessibility of a file by another user. +This is not a proper permissions check, but just a ``rough'' check that +operates as follows: + +If an item in a %require_files% list does not contain any forward slash +characters, it is taken to be the user (and optional group, separated by a +comma) to be checked for subsequent files in the list. If no group is specified +but the user is specified symbolically, the gid associated with the uid is +used. For example: + + require_files = mail:/some/file + require_files = $local_part:$home/.procmailrc + +If a user or group name in a %require_files% list does not exist, the +%require_files% condition fails. + +Exim performs the check by scanning along the components of the file path, and +checking the access for the given uid and gid. It checks for ``x'' access on +directories, and ``r'' access on the final file. Note that this means that file +access control lists, if the operating system has them, are ignored. + +*Warning 1*: When the router is being run to verify addresses for an +incoming SMTP message, Exim is not running as root, but under its own uid. This +may affect the result of a %require_files% check. In particular, 'stat()' +may yield the error EACCES (``Permission denied''). This means that the Exim +user is not permitted to read one of the directories on the file's path. + +*Warning 2*: Even when Exim is running as root while delivering a message, +'stat()' can yield EACCES for a file in an NFS directory that is mounted +without root access. + +In this case, if a check for access by a particular user is requested, Exim +creates a subprocess that runs as that user, and tries the check again in that +process. + +The default action for handling an unresolved EACCES is to consider it to +be caused by a configuration error, + +and routing is deferred because the existence or non-existence of the file +cannot be determined. However, in some circumstances it may be desirable to +treat this condition as if the file did not exist. If the file name (or the +exclamation mark that precedes the file name for non-existence) is preceded by +a plus sign, the EACCES error is treated as if the file did not exist. For +example: + + require_files = +/some/file + +If the router is not an essential part of verification (for example, it +handles users' _.forward_ files), another solution is to set the %verify% +option false so that the router is skipped when verifying. + + + +oindex:[%retry_use_local_part%] +`..'= +%retry_use_local_part%, Use: 'routers', Type: 'boolean', Default: 'see below' +=== + +cindex:[hints database,retry keys] +cindex:[local part,in retry keys] +When a delivery suffers a temporary routing failure, a retry record is created +in Exim's hints database. For addresses whose routing depends only on the +domain, the key for the retry record should not involve the local part, but for +other addresses, both the domain and the local part should be included. +Usually, remote routing is of the former kind, and local routing is of the +latter kind. + +This option controls whether the local part is used to form the key for retry +hints for addresses that suffer temporary errors while being handled by this +router. The default value is true for any router that has %check_local_user% +set, and false otherwise. Note that this option does not apply to hints keys +for transport delays; they are controlled by a generic transport option of the +same name. + +The setting of %retry_use_local_part% applies only to the router on which it +appears. If the router generates child addresses, they are routed +independently; this setting does not become attached to them. + + + +oindex:[%router_home_directory%] +`..'= +%router_home_directory%, Use: 'routers', Type: 'string'!!, Default: 'unset' +=== + +cindex:[router,home directory for] +cindex:[home directory,for router] +This option sets a home directory for use while the router is running. (Compare +%transport_home_directory%, which sets a home directory for later +transporting.) In particular, if used on a ^redirect^ router, this option +sets a value for $home$ while a filter is running. The value is expanded; +forced expansion failure causes the option to be ignored -- other failures +cause the router to defer. + +Expansion of %router_home_directory% happens immediately after the +%check_local_user% test (if configured), before any further expansions take +place. +(See section <<SECTrouprecon>> for a list of the order in which preconditions +are evaluated.) +While the router is running, %router_home_directory% overrides the value of +$home$ that came from %check_local_user%. + +When a router accepts an address and routes it to a transport (including the +cases when a redirect router generates a pipe, file, or autoreply delivery), +the home directory setting for the transport is taken from the first of these +values that is set: + +- The %home_directory% option on the transport; + +- The %transport_home_directory% option on the router; + +- The password data if %check_local_user% is set on the router; + +- The %router_home_directory% option on the router. + +In other words, %router_home_directory% overrides the password data for the +router, but not for the transport. + + + +oindex:[%self%] +`..'= +%self%, Use: 'routers', Type: 'string', Default: 'freeze' +=== + +cindex:[MX record,pointing to local host] +cindex:[local host,MX pointing to] +This option applies to those routers that use a recipient address to find a +list of remote hosts. Currently, these are the ^dnslookup^, ^ipliteral^, +and ^manualroute^ routers. +Certain configurations of the ^queryprogram^ router can also specify a list +of remote hosts. +Usually such routers are configured to send the message to a remote host via an +^smtp^ transport. The %self% option specifies what happens when the first +host on the list turns out to be the local host. +The way in which Exim checks for the local host is described in section +<<SECTreclocipadd>>. + +Normally this situation indicates either an error in Exim's configuration (for +example, the router should be configured not to process this domain), or an +error in the DNS (for example, the MX should not point to this host). For this +reason, the default action is to log the incident, defer the address, and +freeze the message. The following alternatives are provided for use in special +cases: + +%defer%:: +Delivery of the message is tried again later, but the message is not frozen. + +%reroute%: <'domain'>:: +The domain is changed to the given domain, and the address is passed back to +be reprocessed by the routers. No rewriting of headers takes place. This +behaviour is essentially a redirection. + +%reroute: rewrite:% <'domain'>:: +The domain is changed to the given domain, and the address is passed back to be +reprocessed by the routers. Any headers that contain the original domain are +rewritten. + +%pass%:: +The router passes the address to the next router, or to the router named in the +%pass_router% option if it is set. +cindex:[%more% option] +This overrides %no_more%. ++ +During subsequent routing and delivery, the variable $self_hostname$ contains +the name of the local host that the router encountered. This can be used to +distinguish between different cases for hosts with multiple names. The +combination + + self = pass + no_more ++ +ensures that only those addresses that routed to the local host are passed on. +Without %no_more%, addresses that were declined for other reasons would also +be passed to the next router. + +%fail%:: +Delivery fails and an error report is generated. + +%send%:: +cindex:[local host,sending to] +The anomaly is ignored and the address is queued for the transport. This +setting should be used with extreme caution. For an ^smtp^ transport, it makes +sense only in cases where the program that is listening on the SMTP port is not +this version of Exim. That is, it must be some other MTA, or Exim with a +different configuration file that handles the domain in another way. + + + +oindex:[%senders%] +`..'= +%senders%, Use: 'routers'!?, Type: 'address list'!!, Default: 'unset' +=== + +cindex:[router,checking senders] +If this option is set, the router is skipped unless the message's sender +address matches something on the list. +See section <<SECTrouprecon>> for a list of the order in which preconditions +are evaluated. + +There are issues concerning verification when the running of routers is +dependent on the sender. When Exim is verifying the address in an %errors_to% +setting, it sets the sender to the null string. When using the %-bt% option to +check a configuration file, it is necessary also to use the %-f% option to set +an appropriate sender. For incoming mail, the sender is unset when verifying +the sender, but is available when verifying any recipients. If the SMTP +VRFY command is enabled, it must be used after MAIL if the sender +address matters. + + +oindex:[%translate_ip_address%] +`..'= +%translate_ip_address%, Use: 'routers', Type: 'string'!!, Default: 'unset' +=== + +cindex:[IP address,translating] +cindex:[packet radio] +cindex:[router,IP address translation] +There exist some rare networking situations (for example, packet radio) where +it is helpful to be able to translate IP addresses generated by normal routing +mechanisms into other IP addresses, thus performing a kind of manual IP +routing. This should be done only if the normal IP routing of the TCP/IP stack +is inadequate or broken. Because this is an extremely uncommon requirement, the +code to support this option is not included in the Exim binary unless +SUPPORT_TRANSLATE_IP_ADDRESS=yes is set in _Local/Makefile_. + +The %translate_ip_address% string is expanded for every IP address generated +by the router, with the generated address set in $host_address$. If the +expansion is forced to fail, no action is taken. +For any other expansion error, delivery of the message is deferred. +If the result of the expansion is an IP address, that replaces the original +address; otherwise the result is assumed to be a host name -- this is looked up +using 'gethostbyname()' (or 'getipnodebyname()' when available) to produce +one or more replacement IP addresses. For example, to subvert all IP addresses +in some specific networks, this could be added to a router: + +.... +translate_ip_address = \ + ${lookup{${mask:$host_address/26}}lsearch{/some/file}{$value}fail}} +.... + +The file would contain lines like + + 10.2.3.128/26 some.host + 10.8.4.34/26 10.44.8.15 + +You should not make use of this facility unless you really understand what you +are doing. + + + +oindex:[%transport%] +`..'= +%transport%, Use: 'routers', Type: 'string'!!, Default: 'unset' +=== + +This option specifies the transport to be used when a router accepts an address +and sets it up for delivery. A transport is never needed if a router is used +only for verification. The value of the option is expanded at routing time, +after the expansion of %errors_to%, %headers_add%, and %headers_remove%, and +result must be the name of one of the configured transports. If it is not, +delivery is deferred. + +The %transport% option is not used by the ^redirect^ router, but it does have +some private options that set up transports for pipe and file deliveries (see +chapter <<CHAPredirect>>). + + + +oindex:[%transport_current_directory%] +`..'= +%transport_current_directory%, Use: 'routers', Type: 'string'!!, Default: 'unset' +=== + +cindex:[current directory for local transport] +This option associates a current directory with any address that is routed +to a local transport. This can happen either because a transport is +explicitly configured for the router, or because it generates a delivery to a +file or a pipe. During the delivery process (that is, at transport time), this +option string is expanded and is set as the current directory, unless +overridden by a setting on the transport. +If the expansion fails for any reason, including forced failure, an error is +logged, and delivery is deferred. +See chapter <<CHAPenvironment>> for details of the local delivery environment. + + + + +oindex:[%transport_home_directory%] +`..'= +%transport_home_directory%, Use: 'routers', Type: 'string'!!, Default: 'see below' +=== + +cindex:[home directory,for local transport] +This option associates a home directory with any address that is routed to a +local transport. This can happen either because a transport is explicitly +configured for the router, or because it generates a delivery to a file or a +pipe. During the delivery process (that is, at transport time), the option +string is expanded and is set as the home directory, unless overridden by a +setting of %home_directory% on the transport. +If the expansion fails for any reason, including forced failure, an error is +logged, and delivery is deferred. + +If the transport does not specify a home directory, and +%transport_home_directory% is not set for the router, the home directory for +the tranport is taken from the password data if %check_local_user% is set for +the router. Otherwise it is taken from %router_home_directory% if that option +is set; if not, no home directory is set for the transport. + +See chapter <<CHAPenvironment>> for further details of the local delivery +environment. + + + + +oindex:[%unseen%] +`..'= +%unseen%, Use: 'routers', Type: 'boolean'!!, Default: 'false' +=== + +cindex:[router,carrying on after success] +The result of string expansion for this option must be a valid boolean value, +that is, one of the strings ``yes'', ``no'', ``true'', or ``false''. Any other result +causes an error, and delivery is deferred. If the expansion is forced to fail, +the default value for the option (false) is used. Other failures cause delivery +to be deferred. + +When this option is set true, routing does not cease if the router accepts the +address. Instead, a copy of the incoming address is passed to the next router, +overriding a false setting of %more%. There is little point in setting %more% +false if %unseen% is always true, but it may be useful in cases when the value +of %unseen% contains expansion items (and therefore, presumably, is sometimes +true and sometimes false). + +cindex:[copy of message (%unseen% option)] +The %unseen% option can be used to cause copies of messages to be delivered to +some other destination, while also carrying out a normal delivery. In effect, +the current address is made into a ``parent'' that has two children -- one that +is delivered as specified by this router, and a clone that goes on to be routed +further. + +Header lines added to the address (or specified for removal) by this router or +by previous routers affect the ``unseen'' copy of the message only. The clone +that continues to be processed by further routers starts with no added headers +and none specified for removal. + +However, any data that was set by the %address_data% option in the current or +previous routers is passed on. Setting this option has a similar effect to the +%unseen% command qualifier in filter files. + + + +oindex:[%user%] +`..'= +%user%, Use: 'routers', Type: 'string'!!, Default: 'see below' +=== + +cindex:[uid (user id),local delivery] +cindex:[local transports,uid and gid] +cindex:[transport,local] +cindex:[router,user for filter processing] +cindex:[filter,user for processing] +When a router queues an address for a transport, and the transport does not +specify a user, the user given here is used when running the delivery process. +The user may be specified numerically or by name. If expansion fails, the +error is logged and delivery is deferred. +This user is also used by the ^redirect^ router when running a filter file. +The default is unset, except when %check_local_user% is set. In this case, +the default is taken from the password information. If the user is specified as +a name, and %group% is not set, the group associated with the user is used. See +also %initgroups% and %group% and the discussion in chapter <<CHAPenvironment>>. + + + +oindex:[%verify%] +`..'= +%verify%, Use: 'routers'!?, Type: 'boolean', Default: 'true' +=== + +Setting this option has the effect of setting %verify_sender% and +%verify_recipient% to the same value. + + +oindex:[%verify_only%] +`..'= +%verify_only%, Use: 'routers'!?, Type: 'boolean', Default: 'false' +=== + +cindex:[EXPN,with %verify_only%] +cindex:[%-bv% option] +cindex:[router,used only when verifying] +If this option is set, the router is used only when verifying an address or +testing with the %-bv% option, not when actually doing a delivery, testing +with the %-bt% option, or running the SMTP EXPN command. It can be further +restricted to verifying only senders or recipients by means of %verify_sender% +and %verify_recipient%. + +*Warning*: When the router is being run to verify addresses for an incoming +SMTP message, Exim is not running as root, but under its own uid. If the router +accesses any files, you need to make sure that they are accessible to the Exim +user or group. + + +oindex:[%verify_recipient%] +`..'= +%verify_recipient%, Use: 'routers'!?, Type: 'boolean', Default: 'true' +=== + +If this option is false, the router is skipped when verifying recipient +addresses +or testing recipient verification using %-bv%. +See section <<SECTrouprecon>> for a list of the order in which preconditions +are evaluated. + + +oindex:[%verify_sender%] +`..'= +%verify_sender%, Use: 'routers'!?, Type: 'boolean', Default: 'true' +=== + +If this option is false, the router is skipped when verifying sender addresses +or testing sender verification using %-bvs%. +See section <<SECTrouprecon>> for a list of the order in which preconditions +are evaluated. + + + + + + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// + +The accept router +----------------- +cindex:[^accept^ router] +cindex:[routers,^accept^] +The ^accept^ router has no private options of its own. Unless it is being used +purely for verification (see %verify_only%) a transport is required to be +defined by the generic %transport% option. If the preconditions that are +specified by generic options are met, the router accepts the address and queues +it for the given transport. The most common use of this router is for setting +up deliveries to local mailboxes. For example: + + localusers: + driver = accept + domains = mydomain.example + check_local_user + transport = local_delivery + +The %domains% condition in this example checks the domain of the address, and +%check_local_user% checks that the local part is the login of a local user. +When both preconditions are met, the ^accept^ router runs, and queues the +address for the ^local_delivery^ transport. + + + + + + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// + +[[CHAPdnslookup]] +The dnslookup router +-------------------- +cindex:[^dnslookup^ router] +cindex:[routers,^dnslookup^] +The ^dnslookup^ router looks up the hosts that handle mail for the +recipient's domain in the DNS. A transport must always be set for this router, +unless %verify_only% is set. + +If SRV support is configured (see %check_srv% below), Exim first searches for +SRV records. If none are found, or if SRV support is not configured, +MX records are looked up. If no MX records exist, address records are sought. +However, %mx_domains% can be set to disable the direct use of address records. + +MX records of equal priority are sorted by Exim into a random order. Exim then +looks for address records for the host names obtained from MX or SRV records. +When a host has more than one IP address, they are sorted into a random order, +except that IPv6 addresses are always sorted before IPv4 addresses. If all the +IP addresses found are discarded by a setting of the %ignore_target_hosts% +generic option, the router declines. + +Unless they have the highest priority (lowest MX value), MX records that point +to the local host, or to any host name that matches %hosts_treat_as_local%, +are discarded, together with any other MX records of equal or lower priority. + +cindex:[MX record,pointing to local host] +cindex:[local host,MX pointing to] +cindex:[%self% option,in ^dnslookup^ router] +If the host pointed to by the highest priority MX record, or looked up as an +address record, is the local host, or matches %hosts_treat_as_local%, what +happens is controlled by the generic %self% option. + + +[[SECTprowitdnsloo]] +Problems with DNS lookups +~~~~~~~~~~~~~~~~~~~~~~~~~ +There have been problems with DNS servers when SRV records are looked up. +Some mis-behaving servers return a DNS error or timeout when a non-existent +SRV record is sought. Similar problems have in the past been reported for +MX records. The global %dns_again_means_nonexist% option can help with this +problem, but it is heavy-handed because it is a global option. + +For this reason, there are two options, %srv_fail_domains% and +%mx_fail_domains%, that control what happens when a DNS lookup in a +^dnslookup^ router results in a DNS failure or a ``try again'' response. If an +attempt to look up an SRV or MX record causes one of these results, and the +domain matches the relevant list, Exim behaves as if the DNS had responded ``no +such record''. In the case of an SRV lookup, this means that the router proceeds +to look for MX records; in the case of an MX lookup, it proceeds to look for A +or AAAA records, unless the domain matches %mx_domains%, in which case routing +fails. + + + + +Private options for dnslookup +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[options,^dnslookup^ router] +The private options for the ^dnslookup^ router are as follows: + +oindex:[%check_secondary_mx%] +`..'= +%check_secondary_mx%, Use: 'dnslookup', Type: 'boolean', Default: 'false' +=== + +cindex:[MX record,checking for secondary] +If this option is set, the router declines unless the local host is found in +(and removed from) the list of hosts obtained by MX lookup. This can be used to +process domains for which the local host is a secondary mail exchanger +differently to other domains. The way in which Exim decides whether a host is +the local host is described in section <<SECTreclocipadd>>. + + +oindex:[%check_srv%] +`..'= +%check_srv%, Use: 'dnslookup', Type: 'string'!!, Default: 'unset' +=== + +cindex:[SRV record,enabling use of] +The ^dnslookup^ router supports the use of SRV records (see RFC 2782) in +addition to MX and address records. The support is disabled by default. To +enable SRV support, set the %check_srv% option to the name of the service +required. For example, + + check_srv = smtp + +looks for SRV records that refer to the normal smtp service. The option is +expanded, so the service name can vary from message to message or address +to address. This might be helpful if SRV records are being used for a +submission service. If the expansion is forced to fail, the %check_srv% +option is ignored, and the router proceeds to look for MX records in the +normal way. + +When the expansion succeeds, the router searches first for SRV records for +the given service (it assumes TCP protocol). A single SRV record with a +host name that consists of just a single dot indicates ``no such service for +this domain''; if this is encountered, the router declines. If other kinds of +SRV record are found, they are used to construct a host list for delivery +according to the rules of RFC 2782. MX records are not sought in this case. + +When no SRV records are found, MX records (and address records) are sought in +the traditional way. In other words, SRV records take precedence over MX +records, just as MX records take precedence over address records. Note that +this behaviour is not sanctioned by RFC 2782, though a previous draft RFC +defined it. It is apparently believed that MX records are sufficient for email +and that SRV records should not be used for this purpose. However, SRV records +have an additional ``weight'' feature which some people might find useful when +trying to split an SMTP load between hosts of different power. + +See section <<SECTprowitdnsloo>> above for a discussion of Exim's behaviour when +there is a DNS lookup error. + + + +oindex:[%mx_domains%] +`..'= +%mx_domains%, Use: 'dnslookup', Type: 'domain list'!!, Default: 'unset' +=== + +cindex:[MX record,required to exist] +cindex:[SRV record,required to exist] +A domain that matches %mx_domains% is required to have either an MX or an SRV +record in order to be recognised. (The name of this option could be improved.) +For example, if all the mail hosts in 'fict.example' are known to have MX +records, except for those in 'discworld.fict.example', you could use this +setting: + + mx_domains = ! *.discworld.fict.example : *.fict.example + +This specifies that messages addressed to a domain that matches the list but +has no MX record should be bounced immediately instead of being routed using +the address record. + + +oindex:[%mx_fail_domains%] +`..'= +%mx_fail_domains%, Use: 'dnslookup', Type: 'domain list'!!, Default: 'unset' +=== + +If the DNS lookup for MX records for one of the domains in this list causes a +DNS lookup error, Exim behaves as if no MX records were found. See section +<<SECTprowitdnsloo>> for more discussion. + + + + +oindex:[%qualify_single%] +`..'= +%qualify_single%, Use: 'dnslookup', Type: 'boolean', Default: 'true' +=== + +cindex:[DNS,resolver options] +cindex:[DNS,qualifying single-component names] +When this option is true, the resolver option RES_DEFNAMES is set for DNS +lookups. Typically, but not standardly, this causes the resolver to qualify +single-component names with the default domain. For example, on a machine +called 'dictionary.ref.example', the domain 'thesaurus' would be changed to +'thesaurus.ref.example' inside the resolver. For details of what your resolver +actually does, consult your man pages for 'resolver' and 'resolv.conf'. + + + +oindex:[%rewrite_headers%] +`..'= +%rewrite_headers%, Use: 'dnslookup', Type: 'boolean', Default: 'true' +=== + +cindex:[rewriting,header lines] +cindex:[header lines,rewriting] +If the domain name in the address that is being processed is not fully +qualified, it may be expanded to its full form by a DNS lookup. For example, if +an address is specified as 'dormouse@teaparty', the domain might be +expanded to 'teaparty.wonderland.fict.example'. Domain expansion can also +occur as a result of setting the %widen_domains% option. If %rewrite_headers% +is true, all occurrences of the abbreviated domain name in any 'Bcc:', 'Cc:', +'From:', 'Reply-to:', 'Sender:', and 'To:' header lines of the message are +rewritten with the full domain name. + +This option should be turned off only when it is known that no message is +ever going to be sent outside an environment where the abbreviation makes +sense. + +When an MX record is looked up in the DNS and matches a wildcard record, name +servers normally return a record containing the name that has been looked up, +making it impossible to detect whether a wildcard was present or not. However, +some name servers have recently been seen to return the wildcard entry. If the +name returned by a DNS lookup begins with an asterisk, it is not used for +header rewriting. + + +oindex:[%same_domain_copy_routing%] +`..'= +%same_domain_copy_routing%, Use: 'dnslookup', Type: 'boolean', Default: 'false' +=== + +cindex:[address,copying routing] +Addresses with the same domain are normally routed by the ^dnslookup^ router +to the same list of hosts. However, this cannot be presumed, because the router +options and preconditions may refer to the local part of the address. By +default, therefore, Exim routes each address in a message independently. DNS +servers run caches, so repeated DNS lookups are not normally expensive, and in +any case, personal messages rarely have more than a few recipients. + +If you are running mailing lists with large numbers of subscribers at the same +domain, and you are using a ^dnslookup^ router which is independent of the +local part, you can set %same_domain_copy_routing% to bypass repeated DNS +lookups for identical domains in one message. In this case, when ^dnslookup^ +routes an address to a remote transport, any other unrouted addresses in the +message that have the same domain are automatically given the same routing +without processing them independently, +provided the following conditions are met: + +- No router that processed the address specified %headers_add% or +%headers_remove%. + +- The router did not change the address in any way, for example, by ``widening'' +the domain. + + + + +oindex:[%search_parents%] +`..'= +%search_parents%, Use: 'dnslookup', Type: 'boolean', Default: 'false' +=== + +cindex:[DNS,resolver options] +When this option is true, the resolver option RES_DNSRCH is set for DNS +lookups. This is different from the %qualify_single% option in that it applies +to domains containing dots. Typically, but not standardly, it causes the +resolver to search for the name in the current domain and in parent domains. +For example, on a machine in the 'fict.example' domain, if looking up +'teaparty.wonderland' failed, the resolver would try +'teaparty.wonderland.fict.example'. For details of what your resolver +actually does, consult your man pages for 'resolver' and 'resolv.conf'. + +Setting this option true can cause problems in domains that have a wildcard MX +record, because any domain that does not have its own MX record matches the +local wildcard. + + + +oindex:[%srv_fail_domains%] +`..'= +%srv_fail_domains%, Use: 'dnslookup', Type: 'domain list'!!, Default: 'unset' +=== + +If the DNS lookup for SRV records for one of the domains in this list causes a +DNS lookup error, Exim behaves as if no SRV records were found. See section +<<SECTprowitdnsloo>> for more discussion. + + + + +oindex:[%widen_domains%] +`..'= +%widen_domains%, Use: 'dnslookup', Type: 'string list', Default: 'unset' +=== + +cindex:[domain,partial; widening] +If a DNS lookup fails and this option is set, each of its strings in turn is +added onto the end of the domain, and the lookup is tried again. For example, +if + + widen_domains = fict.example:ref.example + +is set and a lookup of 'klingon.dictionary' fails, +'klingon.dictionary.fict.example' is looked up, and if this fails, +'klingon.dictionary.ref.example' is tried. Note that the %qualify_single% +and %search_parents% options can cause some widening to be undertaken inside +the DNS resolver. + + + +Effect of qualify_single and search_parents +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +When a domain from an envelope recipient is changed by the resolver as a result +of the %qualify_single% or %search_parents% options, Exim rewrites the +corresponding address in the message's header lines unless %rewrite_headers% +is set false. Exim then re-routes the address, using the full domain. + +These two options affect only the DNS lookup that takes place inside the router +for the domain of the address that is being routed. They do not affect lookups +such as that implied by + + domains = @mx_any + +that may happen while processing a router precondition before the router is +entered. No widening ever takes place for these lookups. + + + + + + + + + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// + +The ipliteral router +-------------------- +cindex:[^ipliteral^ router] +cindex:[domain literal,routing] +cindex:[routers,^ipliteral^] +This router has no private options. Unless it is being used purely for +verification (see %verify_only%) a transport is required to be defined by the +generic %transport% option. The router accepts the address if its domain part +takes the form of an RFC 2822 domain literal, that is, an IP address enclosed +in square brackets. For example, this router handles the address + + root@[192.168.1.1] + +by setting up delivery to the host with that IP address. + +cindex:[%self% option,in ^ipliteral^ router] +If the IP address matches something in %ignore_target_hosts%, the router +declines. If an IP literal turns out to refer to the local host, the generic +%self% option determines what happens. + +The RFCs require support for domain literals; however, their use is +controversial in today's Internet. If you want to use this router, you must +also set the main configuration option %allow_domain_literals%. Otherwise, +Exim will not recognize the domain literal syntax in addresses. + + + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// + +The iplookup router +------------------- +cindex:[^iplookup^ router] +cindex:[routers,^iplookup^] +The ^iplookup^ router was written to fulfil a specific requirement in +Cambridge University (which in fact no longer exists). For this reason, it is +not included in the binary of Exim by default. If you want to include it, you +must set + + ROUTER_IPLOOKUP=yes + +in your _Local/Makefile_ configuration file. + +The ^iplookup^ router routes an address by sending it over a TCP or UDP +connection to one or more specific hosts. The host can then return the same or +a different address -- in effect rewriting the recipient address in the +message's envelope. The new address is then passed on to subsequent routers. If +this process fails, the address can be passed on to other routers, or delivery +can be deferred. + +Background, for those that are interested: We have an Oracle database of all +Cambridge users, and one of the items of data it maintains for each user is +where to send mail addressed to 'user@cam.ac.uk'. The MX records for +'cam.ac.uk' point to a central machine that has a large alias list that is +abstracted from the database. Mail from outside is switched by this system, and +originally internal mail was also done this way. However, this resulted in a +fair number of messages travelling from some of our larger systems to the +switch and back again. The Oracle machine now runs a UDP service that can be +called by the ^iplookup^ router in Exim to find out where 'user@cam.ac.uk' +addresses really have to go; this saves passing through the central switch, and +in many cases saves doing any remote delivery at all. + +Since ^iplookup^ is just a rewriting router, a transport must not be +specified for it. +cindex:[options,^iplookup^ router] + + +oindex:[%hosts%] +`..'= +%hosts%, Use: 'iplookup', Type: 'string', Default: 'unset' +=== + +This option must be supplied. Its value is a colon-separated list of host +names. The hosts are looked up using 'gethostbyname()' +(or 'getipnodebyname()' when available) +and are tried in order until one responds to the query. If none respond, what +happens is controlled by %optional%. + + +oindex:[%optional%] +`..'= +%optional%, Use: 'iplookup', Type: 'boolean', Default: 'false' +=== + +If %optional% is true, if no response is obtained from any host, the address is +passed to the next router, overriding %no_more%. If %optional% is false, +delivery to the address is deferred. + + +oindex:[%port%] +`..'= +%port%, Use: 'iplookup', Type: 'integer', Default: '0' +=== + +cindex:[port,^iplookup^ router] +This option must be supplied. It specifies the port number for the TCP or UDP +call. + + +oindex:[%protocol%] +`..'= +%protocol%, Use: 'iplookup', Type: 'string', Default: 'udp' +=== + +This option can be set to ``udp'' or ``tcp'' to specify which of the two protocols +is to be used. + + +oindex:[%query%] +`..'= +%query%, Use: 'iplookup', Type: 'string'!!, Default: `\$local_part@\$domain \$local_part@\$domain` +=== + +This defines the content of the query that is sent to the remote hosts. The +repetition serves as a way of checking that a response is to the correct query +in the default case (see %response_pattern% below). + + +oindex:[%reroute%] +`..'= +%reroute%, Use: 'iplookup', Type: 'string'!!, Default: 'unset' +=== + +If this option is not set, the rerouted address is precisely the byte string +returned by the remote host, up to the first white space, if any. If set, the +string is expanded to form the rerouted address. It can include parts matched +in the response by %response_pattern% by means of numeric variables such as +$1$, $2$, etc. The variable $0$ refers to the entire input string, +whether or not a pattern is in use. In all cases, the rerouted address must end +up in the form 'local_part@domain'. + + +oindex:[%response_pattern%] +`..'= +%response_pattern%, Use: 'iplookup', Type: 'string', Default: 'unset' +=== + +This option can be set to a regular expression that is applied to the string +returned from the remote host. If the pattern does not match the response, the +router declines. If %response_pattern% is not set, no checking of the response +is done, unless the query was defaulted, in which case there is a check that +the text returned after the first white space is the original address. This +checks that the answer that has been received is in response to the correct +question. For example, if the response is just a new domain, the following +could be used: + + response_pattern = ^([^@]+)$ + reroute = $local_part@$1 + + + +oindex:[%timeout%] +`..'= +%timeout%, Use: 'iplookup', Type: 'time', Default: '5s' +=== + +This specifies the amount of time to wait for a response from the remote +machine. The same timeout is used for the 'connect()' function for a TCP +call. It does not apply to UDP. + + + + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// + +The manualroute router +---------------------- +cindex:[^manualroute^ router] +cindex:[routers,^manualroute^] +cindex:[domain,manually routing] +The ^manualroute^ router is so-called because it provides a way of manually +routing an address according to its domain. It is mainly used when you want to +route addresses to remote hosts according to your own rules, bypassing the +normal DNS routing that looks up MX records. However, ^manualroute^ can also +route to local transports, a facility that may be useful if you want to save +messages for dial-in hosts in local files. + +The ^manualroute^ router compares a list of domain patterns with the domain it +is trying to route. If there is no match, the router declines. Each pattern has +associated with it a list of hosts and some other optional data, which may +include a transport. The combination of a pattern and its data is called a +``routing rule''. For patterns that do not have an associated transport, the +generic %transport% option must specify a transport, unless the router is being +used purely for verification (see %verify_only%). + +In the case of verification, matching the domain pattern is sufficient for the +router to accept the address. When actually routing an address for delivery, +an address that matches a domain pattern is queued for the associated +transport. If the transport is not a local one, a host list must be associated +with the pattern; IP addresses are looked up for the hosts, and these are +passed to the transport along with the mail address. For local transports, a +host list is optional. If it is present, it is passed in $host$ as a single +text string. + +The list of routing rules can be provided as an inline string in %route_list%, +or the data can be obtained by looking up the domain in a file or database by +setting %route_data%. Only one of these settings may appear in any one +instance of ^manualroute^. The format of routing rules is described below, +following the list of private options. + + +[[SECTprioptman]] +Private options for manualroute +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +cindex:[options,^manualroute^ router] +The private options for the ^manualroute^ router are as follows: + + +oindex:[%host_find_failed%] +`..'= +%host_find_failed%, Use: 'manualroute', Type: 'string', Default: 'freeze' +=== + +This option controls what happens when ^manualroute^ tries to find an IP +address for a host, and the host does not exist. The option can be set to one +of + + decline + defer + fail + freeze + pass + +The default assumes that this state is a serious configuration error. The +difference between ``pass'' and ``decline'' is that the former forces the address +to be passed to the next router (or the router defined by %pass_router%), +cindex:[%more% option] +overriding %no_more%, whereas the latter passes the address to the next router +only if %more% is true. + +This option applies only to a definite ``does not exist'' state; if a host lookup +gets a temporary error, delivery is deferred unless the generic +%pass_on_timeout% option is set. + + +oindex:[%hosts_randomize%] +`..'= +%hosts_randomize%, Use: 'manualroute', Type: 'boolean', Default: 'false' +=== + +cindex:[randomized host list] +cindex:[host,list of; randomized] +If this option is set, the order of the items in a host list in a routing rule +is randomized each time the list is used, unless an option in the routing rule +overrides (see below). Randomizing the order of a host list can be used to do +crude load sharing. However, if more than one mail address is routed by the +same router to the same host list, the host lists are considered to be the same +(even though they may be randomized into different orders) for the purpose of +deciding whether to batch the deliveries into a single SMTP transaction. + +When %hosts_randomize% is true, a host list may be split +into groups whose order is separately randomized. This makes it possible to +set up MX-like behaviour. The boundaries between groups are indicated by an +item that is just `+` in the host list. For example: + + route_list = * host1:host2:host3:+:host4:host5 + +The order of the first three hosts and the order of the last two hosts is +randomized for each use, but the first three always end up before the last two. +If %hosts_randomize% is not set, a `+` item in the list is ignored. If a +randomized host list is passed to an ^smtp^ transport that also has +%hosts_randomize set%, the list is not re-randomized. + + +oindex:[%route_data%] +`..'= +%route_data%, Use: 'manualroute', Type: 'string'!!, Default: 'unset' +=== + +If this option is set, it must expand to yield the data part of a routing rule. +Typically, the expansion string includes a lookup based on the domain. For +example: + + route_data = ${lookup{$domain}dbm{/etc/routes}} + +If the expansion is forced to fail, or the result is an empty string, the +router declines. Other kinds of expansion failure cause delivery to be +deferred. + + +oindex:[%route_list%] +`..'= +%route_list%, Use: 'manualroute', "Type: 'string list, semicolon-separated'", Default: 'unset' +=== + +This string is a list of routing rules, in the form defined below. Note that, +unlike most string lists, the items are separated by semicolons. This is so +that they may contain colon-separated host lists. + + +oindex:[%same_domain_copy_routing%] +`..'= +%same_domain_copy_routing%, Use: 'manualroute', Type: 'boolean', Default: 'false' +=== + +cindex:[address,copying routing] +Addresses with the same domain are normally routed by the ^manualroute^ router +to the same list of hosts. However, this cannot be presumed, because the router +options and preconditions may refer to the local part of the address. By +default, therefore, Exim routes each address in a message independently. DNS +servers run caches, so repeated DNS lookups are not normally expensive, and in +any case, personal messages rarely have more than a few recipients. + +If you are running mailing lists with large numbers of subscribers at the same +domain, and you are using a ^manualroute^ router which is independent of the +local part, you can set %same_domain_copy_routing% to bypass repeated DNS +lookups for identical domains in one message. In this case, when ^manualroute^ +routes an address to a remote transport, any other unrouted addresses in the +message that have the same domain are automatically given the same routing +without processing them independently. However, this is only done if +%headers_add% and %headers_remove% are unset. + + + + +Routing rules in route_list +~~~~~~~~~~~~~~~~~~~~~~~~~~~ +The value of %route_list% is a string consisting of a sequence of routing +rules, separated by semicolons. If a semicolon is needed in a rule, it can be +entered as two semicolons. Empty rules are ignored. The format of each rule is + + <domain pattern> <list of hosts> <options> + +The following example contains two rules, each with a simple domain pattern and +no options: + +.... +route_list = \ + dict.ref.example mail-1.ref.example:mail-2.ref.example ; \ + thes.ref.example mail-3.ref.example:mail-4.ref.example +.... + +The three parts of a rule are separated by white space. The pattern and the +list of hosts can be enclosed in quotes if necessary, and if they are, the +usual quoting rules apply. Each rule in a %route_list% must start with a +single domain pattern, which is the only mandatory item in the rule. The +pattern is in the same format as one item in a domain list (see section +<<SECTdomainlist>>), +except that it may not be the name of an interpolated file. +That is, it may be wildcarded, or a regular expression, or a file or database +lookup (with semicolons doubled, because of the use of semicolon as a separator +in a %route_list%). + +The rules in %route_list% are searched in order until one of the patterns +matches the domain that is being routed. The list of hosts and then options are +then used as described below. If there is no match, the router declines. When +%route_list% is set, %route_data% must not be set. + + + +Routing rules in route_data +~~~~~~~~~~~~~~~~~~~~~~~~~~~ +The use of %route_list% is convenient when there are only a small number of +routing rules. For larger numbers, it is easier to use a file or database to +hold the routing information, and use the %route_data% option instead. +The value of %route_data% is a list of hosts, followed by (optional) options. +Most commonly, %route_data% is set as a string that contains an +expansion lookup. For example, suppose we place two routing rules in a file +like this: + + dict.ref.example: mail-1.ref.example:mail-2.ref.example + thes.ref.example: mail-3.ref.example:mail-4.ref.example + +This data can be accessed by setting + + route_data = ${lookup{$domain}lsearch{/the/file/name}} + +Failure of the lookup results in an empty string, causing the router to +decline. However, you do not have to use a lookup in %route_data%. The only +requirement is that the result of expanding the string is a list of hosts, +possibly followed by options, separated by white space. The list of hosts must +be enclosed in quotes if it contains white space. + + + + +Format of the list of hosts +~~~~~~~~~~~~~~~~~~~~~~~~~~~ +A list of hosts, whether obtained via %route_data% or %route_list%, is always +separately expanded before use. If the expansion fails, the router declines. +The result of the expansion must be a colon-separated list of names and/or +IP addresses. IP addresses are not enclosed in brackets. + +If the list of hosts was obtained from a %route_list% item, the following +variables are set during its expansion: + +- cindex:[numerical variables ($1$ $2$ etc),in ^manualroute^ router] +If the domain was matched against a regular expression, the numeric variables +$1$, $2$, etc. may be set. + +- $0$ is always set to the entire domain. + +- $1$ is also set when partial matching is done in a file lookup. + +- cindex:[$value$] +If the pattern that matched the domain was a lookup item, the data that was +looked up is available in the expansion variable $value$. + + + + +How the list of hosts is used +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +When an address is routed to an ^smtp^ transport by ^manualroute^, each of +the hosts is tried, in the order specified, when carrying out the SMTP +delivery. However, the order can be changed by setting the %hosts_randomize% +option, either on the router (see section <<SECTprioptman>> above), or on the +transport. + +Hosts may be listed by name or by IP address. An unadorned name in the list of +hosts is interpreted as a host name. A name that is followed by `/MX` is +interpreted as an indirection to a sublist of hosts obtained by looking up MX +records in the DNS. For example: + + route_list = * x.y.z:p.q.r/MX:e.f.g + +If the %hosts_randomize% option is set, the order of the items in the list is +randomized before any lookups are done. Exim then scans the list; for any name +that is not followed by `/MX` it looks up an IP address. If this turns out to +be an interface on the local host and the item is not the first in the list, +Exim discards it and any subsequent items. If it is the first item, what +happens is controlled by the +cindex:[%self% option,in ^manualroute^ router] +%self% option of the router. + +A name on the list that is followed by `/MX` is replaced with the list of +hosts obtained by looking up MX records for the name. This is always a DNS +lookup; the %bydns% and %byname% options (see section <<SECThowoptused>> below) +are not relevant here. The order of these hosts is determined by the preference +values in the MX records, according to the usual rules. Because randomizing +happens before the MX lookup, it does not affect the order that is defined by +MX preferences. + +If the local host is present in the sublist obtained from MX records, but is +not the most preferred host in that list, it and any equally or less +preferred hosts are removed before the sublist is inserted into the main list. + +If the local host is the most preferred host in the MX list, what happens +depends on where in the original list of hosts the `/MX` item appears. If it +is not the first item (that is, there are previous hosts in the main list), +Exim discards this name and any subsequent items in the main list. + +If the MX item is first in the list of hosts, and the local host is the +most preferred host, what happens is controlled by the %self% option of the +router. + +DNS failures when lookup up the MX records are treated in the same way as DNS +failures when looking up IP addresses: %pass_on_timeout% and +%host_find_failed% are used when relevant. + +The generic %ignore_target_hosts% option applies to all hosts in the list, +whether obtained from an MX lookup or not. + + + +[[SECThowoptused]] +How the options are used +~~~~~~~~~~~~~~~~~~~~~~~~ +The options are a sequence of words; in practice no more than three are ever +present. One of the words can be the name of a transport; this overrides the +%transport% option on the router for this particular routing rule only. The +other words (if present) control randomization of the list of hosts on a +per-rule basis, and how the IP addresses of the hosts are to be found when +routing to a remote transport. These options are as follows: + +- %randomize%: randomize the order of the hosts in this list, overriding the +setting of %hosts_randomize% for this routing rule only. + +- %no_randomize%: do not randomize the order of the hosts in this list, +overriding the setting of %hosts_randomize% for this routing rule only. + +- %byname%: use 'getipnodebyname()' ('gethostbyname()' on older systems) to +find IP addresses. This function may ultimately cause a DNS lookup, but it may +also look in _/etc/hosts_ or other sources of information. + +- %bydns%: look up address records for the hosts directly in the DNS; fail if +no address records are found. If there is a temporary DNS error (such as a +timeout), delivery is deferred. + +For example: + +.... +route_list = domain1 host1:host2:host3 randomize bydns;\ + domain2 host4:host5 +.... + +If neither %byname% nor %bydns% is given, Exim behaves as follows: First, a DNS +lookup is done. If this yields anything other than HOST_NOT_FOUND, that +result is used. Otherwise, Exim goes on to try a call to 'getipnodebyname()' +or 'gethostbyname()', and the result of the lookup is the result of that +call. + +*Warning*: It has been discovered that on some systems, if a DNS lookup +called via 'getipnodebyname()' times out, HOST_NOT_FOUND is returned +instead of TRY_AGAIN. That is why the default action is to try a DNS +lookup first. Only if that gives a definite ``no such host'' is the local +function called. + + + +If no IP address for a host can be found, what happens is controlled by the +%host_find_failed% option. + +When an address is routed to a local transport, IP addresses are not looked up. +The host list is passed to the transport in the $host$ variable. + + + +Manualroute examples +~~~~~~~~~~~~~~~~~~~~ +In some of the examples that follow, the presence of the %remote_smtp% +transport, as defined in the default configuration file, is assumed: + +- cindex:[smart host,example router] +The ^manualroute^ router can be used to forward all external mail to a +'smart host'. If you have set up, in the main part of the configuration, a +named domain list that contains your local domains, for example, + + domainlist local_domains = my.domain.example ++ +you can arrange for all other domains to be routed to a smart host by making +your first router something like this: ++ + smart_route: + driver = manualroute + domains = !+local_domains + transport = remote_smtp + route_list = * smarthost.ref.example ++ +This causes all non-local addresses to be sent to the single host +'smarthost.ref.example'. If a colon-separated list of smart hosts is given, +they are tried in order +(but you can use %hosts_randomize% to vary the order each time). +Another way of configuring the same thing is this: ++ + smart_route: + driver = manualroute + transport = remote_smtp + route_list = !+local_domains smarthost.ref.example ++ +There is no difference in behaviour between these two routers as they stand. +However, they behave differently if %no_more% is added to them. In the first +example, the router is skipped if the domain does not match the %domains% +precondition; the following router is always tried. If the router runs, it +always matches the domain and so can never decline. Therefore, %no_more% would +have no effect. In the second case, the router is never skipped; it always +runs. However, if it doesn't match the domain, it declines. In this case +%no_more% would prevent subsequent routers from running. + +- cindex:[mail hub example] +A 'mail hub' is a host which receives mail for a number of domains via MX +records in the DNS and delivers it via its own private routing mechanism. Often +the final destinations are behind a firewall, with the mail hub being the one +machine that can connect to machines both inside and outside the firewall. The +^manualroute^ router is usually used on a mail hub to route incoming messages +to the correct hosts. For a small number of domains, the routing can be inline, +using the %route_list% option, but for a larger number a file or database +lookup is easier to manage. ++ +If the domain names are in fact the names of the machines to which the mail is +to be sent by the mail hub, the configuration can be quite simple. For +example, + + hub_route: + driver = manualroute + transport = remote_smtp + route_list = *.rhodes.tvs.example $domain ++ +This configuration routes domains that match `*.rhodes.tvs.example` to hosts +whose names are the same as the mail domains. A similar approach can be taken +if the host name can be obtained from the domain name by a string manipulation +that the expansion facilities can handle. Otherwise, a lookup based on the +domain can be used to find the host: + + through_firewall: + driver = manualroute + transport = remote_smtp + route_data = ${lookup {$domain} cdb {/internal/host/routes}} ++ +The result of the lookup must be the name or IP address of the host (or +hosts) to which the address is to be routed. If the lookup fails, the route +data is empty, causing the router to decline. The address then passes to the +next router. + +- cindex:[batched SMTP output example] +cindex:[SMTP,batched outgoing; example] +You can use ^manualroute^ to deliver messages to pipes or files in batched +SMTP format for onward transportation by some other means. This is one way of +storing mail for a dial-up host when it is not connected. The route list entry +can be as simple as a single domain name in a configuration like this: + + save_in_file: + driver = manualroute + transport = batchsmtp_appendfile + route_list = saved.domain.example ++ +though often a pattern is used to pick up more than one domain. If there are +several domains or groups of domains with different transport requirements, +different transports can be listed in the routing information: ++ +.... +save_in_file: + driver = manualroute + route_list = \ + *.saved.domain1.example $domain batch_appendfile; \ + *.saved.domain2.example \ + ${lookup{$domain}dbm{/domain2/hosts}{$value}fail} \ + batch_pipe +.... ++ +The first of these just passes the domain in the $host$ variable, which +doesn't achieve much (since it is also in $domain$), but the second does a +file lookup to find a value to pass, causing the router to decline to handle +the address if the lookup fails. + +- cindex:[UUCP,example of router for] +Routing mail directly to UUCP software is a specific case of the use of +^manualroute^ in a gateway to another mail environment. This is an example of +one way it can be done: ++ +.... +# Transport +uucp: + driver = pipe + user = nobody + command = /usr/local/bin/uux -r - \ + ${substr_-5:$host}!rmail ${local_part} + return_fail_output = true + +# Router +uucphost: + transport = uucp + driver = manualroute + route_data = \ + ${lookup{$domain}lsearch{/usr/local/exim/uucphosts}} +.... ++ +The file _/usr/local/exim/uucphosts_ contains entries like + + darksite.ethereal.example: darksite.UUCP ++ +It can be set up more simply without adding and removing ``.UUCP'' but this way +makes clear the distinction between the domain name +'darksite.ethereal.example' and the UUCP host name 'darksite'. + + + + + + + + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// + +[[CHAPdriverlast]] +The queryprogram router +----------------------- +cindex:[^queryprogram^ router] +cindex:[routers,^queryprogram^] +cindex:[routing,by external program] +The ^queryprogram^ router routes an address by running an external command and +acting on its output. This is an expensive way to route, and is intended mainly +for use in lightly-loaded systems, or for performing experiments. However, if +it is possible to use the precondition options (%domains%, %local_parts%, +etc) to skip this router for most addresses, it could sensibly be used in +special cases, even on a busy host. There are the following private options: +cindex:[options,^queryprogram^ router] + +oindex:[%command%] +`..'= +%command%, Use: 'queryprogram', Type: 'string'!!, Default: 'unset' +=== + +This option must be set. It specifies the command that is to be run. The +command is split up into a command name and arguments, and then each is +expanded separately (exactly as for a ^pipe^ transport, described in chapter +<<CHAPpipetransport>>). + + +oindex:[%command_group%] +`..'= +%command_group%, Use: 'queryprogram', Type: 'string', Default: 'unset' +=== + +cindex:[gid (group id),in ^queryprogram^ router] +This option specifies a gid to be set when running the command. It must be set +if %command_user% specifies a numerical uid. If it begins with a digit, it is +interpreted as the numerical value of the gid. Otherwise it is looked up using +'getgrnam()'. + + +oindex:[%command_user%] +`..'= +%command_user%, Use: 'queryprogram', Type: 'string', Default: 'unset' +=== + +cindex:[uid (user id),for ^queryprogram^] +This option must be set. It specifies the uid which is set when running the +command. If it begins with a digit it is interpreted as the numerical value of +the uid. Otherwise, it is looked up using 'getpwnam()' to obtain a value for +the uid and, if %command_group% is not set, a value for the gid also. + + +oindex:[%current_directory%] +`..'= +%current_directory%, Use: 'queryprogram', Type: 'string', Default: '/' +=== + +This option specifies an absolute path which is made the current directory +before running the command. + + +oindex:[%timeout%] +`..'= +%timeout%, Use: 'queryprogram', Type: 'time', Default: '1h' +=== + +If the command does not complete within the timeout period, its process group +is killed and the message is frozen. A value of zero time specifies no +timeout. + + +The standard output of the command is connected to a pipe, which is read when +the command terminates. It should consist of a single line of output, +containing up to five fields, separated by white space. The maximum length of +the line is 1023 characters. Longer lines are silently truncated. The first +field is one of the following words (case-insensitive): + +- 'Accept': routing succeeded; the remaining fields specify what to do (see +below). + +- 'Decline': the router declines; pass the address to the next router, unless +%no_more% is set. + +- 'Fail': routing failed; do not pass the address to any more routers. Any +subsequent text on the line is an error message. If the router is run as part +of address verification during an incoming SMTP message, the message is +included in the SMTP response. + +- 'Defer': routing could not be completed at this time; try again later. Any +subsequent text on the line is an error message which is logged. It is not +included in any SMTP response. + +- 'Freeze': the same as 'defer', except that the message is frozen. + +- 'Pass': pass the address to the next router (or the router specified by +%pass_router%), overriding %no_more%. + +- 'Redirect': the message is redirected. The remainder of the line is a list of +new addresses, which are routed independently, starting with the first router, +or the router specified by %redirect_router%, if set. + +When the first word is 'accept', the remainder of the line consists of a +number of keyed data values, as follows (split into two lines here, to fit on +the page): + + ACCEPT TRANSPORT=<transport> HOSTS=<list of hosts> + LOOKUP=byname|bydns DATA=<text> + +The data items can be given in any order, and all are optional. If no transport +is included, the transport specified by the generic %transport% option is used. +The list of hosts and the lookup type are needed only if the transport is an +^smtp^ transport that does not itself supply a list of hosts. + +The format of the list of hosts is the same as for the ^manualroute^ router. +As well as host names and IP addresses, it may contain names followed by +`/MX` to specify sublists of hosts that are obtained by looking up MX +records. + +If the lookup type is not specified, Exim behaves as follows when trying to +find an IP address for each host: First, a DNS lookup is done. If this yields +anything other than HOST_NOT_FOUND, that result is used. Otherwise, Exim +goes on to try a call to 'getipnodebyname()' or 'gethostbyname()', and the +result of the lookup is the result of that call. + +If the DATA field is set, its value is placed in the $address_data$ +variable. For example, this return line + + accept hosts=x1.y.example:x2.y.example data="rule1" + +routes the address to the default transport, passing a list of two hosts. When +the transport runs, the string ``rule1'' is in $address_data$. + + + + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// + +[[CHAPredirect]] +The redirect router +------------------- +cindex:[^redirect^ router] +cindex:[routers,^redirect^] +cindex:[alias file,in a ^redirect^ router] +cindex:[address redirection,^redirect^ router] +The ^redirect^ router handles several kinds of address redirection. Its most +common uses are for resolving local part aliases from a central alias file +(usually called _/etc/aliases_) and for handling users' personal _.forward_ +files, but it has many other potential uses. The incoming address can be +redirected in several different ways: + +- It can be replaced by one or more new addresses which are themselves routed +independently. + +- It can be routed to be delivered to a given file or directory. + +- It can be routed to be delivered to a specified pipe command. + +- It can cause an automatic reply to be generated. + +- It can be forced to fail, with a custom error message. + +- It can be temporarily deferred. + +- It can be discarded. + +The generic %transport% option must not be set for ^redirect^ routers. +However, there are some private options which define transports for delivery to +files and pipes, and for generating autoreplies. See the %file_transport%, +%pipe_transport% and %reply_transport% descriptions below. + + + +Redirection data +~~~~~~~~~~~~~~~~ +The router operates by interpreting a text string which it obtains either by +expanding the contents of the %data% option, or by reading the entire contents +of a file whose name is given in the %file% option. These two options are +mutually exclusive. The first is commonly used for handling system aliases, in +a configuration like this: + + system_aliases: + driver = redirect + data = ${lookup{$local_part}lsearch{/etc/aliases}} + +If the lookup fails, the expanded string in this example is empty. When the +expansion of %data% results in an empty string, the router declines. A forced +expansion failure also causes the router to decline; other expansion failures +cause delivery to be deferred. + +A configuration using %file% is commonly used for handling users' _.forward_ +files, like this: + + userforward: + driver = redirect + check_local_user + file = $home/.forward + no_verify + +If the file does not exist, or causes no action to be taken (for example, it is +empty or consists only of comments), the router declines. *Warning*: This +is not the case when the file contains syntactically valid items that happen to +yield empty addresses, for example, items containing only RFC 2822 address +comments. + + + +Forward files and address verification +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[address redirection,while verifying] +It is usual to set %no_verify% on ^redirect^ routers which handle users' +_.forward_ files, as in the example above. There are two reasons for this: + +- When Exim is receiving an incoming SMTP message from a remote host, it is +running under the Exim uid, not as root. +No additional groups are set up, even if the Exim uid is a member of other +groups (that is, the 'initgroups()' function is not run). +Exim is unable to change uid to read the file as the user, and it may not be +able to read it as the Exim user. So in practice the router may not be able to +operate. + +- However, even when the router can operate, the existence of a _.forward_ file +is unimportant when verifying an address. What should be checked is whether the +local part is a valid user name or not. Cutting out the redirection processing +saves some resources. + + + + + + +Interpreting redirection data +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[Sieve filter,specifying in redirection data] +cindex:[filter,specifying in redirection data] +The contents of the data string, whether obtained from %data% or %file%, can be +interpreted in two different ways: + +- If the %allow_filter% option is set true, and the data begins with the text +``#Exim filter'' or ``#Sieve filter'', it is interpreted as a list of +'filtering' instructions in the form of an Exim or Sieve filter file, +respectively. Details of the syntax and semantics of filter files are described +in a separate document entitled 'Exim's interfaces to mail filtering'; this +document is intended for use by end users. + +- Otherwise, the data must be a comma-separated list of redirection items, as +described in the next section. + +When a message is redirected to a file (a ``mail folder''), the file name given +in a non-filter redirection list must always be an absolute path. A filter may +generate a relative path -- how this is handled depends on the transport's +configuration. See section <<SECTfildiropt>> for a discussion of this issue for +the ^appendfile^ transport. + + + +[[SECTitenonfilred]] +Items in a non-filter redirection list +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[address redirection,non-filter list items] +When the redirection data is not an Exim or Sieve filter, for example, if it +comes from a conventional alias or forward file, it consists of a list of +addresses, file names, pipe commands, or certain special items (see section +<<SECTspecitredli>> below). The special items can be individually enabled or +disabled by means of options whose names begin with %allow_% or %forbid_%, +depending on their default values. The items in the list are separated by +commas or newlines. +If a comma is required in an item, the entire item must be enclosed in double +quotes. + +Lines starting with a # character are comments, and are ignored, and # may +also appear following a comma, in which case everything between the # and the +next newline character is ignored. + +If an item is entirely enclosed in double quotes, these are removed. Otherwise +double quotes are retained because some forms of mail address require their use +(but never to enclose the entire address). In the following description, ``item'' +refers to what remains after any surrounding double quotes have been removed. + +*Warning*: If you use an Exim expansion to construct a redirection address, +and the expansion contains a reference to $local_part$, you should make use +of the %quote% expansion operator, in case the local part contains special +characters. For example, to redirect all mail for the domain +'obsolete.example', retaining the existing local part, you could use this +setting: + + data = ${quote:$local_part}@newdomain.example + + + + +[[SECTredlocmai]] +Redirecting to a local mailbox +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[routing,loops in] +cindex:[loop while routing, avoidance of] +cindex:[address redirection,to local mailbox] +A redirection item may safely be the same as the address currently under +consideration. This does not cause a routing loop, because a router is +automatically skipped if any ancestor of the address that is being processed +is the same as the current address and was processed by the current router. +Such an address is therefore passed to the following routers, so it is handled +as if there were no redirection. When making this loop-avoidance test, the +complete local part, including any prefix or suffix, is used. + +cindex:[address redirection,local part without domain] +Specifying the same local part without a domain is a common usage in personal +filter files when the user wants to have messages delivered to the local +mailbox and also forwarded elsewhere. For example, the user whose login is +'cleo' might have a _.forward_ file containing this: + + cleo, cleopatra@egypt.example + +cindex:[backslash in alias file] +cindex:[alias file,backslash in] +For compatibility with other MTAs, such unqualified local parts may be +preceeded by ``\'', but this is not a requirement for loop prevention. However, +it does make a difference if more than one domain is being handled +synonymously. + +If an item begins with ``\'' and the rest of the item parses as a valid RFC 2822 +address that does not include a domain, the item is qualified using the domain +of the incoming address. In the absence of a leading ``\'', unqualified +addresses are qualified using the value in %qualify_recipient%, but you can +force the incoming domain to be used by setting %qualify_preserve_domain%. + +Care must be taken if there are alias names for local users. +Consider an MTA handling a single local domain where the system alias file +contains: + + Sam.Reman: spqr + +Now suppose that Sam (whose login id is 'spqr') wants to save copies of +messages in the local mailbox, and also forward copies elsewhere. He creates +this forward file: + + Sam.Reman, spqr@reme.elsewhere.example + +With these settings, an incoming message addressed to 'Sam.Reman' fails. The +^redirect^ router for system aliases does not process 'Sam.Reman' the +second time round, because it has previously routed it, +and the following routers presumably cannot handle the alias. The forward file +should really contain + + spqr, spqr@reme.elsewhere.example + +but because this is such a common error, the %check_ancestor% option (see +below) exists to provide a way to get round it. This is normally set on a +^redirect^ router that is handling users' _.forward_ files. + + + +[[SECTspecitredli]] +Special items in redirection lists +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +In addition to addresses, the following types of item may appear in redirection +lists (that is, in non-filter redirection data): + +- cindex:[pipe,in redirection list] +cindex:[address redirection,to pipe] +An item is treated as a pipe command if it begins with ``|'' and does not parse +as a valid RFC 2822 address that includes a domain. A transport for running the +command must be specified by the %pipe_transport% option. +Normally, either the router or the transport specifies a user and a group under +which to run the delivery. The default is to use the Exim user and group. ++ +Single or double quotes can be used for enclosing the individual arguments of +the pipe command; no interpretation of escapes is done for single quotes. If +the command contains a comma character, it is necessary to put the whole item +in double quotes, for example: + + "|/some/command ready,steady,go" ++ +since items in redirection lists are terminated by commas. Do not, however, +quote just the command. An item such as + + |"/some/command ready,steady,go" ++ +is interpreted as a pipe with a rather strange command name, and no arguments. + +- cindex:[file,in redirection list] +cindex:[address redirection,to file] +An item is interpreted as a path name if it begins with ``/'' and does not parse +as a valid RFC 2822 address that includes a domain. For example, + + /home/world/minbari ++ +is treated as a file name, but + + /s=molari/o=babylon/@x400gate.way ++ +is treated as an address. For a file name, a transport must be specified using +the %file_transport% option. However, if the generated path name ends with a +forward slash character, it is interpreted as a directory name rather than a +file name, and %directory_transport% is used instead. ++ +Normally, either the router or the transport specifies a user and a group under +which to run the delivery. The default is to use the Exim user and group. ++ +cindex:[_/dev/null_] +However, if a redirection item is the path _/dev/null_, delivery to it is +bypassed at a high level, and the log entry shows ``\*\*bypassed\*\*'' +instead of a transport name. In this case the user and group are not used. + +- cindex:[included address list] +cindex:[address redirection,included external list] +If an item is of the form + + :include:<path name> ++ +a list of further items is taken from the given file and included at that +point. *Note*: such a file can not be a filter file; it is just an out-of-line +addition to the list. The items in the included list are separated by commas or +newlines and are not subject to expansion. If this is the first item in an +alias list in an ^lsearch^ file, a colon must be used to terminate the alias +name. This example is incorrect: + + list1 :include:/opt/lists/list1 ++ +It must be given as + + list1: :include:/opt/lists/list1 ++ +- cindex:[address redirection,to black hole] +Sometimes you want to throw away mail to a particular local part. Making the +%data% option expand to an empty string does not work, because that causes the +router to decline. Instead, the alias item +cindex:[black hole] +cindex:[abandoning mail] + + :blackhole: ++ +can be used. It does what its name implies. No delivery is done, and no error +message is generated. This has the same effect as specifing _/dev/null_, but +can be independently disabled. ++ +*Warning*: If `:blackhole:` appears anywhere in a redirection list, no +delivery is done for the original local part, even if other redirection items +are present. If you are generating a multi-item list (for example, by reading a +database) and need the ability to provide a no-op item, you must use +_/dev/null_. + +- cindex:[delivery,forcing failure] +cindex:[delivery,forcing deferral] +cindex:[failing delivery,forcing] +cindex:[deferred delivery, forcing] +cindex:[customizing,failure message] +An attempt to deliver a particular address can be deferred or forced to fail by +redirection items of the form + + :defer: + :fail: ++ +respectively. When a redirection list contains such an item, it applies to the +entire redirection; any other items in the list are ignored (':blackhole:' is +different). Any text following ':fail:' or ':defer:' is placed in the error +text associated with the failure. For example, an alias file might contain: + + X.Employee: :fail: Gone away, no forwarding address ++ +In the case of an address that is being verified from an ACL or as the subject +of a +cindex:[VRFY error text, display of] +VRFY command, the text is included in the SMTP error response by +default. +cindex:[EXPN error text, display of] +The text is not included in the response to an EXPN command. ++ +In an ACL, an explicitly provided message overrides the default, but the +default message is available in the variable $acl_verify_message$ and can +therefore be included in a custom message if this is desired. Exim sends a 451 +SMTP code for a ':defer:', and 550 for ':fail:'. In non-SMTP cases the text +is included in the error message that Exim generates. ++ +Normally the error text is the rest of the redirection list -- a comma does not +terminate it -- but a newline does act as a terminator. Newlines are not +normally present in alias expansions. In ^lsearch^ lookups they are removed as +part of the continuation process, but they may exist in other kinds of lookup +and in ':include:' files. ++ +During routing for message delivery (as opposed to verification), a redirection +containing ':fail:' causes an immediate failure of the incoming address, +whereas ':defer:' causes the message to remain on the queue so that a +subsequent delivery attempt can happen at a later time. If an address is +deferred for too long, it will ultimately fail, because the normal retry +rules still apply. + +- cindex:[alias file,exception to default] +Sometimes it is useful to use a single-key search type with a default (see +chapter <<CHAPfdlookup>>) to look up aliases. However, there may be a need for +exceptions to the default. These can be handled by aliasing them to + + :unknown: ++ +This differs from ':fail:' in that it causes the ^redirect^ router to decline, +whereas ':fail:' forces routing to fail. A lookup which results in an empty +redirection list has the same effect. + + + +Duplicate addresses +~~~~~~~~~~~~~~~~~~~ +cindex:[duplicate addresses] +cindex:[address duplicate, discarding] +cindex:[pipe,duplicated] +Exim removes duplicate addresses from the list to which it is delivering, so as +to deliver just one copy to each address. This does not apply to deliveries +routed to pipes by different immediate parent addresses, but an indirect +aliasing scheme of the type + + pipe: |/some/command $local_part + localpart1: pipe + localpart2: pipe + +does not work with a message that is addressed to both local parts, because +when the second is aliased to the intermediate local part ``pipe'' it gets +discarded as being the same as a previously handled address. However, a scheme +such as + + localpart1: |/some/command $local_part + localpart2: |/some/command $local_part + +does result in two different pipe deliveries, because the immediate parents of +the pipes are distinct. + + + +Repeated redirection expansion +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[repeated redirection expansion] +cindex:[address redirection,repeated for each delivery attempt] +When a message cannot be delivered to all of its recipients immediately, +leading to two or more delivery attempts, redirection expansion is carried out +afresh each time for those addresses whose children were not all previously +delivered. If redirection is being used as a mailing list, this can lead to new +members of the list receiving copies of old messages. The %one_time% option +can be used to avoid this. + + +Errors in redirection lists +~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[address redirection,errors] +If %skip_syntax_errors% is set, a malformed address that causes a parsing +error is skipped, and an entry is written to the main log. This may be useful +for mailing lists that are automatically managed. Otherwise, if an error is +detected while generating the list of new addresses, the original address is +deferred. See also %syntax_errors_to%. + + + +Private options for the redirect router +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +cindex:[options,^redirect^ router] +The private options for the ^redirect^ router are as follows: + + +oindex:[%allow_defer%] +`..'= +%allow_defer%, Use: 'redirect', Type: 'boolean', Default: 'false' +=== + +Setting this option allows the use of ':defer:' in non-filter redirection +data, +or the %defer% command in an Exim filter file. + + +oindex:[%allow_fail%] +`..'= +%allow_fail%, Use: 'redirect', Type: 'boolean', Default: 'false' +=== + +cindex:[failing delivery,from filter] +If this option is true, the ':fail:' item can be used in a redirection list, +and the %fail% command may be used in a filter file. + + +oindex:[%allow_filter%] +`..'= +%allow_filter%, Use: 'redirect', Type: 'boolean', Default: 'false' +=== + +cindex:[filter,enabling use of] +cindex:[Sieve filter,enabling use of] +Setting this option allows Exim to interpret redirection data that starts with +``#Exim filter'' or ``#Sieve filter'' as a set of filtering instructions. There +are some features of Exim filter files that some administrators may wish to +lock out; see the %forbid_filter_xxx% options below. + +It is also possible to lock out Exim filters or Sieve filters while allowing +the other type; see %forbid_exim_filter% and %forbid_sieve_filter%. + + +The filter is run using the uid and gid set by the generic %user% and %group% +options. These take their defaults from the password data if +%check_local_user% is set, so in the normal case of users' personal filter +files, the filter is run as the relevant user. When %allow_filter% is set +true, Exim insists that either %check_local_user% or %user% is set. + + + +oindex:[%allow_freeze%] +`..'= +%allow_freeze%, Use: 'redirect', Type: 'boolean', Default: 'false' +=== + +cindex:[freezing messages,allowing in filter] +Setting this option allows the use of the %freeze% command in an Exim filter. +This command is more normally encountered in system filters, and is disabled by +default for redirection filters because it isn't something you usually want to +let ordinary users do. + + + +oindex:[%check_ancestor%] +`..'= +%check_ancestor%, Use: 'redirect', Type: 'boolean', Default: 'false' +=== + +This option is concerned with handling generated addresses that are the same +as some address in the list of redirection ancestors of the current address. +Although it is turned off by default in the code, it is set in the default +configuration file for handling users' _.forward_ files. It is recommended +for this use of the ^redirect^ router. + +When %check_ancestor% is set, if a generated address (including the domain) is +the same as any ancestor of the current address, it is replaced by a copy of +the current address. This helps in the case where local part A is aliased to B, +and B has a _.forward_ file pointing back to A. For example, within a single +domain, the local part ``Joe.Bloggs'' is aliased to ``jb'' and _~jb/.forward_ +contains: + + \Joe.Bloggs, <other item(s)> + +Without the %check_ancestor% setting, either local part (``jb'' or ``joe.bloggs'') +gets processed once by each router and so ends up as it was originally. If ``jb'' +is the real mailbox name, mail to ``jb'' gets delivered (having been turned into +``joe.bloggs'' by the _.forward_ file and back to ``jb'' by the alias), but mail +to ``joe.bloggs'' fails. Setting %check_ancestor% on the ^redirect^ router that +handles the _.forward_ file prevents it from turning ``jb'' back into +``joe.bloggs'' when that was the original address. See also the %repeat_use% +option below. + + +oindex:[%check_group%] +`..'= +%check_group%, Use: 'redirect', Type: 'boolean', Default: 'see below' +=== + +When the %file% option is used, the group owner of the file is checked only +when this option is set. The permitted groups are those listed in the +%owngroups% option, together with the user's default group if +%check_local_user% is set. If the file has the wrong group, routing is +deferred. The default setting for this option is true if %check_local_user% +is set and the %modemask% option permits the group write bit, or if the +%owngroups% option is set. Otherwise it is false, and no group check occurs. + + + +oindex:[%check_owner%] +`..'= +%check_owner%, Use: 'redirect', Type: 'boolean', Default: 'see below' +=== + +When the %file% option is used, the owner of the file is checked only when this +option is set. If %check_local_user% is set, the local user is permitted; +otherwise the owner must be one of those listed in the %owners% option. The +default value for this option is true if %check_local_user% or %owners% is +set. Otherwise the default is false, and no owner check occurs. + + +oindex:[%data%] +`..'= +%data%, Use: 'redirect', Type: 'string'!!, Default: 'unset' +=== + +This option is mutually exclusive with %file%. One or other of them must be +set, but not both. The contents of %data% are expanded, and then used as the +list of forwarding items, or as a set of filtering instructions. If the +expansion is forced to fail, or the result is an empty string or a string that +has no effect (consists entirely of comments), the router declines. + +When filtering instructions are used, the string must begin with ``#Exim +filter'', and all comments in the string, including this initial one, must be +terminated with newline characters. For example: + +.... +data = #Exim filter\n\ + if $h_to: contains Exim then save $home/mail/exim endif +.... + +If you are reading the data from a database where newlines cannot be included, +you can use the $\{sg\}$ expansion item to turn the escape string of your +choice into a newline. + + +oindex:[%directory_transport%] +`..'= +%directory_transport%, Use: 'redirect', Type: 'string'!!, Default: 'unset' +=== + +A ^redirect^ router sets up a direct delivery to a directory when a path name +ending with a slash is specified as a new ``address''. The transport used is +specified by this option, which, after expansion, must be the name of a +configured transport. This should normally be an ^appendfile^ transport. + + +oindex:[%file%] +`..'= +%file%, Use: 'redirect', Type: 'string'!!, Default: 'unset' +=== + +This option specifies the name of a file that contains the redirection data. It +is mutually exclusive with the %data% option. The string is expanded before +use; if the expansion is forced to fail, the router declines. Other expansion +failures cause delivery to be deferred. The result of a successful expansion +must be an absolute path. The entire file is read and used as the redirection +data. If the data is an empty string or a string that has no effect (consists +entirely of comments), the router declines. + +cindex:[NFS,checking for file existence] +If the attempt to open the file fails with a ``does not exist'' error, Exim +runs a check on the containing directory, +unless %ignore_enotdir% is true (see below). +If the directory does not appear to exist, delivery is deferred. This can +happen when users' _.forward_ files are in NFS-mounted directories, and there +is a mount problem. If the containing directory does exist, but the file does +not, the router declines. + + +oindex:[%file_transport%] +`..'= +%file_transport%, Use: 'redirect', Type: 'string'!!, Default: 'unset' +=== + +A ^redirect^ router sets up a direct delivery to a file when a path name not +ending in a slash is specified as a new ``address''. The transport used is +specified by this option, which, after expansion, must be the name of a +configured transport. +This should normally be an ^appendfile^ transport. +When it is running, the file name is in $address_file$. + + +oindex:[%forbid_blackhole%] +`..'= +%forbid_blackhole%, Use: 'redirect', Type: 'boolean', Default: 'false' +=== + +If this option is true, the ':blackhole:' item may not appear in a redirection +list. + + +oindex:[%forbid_exim_filter%] +`..'= +%forbid_exim_filter%, Use: 'redirect', Type: 'boolean', Default: 'false' +=== + +If this option is set true, only Sieve filters are permitted when +%allow_filter% is true. + + + + +oindex:[%forbid_file%] +`..'= +%forbid_file%, Use: 'redirect', Type: 'boolean', Default: 'false' +=== + +cindex:[delivery,to file; forbidding] +cindex:[Sieve filter,forbidding delivery to a file] +cindex:[Sieve filter,``keep'' facility; disabling] +If this option is true, this router may not generate a new address that +specifies delivery to a local file or directory, either from a filter or from a +conventional forward file. This option is forced to be true if %one_time% is +set. It applies to Sieve filters as well as to Exim filters, but if true, it +locks out the Sieve's ``keep'' facility. + + +oindex:[%forbid_filter_existstest%] +`..'= +%forbid_filter_existstest%, Use: 'redirect', Type: 'boolean', Default: 'false' +=== + +cindex:[filter,locking out certain features] +If this option is true, string expansions in Exim filters are not allowed to +make use of the %exists% condition. + + +oindex:[%forbid_filter_logwrite%] +`..'= +%forbid_filter_logwrite%, Use: 'redirect', Type: 'boolean', Default: 'false' +=== + +If this option is true, use of the logging facility in Exim filters is not +permitted. Logging is in any case available only if the filter is being run +under some unprivileged uid (which is normally the case for ordinary users' +_.forward_ files). + + +oindex:[%forbid_filter_lookup%] +`..'= +%forbid_filter_lookup%, Use: 'redirect', Type: 'boolean', Default: 'false' +=== + +If this option is true, string expansions in Exim filter files are not allowed +to make use of %lookup% items. + + +oindex:[%forbid_filter_perl%] +`..'= +%forbid_filter_perl%, Use: 'redirect', Type: 'boolean', Default: 'false' +=== + +This option is available only if Exim is built with embedded Perl support. If +it is true, string expansions in Exim filter files are not allowed to make use +of the embedded Perl support. + + +oindex:[%forbid_filter_readfile%] +`..'= +%forbid_filter_readfile%, Use: 'redirect', Type: 'boolean', Default: 'false' +=== + +If this option is true, string expansions in Exim filter files are not allowed +to make use of %readfile% items. + + +oindex:[%forbid_filter_readsocket%] +`..'= +%forbid_filter_readsocket%, Use: 'redirect', Type: 'boolean', Default: 'false' +=== + +If this option is true, string expansions in Exim filter files are not allowed +to make use of %readsocket% items. + + +oindex:[%forbid_filter_reply%] +`..'= +%forbid_filter_reply%, Use: 'redirect', Type: 'boolean', Default: 'false' +=== + +If this option is true, this router may not generate an automatic reply +message. Automatic replies can be generated only from Exim + +or Sieve filter files, not from traditional forward files. + +This option is forced to be true if %one_time% is set. + + +oindex:[%forbid_filter_run%] +`..'= +%forbid_filter_run%, Use: 'redirect', Type: 'boolean', Default: 'false' +=== + +If this option is true, string expansions in Exim filter files are not allowed +to make use of %run% items. + + +oindex:[%forbid_include%] +`..'= +%forbid_include%, Use: 'redirect', Type: 'boolean', Default: 'false' +=== + +If this option is true, items of the form + + :include:<path name> + +are not permitted in non-filter redirection lists. + + +oindex:[%forbid_pipe%] +`..'= +%forbid_pipe%, Use: 'redirect', Type: 'boolean', Default: 'false' +=== + +cindex:[delivery,to pipe; forbidding] +If this option is true, this router may not generate a new address which +specifies delivery to a pipe, either from an Exim filter or from a conventional +forward file. This option is forced to be true if %one_time% is set. + + +oindex:[%forbid_sieve_filter%] +`..'= +%forbid_sieve_filter%, Use: 'redirect', Type: 'boolean', Default: 'false' +=== + +If this option is set true, only Exim filters are permitted when +%allow_filter% is true. + + + + +oindex:[%hide_child_in_errmsg%] +`..'= +%hide_child_in_errmsg%, Use: 'redirect', Type: 'boolean', Default: 'false' +=== + +cindex:[bounce message,redirection details; suppressing] +If this option is true, it prevents Exim from quoting a child address if it +generates a bounce or delay message for it. Instead it says ``an address +generated from <''the top level address'>'. Of course, this applies only to +bounces generated locally. If a message is forwarded to another host, 'its' +bounce may well quote the generated address. + + +oindex:[%ignore_eacces%] +`..'= +%ignore_eacces%, Use: 'redirect', Type: 'boolean', Default: 'false' +=== + +cindex:[EACCES] +If this option is set and an attempt to open a redirection file yields the +EACCES error (permission denied), the ^redirect^ router behaves as if the +file did not exist. + + +oindex:[%ignore_enotdir%] +`..'= +%ignore_enotdir%, Use: 'redirect', Type: 'boolean', Default: 'false' +=== + +cindex:[ENOTDIR] +If this option is set and an attempt to open a redirection file yields the +ENOTDIR error (something on the path is not a directory), the ^redirect^ +router behaves as if the file did not exist. + +Setting %ignore_enotdir% has another effect as well: When a ^redirect^ +router that has the %file% option set discovers that the file does not exist +(the ENOENT error), it tries to 'stat()' the parent directory, as a check +against unmounted NFS directories. If the parent can not be statted, delivery +is deferred. However, it seems wrong to do this check when %ignore_enotdir% is +set, because that option tells Exim to ignore ``something on the path is not a +directory'' (the ENOTDIR error). This is a confusing area, because it seems +that some operating systems give ENOENT where others give ENOTDIR. + + + +oindex:[%include_directory%] +`..'= +%include_directory%, Use: 'redirect', Type: 'string', Default: 'unset' +=== + +If this option is set, the path names of any ':include:' items in a redirection +list must start with this directory. + + +oindex:[%modemask%] +`..'= +%modemask%, Use: 'redirect', Type: 'octal integer', Default: '022' +=== + +This specifies mode bits which must not be set for a file specified by the +%file% option. If any of the forbidden bits are set, delivery is deferred. + + +oindex:[%one_time%] +`..'= +%one_time%, Use: 'redirect', Type: 'boolean', Default: 'false' +=== + +cindex:[one-time aliasing/forwarding expansion] +cindex:[alias file,one-time expansion] +cindex:[forward file,one-time expansion] +cindex:[mailing lists,one-time expansion] +cindex:[address redirection,one-time expansion] +Sometimes the fact that Exim re-evaluates aliases and reprocesses redirection +files each time it tries to deliver a message causes a problem +when one or more of the generated addresses fails be delivered at the first +attempt. The problem is not one of duplicate delivery -- Exim is clever enough +to handle that -- but of what happens when the redirection list changes during +the time that the message is on Exim's queue. This is particularly true in the +case of mailing lists, where new subscribers might receive copies of messages +that were posted before they subscribed. + +If %one_time% is set and any addresses generated by the router fail to +deliver at the first attempt, the failing addresses are added to the message as +``top level'' addresses, and the parent address that generated them is marked +``delivered''. Thus, redirection does not happen again at the next +delivery attempt. + +*Warning 1*: This means that any header line addition or removal that is +specified by this router would be lost if delivery did not succeed at the +first attempt. For this reason, the %headers_add% and %headers_remove% +generic options are not permitted when %one_time% is set. + +*Warning 2*: To ensure that the router generates only addresses (as opposed +to pipe or file deliveries or auto-replies) %forbid_file%, %forbid_pipe%, +and %forbid_filter_reply% are forced to be true when %one_time% is set. + +The original top-level address is remembered with each of the generated +addresses, and is output in any log messages. However, any intermediate parent +addresses are not recorded. This makes a difference to the log only if +%all_parents% log selector is set. It is expected that %one_time% will +typically be used for mailing lists, where there is normally just one level of +expansion. + + +oindex:[%owners%] +`..'= +%owners%, Use: 'redirect', Type: 'string list', Default: 'unset' +=== + +cindex:[ownership,alias file] +cindex:[ownership,forward file] +cindex:[alias file,ownership] +cindex:[forward file,ownership] +This specifies a list of permitted owners for the file specified by %file%. +This list is in addition to the local user when %check_local_user% is set. +See %check_owner% above. + + +oindex:[%owngroups%] +`..'= +%owngroups%, Use: 'redirect', Type: 'string list', Default: 'unset' +=== + +This specifies a list of permitted groups for the file specified by %file%. The +list is in addition to the local user's primary group when %check_local_user% +is set. See %check_group% above. + + +oindex:[%pipe_transport%] +`..'= +%pipe_transport%, Use: 'redirect', Type: 'string'!!, Default: 'unset' +=== + +A ^redirect^ router sets up a direct delivery to a pipe when a string starting +with a vertical bar character is specified as a new ``address''. The transport +used is specified by this option, which, after expansion, must be the name of a +configured transport. +This should normally be a ^pipe^ transport. +When the transport is run, the pipe command is in $address_pipe$. + + +oindex:[%qualify_domain%] +`..'= +%qualify_domain%, Use: 'redirect', Type: 'string'!!, Default: 'unset' +=== + +If this option is set and an unqualified address (one without a domain) is +generated, it is qualified with the domain specified by expanding this string, +instead of the global setting in %qualify_recipient%. If the expansion fails, +the router declines. If you want to revert to the default, you can have the +expansion generate $qualify_recipient$. + + +oindex:[%qualify_preserve_domain%] +`..'= +%qualify_preserve_domain%, Use: 'redirect', Type: 'boolean', Default: 'false' +=== + +cindex:[domain,in redirection; preserving] +cindex:[preserving domain in redirection] +cindex:[address redirection,domain; preserving] +If this is set and an unqualified address (one without a domain) is generated, +it is qualified with the domain of the +parent address (the immediately preceding ancestor) instead of the local +%qualify_domain% or global %qualify_recipient% value. + + +oindex:[%repeat_use%] +`..'= +%repeat_use%, Use: 'redirect', Type: 'boolean', Default: 'true' +=== + +If this option is set false, the router is skipped for a child address that has +any ancestor that was routed by this router. This test happens before any of +the other preconditions are tested. Exim's default anti-looping rules skip +only when the ancestor is the same as the current address. See also +%check_ancestor% above and the generic %redirect_router% option. + + +oindex:[%reply_transport%] +`..'= +%reply_transport%, Use: 'redirect', Type: 'string'!!, Default: 'unset' +=== + +A ^redirect^ router sets up an automatic reply when a %mail% or %vacation% +command is used in a filter file. The transport used is specified by this +option, which, after expansion, must be the name of a configured transport. +This should normally be an ^autoreply^ transport. Other transports are +unlikely to do anything sensible or useful. + + +oindex:[%rewrite%] +`..'= +%rewrite%, Use: 'redirect', Type: 'boolean', Default: 'true' +=== + +cindex:[address redirection,disabling rewriting] +If this option is set false, addresses generated by the router are not +subject to address rewriting. Otherwise, they are treated like new addresses +and are rewritten according to the global rewriting rules. + + + +oindex:[%sieve_vacation_directory%] +`..'= +%sieve_vacation_directory%, Use: 'redirect', Type: 'string'!!, Default: 'unset' +=== + +cindex:[Sieve filter,vacation directory] +To enable the ``vacation'' extension for Sieve filters, you must set +%sieve_vacation_directory% to the directory where vacation databases are held +(do not put anything else in that directory), and ensure that the +%reply_transport% option refers to an ^autoreply^ transport. + + + + +oindex:[%skip_syntax_errors%] +`..'= +%skip_syntax_errors%, Use: 'redirect', Type: 'boolean', Default: 'false' +=== + +cindex:[forward file,broken] +cindex:[address redirection,broken files] +cindex:[alias file,broken] +cindex:[broken alias or forward files] +cindex:[ignoring faulty addresses] +cindex:[skipping faulty addresses] +cindex:[error,skipping bad syntax] +If %skip_syntax_errors% is set, syntactically malformed addresses in +non-filter redirection data are skipped, and each failing address is logged. If +%syntax_errors_to% is set, a message is sent to the address it defines, +giving details of the failures. If %syntax_errors_text% is set, its contents +are expanded and placed at the head of the error message generated by +%syntax_errors_to%. Usually it is appropriate to set %syntax_errors_to% to +be the same address as the generic %errors_to% option. The +%skip_syntax_errors% option is often used when handling mailing lists. + +If all the addresses in a redirection list are skipped because of syntax +errors, the router declines to handle the original address, and it is passed to +the following routers. + +If %skip_syntax_errors% is set when an Exim filter is interpreted, any syntax +error in the filter causes filtering to be abandoned without any action being +taken. The incident is logged, and the router declines to handle the address, +so it is passed to the following routers. + +cindex:[Sieve filter,syntax errors in] +Syntax errors in a Sieve filter file cause the ``keep'' action to occur. This +action is specified by RFC 3028. The values of %skip_syntax_errors%, +%syntax_errors_to%, and %syntax_errors_text% are not used. + +%skip_syntax_errors% can be used to specify that errors in users' forward +lists or filter files should not prevent delivery. The %syntax_errors_to% +option, used with an address that does not get redirected, can be used to +notify users of these errors, by means of a router like this: + +.... +userforward: + driver = redirect + allow_filter + check_local_user + file = $home/.forward + file_transport = address_file + pipe_transport = address_pipe + reply_transport = address_reply + no_verify + skip_syntax_errors + syntax_errors_to = real-$local_part\$domain + syntax_errors_text = \ + This is an automatically generated message. An error has\n\ + been found in your .forward file. Details of the error are\n\ + reported below. While this error persists, you will receive\n\ + a copy of this message for every message that is addressed\n\ + to you. If your .forward file is a filter file, or if it is\n\ + a non-filter file containing no valid forwarding addresses,\n\ + a copy of each incoming message will be put in your normal\n\ + mailbox. If a non-filter file contains at least one valid\n\ + forwarding address, forwarding to the valid addresses will\n\ + happen, and those will be the only deliveries that occur. +.... + +You also need a router to ensure that local addresses that are prefixed by +`real-` are recognized, but not forwarded or filtered. For example, you could +put this immediately before the ^userforward^ router: + + real_localuser: + driver = accept + check_local_user + local_part_prefix = real- + transport = local_delivery + + + +oindex:[%syntax_errors_text%] +`..'= +%syntax_errors_text%, Use: 'redirect', Type: 'string'!!, Default: 'unset' +=== + +See %skip_syntax_errors% above. + + +oindex:[%syntax_errors_to%] +`..'= +%syntax_errors_to%, Use: 'redirect', Type: 'string', Default: 'unset' +=== + +See %skip_syntax_errors% above. + + + + + + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// + +[[CHAPenvironment]] +[titleabbrev="Environment for local transports"] +Environment for running local transports +---------------------------------------- +cindex:[local transports,environment for] +cindex:[environment for local transports] +cindex:[transport,local; environment for] +Local transports handle deliveries to files and pipes. (The ^autoreply^ +transport can be thought of as similar to a pipe.) Exim always runs transports +in subprocesses, under specified uids and gids. Typical deliveries to local +mailboxes run under the uid and gid of the local user. + +Exim also sets a specific current directory while running the transport; for +some transports a home directory setting is also relevant. The ^pipe^ +transport is the only one that sets up environment variables; see section +<<SECTpipeenv>> for details. + +The values used for the uid, gid, and the directories may come from several +different places. In many cases, the router that handles the address associates +settings with that address as a result of its %check_local_user%, %group%, or +%user% options. However, values may also be given in the transport's own +configuration, and these override anything that comes from the router. + + + +Concurrent deliveries +~~~~~~~~~~~~~~~~~~~~~ +cindex:[concurrent deliveries] +cindex:[simultaneous deliveries] +If two different messages for the same local recpient arrive more or less +simultaneously, the two delivery processes are likely to run concurrently. When +the ^appendfile^ transport is used to write to a file, Exim applies locking +rules to stop concurrent processes from writing to the same file at the same +time. + +However, when you use a ^pipe^ transport, it is up to you to arrange any +locking that is needed. Here is a silly example: + + my_transport: + driver = pipe + command = /bin/sh -c 'cat >>/some/file' + +This is supposed to write the message at the end of the file. However, if two +messages arrive at the same time, the file will be scrambled. You can use the +%exim_lock% utility program (see section <<SECTmailboxmaint>>) to lock a file +using the same algorithm that Exim itself uses. + + + + +[[SECTenvuidgid]] +Uids and gids +~~~~~~~~~~~~~ +cindex:[local transports,uid and gid] +cindex:[transport,local; uid and gid] +All transports have the options %group% and %user%. If %group% is set, it +overrides any group that the router set in the address, even if %user% is not +set for the transport. This makes it possible, for example, to run local mail +delivery under the uid of the recipient (set by the router), but in a special +group (set by the transport). For example: + + # Routers ... + # User/group are set by check_local_user in this router + local_users: + driver = accept + check_local_user + transport = group_delivery + + # Transports ... + # This transport overrides the group + group_delivery: + driver = appendfile + file = /var/spool/mail/$local_part + group = mail + +If %user% is set for a transport, its value overrides what is set in the +address. If %user% is non-numeric and %group% is not set, the gid associated +with the user is used. If %user% is numeric, %group% must be set. + +cindex:[%initgroups% option] +When the uid is taken from the transport's configuration, the 'initgroups()' +function is called for the groups associated with that uid if the %initgroups% +option is set for the transport. When the uid is not specified by the +transport, but is associated with the address by a router, the option for +calling 'initgroups()' is taken from the router configuration. + +cindex:[^pipe^ transport,uid for] +The ^pipe^ transport contains the special option %pipe_as_creator%. If this +is set and %user% is not set, the uid of the process that called Exim to +receive the message is used, and if %group% is not set, the corresponding +original gid is also used. + + + +Current and home directories +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[current directory for local transport] +cindex:[home directory,for local transport] +cindex:[transport,local; home directory for] +cindex:[transport,local; current directory for] +Routers may set current and home directories for local transports by means of +the %transport_current_directory% and %transport_home_directory% options. +However, if the transport's %current_directory% or %home_directory% options +are set, they override the router's values. In detail, the home directory +for a local transport is taken from the first of these values that is set: + +- The %home_directory% option on the transport; + +- The %transport_home_directory% option on the router; + +- The password data if %check_local_user% is set on the router; + +- The %router_home_directory% option on the router. + +The current directory is taken from the first of these values that is set: + +- The %current_directory% option on the transport; + +- The %transport_current_directory% option on the router. + + +If neither the router nor the transport sets a current directory, Exim uses the +value of the home directory, if it is set. Otherwise it sets the current +directory to _/_ before running a local transport. + + + +Expansion variables derived from the address +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Normally a local delivery is handling a single address, and in that case the +variables such as $domain$ and $local_part$ are set during local +deliveries. However, in some circumstances more than one address may be handled +at once (for example, while writing batch SMTP for onward transmission by some +other means). In this case, the variables associated with the local part are +never set, $domain$ is set only if all the addresses have the same +domain, and $original_domain$ is never set. + + + + + + + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// + +[[CHAPtransportgeneric]] +Generic options for transports +------------------------------ + +cindex:[generic options,transport] +cindex:[options,generic; for transports] +cindex:[transport,generic options for] +The following generic options apply to all transports: + + +oindex:[%body_only%] +`..'= +%body_only%, Use: 'transports', Type: 'boolean', Default: 'false' +=== + +cindex:[transport,body only] +cindex:[message,transporting body only] +cindex:[body of message,transporting] +If this option is set, the message's headers are not transported. It is +mutually exclusive with %headers_only%. If it is used with the ^appendfile^ or +^pipe^ transports, the settings of %message_prefix% and %message_suffix% +should be checked, because this option does not automatically suppress them. + + +oindex:[%current_directory%] +`..'= +%current_directory%, Use: 'transports', Type: 'string'!!, Default: 'unset' +=== + +cindex:[transport,current directory for] +This specifies the current directory that is to be set while running the +transport, overriding any value that may have been set by the router. +If the expansion fails for any reason, including forced failure, an error is +logged, and delivery is deferred. + + +oindex:[%disable_logging%] +`..'= +%disable_logging%, Use: 'transports', Type: 'boolean', Default: 'false' +=== + +If this option is set true, nothing is logged for any +deliveries by the transport or for any +transport errors. You should not set this option unless you really, really know +what you are doing. + + +oindex:[%debug_print%] +`..'= +%debug_print%, Use: 'transports', Type: 'string'!!, Default: 'unset' +=== + +cindex:[testing,variables in drivers] +If this option is set and debugging is enabled (see the %-d% command line +option), the string is expanded and included in the debugging output when the +transport is run. +If expansion of the string fails, the error message is written to the debugging +output, and Exim carries on processing. +This facility is provided to help with checking out the values of variables and +so on when debugging driver configurations. For example, if a %headers_add% +option is not working properly, %debug_print% could be used to output the +variables it references. A newline is added to the text if it does not end with +one. + + +oindex:[%delivery_date_add%] +`..'= +%delivery_date_add%, Use: 'transports', Type: 'boolean', Default: 'false' +=== + +cindex:['Delivery-date:' header line] +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. + + +oindex:[%driver%] +`..'= +%driver%, Use: 'transports', Type: 'string', Default: 'unset' +=== + +This specifies which of the available transport drivers is to be used. +There is no default, and this option must be set for every transport. + + +oindex:[%envelope_to_add%] +`..'= +%envelope_to_add%, Use: 'transports', Type: 'boolean', Default: 'false' +=== + +cindex:['Envelope-to:' header line] +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 the transport is +configured to handle several addresses at once, or if more than one original +address was redirected 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. + + +oindex:[%group%] +`..'= +%group%, Use: 'transports', Type: 'string'!!, Default: 'Exim group' +=== + +cindex:[transport,group; specifying] +This option specifies a gid for running the transport process, overriding any +value that the router supplies, and also overriding any value associated with +%user% (see below). + + +oindex:[%headers_add%] +`..'= +%headers_add%, Use: 'transports', Type: 'string'!!, Default: 'unset' +=== + +cindex:[header lines,adding in transport] +cindex:[transport,header lines; adding] +This option specifies a string of text that is expanded and added to the header +portion of a message as it is transported, as described in section +<<SECTheadersaddrem>>. Additional header lines can also be specified by routers. +If the result of the expansion is an empty string, or if the expansion is +forced to fail, no action is taken. Other expansion failures are treated as +errors and cause the delivery to be deferred. + + + +oindex:[%headers_only%] +`..'= +%headers_only%, Use: 'transports', Type: 'boolean', Default: 'false' +=== + +cindex:[transport,header lines only] +cindex:[message,transporting headers only] +cindex:[header lines,transporting] +If this option is set, the message's body is not transported. It is mutually +exclusive with %body_only%. If it is used with the ^appendfile^ or ^pipe^ +transports, the settings of %message_prefix% and %message_suffix% should be +checked, since this option does not automatically suppress them. + + +oindex:[%headers_remove%] +`..'= +%headers_remove%, Use: 'transports', Type: 'string'!!, Default: 'unset' +=== + +cindex:[header lines,removing] +cindex:[transport,header lines; removing] +This option specifies a string that is expanded into a list of header names; +these headers are omitted from the message as it is transported, as described +in section <<SECTheadersaddrem>>. Header removal can also be specified by +routers. If the result of the expansion is an empty string, or if the expansion +is forced to fail, no action is taken. Other expansion failures are treated as +errors and cause the delivery to be deferred. + + + +oindex:[%headers_rewrite%] +`..'= +%headers_rewrite%, Use: 'transports', Type: 'string', Default: 'unset' +=== + +cindex:[transport,header lines; rewriting] +cindex:[rewriting,at transport time] +This option allows addresses in header lines to be rewritten at transport time, +that is, as the message is being copied to its destination. The contents of the +option are a colon-separated list of rewriting rules. Each rule is in exactly +the same form as one of the general rewriting rules that are applied when a +message is received. These are described in chapter <<CHAPrewrite>>. For example, + +.... +headers_rewrite = a@b c@d f : \ + x@y w@z +.... + +changes %a@b% into %c@d% in 'From:' header lines, and %x@y% into %w@z% in +all address-bearing header lines. The rules are applied to the header lines +just before they are written out at transport time, so they affect only those +copies of the message that pass through the transport. However, only the +message's original header lines, and any that were added by a system filter, +are rewritten. If a router or transport adds header lines, they are +not affected by this option. These rewriting rules are 'not' applied to the +envelope. You can change the return path using %return_path%, but you cannot +change envelope recipients at this time. + + +oindex:[%home_directory%] +`..'= +%home_directory%, Use: 'transports', Type: 'string'!!, Default: 'unset' +=== + +cindex:[transport,home directory for] +This option specifies a home directory setting for the transport, overriding +any value that may be set by the router. The home directory is placed in +$home$ while expanding the transport's private options. It is also used as +the current directory if no current directory is set by the +%current_directory% option on the transport or the +%transport_current_directory% option on the router. +If the expansion fails for any reason, including forced failure, an error is +logged, and delivery is deferred. + + +oindex:[%initgroups%] +`..'= +%initgroups%, Use: 'transports', Type: 'boolean', Default: 'false' +=== + +cindex:[additional groups] +cindex:[groups, additional] +cindex:[transport,group; additional] +If this option is true and the uid for the delivery process is provided by the +transport, the 'initgroups()' function is called when running the transport +to ensure that any additional groups associated with the uid are set up. + + +oindex:[%message_size_limit%] +`..'= +%message_size_limit%, Use: 'transports', Type: 'string'!!, Default: '0' +=== + +cindex:[limit,message size per transport] +cindex:[size of message, limit] +cindex:[transport,message size; limiting] +This option controls the size of messages passed through the transport. It is +expanded before use; the result of the expansion must be a sequence of digits, +optionally followed by K or M. +If the expansion fails for any reason, including forced failure, or if the +result is not of the required form, delivery is deferred. +If the value is greater than zero and the size of a message exceeds this +limit, the address is failed. If there is any chance that the resulting bounce +message could be routed to the same transport, you should ensure that +%return_size_limit% is less than the transport's %message_size_limit%, as +otherwise the bounce message will fail to get delivered. + + + +oindex:[%rcpt_include_affixes%] +`..'= +%rcpt_include_affixes%, Use: 'transports', Type: 'boolean', Default: 'false' +=== + +cindex:[prefix,for local part; including in envelope] +cindex:[suffix,for local part; including in envelope] +cindex:[local part,prefix] +cindex:[local part,suffix] +When this option is false (the default), and an address that has had any +affixes (prefixes or suffixes) removed from the local part is delivered by any +form of SMTP or LMTP, the affixes are not included. For example, if a router +that contains + + local_part_prefix = *- + +routes the address 'abc-xyz@some.domain' to an SMTP transport, the envelope +is delivered with + + RCPT TO:<xyz@some.domain> + +If %rcpt_include_affixes% is set true, the whole local part is included in +the RCPT command. This option applies to BSMTP deliveries by the +^appendfile^ and ^pipe^ transports as well as to the ^lmtp^ and ^smtp^ +transports. + + +oindex:[%retry_use_local_part%] +`..'= +%retry_use_local_part%, Use: 'transports', Type: 'boolean', Default: 'see below' +=== + +cindex:[hints database,retry keys] +When a delivery suffers a temporary failure, a retry record is created +in Exim's hints database. For remote deliveries, the key for the retry record +is based on the name and/or IP address of the failing remote host. For local +deliveries, the key is normally the entire address, including both the local +part and the domain. This is suitable for most common cases of local delivery +temporary failure -- for example, exceeding a mailbox quota should delay only +deliveries to that mailbox, not to the whole domain. + +However, in some special cases you may want to treat a temporary local delivery +as a failure associated with the domain, and not with a particular local part. +(For example, if you are storing all mail for some domain in files.) You can do +this by setting %retry_use_local_part% false. + +For all the local transports, its default value is true. For remote transports, +the default value is false for tidiness, but changing the value has no effect +on a remote transport in the current implementation. + + +oindex:[%return_path%] +`..'= +%return_path%, Use: 'transports', Type: 'string'!!, Default: 'unset' +=== + +cindex:[envelope sender] +cindex:[transport,return path; changing] +cindex:[return path,changing in transport] +If this option is set, the string is expanded at transport time and replaces +the existing return path (envelope sender) value in the copy of the message +that is being delivered. An empty return path is permitted. This feature is +designed for remote deliveries, where the value of this option is used in the +SMTP MAIL command. If you set %return_path% for a local transport, the +only effect is to change the address that is placed in the 'Return-path:' +header line, if one is added to the message (see the next option). + +The expansion can refer to the existing value via $return_path$. This is +either the message's envelope sender, or an address set by the +%errors_to% option on a router. If the expansion is forced to fail, no +replacement occurs; if it fails for another reason, delivery is deferred. This +option can be used to support VERP (Variable Envelope Return Paths) -- see +chapter <<CHAPSMTP>>. + +*Note*: If a delivery error is detected locally, +including the case when a remote server rejects a message at SMTP time, +the bounce message is not sent to the value of this option, but to the +previously set errors address (which defaults to the incoming sender address). + + + +oindex:[%return_path_add%] +`..'= +%return_path_add%, Use: 'transports', Type: 'boolean', Default: 'false' +=== + +cindex:['Return-path:' header line] +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 2821 states that the 'Return-path:' header is added to a message ``when the +delivery SMTP server makes the final delivery''. This 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. + + +oindex:[%shadow_condition%] +`..'= +%shadow_condition%, Use: 'transports', Type: 'string'!!, Default: 'unset' +=== + +See %shadow_transport% below. + + +oindex:[%shadow_transport%] +`..'= +%shadow_transport%, Use: 'transports', Type: 'string', Default: 'unset' +=== + +cindex:[shadow transport] +cindex:[transport,shadow] +A local transport may set the %shadow_transport% option to the name of another +local transport. Shadow remote transports are not supported. + +Whenever a delivery to the main transport succeeds, and either +%shadow_condition% is unset, or its expansion does not result in the empty +string or one of the strings ``0'' or ``no'' or ``false'', the message is also passed +to the shadow transport, with the same delivery address or addresses. +If expansion fails, no action is taken except that non-forced expansion +failures cause a log line to be written. + +The result of the shadow transport is discarded and does not affect the +subsequent processing of the message. Only a single level of shadowing is +provided; the %shadow_transport% option is ignored on any transport when it is +running as a shadow. Options concerned with output from pipes are also ignored. + +The log line for the successful delivery has an item added on the end, of the +form + + ST=<shadow transport name> + +If the shadow transport did not succeed, the error message is put in +parentheses afterwards. + +Shadow transports can be used for a number of different purposes, including +keeping more detailed log information than Exim normally provides, and +implementing automatic acknowledgement policies based on message headers that +some sites insist on. + + +oindex:[%transport_filter%] +`..'= +%transport_filter%, Use: 'transports', Type: 'string'!!, Default: 'unset' +=== + +cindex:[transport,filter] +cindex:[filter,transport filter] +This option sets up a filtering (in the Unix shell sense) process for messages +at transport time. It should not be confused with mail filtering as set up by +individual users or via a system filter. + +When the message is about to be written out, the command specified by +%transport_filter% is started up in a separate process, and the entire +message, including the header lines, is passed to it on its standard input +(this in fact is done from a third process, to avoid deadlock). +The command must be specified as an absolute path. + +The lines of the message that are written to the transport filter are +terminated by newline (``\n''). + +The message is passed to the filter before any SMTP-specific processing, such +as turning ``\n'' into ``\r\n'' and escaping lines beginning with a dot, and +also before any processing implied by the settings of %check_string% and +%escape_string% in the ^appendfile^ or ^pipe^ transports. + +The standard error for the filter process is set to the same destination as its +standard output; this is read and written to the message's ultimate +destination. + +The filter can perform any transformations it likes, but of course should take +care not to break RFC 2822 syntax. A demonstration Perl script is provided in +_util/transport-filter.pl_; this makes a few arbitrary modifications just to +show the possibilities. Exim does not check the result, except to test for a +final newline when SMTP is in use. All messages transmitted over SMTP must end +with a newline, so Exim supplies one if it is missing. + +cindex:[SMTP,SIZE] +A problem might arise if the filter increases the size of a message that is +being sent down an SMTP connection. If the receiving SMTP server has indicated +support for the SIZE parameter, Exim will have sent the size of the message +at the start of the SMTP session. If what is actually sent is substantially +more, the server might reject the message. This can be worked round by setting +the %size_addition% option on the ^smtp^ transport, either to allow for +additions to the message, or to disable the use of SIZE altogether. + +The value of the %transport_filter% option is the command string for starting +the filter, which is run directly from Exim, not under a shell. The string is +parsed by Exim in the same way as a command string for the ^pipe^ transport: +Exim breaks it up into arguments and then expands each argument separately. The +special argument $pipe_addresses$ is replaced by a number of arguments, one +for each address that applies to this delivery. (This isn't an ideal name for +this feature here, but as it was already implemented for the ^pipe^ +transport, it seemed sensible not to change it.) + +cindex:[$host$] +cindex:[$host_address$] +The expansion variables $host$ and $host_address$ are available when the +transport is a remote one. They contain the name and IP address of the host to +which the message is being sent. For example: + +.... +transport_filter = /some/directory/transport-filter.pl \ + $host $host_address $sender_address $pipe_addresses +.... + +The filter process is run under the same uid and gid as the normal delivery. +For remote deliveries this is the Exim uid/gid by default. + +The command should normally yield a zero return code. A non-zero code is taken +to mean that the transport filter failed in some way. Delivery of the message +is deferred. It is not possible to cause a message to be bounced from a +transport filter. + + +If a transport filter is set on an autoreply transport, the original message is +passed through the filter as it is being copied into the newly generated +message, which happens if the %return_message% option is set. + + +oindex:[%transport_filter_timeout%] +`..'= +%transport_filter_timeout%, Use: 'transports', Type: 'time', Default: '5m' +=== + +cindex:[transport filter, timeout] +When Exim is reading the output of a transport filter, it a applies a timeout +that can be set by this option. Exceeding the timeout is treated as a +temporary delivery failure. + + + +oindex:[%user%] +`..'= +%user%, Use: 'transports', Type: 'string'!!, Default: 'Exim user' +=== + +cindex:[uid (user id),local delivery] +cindex:[transport user, specifying] +This option specifies the user under whose uid the delivery process is to be +run, overriding any uid that may have been set by the router. If the user is +given as a name, the uid is looked up from the password data, and the +associated group is taken as the value of the gid to be used if the %group% +option is not set. + +For deliveries that use local transports, a user and group are normally +specified explicitly or implicitly (for example, as a result of +%check_local_user%) by the router or transport. + +cindex:[hints database,access by remote transport] +For remote transports, you should leave this option unset unless you really are +sure you know what you are doing. When a remote transport is running, it needs +to be able to access Exim's hints databases, because each host may have its own +retry data. + + + + + + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// + +[[CHAPbatching]] +[titleabbrev="Address batching"] +Address batching in local transports +------------------------------------ +cindex:[transport,local; address batching in] +The only remote transport (^smtp^) is normally configured to handle more than +one address at a time, so that when several addresses are routed to the same +remote host, just one copy of the message is sent. Local transports, however, +normally handle one address at a time. That is, a separate instance of the +transport is run for each address that is routed to the transport. A separate +copy of the message is delivered each time. + +cindex:[batched local delivery] +cindex:[%batch_max%] +cindex:[%batch_id%] +In special cases, it may be desirable to handle several addresses at once in a +local transport, for example: + +- In an ^appendfile^ transport, when storing messages in files for later +delivery by some other means, a single copy of the message with multiple +recipients saves space. + +- In an ^lmtp^ transport, when delivering over ``local SMTP'' to some process, +a single copy saves time, and is the normal way LMTP is expected to work. + +- In a ^pipe^ transport, when passing the message +to a scanner program or +to some other delivery mechanism such as UUCP, multiple recipients may be +acceptable. + +The three local transports (^appendfile^, ^lmtp^, and ^pipe^) all have +the same options for controlling multiple (``batched'') deliveries, namely +%batch_max% and %batch_id%. To save repeating the information for each +transport, these options are described here. + +The %batch_max% option specifies the maximum number of addresses that can be +delivered together in a single run of the transport. Its default value is one. +When more than one address is routed to a transport that has a %batch_max% +value greater than one, the addresses are delivered in a batch (that is, in a +single run of the transport), subject to certain conditions: + +- If any of the transport's options contain a reference to $local_part$, no +batching is possible. + +- If any of the transport's options contain a reference to $domain$, only +addresses with the same domain are batched. + +- cindex:[customizing,batching condition] +If %batch_id% is set, it is expanded for each address, and only those +addresses with the same expanded value are batched. This allows you to specify +customized batching conditions. +Failure of the expansion for any reason, including forced failure, disables +batching, but it does not stop the delivery from taking place. + +- Batched addresses must also have the same errors address (where to send +delivery errors), the same header additions and removals, the same user and +group for the transport, and if a host list is present, the first host must +be the same. + +cindex:['Envelope-to:' header line] +If the generic %envelope_to_add% option is set for the transport, the +'Envelope-to:' header that is added to the message contains all the addresses +that are batched together. + +The ^appendfile^ and ^pipe^ transports have an option called %use_bsmtp%, +which causes them to deliver the message in ``batched SMTP'' format, with the +envelope represented as SMTP commands. The %check_string% and %escape_string% +options are forced to the values + + check_string = "." + escape_string = ".." + +when batched SMTP is in use. A full description of the batch SMTP mechanism is +given in section <<SECTbatchSMTP>>. The ^lmtp^ transport does not have a +%use_bsmtp% option, because it always delivers using the SMTP protocol. + +cindex:[^pipe^ transport,with multiple addresses] +If you are not using BSMTP, but are using a ^pipe^ transport, you can include +$pipe_addresses$ as part of the command. This is not a true variable; it is +a bit of magic that causes each of the recipient addresses to be inserted into +the command as a separate argument. This provides a way of accessing all the +addresses that are being delivered in the batch. + +If you are using a batching ^appendfile^ transport without %use_bsmtp%, the +only way to preserve the recipient addresses is to set the %envelope_to_add% +option. This causes an 'Envelope-to:' header line to be added to the message, +containing all the recipients. + + + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// + +[[CHAPappendfile]] +The appendfile transport +------------------------ +cindex:[^appendfile^ transport] +cindex:[transports,^appendfile^] +cindex:[directory creation] +cindex:[creating directories] +The ^appendfile^ transport delivers a message by appending it to an existing +file, or by creating an entirely new file in a specified directory. Single +files to which messages are appended can be in the traditional Unix mailbox +format, or optionally in the MBX format supported by the Pine MUA and +University of Washington IMAP daemon, 'inter alia'. When each message is +being delivered as a separate file, ``maildir'' format can optionally be used to +give added protection against failures that happen part-way through the +delivery. A third form of separate-file delivery known as ``mailstore'' is also +supported. For all file formats, Exim attempts to create as many levels of +directory as necessary, provided that %create_directory% is set. + +The code for the optional formats is not included in the Exim binary by +default. It is necessary to set SUPPORT_MBX, SUPPORT_MAILDIR and/or +SUPPORT_MAILSTORE in _Local/Makefile_ to have the appropriate code +included. + +cindex:[quota,system] +Exim recognises system quota errors, and generates an appropriate message. Exim +also supports its own quota control within the transport, for use when the +system facility is unavailable or cannot be used for some reason. + +If there is an error while appending to a 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. If there is an error while +creating an entirely new file, the new file is removed. + +Before appending to a 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. + +^appendfile^ is most commonly used for local deliveries to users' mailboxes. +However, it can also be used as a pseudo-remote transport for putting messages +into files for remote delivery by some means other than Exim. ``Batch SMTP'' +format is often used in this case (see the %use_bsmtp% option). + + + +[[SECTfildiropt]] +The file and directory options +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +The %file% option specifies a single file, to which the message is appended; +the %directory% option specifies a directory, in which a new file containing +the message is created. Only one of these two options can be set, and for +normal deliveries to mailboxes, one of them 'must' be set. + +However, ^appendfile^ is also used for delivering messages to files or +directories whose names (or parts of names) are obtained from alias, +forwarding, or filtering operations (for example, a %save% command in a user's +Exim filter). When such a transport is running, $local_part$ contains the +local part that was aliased or forwarded, and $address_file$ contains the +name (or partial name) of the file or directory generated by the redirection +operation. There are two cases: + +- If neither %file% nor %directory% is set, the redirection operation +must specify an absolute path (one that begins with `/`). This is the most +common case when users with local accounts use filtering to sort mail into +different folders. See for example, the ^address_file^ transport in the +default configuration. If the path ends with a slash, it is assumed to be the +name of a directory. A delivery to a directory can also be forced by setting +%maildir_format% or %mailstore_format%. + +- If %file% or %directory% is set for a delivery from a redirection, it is used +to determine the file or directory name for the delivery. Normally, the +contents of $address_file$ are used in some way in the string expansion. + + +cindex:[Sieve filter,configuring ^appendfile^] +cindex:[Sieve filter,relative mailbox path handling] +As an example of the second case, consider an environment where users do not +have home directories. They may be permitted to use Exim filter commands of the +form: + + save folder23 + +or Sieve filter commands of the form: + + require "fileinto"; + fileinto "folder23"; + +In this situation, the expansion of %file% or %directory% in the transport must +transform the relative path into an appropriate absolute file name. In the case +of Sieve filters, the name 'inbox' must be handled. It is the name that is +used as a result of a ``keep'' action in the filter. This example shows one way +of handling this requirement: + +.... +file = ${if eq{$address_file}{inbox} \ + {/var/mail/$local_part} \ + {${if eq{${substr_0_1:$address_file}}{/} \ + {$address_file} \ + {$home/mail/$address_file} \ + }} \ + } +.... + +With this setting of %file%, 'inbox' refers to the standard mailbox location, +absolute paths are used without change, and other folders are in the _mail_ +directory within the home directory. + +*Note 1*: While processing an Exim filter, a relative path such as +_folder23_ is turned into an absolute path if a home directory is known to +the router. In particular, this is the case if %check_local_user% is set. If +you want to prevent this happening at routing time, you can set +%router_home_directory% empty. This forces the router to pass the relative +path to the transport. + +*Note 2*: An absolute path in $address_file$ is not treated specially; +the %file% or %directory% option is still used if it is set. + + + + +Private options for appendfile +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[options,^appendfile^ transport] + + + +oindex:[%allow_fifo%] +`..'= +%allow_fifo%, Use: 'appendfile', Type: 'boolean', Default: 'false' +=== + +cindex:[fifo (named pipe)] +cindex:[named pipe (fifo)] +cindex:[pipe,named (fifo)] +Setting this option permits delivery to named pipes (FIFOs) as well as to +regular files. If no process is reading the named pipe at delivery time, the +delivery is deferred. + + +oindex:[%allow_symlink%] +`..'= +%allow_symlink%, Use: 'appendfile', Type: 'boolean', Default: 'false' +=== + +cindex:[symbolic link,to mailbox] +cindex:[mailbox,symbolic link] +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. + + +oindex:[%batch_id%] +`..'= +%batch_id%, Use: 'appendfile', Type: 'string'!!, Default: 'unset' +=== + +See the description of local delivery batching in chapter <<CHAPbatching>>. +However, batching is automatically disabled for ^appendfile^ deliveries that +happen as a result of forwarding or aliasing or other redirection directly to a +file. + + +oindex:[%batch_max%] +`..'= +%batch_max%, Use: 'appendfile', Type: 'integer', Default: '1' +=== + +See the description of local delivery batching in chapter <<CHAPbatching>>. + + +oindex:[%check_group%] +`..'= +%check_group%, Use: 'appendfile', Type: 'boolean', Default: 'false' +=== + +When this option is set, the group owner of the file defined by the %file% +option is checked to see that it is the same as the group under which the +delivery process is running. The default setting is false because the default +file mode is 0600, which means that the group is irrelevant. + + +oindex:[%check_owner%] +`..'= +%check_owner%, Use: 'appendfile', Type: 'boolean', Default: 'true' +=== + +When this option is set, the owner of the file defined by the %file% option is +checked to ensure that it is the same as the user under which the delivery +process is running. + + +oindex:[%check_string%] +`..'= +%check_string%, Use: 'appendfile', Type: 'string', Default: 'see below' +=== + +cindex:[``From'' line] +As ^appendfile^ writes the message, the start of each line is tested for +matching %check_string%, and if it does, the initial matching characters are +replaced by the contents of %escape_string%. The value of %check_string% is a +literal string, not a regular expression, and the case of any letters it +contains is significant. + +If %use_bsmtp% is set the values of %check_string% and %escape_string% are +forced to ``.'' and ``..'' respectively, and any settings in the configuration are +ignored. Otherwise, they default to ``From '' and ``>From '' when the %file% option +is set, and unset when +any of the %directory%, %maildir%, or %mailstore% options are set. + +The default settings, along with %message_prefix% and %message_suffix%, are +suitable for traditional ``BSD'' mailboxes, where a line beginning with ``From +'' indicates the start of a new message. All four options need changing if +another format is used. For example, to deliver to mailboxes in MMDF format: +cindex:[MMDF format mailbox] +cindex:[mailbox,MMDF format] + + check_string = "\1\1\1\1\n" + escape_string = "\1\1\1\1 \n" + message_prefix = "\1\1\1\1\n" + message_suffix = "\1\1\1\1\n" + +oindex:[%create_directory%] +`..'= +%create_directory%, Use: 'appendfile', Type: 'boolean', Default: 'true' +=== + +cindex:[directory creation] +When this option is true, Exim attempts to create any missing superior +directories for the file that it is about to write. A created directory's mode +is given by the %directory_mode% option. + +The group ownership of a newly created directory is highly dependent on the +operating system (and possibly the file system) that is being used. For +example, in Solaris, if the parent directory has the setgid bit set, its group +is propagated to the child; if not, the currently set group is used. However, +in FreeBSD, the parent's group is always used. + + + +oindex:[%create_file%] +`..'= +%create_file%, Use: 'appendfile', Type: 'string', Default: 'anywhere' +=== + +This option constrains the location of files and directories that are created +by this transport. It applies to files defined by the %file% option and +directories defined by the %directory% option. In the case of maildir delivery, +it applies to the top level directory, not the maildir directories beneath. + +The option 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 +for the transport. This option is not useful when an explicit file name is +given for normal mailbox deliveries. It is intended for the case when file +names are generated from users' _.forward_ files. These are usually handled +by an ^appendfile^ transport called %address_file%. See also +%file_must_exist%. + + +oindex:[%directory%] +`..'= +%directory%, Use: 'appendfile', Type: 'string'!!, Default: 'unset' +=== + +This option is mutually exclusive with the %file% option, but one of %file% or +%directory% must be set, unless the delivery is the direct result of a +redirection (see section <<SECTfildiropt>>). + +When %directory% is set, the string is expanded, and the message is delivered +into a new file or files in or below the given directory, instead of being +appended to a single mailbox file. A number of different formats are provided +(see %maildir_format% and %mailstore_format%), and see section <<SECTopdir>> +for further details of this form of delivery. + + +oindex:[%directory_file%] +`..'= +%directory_file%, Use: 'appendfile', Type: 'string'!!, Default: `q\$\{base62{co}\$tod_epoch\}-\$inode` +=== + +cindex:[base62] +When %directory% is set, but neither %maildir_format% nor %mailstore_format% +is set, ^appendfile^ delivers each message into a file whose name is obtained +by expanding this string. The default value generates a unique name from the +current time, in base 62 form, and the inode of the file. The variable +$inode$ is available only when expanding this option. + + +oindex:[%directory_mode%] +`..'= +%directory_mode%, Use: 'appendfile', Type: 'octal integer', Default: '0700' +=== + +If ^appendfile^ creates any directories as a result of the %create_directory% +option, their mode is specified by this option. + + +oindex:[%escape_string%] +`..'= +%escape_string%, Use: 'appendfile', Type: 'string', Default: 'see description' +=== + +See %check_string% above. + + +oindex:[%file%] +`..'= +%file%, Use: 'appendfile', Type: 'string'!!, Default: 'unset' +=== + +This option is mutually exclusive with the %directory% option, but one of +%file% or %directory% must be set, unless the delivery is the direct result of +a redirection (see section <<SECTfildiropt>>). The %file% option specifies a +single file, to which the message is appended. One or more of +%use_fcntl_lock%, %use_flock_lock%, or %use_lockfile% must be set with +%file%. + +cindex:[NFS,lock file] +cindex:[locking files] +cindex:[lock files] +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. 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 + +cindex:[``sticky'' bit] +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. + + + +oindex:[%file_format%] +`..'= +%file_format%, Use: 'appendfile', Type: 'string', Default: 'unset' +=== + +cindex:[file,mailbox; checking existing format] +This option requests the transport to check the format of an existing file +before adding to it. The check consists of matching a specific string at the +start of the file. The value of the option consists of an even number of +colon-separated strings. The first of each pair is the test string, and the +second is the name of a transport. If the transport associated with a matched +string is not the current transport, control is passed over to the other +transport. For example, suppose the standard ^local_delivery^ transport has +this added to it: + +.... +file_format = "From : local_delivery :\ + \1\1\1\1\n : local_mmdf_delivery" +.... + +Mailboxes that begin with ``From'' are still handled by this transport, but if a +mailbox begins with four binary ones followed by a newline, control is passed +to a transport called %local_mmdf_delivery%, which presumably is configured +to do the delivery in MMDF format. If a mailbox does not exist or is empty, it +is assumed to match the current transport. If the start of a mailbox doesn't +match any string, or if the transport named for a given string is not defined, +delivery is deferred. + + +oindex:[%file_must_exist%] +`..'= +%file_must_exist%, Use: 'appendfile', 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. + + +oindex:[%lock_fcntl_timeout%] +`..'= +%lock_fcntl_timeout%, Use: 'appendfile', Type: 'time', Default: '0s' +=== + +cindex:[timeout,mailbox locking] +cindex:[mailbox locking,blocking and non-blocking] +cindex:[locking files] +By default, the ^appendfile^ transport uses non-blocking calls to 'fcntl()' +when locking an open mailbox file. If the call fails, the delivery process +sleeps for %lock_interval% and tries again, up to %lock_retries% times. +Non-blocking calls are used so that the file is not kept open during the wait +for the lock; the reason for this is to make it as safe as possible for +deliveries over NFS in the case when processes might be accessing an NFS +mailbox without using a lock file. This should not be done, but +misunderstandings and hence misconfigurations are not unknown. + +On a busy system, however, the performance of a non-blocking lock approach is +not as good as using a blocking lock with a timeout. In this case, the waiting +is done inside the system call, and Exim's delivery process acquires the lock +and can proceed as soon as the previous lock holder releases it. + +If %lock_fcntl_timeout% is set to a non-zero time, blocking locks, with that +timeout, are used. There may still be some retrying: the maximum number of +retries is + + (lock_retries * lock_interval) / lock_fcntl_timeout + +rounded up to the next whole number. In other words, the total time during +which ^appendfile^ is trying to get a lock is roughly the same, unless +%lock_fcntl_timeout% is set very large. + +You should consider setting this option if you are getting a lot of delayed +local deliveries because of errors of the form + + failed to lock mailbox /some/file (fcntl) + + + +oindex:[%lock_flock_timeout%] +`..'= +%lock_flock_timeout%, Use: 'appendfile', Type: 'time', Default: '0s' +=== + +This timeout applies to file locking when using 'flock()' (see %use_flock%); +the timeout operates in a similar manner to %lock_fcntl_timeout%. + + +oindex:[%lock_interval%] +`..'= +%lock_interval%, Use: 'appendfile', Type: 'time', Default: '3s' +=== + +This specifies the time to wait between attempts to lock the file. See below +for details of locking. + + +oindex:[%lock_retries%] +`..'= +%lock_retries%, Use: 'appendfile', 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. + + +oindex:[%lockfile_mode%] +`..'= +%lockfile_mode%, Use: 'appendfile', Type: 'octal integer', Default: '0600' +=== + +This specifies the mode of the created lock file, when a lock file is being +used (see %use_lockfile%). + + +oindex:[%lockfile_timeout%] +`..'= +%lockfile_timeout%, Use: 'appendfile', Type: 'time', Default: '30m' +=== + +cindex:[timeout,mailbox locking] +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. + + +oindex:[%mailbox_filecount%] +`..'= +%mailbox_filecount%, Use: 'appendfile', Type: 'string'!!, Default: 'unset' +=== + +cindex:[mailbox,specifying size of] +cindex:[size,of mailbox] +If this option is set, it is expanded, and the result is taken as the current +number of files in the mailbox. It must be a decimal number, optionally +followed by K or M. This provides a way of obtaining this information from an +external source that maintains the data. + + +oindex:[%mailbox_size%] +`..'= +%mailbox_size%, Use: 'appendfile', Type: 'string'!!, Default: 'unset' +=== + +cindex:[mailbox,specifying size of] +cindex:[size,of mailbox] +If this option is set, it is expanded, and the result is taken as the current +size the mailbox. It must be a decimal number, optionally followed by K or M. +This provides a way of obtaining this information from an external source that +maintains the data. This is likely to be helpful for maildir deliveries where +it is computationally expensive to compute the size of a mailbox. + + + +oindex:[%maildir_format%] +`..'= +%maildir_format%, Use: 'appendfile', Type: 'boolean', Default: 'false' +=== + +cindex:[maildir format,specifying] +If this option is set with the %directory% option, the delivery is into a new +file, in the ``maildir'' format that is used by other mail software. When the +transport is activated directly from a ^redirect^ router (for example, the +^address_file^ transport in the default configuration), setting +%maildir_format% causes the path received from the router to be treated as a +directory, whether or not it ends with `/`. This option is available only if +SUPPORT_MAILDIR is present in _Local/Makefile_. See section +<<SECTmaildirdelivery>> below for further details. + + +oindex:[%maildir_quota_directory_regex%] +`..'= +%maildir_quota_directory_regex%, Use: 'appendfile', Type: 'string', Default: 'See below' +=== + +cindex:[maildir format,quota; directories included in] +cindex:[quota,maildir; directories included in] +This option is relevant only when %maildir_use_size_file% is set. It defines +a regular expression for specifying directories that should be included in the +quota calculation. The default value is + + maildir_quota_directory_regex = ^(?:cur|new|\..*)$ + +which includes the _cur_ and _new_ directories, and any maildir++ folders +(directories whose names begin with a dot). If you want to exclude the +_Trash_ +folder from the count (as some sites do), you need to change this setting to + + maildir_quota_directory_regex = ^(?:cur|new|\.(?!Trash).*)$ + +This uses a negative lookahead in the regular expression to exclude the +directory whose name is _.Trash_. + + +oindex:[%maildir_retries%] +`..'= +%maildir_retries%, Use: 'appendfile', Type: 'integer', Default: '10' +=== + +This option specifies the number of times to retry when writing a file in +``maildir'' format. See section <<SECTmaildirdelivery>> below. + + +oindex:[%maildir_tag%] +`..'= +%maildir_tag%, Use: 'appendfile', Type: 'string'!!, Default: 'unset' +=== + +This option applies only to deliveries in maildir format, and is described in +section <<SECTmaildirdelivery>> below. + + +oindex:[%maildir_use_size_file%] +`..'= +%maildir_use_size_file%, Use: 'appendfile', Type: 'boolean', Default: 'false' +=== + +cindex:[maildir format,_maildirsize_ file] +Setting this option true enables support for _maildirsize_ files. Exim +creates a _maildirsize_ file in a maildir if one does not exist, taking the +quota from the %quota% option of the transport. If %quota% is unset, the value +is zero. See section <<SECTmaildirdelivery>> below for further details. + + +oindex:[%mailstore_format%] +`..'= +%mailstore_format%, Use: 'appendfile', Type: 'boolean', Default: 'false' +=== + +cindex:[mailstore format,specifying] +If this option is set with the %directory% option, the delivery is into two new +files in ``mailstore'' format. The option is available only if +SUPPORT_MAILSTORE is present in _Local/Makefile_. See section +<<SECTopdir>> below for further details. + + +oindex:[%mailstore_prefix%] +`..'= +%mailstore_prefix%, Use: 'appendfile', Type: 'string'!!, Default: 'unset' +=== + +This option applies only to deliveries in mailstore format, and is described in +section <<SECTopdir>> below. + + +oindex:[%mailstore_suffix%] +`..'= +%mailstore_suffix%, Use: 'appendfile', Type: 'string'!!, Default: 'unset' +=== + +This option applies only to deliveries in mailstore format, and is described in +section <<SECTopdir>> below. + + +oindex:[%mbx_format%] +`..'= +%mbx_format%, Use: 'appendfile', Type: 'boolean', Default: 'false' +=== + +cindex:[locking files] +cindex:[file,locking] +cindex:[file,MBX format] +cindex:[MBX format, specifying] +This option is available only if Exim has been compiled with SUPPORT_MBX +set in _Local/Makefile_. If %mbx_format% is set with the %file% option, +the message is appended to the mailbox file in MBX format instead of +traditional Unix format. This format is supported by Pine4 and its associated +IMAP and POP daemons, by means of the 'c-client' library that they all use. + +*Note*: The %message_prefix% and %message_suffix% options are not +automatically changed by the use of %mbx_format%. They should normally be set +empty when using MBX format, so this option almost always appears in this +combination: + + mbx_format = true + message_prefix = + message_suffix = + + +If none of the locking options are mentioned in the configuration, +%use_mbx_lock% is assumed and the other locking options default to false. It +is possible to specify the other kinds of locking with %mbx_format%, but +%use_fcntl_lock% and %use_mbx_lock% are mutually exclusive. MBX locking +interworks with 'c-client', providing for shared access to the mailbox. It +should not be used if any program that does not use this form of locking is +going to access the mailbox, nor should it be used if the mailbox file is NFS +mounted, because it works only when the mailbox is accessed from a single host. + +If you set %use_fcntl_lock% with an MBX-format mailbox, you cannot use +the standard version of 'c-client', because as long as it has a mailbox open +(this means for the whole of a Pine or IMAP session), Exim will not be able to +append messages to it. + + +oindex:[%message_prefix%] +`..'= +%message_prefix%, Use: 'appendfile', Type: 'string'!!, Default: 'see below' +=== + +cindex:[``From'' line] +The string specified here is expanded and output at the start of every message. +The default is unset unless %file% is specified and %use_bsmtp% is not set, in +which case it is: + +.... +message_prefix = "From ${if def:return_path{$return_path}\ + {MAILER-DAEMON}} $tod_bsdinbox\n" +.... + + + +oindex:[%message_suffix%] +`..'= +%message_suffix%, Use: 'appendfile', Type: 'string'!!, Default: 'see below' +=== + +The string specified here is expanded and output at the end of every message. +The default is unset unless %file% is specified and %use_bsmtp% is not set, in +which case it is a single newline character. The suffix can be suppressed by +setting + + message_suffix = + + + +oindex:[%mode%] +`..'= +%mode%, Use: 'appendfile', Type: 'octal 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, the mode of the output file is always forced to take that +value, and this option is ignored. + + +oindex:[%mode_fail_narrower%] +`..'= +%mode_fail_narrower%, Use: 'appendfile', 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 deferred (``mailbox has the wrong mode''); otherwise Exim +continues with the delivery attempt, using the existing mode of the file. + + +oindex:[%notify_comsat%] +`..'= +%notify_comsat%, Use: 'appendfile', 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. + + +oindex:[%quota%] +`..'= +%quota%, Use: 'appendfile', Type: 'string'!!, Default: 'unset' +=== + +cindex:[quota,imposed by Exim] +This option imposes a limit on the size of the file to which Exim is appending, +or to the total space used in the directory tree when the %directory% option is +set. In the latter case, computation of the space used is expensive, because +all the files in the directory (and any sub-directories) have to be +individually inspected and their sizes summed. +(See %quota_size_regex% and %maildir_use_size_file% for ways to avoid this +in environments where users have no shell access to their mailboxes). + +As there is no interlock against two simultaneous deliveries into a +multi-file mailbox, it is possible for the quota to be overrun in this case. +For single-file mailboxes, of course, an interlock is a necessity. + +A file's size is taken as its 'used' value. Because of blocking effects, this +may be a lot less than the actual amount of disk space allocated to the file. +If the sizes of a number of files are being added up, the rounding effect can +become quite noticeable, especially on systems that have large block sizes. +Nevertheless, it seems best to stick to the 'used' figure, because this is +the obvious value which users understand most easily. + +The value of the option 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, before it changes uid for the +delivery. This means that files which 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. + +*Note*: A value of zero is interpreted as ``no quota''. + +By default, Exim's quota checking mimics system quotas, and restricts the +mailbox to the specified maximum size, though the value is not accurate to the +last byte, owing to separator lines and additional headers that may get added +during message delivery. When a mailbox is nearly full, large messages may get +refused even though small ones are accepted, because the size of the current +message is added to the quota when the check is made. This behaviour can be +changed by setting %quota_is_inclusive% false. When this is done, the check +for exceeding the quota does not include the current message. Thus, deliveries +continue until the quota has been exceeded; thereafter, no further messages are +delivered. See also %quota_warn_threshold%. + + +oindex:[%quota_directory%] +`..'= +%quota_directory%, Use: 'appendfile', Type: 'string'!!, Default: 'unset' +=== + +This option defines the directory to check for quota purposes when delivering +into individual files. The default is the delivery directory, or, if a file +called _maildirfolder_ exists in a maildir directory, the parent of the +delivery directory. + + +oindex:[%quota_filecount%] +`..'= +%quota_filecount%, Use: 'appendfile', Type: 'string'!!, Default: '0' +=== + +This option applies when the %directory% option is set. It limits the total +number of files in the directory (compare the inode limit in system quotas). It +can only be used if %quota% is also set. The value is expanded; an expansion +failure causes delivery to be deferred. + + +oindex:[%quota_is_inclusive%] +`..'= +%quota_is_inclusive%, Use: 'appendfile', Type: 'boolean', Default: 'true' +=== + +See %quota% above. + + +oindex:[%quota_size_regex%] +`..'= +%quota_size_regex%, Use: 'appendfile', Type: 'string', Default: 'unset' +=== + +This option applies when one of the delivery modes that writes a separate file +for each message is being used. When Exim wants to find the size of one of +these files in order to test the quota, it first checks %quota_size_regex%. +If this is set to a regular expression that matches the file name, and it +captures one string, that string is interpreted as a representation of the +file's size. The value of %quota_size_regex% is not expanded. + +This feature is useful only when users have no shell access to their mailboxes +-- otherwise they could defeat the quota simply by renaming the files. This +facility can be used with maildir deliveries, by setting %maildir_tag% to add +the file length to the file name. For example: + + maildir_tag = ,S=$message_size + quota_size_regex = ,S=(\d+) + +The regular expression should not assume that the length is at the end of the +file name (even though %maildir_tag% puts it there) because maildir MUAs +sometimes add other information onto the ends of message file names. + + +oindex:[%quota_warn_message%] +`..'= +%quota_warn_message%, Use: 'appendfile', Type: 'string'!!, Default: 'see below' +=== + +See below for the use of this option. If it is not set when +%quota_warn_threshold% is set, it defaults to + +.... +quota_warn_message = "\ + To: $local_part@$domain\n\ + Subject: Your mailbox\n\n\ + This message is automatically created \ + by mail delivery software.\n\n\ + The size of your mailbox has exceeded \ + a warning threshold that is\n\ + set by the system administrator.\n" +.... + + + +oindex:[%quota_warn_threshold%] +`..'= +%quota_warn_threshold%, Use: 'appendfile', Type: 'string'!!, Default: '0' +=== + +cindex:[quota,warning threshold] +cindex:[mailbox,size warning] +cindex:[size,of mailbox] +This option is expanded in the same way as %quota% (see above). If the +resulting value is greater than zero, and delivery of the message causes the +size of the file or total space in the directory tree to cross the given +threshold, a warning message is sent. If %quota% is also set, the threshold may +be specified as a percentage of it by following the value with a percent sign. +For example: + + quota = 10M + quota_warn_threshold = 75% + +If %quota% is not set, a setting of %quota_warn_threshold% that ends with a +percent sign is ignored. + +The warning message itself is specified by the %quota_warn_message% option, +and it must start with a 'To:' header line containing the recipient(s). A +'Subject:' line should also normally be supplied. The %quota% option does not +have to be set in order to use this option; they are independent of one +another except when the threshold is specified as a percentage. + + +oindex:[%use_bsmtp%] +`..'= +%use_bsmtp%, Use: 'appendfile', Type: 'boolean', Default: 'false' +=== + +cindex:[envelope sender] +If this option is set true, ^appendfile^ writes messages in ``batch SMTP'' +format, with the envelope sender and recipient(s) included as SMTP commands. If +you want to include a leading HELO command with such messages, you can do +so by setting the %message_prefix% option. See section <<SECTbatchSMTP>> for +details of batch SMTP. + + +oindex:[%use_crlf%] +`..'= +%use_crlf%, Use: 'appendfile', Type: 'boolean', Default: 'false' +=== + +cindex:[carriage return] +cindex:[linefeed] +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. + +The contents of the %message_prefix% and %message_suffix% options are written +verbatim, so must contain their own carriage return characters if these are +needed. In cases where these options have non-empty defaults, the values end +with a single linefeed, so they +must +be changed to end with `\r\n` if %use_crlf% is set. + + +oindex:[%use_fcntl_lock%] +`..'= +%use_fcntl_lock%, Use: 'appendfile', Type: 'boolean', Default: 'see below' +=== + +This option controls the use of the 'fcntl()' function to lock a file for +exclusive use when a message is being appended. It is set by default unless +%use_flock_lock% is set. Otherwise, it should be turned off only if you know +that all your MUAs use lock file locking. When both %use_fcntl_lock% and +%use_flock_lock% are unset, %use_lockfile% must be set. + + +oindex:[%use_flock_lock%] +`..'= +%use_flock_lock%, Use: 'appendfile', Type: 'boolean', Default: 'false' +=== + +This option is provided to support the use of 'flock()' for file locking, for +the few situations where it is needed. Most modern operating systems support +'fcntl()' and 'lockf()' locking, and these two functions interwork with +each other. Exim uses 'fcntl()' locking by default. + +This option is required only if you are using an operating system where +'flock()' is used by programs that access mailboxes (typically MUAs), and +where 'flock()' does not correctly interwork with 'fcntl()'. You can use +both 'fcntl()' and 'flock()' locking simultaneously if you want. + +cindex:[Solaris,'flock()' support] +Not all operating systems provide 'flock()'. Some versions of Solaris do not +have it (and some, I think, provide a not quite right version built on top of +'lockf()'). If the OS does not have 'flock()', Exim will be built without +the ability to use it, and any attempt to do so will cause a configuration +error. + +*Warning*: 'flock()' locks do not work on NFS files (unless 'flock()' +is just being mapped onto 'fcntl()' by the OS). + + +oindex:[%use_lockfile%] +`..'= +%use_lockfile%, Use: 'appendfile', Type: 'boolean', Default: 'see below' +=== + +If this option is turned off, Exim does not attempt to create a lock file when +appending to a mailbox file. In this situation, the only locking is by +'fcntl()'. 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. + +cindex:[NFS,lock file] +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. + +The %use_lockfile% option is set by default unless %use_mbx_lock% is set. It +is not possible to turn both %use_lockfile% and %use_fcntl_lock% off, except +when %mbx_format% is set. + + +oindex:[%use_mbx_lock%] +`..'= +%use_mbx_lock%, Use: 'appendfile', Type: 'boolean', Default: 'see below' +=== + +This option is available only if Exim has been compiled with SUPPORT_MBX +set in _Local/Makefile_. Setting the option specifies that special MBX +locking rules be used. It is set by default if %mbx_format% is set and none of +the locking options are mentioned in the configuration. The locking rules are +the same as are used by the 'c-client' library that underlies Pine and the +IMAP4 and POP daemons that come with it (see the discussion below). The rules +allow for shared access to the mailbox. However, this kind of locking does not +work when the mailbox is NFS mounted. + +You can set %use_mbx_lock% with either (or both) of %use_fcntl_lock% and +%use_flock_lock% to control what kind of locking is used in implementing the +MBX locking rules. The default is to use 'fcntl()' if %use_mbx_lock% is set +without %use_fcntl_lock% or %use_flock_lock%. + + + + +[[SECTopappend]] +Operational details for appending +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[appending to a file] +cindex:[file,appending] +Before appending to a file, the following preparations are made: + +- If the name of the file is _/dev/null_, no action is taken, and a success +return is given. + +- cindex:[directory creation] +If any directories on the file's path are missing, Exim creates them if the +%create_directory% option is set. A created directory's mode is given by the +%directory_mode% option. + +- If %file_format% is set, the format of an existing file is checked. If this +indicates that a different transport should be used, control is passed to that +transport. + +- cindex:[file,locking] +cindex:[locking files] +cindex:[NFS,lock file] +If %use_lockfile% is set, a lock file is built in a way that will work +reliably over NFS, as follows: ++ +-- +. Create a ``hitching post'' file whose name is that of the lock file with the +current time, primary host name, and process id added, by opening for writing +as a new file. If this fails with an access error, delivery is deferred. + +. Close the hitching post file, and hard link it to the lock file name. + +. If the call to 'link()' succeeds, creation of the lock file has succeeded. +Unlink the hitching post name. + +. Otherwise, use 'stat()' to get information about the hitching post file, and +then unlink hitching post name. If the number of links is exactly two, creation +of the lock file succeeded but something (for example, an NFS server crash and +restart) caused this fact not to be communicated to the 'link()' call. + +. If creation of the lock file failed, wait for %lock_interval% and try again, +up to %lock_retries% times. However, since any program that writes to a +mailbox should complete its task very quickly, it is reasonable to time out old +lock files that are normally the result of user agent and system crashes. If an +existing lock file is older than %lockfile_timeout% Exim attempts to unlink it +before trying again. +-- ++ +- A call is made to 'lstat()' to discover whether the main file exists, and if +so, what its characteristics are. If 'lstat()' fails for any reason other +than non-existence, delivery is deferred. + +- cindex:[symbolic link,to mailbox] +cindex:[mailbox,symbolic link] +If the file does exist and is a symbolic link, delivery is deferred, unless the +%allow_symlink% option is set, in which case the ownership of the link is +checked, and then 'stat()' is called to find out about the real file, which +is then subjected to the checks below. The check on the top-level link +ownership prevents one user creating a link for another's mailbox in a sticky +directory, though allowing symbolic links in this case is definitely not a good +idea. If there is a chain of symbolic links, the intermediate ones are not +checked. + +- If the file already exists but is not a regular file, or if the file's owner +and group (if the group is being checked -- see %check_group% above) are +different from the user and group under which the delivery is running, +delivery is deferred. + +- If the file's permissions are more generous than specified, they are reduced. +If they are insufficient, delivery is deferred, unless %mode_fail_narrower% +is set false, in which case the delivery is tried using the existing +permissions. + +- The file's inode number is saved, and the file is then opened for appending. +If this fails because the file has vanished, ^appendfile^ behaves as if it +hadn't existed (see below). For any other failures, delivery is deferred. + +- If the file is opened successfully, check that the inode number hasn't +changed, that it is still a regular file, and that the owner and permissions +have not changed. If anything is wrong, defer delivery and freeze the message. + +- If the file did not exist originally, defer delivery if the %file_must_exist% +option is set. Otherwise, check that the file is being created in a permitted +directory if the %create_file% option is set (deferring on failure), and then +open for writing as a new file, with the O_EXCL and O_CREAT options, +except when dealing with a symbolic link (the %allow_symlink% option must be +set). In this case, which can happen if the link points to a non-existent file, +the file is opened for writing using O_CREAT but not O_EXCL, because +that prevents link following. + +- cindex:[loop,while file testing] +If opening fails because the file exists, obey the tests given above for +existing files. However, to avoid looping in a situation where the file is +being continuously created and destroyed, the exists/not-exists loop is broken +after 10 repetitions, and the message is then frozen. + +- If opening fails with any other error, defer delivery. + +- cindex:[file,locking] +cindex:[locking files] +Once the file is open, unless both %use_fcntl_lock% and %use_flock_lock% +are false, it is locked using 'fcntl()' or 'flock()' or both. If +%use_mbx_lock% is false, an exclusive lock is requested in each case. +However, if %use_mbx_lock% is true, +Exim takes out a shared lock on the open file, +and an exclusive lock on the file whose name is + + /tmp/.<device-number>.<inode-number> ++ +using the device and inode numbers of the open mailbox file, in accordance with +the MBX locking rules. ++ +If Exim fails to lock the file, there are two possible courses of action, +depending on the value of the locking timeout. This is obtained from +%lock_fcntl_timeout% or %lock_flock_timeout%, as appropriate. ++ +If the timeout value is zero, the file is closed, Exim waits for +%lock_interval%, and then goes back and re-opens the file as above and tries +to lock it again. This happens up to %lock_retries% times, after which the +delivery is deferred. ++ +If the timeout has a value greater than zero, blocking calls to 'fcntl()' or +'flock()' are used (with the given timeout), so there has already been some +waiting involved by the time locking fails. Nevertheless, Exim does not give up +immediately. It retries up to + + (lock_retries * lock_interval) / <timeout> ++ +times (rounded up). + + +At the end of delivery, Exim closes the file (which releases the 'fcntl()' +and/or 'flock()' locks) and then deletes the lock file if one was created. + + +[[SECTopdir]] +Operational details for delivery to a new file +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[delivery,to single file] +cindex:[``From'' line] +When the %directory% option is set instead of %file%, each message is delivered +into a newly-created file or set of files. When ^appendfile^ is activated +directly from a ^redirect^ router, neither %file% nor %directory% is normally +set, because the path for delivery is supplied by the router. (See for example, +the ^address_file^ transport in the default configuration.) In this case, +delivery is to a new file if either the path name ends in `/`, or the +%maildir_format% or %mailstore_format% option is set. + +No locking is required while writing the message to 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 values for +%check_string%, %message_prefix%, and %message_suffix% are all unset when +any of %directory%, %maildir_format%, or %mailstore_format% is set. + +If Exim is required to check a %quota% setting, it adds up the sizes of all the +files in the delivery directory by default. However, you can specify a +different directory by setting %quota_directory%. Also, for maildir deliveries +(see below) the _maildirfolder_ convention is honoured. + + +cindex:[maildir format] +cindex:[mailstore format] +There are three different ways in which delivery to individual files can be +done, controlled by the settings of the %maildir_format% and +%mailstore_format% options. Note that code to support maildir or mailstore +formats is not included in the binary unless SUPPORT_MAILDIR or +SUPPORT_MAILSTORE, respectively, is set in _Local/Makefile_. + +cindex:[directory creation] +In all three cases an attempt is made to create the directory and any necessary +sub-directories if they do not exist, provided that the %create_directory% +option is set (the default). The location of a created directory can be +constrained by setting %create_file%. A created directory's mode is given by +the %directory_mode% option. If creation fails, or if the %create_directory% +option is not set when creation is required, delivery is deferred. + + + +[[SECTmaildirdelivery]] +Maildir delivery +~~~~~~~~~~~~~~~~ +cindex:[maildir format,description of] +If the %maildir_format% option is true, Exim delivers each message by writing +it to a file whose name is _tmp/<stime>.H<mtime>P<pid>.<host>_ in the +given directory. If the delivery is successful, the file is renamed into the +_new_ subdirectory. + +In the file name, <'stime'> is the current time of day in seconds, and +<'mtime'> is the microsecond fraction of the time. After a maildir delivery, +Exim checks that the time-of-day clock has moved on by at least one microsecond +before terminating the delivery process. This guarantees uniqueness for the +file name. However, as a precaution, Exim calls 'stat()' for the file before +opening it. If any response other than ENOENT (does not exist) is given, +Exim waits 2 seconds and tries again, up to %maildir_retries% times. + +cindex:[quota,in maildir delivery] +cindex:[maildir++] +If Exim is required to check a %quota% setting before a maildir delivery, and +%quota_directory% is not set, it looks for a file called _maildirfolder_ in +the maildir directory (alongside _new_, _cur_, _tmp_). If this exists, +Exim assumes the directory is a maildir++ folder directory, which is one level +down from the user's top level mailbox directory. This causes it to start at +the parent directory instead of the current directory when calculating the +amount of space used. + +One problem with delivering into a multi-file mailbox is that it is +computationally expensive to compute the size of the mailbox for quota +checking. Various approaches have been taken to reduce the amount of work +needed. The next two sections describe two of them. A third alternative is to +use some external process for maintaining the size data, and use the expansion +of the %mailbox_size% option as a way of importing it into Exim. + + + + +Using tags to record message sizes +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +If %maildir_tag% is set, the string is expanded for each delivery. +When the maildir file is renamed into the _new_ sub-directory, the +tag is added to its name. However, if adding the tag takes the length of the +name to the point where the test 'stat()' call fails with ENAMETOOLONG, +the tag is dropped and the maildir file is created with no tag. + +Tags can be used to encode the size of files in their names; see +%quota_size_regex% above for an example. The expansion of %maildir_tag% +happens after the message has been written. The value of the $message_size$ +variable is set to the number of bytes actually written. If the expansion is +forced to fail, the tag is ignored, but a non-forced failure causes delivery to +be deferred. The expanded tag may contain any printing characters except ``/''. +Non-printing characters in the string are ignored; if the resulting string is +empty, it is ignored. If it starts with an alphanumeric character, a leading +colon is inserted. + + + +Using a maildirsize file +~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[quota,in maildir delivery] +cindex:[maildir format,_maildirsize_ file] +If %maildir_use_size_file% is true, Exim implements the maildir++ rules for +storing quota and message size information in a file called _maildirsize_ +within the maildir directory. If this file does not exist, Exim creates it, +setting the quota from the %quota% option of the transport. If the maildir +directory itself does not exist, it is created before any attempt to write a +_maildirsize_ file. + +The _maildirsize_ file is used to hold information about the sizes of +messages in the maildir, thus speeding up quota calculations. The quota value +in the file is just a cache; if the quota is changed in the transport, the new +value overrides the cached value when the next message is delivered. The cache +is maintained for the benefit of other programs that access the maildir and +need to know the quota. + +If the %quota% option in the transport is unset or zero, the _maildirsize_ +file is maintained (with a zero quota setting), but no quota is imposed. + +A regular expression is available for controlling which directories in the +maildir participate in quota calculations. See the description of the +%maildir_quota_directory_regex% option above for details. + + + +Mailstore delivery +~~~~~~~~~~~~~~~~~~ +cindex:[mailstore format,description of] +If the %mailstore_format% option is true, each message is written as two files +in the given directory. A unique base name is constructed from the message id +and the current delivery process, and the files that are written use this base +name plus the suffixes _.env_ and _.msg_. The _.env_ file contains the +message's envelope, and the _.msg_ file contains the message itself. + +During delivery, the envelope is first written to a file with the suffix +_.tmp_. The _.msg_ file is then written, and when it is complete, the +_.tmp_ file is renamed as the _.env_ file. Programs that access messages in +mailstore format should wait for the presence of both a _.msg_ and a _.env_ +file before accessing either of them. An alternative approach is to wait for +the absence of a _.tmp_ file. + +The envelope file starts with any text defined by the %mailstore_prefix% +option, expanded and terminated by a newline if there isn't one. Then follows +the sender address on one line, then all the recipient addresses, one per line. +There can be more than one recipient only if the %batch_max% option is set +greater than one. Finally, %mailstore_suffix% is expanded and the result +appended to the file, followed by a newline if it does not end with one. + +If expansion of %mailstore_prefix% or %mailstore_suffix% ends with a forced +failure, it is ignored. Other expansion errors are treated as serious +configuration errors, and delivery is deferred. + + + +Non-special new file delivery +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +If neither %maildir_format% nor %mailstore_format% is set, a single new file +is created directly in the named directory. For example, when delivering +messages into files in batched SMTP format for later delivery to some host (see +section <<SECTbatchSMTP>>), 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 obtained by +expanding the contents of the %directory_file% option. + + + + + + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// + +The autoreply transport +----------------------- +cindex:[transports,^autoreply^] +cindex:[^autoreply^ transport] +The ^autoreply^ transport is not a true transport in that it does not cause +the message to be transmitted. Instead, it generates a new mail message. + +If the router that passes the message to this transport does not have the +%unseen% option set, the original message (for the current recipient) is not +delivered anywhere. However, when the %unseen% option is set on the router that +passes the message to this transport, routing of the address continues, so +another router can set up a normal message delivery. + + +The ^autoreply^ transport is usually run as the result of mail filtering, a +``vacation'' message being the standard example. However, it can also be run +directly from a router like any other transport. To reduce the possibility of +message cascades, messages created by the ^autoreply^ transport always have +empty envelope sender addresses, like bounce messages. + +The parameters of the message to be sent can be specified in the configuration +by options described below. However, these are used only when the address +passed to the transport does not contain its own reply information. When the +transport is run as a consequence of a +%mail% +or %vacation% command in a filter file, the parameters of the message are +supplied by the filter, and passed with the address. The transport's options +that define the message are then ignored (so they are not usually set in this +case). The message is specified entirely by the filter or by the transport; it +is never built from a mixture of options. However, the %file_optional%, +%mode%, and %return_message% options apply in all cases. + +^Autoreply^ is implemented as a local transport. When used as a result of a +command in a user's filter file, ^autoreply^ normally runs under the uid and +gid of the user, and with appropriate current and home directories (see chapter +<<CHAPenvironment>>). + +There is a subtle difference between routing a message to a ^pipe^ transport +that generates some text to be returned to the sender, and routing it to an +^autoreply^ transport. This difference is noticeable only if more than one +address from the same message is so handled. In the case of a pipe, the +separate outputs from the different addresses are gathered up and returned to +the sender in a single message, whereas if ^autoreply^ is used, a separate +message is generated for each address that is passed to it. + +Non-printing characters are not permitted in the header lines generated for the +message that ^autoreply^ creates, with the exception of newlines that are +immediately followed by whitespace. If any non-printing characters are found, +the transport defers. +Whether characters with the top bit set count as printing characters or not is +controlled by the %print_topbitchars% global option. + +If any of the generic options for manipulating headers (for example, +%headers_add%) are set on an ^autoreply^ transport, they apply to the copy of +the original message that is included in the generated message when +%return_message% is set. They do not apply to the generated message itself. + +If the ^autoreply^ transport receives return code 2 from Exim when it submits +the message, indicating that there were no recipients, it does not treat this +as an error. This means that autoreplies sent to $sender_address$ when this +is empty (because the incoming message is a bounce message) do not cause +problems. They are just discarded. + + + +Private options for autoreply +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[options,^autoreply^ transport] + +oindex:[%bcc%] +`..'= +%bcc%, Use: 'autoreply', Type: 'string'!!, Default: 'unset' +=== + +This specifies the addresses that are to receive ``blind carbon copies'' of the +message when the message is specified by the transport. + + +oindex:[%cc%] +`..'= +%cc%, Use: 'autoreply', Type: 'string'!!, Default: 'unset' +=== + +This specifies recipients of the message and the contents of the 'Cc:' header +when the message is specified by the transport. + + +oindex:[%file%] +`..'= +%file%, Use: 'autoreply', Type: 'string'!!, Default: 'unset' +=== + +The contents of the file are sent as the body of the message when the message +is specified by the transport. If both %file% and %text% are set, the text +string comes first. + + +oindex:[%file_expand%] +`..'= +%file_expand%, Use: 'autoreply', Type: 'boolean', Default: 'false' +=== + +If this is set, the contents of the file named by the %file% option are +subjected to string expansion as they are added to the message. + + +oindex:[%file_optional%] +`..'= +%file_optional%, Use: 'autoreply', Type: 'boolean', Default: 'false' +=== + +If this option is true, no error is generated if the file named by the %file% +option or passed with the address does not exist or cannot be read. + + +oindex:[%from%] +`..'= +%from%, Use: 'autoreply', Type: 'string'!!, Default: 'unset' +=== + +This specifies the contents of the 'From:' header when the message is specified +by the transport. + + +oindex:[%headers%] +`..'= +%headers%, Use: 'autoreply', Type: 'string'!!, Default: 'unset' +=== + +This specifies additional RFC 2822 headers that are to be added to the message when +the message is specified by the transport. Several can be given by using ``\n'' +to separate them. There is no check on the format. + + +oindex:[%log%] +`..'= +%log%, Use: 'autoreply', Type: 'string'!!, Default: 'unset' +=== + +This option names a file in which a record of every message sent is logged when +the message is specified by the transport. + + +oindex:[%mode%] +`..'= +%mode%, Use: 'autoreply', Type: 'octal integer', Default: '0600' +=== + +If either the log file or the ``once'' file has to be created, this mode is used. + + +oindex:[%never_mail%] +`..'= +%never_mail%, Use: 'autoreply', Type: 'address list'!!, Default: 'unset' +=== + +If any run of the transport creates a message with a recipient that matches any +item in the list, that recipient is quietly discarded. If all recipients are +discarded, no message is created. + + + +oindex:[%once%] +`..'= +%once%, Use: 'autoreply', Type: 'string'!!, Default: 'unset' +=== + +This option names a file or DBM database in which a record of each +'To:' recipient is kept when the message is specified by the transport. +*Note*: This does not apply to 'Cc:' or 'Bcc:' recipients. +If %once_file_size% is not set, a DBM database is used, and it is allowed to +grow as large as necessary. If a potential recipient is already in the +database, no message is sent by default. However, if %once_repeat% specifies a +time greater than zero, the message is sent if that much time has elapsed since +a message was last sent to this recipient. If %once% is unset, the message is +always sent. + +If %once_file_size% is set greater than zero, it changes the way Exim +implements the %once% option. Instead of using a DBM file to record every +recipient it sends to, it uses a regular file, whose size will never get larger +than the given value. In the file, it keeps a linear list of recipient +addresses and times at which they were sent messages. If the file is full when +a new address needs to be added, the oldest address is dropped. If +%once_repeat% is not set, this means that a given recipient may receive +multiple messages, but at unpredictable intervals that depend on the rate of +turnover of addresses in the file. If %once_repeat% is set, it specifies a +maximum time between repeats. + + +oindex:[%once_file_size%] +`..'= +%once_file_size%, Use: 'autoreply', Type: 'integer', Default: '0' +=== + +See %once% above. + + +oindex:[%once_repeat%] +`..'= +%once_repeat%, Use: 'autoreply', Type: 'time'!!, Default: '0s' +=== + +See %once% above. +After expansion, the value of this option must be a valid time value. + + +oindex:[%reply_to%] +`..'= +%reply_to%, Use: 'autoreply', Type: 'string'!!, Default: 'unset' +=== + +This specifies the contents of the 'Reply-To:' header when the message is +specified by the transport. + + +oindex:[%return_message%] +`..'= +%return_message%, Use: 'autoreply', Type: 'boolean', Default: 'false' +=== + +If this is set, a copy of the original message is returned with the new +message, subject to the maximum size set in the %return_size_limit% global +configuration option. + + +oindex:[%subject%] +`..'= +%subject%, Use: 'autoreply', Type: 'string'!!, Default: 'unset' +=== + +This specifies the contents of the 'Subject:' header when the message is +specified by the transport. + +It is tempting to quote the original subject in automatic responses. For +example: + + subject = Re: $h_subject: + +There is a danger in doing this, however. It may allow a third party to +subscribe your users to an opt-in mailing list, provided that the list accepts +bounce messages as subscription confirmations. Well-managed lists require a +non-bounce message to confirm a subscription, so the danger is relatively +small. + + + +oindex:[%text%] +`..'= +%text%, Use: 'autoreply', Type: 'string'!!, Default: 'unset' +=== + +This specifies a single string to be used as the body of the message when the +message is specified by the transport. If both %text% and %file% are set, the +text comes first. + + +oindex:[%to%] +`..'= +%to%, Use: 'autoreply', Type: 'string'!!, Default: 'unset' +=== + +This specifies recipients of the message and the contents of the 'To:' header +when the message is specified by the transport. + + + + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// + +[[CHAPLMTP]] +The lmtp transport +------------------ +cindex:[transports,^lmtp^] +cindex:[^lmtp^ transport] +cindex:[LMTP,over a pipe] +cindex:[LMTP,over a socket] +The ^lmtp^ transport runs the LMTP protocol (RFC 2033) over a pipe to a +specified command +or by interacting with a Unix domain socket. +This transport is something of a cross between the ^pipe^ and ^smtp^ +transports. Exim also has support for using LMTP over TCP/IP; this is +implemented as an option for the ^smtp^ transport. Because LMTP is expected +to be of minority interest, the default build-time configure in _src/EDITME_ +has it commented out. You need to ensure that + + TRANSPORT_LMTP=yes + +is present in your _Local/Makefile_ in order to have the ^lmtp^ transport +included in the Exim binary. + +cindex:[options,^lmtp^ transport] +The private options of the ^lmtp^ transport are as follows: + +oindex:[%batch_id%] +`..'= +%batch_id%, Use: 'lmtp', Type: 'string'!!, Default: 'unset' +=== + +See the description of local delivery batching in chapter <<CHAPbatching>>. + + +oindex:[%batch_max%] +`..'= +%batch_max%, Use: 'lmtp', Type: 'integer', Default: '1' +=== + +This limits the number of addresses that can be handled in a single delivery. +Most LMTP servers can handle several addresses at once, so it is normally a +good idea to increase this value. See the description of local delivery +batching in chapter <<CHAPbatching>>. + + +oindex:[%command%] +`..'= +%command%, Use: 'lmtp', Type: 'string'!!, Default: 'unset' +=== + +This option must be set if %socket% is not set. +The string is a command which is run in a separate process. It is split up into +a command name and list of arguments, each of which is separately expanded (so +expansion cannot change the number of arguments). The command is run directly, +not via a shell. The message is passed to the new process using the standard +input and output to operate the LMTP protocol. + + +oindex:[%socket%] +`..'= +%socket%, Use: 'lmtp', Type: 'string'!!, Default: 'unset' +=== + +This option must be set if %command% is not set. The result of expansion must +be the name of a Unix domain socket. The transport connects to the socket and +delivers the message to it using the LMTP protocol. + + +oindex:[%timeout%] +`..'= +%timeout%, Use: 'lmtp', Type: 'time', Default: '5m' +=== + +The transport is aborted if the created process +or Unix domain socket +does not respond to LMTP commands or message input within this timeout. + + +Here is an example of a typical LMTP transport: + + lmtp: + driver = lmtp + command = /some/local/lmtp/delivery/program + batch_max = 20 + user = exim + +This delivers up to 20 addresses at a time, in a mixture of domains if +necessary, running as the user 'exim'. + + + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// + +[[CHAPpipetransport]] +The pipe transport +------------------ +cindex:[transports,^pipe^] +cindex:[^pipe^ transport] +The ^pipe^ transport is used to deliver messages via a pipe to a command +running in another process. + +One example is the +use of ^pipe^ as a pseudo-remote transport for passing messages to some other +delivery mechanism (such as UUCP). Another is the use by individual users to +automatically process their incoming messages. The ^pipe^ transport can be +used in one of the following ways: + +- A router routes one address to a transport in the normal way, and the transport +is configured as a ^pipe^ transport. In this case, $local_part$ contains +the local part of the address (as usual), and the command that is run is +specified by the %command% option on the transport. + +- If the %batch_max% option is set greater than 1 (the default), the transport +can be called upon to handle more than one address in a single run. In this +case, $local_part$ is not set (because it is not unique). However, the +pseudo-variable $pipe_addresses$ (described in section <<SECThowcommandrun>> +below) contains all the addresses that are being handled. + +- A router redirects an address directly to a pipe command (for example, from an +alias or forward file). In this case, $local_part$ contains the local part +that was redirected, and $address_pipe$ contains the text of the pipe +command itself. The %command% option on the transport is ignored. + + +The ^pipe^ transport is a non-interactive delivery method. Exim can also +deliver messages over pipes using the LMTP interactive protocol. This is +implemented by the ^lmtp^ transport. + +In the case when ^pipe^ is run as a consequence of an entry in a local user's +_.forward_ file, the command runs under the uid and gid of that user. In +other cases, the uid and gid have to be specified explicitly, either on the +transport or on the router that handles the address. Current and ``home'' +directories are also controllable. See chapter <<CHAPenvironment>> for details of +the local delivery environment. + + + +Concurrent delivery +~~~~~~~~~~~~~~~~~~~ +If two messages arrive at almost the same time, and both are routed to a pipe +delivery, the two pipe transports may be run concurrently. You must ensure that +any pipe commands you set up are robust against this happening. If the commands +write to a file, the %exim_lock% utility might be of use. + + + + +Returned status and data +~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[^pipe^ transport,returned data] +If the command exits with a non-zero return code, the delivery is deemed to +have failed, unless either the %ignore_status% option is set (in which case +the return code is treated as zero), or the return code is one of those listed +in the %temp_errors% option, which are interpreted as meaning ``try again +later''. In this case, delivery is deferred. Details of a permanent failure are +logged, but are not included in the bounce message, which merely contains +``local delivery failed''. + +If the return code is greater than 128 and the command being run is a shell +script, it normally means that the script was terminated by a signal whose +value is the return code minus 128. + +If Exim is unable to run the command (that is, if 'execve()' fails), the +return code is set to 127. This is the value that a shell returns if it is +asked to run a non-existent command. The wording for the log line suggests that +a non-existent command may be the problem. + +The %return_output% option can affect the result of a pipe delivery. If it is +set and the command produces any output on its standard output or standard +error streams, the command is considered to have failed, even if it gave a zero +return code or if %ignore_status% is set. The output from the command is +included as part of the bounce message. The %return_fail_output% option is +similar, except that output is returned only when the command exits with a +failure return code, that is, a value other than zero or a code that matches +%temp_errors%. + + + +[[SECThowcommandrun]] +How the command is run +~~~~~~~~~~~~~~~~~~~~~~ +cindex:[^pipe^ transport,path for command] +The command line is (by default) broken down into a command name and arguments +by the ^pipe^ transport itself. The %allow_commands% and %restrict_to_path% +options can be used to restrict the commands that may be run. + +cindex:[quoting,in pipe command] +Unquoted arguments are delimited by white space. If an argument appears in +double quotes, backslash is interpreted as an escape character in the usual +way. If an argument appears in single quotes, no escaping is done. + +String expansion is applied to the command line except when it comes from a +traditional _.forward_ file (commands from a filter file are expanded). The +expansion is applied to each argument in turn rather than to the whole line. +For this reason, any string expansion item that contains white space must be +quoted so as to be contained within a single argument. A setting such as + + command = /some/path ${if eq{$local_part}{postmaster}{xxx}{yyy}} + +will not work, because the expansion item gets split between several +arguments. You have to write + + command = /some/path "${if eq{$local_part}{postmaster}{xxx}{yyy}}" + +to ensure that it is all in one argument. The expansion is done in this way, +argument by argument, so that the number of arguments cannot be changed as a +result of expansion, and quotes or backslashes in inserted variables do not +interact with external quoting. + +cindex:[transport,filter] +cindex:[filter,transport filter] +Special handling takes place when an argument consists of precisely the text +`\$pipe_addresses\}`. This is not a general expansion variable; the only +place this string is recognized is when it appears as an argument for a pipe or +transport filter command. It causes each address that is being handled to be +inserted in the argument list at that point 'as a separate argument'. This +avoids any problems with spaces or shell metacharacters, and is of use when a +^pipe^ transport is handling groups of addresses in a batch. + +After splitting up into arguments and expansion, the resulting command is run +in a subprocess directly from the transport, 'not' under a shell. The +message that is being delivered is supplied on the standard input, and the +standard output and standard error are both connected to a single pipe that is +read by Exim. The %max_output% option controls how much output the command may +produce, and the %return_output% and %return_fail_output% options control +what is done with it. + +Not running the command under a shell (by default) lessens the security risks +in cases when a command from a user's filter file is built out of data that was +taken from an incoming message. If a shell is required, it can of course be +explicitly specified as the command to be run. However, there are circumstances +where existing commands (for example, in _.forward_ files) expect to be run +under a shell and cannot easily be modified. To allow for these cases, there is +an option called %use_shell%, which changes the way the ^pipe^ transport +works. Instead of breaking up the command line as just described, it expands it +as a single string and passes the result to _/bin/sh_. The +%restrict_to_path% option and the $pipe_addresses$ facility cannot be used +with %use_shell%, and the whole mechanism is inherently less secure. + + + +[[SECTpipeenv]] +Environment variables +~~~~~~~~~~~~~~~~~~~~~ +cindex:[^pipe^ transport,environment for command] +cindex:[environment for pipe transport] +The environment variables listed below are set up when the command is invoked. +This list is a compromise for maximum compatibility with other MTAs. Note that +the %environment% option can be used to add additional variables to this +environment. + +&&& +`DOMAIN ` the domain of the address +`HOME ` the home directory, if set +`HOST ` the host name when called from a router (see below) +`LOCAL_PART ` see below +`LOCAL_PART_PREFIX ` see below +`LOCAL_PART_SUFFIX ` see below +`LOGNAME ` see below +`MESSAGE_ID ` the message's id +`PATH ` as specified by the %path% option below +`QUALIFY_DOMAIN ` the sender qualification domain +`RECIPIENT ` the complete recipient address +`SENDER ` the sender of the message (empty if a bounce) +`SHELL ` `/bin/sh` +`TZ ` the value of the %timezone% option, if set +`USER ` see below +&&& + +When a ^pipe^ transport is called directly from (for example) an ^accept^ +router, LOCAL_PART is set to the local part of the address. When it is +called as a result of a forward or alias expansion, LOCAL_PART is set to +the local part of the address that was expanded. In both cases, any affixes are +removed from the local part, and made available in LOCAL_PART_PREFIX and +LOCAL_PART_SUFFIX, respectively. LOGNAME and USER are set to the +same value as LOCAL_PART for compatibility with other MTAs. + +cindex:[HOST] +HOST is set only when a ^pipe^ transport is called from a router that +associates hosts with an address, typically when using ^pipe^ as a +pseudo-remote transport. HOST is set to the first host name specified by +the router. + +cindex:[HOME] +If the transport's generic %home_directory% option is set, its value is used +for the HOME environment variable. Otherwise, a home directory may be set +by the router's %transport_home_directory% option, which defaults to the +user's home directory if %check_local_user% is set. + + +Private options for pipe +~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[options,^pipe^ transport] + + + +oindex:[%allow_commands%] +`..'= +%allow_commands%, Use: 'pipe', Type: 'string list'!!, Default: 'unset' +=== + +cindex:[^pipe^ transport,permitted commands] +The string is expanded, and is then interpreted as a colon-separated list of +permitted commands. If %restrict_to_path% is not set, the only commands +permitted are those in the %allow_commands% list. They need not be absolute +paths; the %path% option is still used for relative paths. If +%restrict_to_path% is set with %allow_commands%, the command must either be +in the %allow_commands% list, or a name without any slashes that is found on +the path. In other words, if neither %allow_commands% nor %restrict_to_path% +is set, there is no restriction on the command, but otherwise only commands +that are permitted by one or the other are allowed. For example, if + + allow_commands = /usr/bin/vacation + +and %restrict_to_path% is not set, the only permitted command is +_/usr/bin/vacation_. The %allow_commands% option may not be set if +%use_shell% is set. + + +oindex:[%batch_id%] +`..'= +%batch_id%, Use: 'pipe', Type: 'string'!!, Default: 'unset' +=== + +See the description of local delivery batching in chapter <<CHAPbatching>>. + + +oindex:[%batch_max%] +`..'= +%batch_max%, Use: 'pipe', Type: 'integer', Default: '1' +=== + +This limits the number of addresses that can be handled in a single delivery. +See the description of local delivery batching in chapter <<CHAPbatching>>. + + +oindex:[%check_string%] +`..'= +%check_string%, Use: 'pipe', Type: 'string', Default: 'unset' +=== + +As ^pipe^ writes the message, the start of each line is tested for matching +%check_string%, and if it does, the initial matching characters are replaced +by the contents of %escape_string%, provided both are set. The value of +%check_string% is a literal string, not a regular expression, and the case of +any letters it contains is significant. When %use_bsmtp% is set, the contents +of %check_string% and %escape_string% are forced to values that implement the +SMTP escaping protocol. Any settings made in the configuration file are +ignored. + + +oindex:[%command%] +`..'= +%command%, Use: 'pipe', Type: 'string'!!, Default: 'unset' +=== + +This option need not be set when ^pipe^ is being used to deliver to pipes +obtained directly from address redirections. In other cases, the option must be +set, to provide a command to be run. It need not yield an absolute path (see +the %path% option below). The command is split up into separate arguments by +Exim, and each argument is separately expanded, as described in section +<<SECThowcommandrun>> above. + + +oindex:[%environment%] +`..'= +%environment%, Use: 'pipe', Type: 'string'!!, Default: 'unset' +=== + +cindex:[^pipe^ transport,environment for command] +cindex:[environment for ^pipe^ transport] +This option is used to add additional variables to the environment in which the +command runs (see section <<SECTpipeenv>> for the default list). Its value is a +string which is expanded, and then interpreted as a colon-separated list of +environment settings of the form ``<''name'>=<'value'>'. + + +oindex:[%escape_string%] +`..'= +%escape_string%, Use: 'pipe', Type: 'string', Default: 'unset' +=== + +See %check_string% above. + + +oindex:[%freeze_exec_fail%] +`..'= +%freeze_exec_fail%, Use: 'pipe', Type: 'boolean', Default: 'false' +=== + +cindex:[exec failure] +cindex:[failure of exec] +cindex:[^pipe^ transport,failure of exec] +Failure to exec the command in a pipe transport is by default treated like +any other failure while running the command. However, if %freeze_exec_fail% +is set, failure to exec is treated specially, and causes the message to be +frozen, whatever the setting of %ignore_status%. + + +oindex:[%ignore_status%] +`..'= +%ignore_status%, Use: 'pipe', Type: 'boolean', Default: 'false' +=== + +If this option is true, the status returned by the subprocess that is set up to +run the command is ignored, and Exim behaves as if zero had been returned. +Otherwise, a non-zero status +or termination by signal +causes an error return from the transport unless the status value is one of +those listed in %temp_errors%; these cause the delivery to be deferred and +tried again later. + + +oindex:[%log_defer_output%] +`..'= +%log_defer_output%, Use: 'pipe', Type: 'boolean', Default: 'false' +=== + +cindex:[^pipe^ transport,logging output] +If this option is set, and the status returned by the command is +one of the codes listed in %temp_errors% (that is, delivery was deferred), +and any output was produced, the first line of it is written to the main log. + + +oindex:[%log_fail_output%] +`..'= +%log_fail_output%, Use: 'pipe', Type: 'boolean', Default: 'false' +=== + +If this option is set, and the command returns any output, and also ends with a +return code that is neither zero nor one of the return codes listed in +%temp_errors% (that is, the delivery failed), the first line of output is +written to the main log. + +This option and %log_output% are mutually exclusive. Only one of them may be +set. + + + +oindex:[%log_output%] +`..'= +%log_output%, Use: 'pipe', Type: 'boolean', Default: 'false' +=== + +If this option is set and the command returns any output, the first line of +output is written to the main log, whatever the return code. + +This option and %log_fail_output% are mutually exclusive. Only one of them +may be set. + + + +oindex:[%max_output%] +`..'= +%max_output%, Use: 'pipe', Type: 'integer', Default: '20K' +=== + +This specifies the maximum amount of output that the command may produce on its +standard output and standard error file combined. If the limit is exceeded, the +process running the command is killed. This is intended as a safety measure to +catch runaway processes. The limit is applied independently of the settings of +the options that control what is done with such output (for example, +%return_output%). Because of buffering effects, the amount of output may +exceed the limit by a small amount before Exim notices. + + +oindex:[%message_prefix%] +`..'= +%message_prefix%, Use: 'pipe', Type: 'string'!!, Default: 'see below' +=== + +The string specified here is expanded and output at the start of every message. +The default is unset if %use_bsmtp% is set. Otherwise it is + +.... +message_prefix = \ + From ${if def:return_path{$return_path}{MAILER-DAEMON}}\ + ${tod_bsdinbox}\n +.... + +cindex:[Cyrus] +cindex:[%tmail%] +cindex:[``From'' line] +This is required by the commonly used _/usr/bin/vacation_ program. +However, it must 'not' be present if delivery is to the Cyrus IMAP server, +or to the %tmail% local delivery agent. The prefix can be suppressed by setting + + message_prefix = + + + +oindex:[%message_suffix%] +`..'= +%message_suffix%, Use: 'pipe', Type: 'string'!!, Default: 'see below' +=== + +The string specified here is expanded and output at the end of every message. +The default is unset if %use_bsmtp% is set. Otherwise it is a single newline. +The suffix can be suppressed by setting + + message_suffix = + + + +oindex:[%path%] +`..'= +%path%, Use: 'pipe', Type: 'string', Default: `/usr/bin` +=== + +This option specifies the string that is set up in the PATH environment +variable of the subprocess. If the %command% option does not yield an absolute +path name, the command is sought in the PATH directories, in the usual way. +*Warning*: This does not apply to a command specified as a transport +filter. + + +oindex:[%pipe_as_creator%] +`..'= +%pipe_as_creator%, Use: 'pipe', Type: 'boolean', Default: 'false' +=== + +cindex:[uid (user id),local delivery] +If the generic %user% option is not set and this option is true, the delivery +process is run under the uid that was in force when Exim was originally called +to accept the message. If the group id is not otherwise set (via the generic +%group% option), the gid that was in force when Exim was originally called to +accept the message is used. + + +oindex:[%restrict_to_path%] +`..'= +%restrict_to_path%, Use: 'pipe', Type: 'boolean', Default: 'false' +=== + +When this option is set, any command name not listed in %allow_commands% must +contain no slashes. The command is searched for only in the directories listed +in the %path% option. This option is intended for use in the case when a pipe +command has been generated from a user's _.forward_ file. This is usually +handled by a ^pipe^ transport called %address_pipe%. + + +oindex:[%return_fail_output%] +`..'= +%return_fail_output%, Use: 'pipe', Type: 'boolean', Default: 'false' +=== + +If this option is true, and the command produced any output and ended with a +return code other than zero or one of the codes listed in %temp_errors% (that +is, the delivery failed), the output is returned in the bounce message. +However, if the message has a null sender (that is, it is itself a bounce +message), output from the command is discarded. + +This option and %return_output% are mutually exclusive. Only one of them may +be set. + + + +oindex:[%return_output%] +`..'= +%return_output%, Use: 'pipe', Type: 'boolean', Default: 'false' +=== + +If this option is true, and the command produced any output, the delivery is +deemed to have failed whatever the return code from the command, and the output +is returned in the bounce message. Otherwise, the output is just discarded. +However, if the message has a null sender (that is, it is a bounce message), +output from the command is always discarded, whatever the setting of this +option. + +This option and %return_fail_output% are mutually exclusive. Only one of them +may be set. + + + +oindex:[%temp_errors%] +`..'= +%temp_errors%, Use: 'pipe', Type: 'string list', Default: 'see below' +=== + +cindex:[^pipe^ transport,temporary failure] +This option contains either a colon-separated list of numbers, or a single +asterisk. If %ignore_status% is false +and %return_output% is not set, +and the command exits with a non-zero return code, the failure is treated as +temporary and the delivery is deferred if the return code matches one of the +numbers, or if the setting is a single asterisk. Otherwise, non-zero return +codes are treated as permanent errors. The default setting contains the codes +defined by EX_TEMPFAIL and EX_CANTCREAT in _sysexits.h_. If Exim is +compiled on a system that does not define these macros, it assumes values of 75 +and 73, respectively. + + +oindex:[%timeout%] +`..'= +%timeout%, Use: 'pipe', Type: 'time', Default: '1h' +=== + +If the command fails to complete within this time, it is killed. This normally +causes the delivery to fail. A zero time interval specifies no timeout. In +order to ensure that any subprocesses created by the command are also killed, +Exim makes the initial process a process group leader, and kills the whole +process group on a timeout. However, this can be defeated if one of the +processes starts a new process group. + + +oindex:[%umask%] +`..'= +%umask%, Use: 'pipe', Type: 'octal integer', Default: '022' +=== + +This specifies the umask setting for the subprocess that runs the command. + + +oindex:[%use_bsmtp%] +`..'= +%use_bsmtp%, Use: 'pipe', Type: 'boolean', Default: 'false' +=== + +cindex:[envelope sender] +If this option is set true, the ^pipe^ transport writes messages in ``batch +SMTP'' format, with the envelope sender and recipient(s) included as SMTP +commands. If you want to include a leading HELO command with such messages, +you can do so by setting the %message_prefix% option. See section +<<SECTbatchSMTP>> for details of batch SMTP. + + +oindex:[%use_crlf%] +`..'= +%use_crlf%, Use: 'pipe', Type: 'boolean', Default: 'false' +=== + +cindex:[carriage return] +cindex:[linefeed] +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 pipe is then an exact image +of what would be sent down a real SMTP connection. + +The contents of the %message_prefix% and %message_suffix% options are written +verbatim, so must contain their own carriage return characters if these are +needed. Since the default values for both %message_prefix% and +%message_suffix% end with a single linefeed, their values +must +be changed to end with `\r\n` if %use_crlf% is set. + + +oindex:[%use_shell%] +`..'= +%use_shell%, Use: 'pipe', Type: 'boolean', Default: 'false' +=== + +If this option is set, it causes the command to be passed to _/bin/sh_ +instead of being run directly from the transport, as described in section +<<SECThowcommandrun>>. This is less secure, but is needed in some situations +where the command is expected to be run under a shell and cannot easily be +modified. The %allow_commands% and %restrict_to_path% options, and the +`\$pipe_addresses` facility are incompatible with %use_shell%. The +command is expanded as a single string, and handed to _/bin/sh_ as data for +its %-c% option. + + + +Using an external local delivery agent +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[local delivery,using an external agent] +cindex:['procmail'] +cindex:[external local delivery] +cindex:[delivery,'procmail'] +cindex:[delivery,by external agent] +The ^pipe^ transport can be used to pass all messages that require local +delivery to a separate local delivery agent such as %procmail%. When doing +this, care must be taken to ensure that the pipe is run under an appropriate +uid and gid. In some configurations one wants this to be a uid that is trusted +by the delivery agent to supply the correct sender of the message. It may be +necessary to recompile or reconfigure the delivery agent so that it trusts an +appropriate user. The following is an example transport and router +configuration for %procmail%: + + # transport + procmail_pipe: + driver = pipe + command = /usr/local/bin/procmail -d $local_part + return_path_add + delivery_date_add + envelope_to_add + check_string = "From " + escape_string = ">From " + user = $local_part + group = mail + + # router + procmail: + driver = accept + check_local_user + transport = procmail_pipe + + +In this example, the pipe is run as the local user, but with the group set to +'mail'. An alternative is to run the pipe as a specific user such as 'mail' +or 'exim', but in this case you must arrange for %procmail% to trust that +user to supply a correct sender address. If you do not specify either a %group% +or a %user% option, the pipe command is run as the local user. The home +directory is the user's home directory by default. + +Note that the command that the pipe transport runs does 'not' begin with + + IFS=" " + +as shown in the %procmail% documentation, because Exim does not by default use +a shell to run pipe commands. + +cindex:[Cyrus] +The next example shows a transport and a router for a system where local +deliveries are handled by the Cyrus IMAP server. + +.... +# transport +local_delivery_cyrus: + driver = pipe + command = /usr/cyrus/bin/deliver \ + -m ${substr_1:$local_part_suffix} -- $local_part + user = cyrus + group = mail + return_output + log_output + message_prefix = + message_suffix = + +# router +local_user_cyrus: + driver = accept + check_local_user + local_part_suffix = .* + transport = local_delivery_cyrus +.... + +Note the unsetting of %message_prefix% and %message_suffix%, and the use of +%return_output% to cause any text written by Cyrus to be returned to the +sender. + + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// + +[[CHAPsmtptrans]] +The smtp transport +------------------ +cindex:[transports,^smtp^] +cindex:[^smtp^ transport] +The ^smtp^ transport delivers messages over TCP/IP connections using the SMTP +or LMTP protocol. The list of hosts to try can either be taken from the address +that is being processed (having been set up by the router), or specified +explicitly for the transport. Timeout and retry processing (see chapter +<<CHAPretry>>) is applied to each IP address independently. + + +Multiple messages on a single connection +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +The sending of multiple messages over a single TCP/IP connection can arise in +two ways: + +- If a message contains more than %max_rcpt% (see below) addresses that are +routed to the same host, more than one copy of the message has to be sent to +that host. In this situation, multiple copies may be sent in a single run of +the ^smtp^ transport over a single TCP/IP connection. (What Exim actually does +when it has too many addresses to send in one message also depends on the value +of the global %remote_max_parallel% option. Details are given in section +<<SECToutSMTPTCP>>.) + +- cindex:[hints database,remembering routing] +When a message has been successfully delivered over a TCP/IP connection, Exim +looks in its hints database to see if there are any other messages awaiting a +connection to the same host. If there are, a new delivery process is started +for one of them, and the current TCP/IP connection is passed on to it. The new +process may in turn send multiple copies and possibly create yet another +process. + + +For each copy sent over the same TCP/IP connection, a sequence counter is +incremented, and if it ever gets to the value of %connection_max_messages%, +no further messages are sent over that connection. + + + +Use of the \$host variable +~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[$host$] +cindex:[$host_address$] +At the start of a run of the ^smtp^ transport, the values of $host$ and +$host_address$ are the name and IP address of the first host on the host list +passed by the router. However, when the transport is about to connect to a +specific host, and while it is connected to that host, $host$ and +$host_address$ are set to the values for that host. These are the values +that are in force when the %helo_data%, %hosts_try_auth%, %interface%, +%serialize_hosts%, and the various TLS options are expanded. + + + +Private options for smtp +~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[options,^smtp^ transport] +The private options of the ^smtp^ transport are as follows: + + +oindex:[%allow_localhost%] +`..'= +%allow_localhost%, Use: 'smtp', Type: 'boolean', Default: 'false' +=== + +cindex:[local host,sending to] +cindex:[fallback,hosts specified on transport] +When a host specified in %hosts% or %fallback_hosts% (see below) turns out to +be the local host, or is listed in %hosts_treat_as_local%, delivery is +deferred by default. However, if %allow_localhost% is set, Exim goes on to do +the delivery anyway. This should be used only in special cases when the +configuration ensures that no looping will result (for example, a differently +configured Exim is listening on the port to which the message is sent). + + +oindex:[%authenticated_sender%] +`..'= +%authenticated_sender%, Use: 'smtp', Type: 'string'!!, Default: 'unset' +=== + +cindex:[Cyrus] +When Exim has authenticated as a client, this option sets a value for the +AUTH= item on outgoing MAIL commands, overriding any existing +authenticated sender value. If the string expansion is forced to fail, the +option is ignored. Other expansion failures cause delivery to be deferred. If +the result of expansion is an empty string, that is also ignored. + +If the SMTP session is not authenticated, the expansion of +%authenticated_sender% still happens (and can cause the delivery to be +deferred if it fails), but no AUTH= item is added to MAIL commands. + +This option allows you to use the ^smtp^ transport in LMTP mode to +deliver mail to Cyrus IMAP and provide the proper local part as the +``authenticated sender'', via a setting such as: + + authenticated_sender = $local_part + +This removes the need for IMAP subfolders to be assigned special ACLs to +allow direct delivery to those subfolders. + +Because of expected uses such as that just described for Cyrus (when no +domain is involved), there is no checking on the syntax of the provided +value. + + +oindex:[%command_timeout%] +`..'= +%command_timeout%, Use: 'smtp', Type: 'time', Default: '5m' +=== + +This sets a timeout for receiving a response to an SMTP command that has been +sent out. It is also used when waiting for the initial banner line from the +remote host. Its value must not be zero. + + +oindex:[%connect_timeout%] +`..'= +%connect_timeout%, Use: 'smtp', Type: 'time', Default: '5m' +=== + +This sets a timeout for the 'connect()' function, which sets up a TCP/IP call +to a remote host. A setting of zero allows the system timeout (typically +several minutes) to act. To have any effect, the value of this option must be +less than the system timeout. However, it has been observed that on some +systems there is no system timeout, which is why the default value for this +option is 5 minutes, a value recommended by RFC 1123. + + +oindex:[%connection_max_messages%] +`..'= +%connection_max_messages%, Use: 'smtp', Type: 'integer', Default: '500' +=== + +cindex:[SMTP,passed connection] +cindex:[SMTP,multiple deliveries] +cindex:[multiple SMTP deliveries] +This controls the maximum number of separate message deliveries that are sent +over a single TCP/IP connection. If the value is zero, there is no limit. +For testing purposes, this value can be overridden by the %-oB% command line +option. + + +oindex:[%data_timeout%] +`..'= +%data_timeout%, Use: 'smtp', Type: 'time', Default: '5m' +=== + +This sets a timeout for the transmission of each block in the data portion of +the message. As a result, the overall timeout for a message depends on the size +of the message. Its value must not be zero. See also %final_timeout%. + + +oindex:[%delay_after_cutoff%] +`..'= +%delay_after_cutoff%, Use: 'smtp', Type: 'boolean', Default: 'true' +=== + +This option controls what happens when all remote IP addresses for a given +domain have been inaccessible for so long that they have passed their retry +cutoff times. + +In the default state, if the next retry time has not been reached for any of +them, the address is bounced without trying any deliveries. In other words, +Exim delays retrying an IP address after the final cutoff time until a new +retry time is reached, and can therefore bounce an address without ever trying +a delivery, when machines have been down for a long time. Some people are +unhappy at this prospect, so... + +If %delay_after_cutoff% is set false, Exim behaves differently. If all IP +addresses are past their final cutoff time, Exim tries to deliver to those +IP addresses that have not been tried since the message arrived. If there are +none, of if they all fail, the address is bounced. In other words, it does not +delay when a new message arrives, but immediately tries those expired IP +addresses that haven't been tried since the message arrived. If there is a +continuous stream of messages for the dead hosts, unsetting +%delay_after_cutoff% means that there will be many more attempts to deliver +to them. + + +oindex:[%dns_qualify_single%] +`..'= +%dns_qualify_single%, Use: 'smtp', Type: 'boolean', Default: 'true' +=== + +If the %hosts% or %fallback_hosts% option is being used, +and the %gethostbyname% option is false, +the RES_DEFNAMES resolver option is set. See the %qualify_single% option +in chapter <<CHAPdnslookup>> for more details. + + +oindex:[%dns_search_parents%] +`..'= +%dns_search_parents%, Use: 'smtp', Type: 'boolean', Default: 'false' +=== + +cindex:[%search_parents%] +If the %hosts% or %fallback_hosts% option is being used, and the +%gethostbyname% option is false, the RES_DNSRCH resolver option is set. +See the %search_parents% option in chapter <<CHAPdnslookup>> for more details. + + + +oindex:[%fallback_hosts%] +`..'= +%fallback_hosts%, Use: 'smtp', Type: 'string list', Default: 'unset' +=== + +cindex:[fallback,hosts specified on transport] +String expansion is not applied to this option. The argument must be a +colon-separated list of host names or IP addresses. Fallback hosts can also be +specified on routers, which associate them with the addresses they process. As +for the %hosts% option without %hosts_override%, %fallback_hosts% specified +on the transport is used only if the address does not have its own associated +fallback host list. Unlike %hosts%, a setting of %fallback_hosts% on an +address is not overridden by %hosts_override%. However, %hosts_randomize% +does apply to fallback host lists. + +If Exim is unable to deliver to any of the hosts for a particular address, and +the errors are not permanent rejections, the address is put on a separate +transport queue with its host list replaced by the fallback hosts, unless the +address was routed via MX records and the current host was in the original MX +list. In that situation, the fallback host list is not used. + +Once normal deliveries are complete, the fallback queue is delivered by +re-running the same transports with the new host lists. If several failing +addresses have the same fallback hosts (and %max_rcpt% permits it), a single +copy of the message is sent. + +The resolution of the host names on the fallback list is controlled by the +%gethostbyname% option, as for the %hosts% option. Fallback hosts apply +both to cases when the host list comes with the address and when it is taken +from %hosts%. This option provides a ``use a smart host only if delivery fails'' +facility. + + +oindex:[%final_timeout%] +`..'= +%final_timeout%, Use: 'smtp', Type: 'time', Default: '10m' +=== + +This is the timeout that applies while waiting for the response to the final +line containing just ``.'' that terminates a message. Its value must not be zero. + + +oindex:[%gethostbyname%] +`..'= +%gethostbyname%, Use: 'smtp', Type: 'boolean', Default: 'false' +=== + +If this option is true when the %hosts% and/or %fallback_hosts% options are +being used, names are looked up using 'gethostbyname()' +(or 'getipnodebyname()' when available) +instead of using the DNS. Of course, that function may in fact use the DNS, but +it may also consult other sources of information such as _/etc/hosts_. + +oindex:[%helo_data%] +`..'= +%helo_data%, Use: 'smtp', Type: 'string'!!, Default: `\$primary_hostname` +=== + +cindex:[HELO argument, setting] +cindex:[EHLO argument, setting] +The value of this option is expanded, and used as the argument for the EHLO +or HELO command that starts the outgoing SMTP session. + + +oindex:[%hosts%] +`..'= +%hosts%, Use: 'smtp', Type: 'string list'!!, Default: 'unset' +=== + +Hosts are associated with an address by a router such as ^dnslookup^, which +finds the hosts by looking up the address domain in the DNS. However, addresses +can be passed to the ^smtp^ transport by any router, and not all of them can +provide an associated host list. The %hosts% option specifies a list of hosts +which are used if the address being processed does not have any hosts +associated with it. The hosts specified by %hosts% are also used, whether or +not the address has its own hosts, if %hosts_override% is set. + +The string is first expanded, before being interpreted as a colon-separated +list of host names or IP addresses. If the expansion fails, delivery is +deferred. Unless the failure was caused by the inability to complete a lookup, +the error is logged to the panic log as well as the main log. Host names are +looked up either by searching directly for address records in the DNS or by +calling 'gethostbyname()' +(or 'getipnodebyname()' when available), +depending on the setting of the %gethostbyname% option. When Exim is compiled +with IPv6 support, if a host that is looked up in the DNS has both IPv4 and +IPv6 addresses, both types of address are used. + +During delivery, the hosts are tried in order, subject to their retry status, +unless %hosts_randomize% is set. + + +oindex:[%hosts_avoid_esmtp%] +`..'= +%hosts_avoid_esmtp%, Use: 'smtp', Type: 'host list'!!, Default: 'unset' +=== + +cindex:[ESMTP, avoiding use of] +cindex:[HELO,forcing use of] +cindex:[EHLO,avoiding use of] +cindex:[PIPELINING,avoiding the use of] +This option is for use with broken hosts that announce ESMTP facilities (for +example, PIPELINING) and then fail to implement them properly. When a host +matches %hosts_avoid_esmtp%, Exim sends HELO rather than EHLO at the +start of the SMTP session. This means that it cannot use any of the ESMTP +facilities such as AUTH, PIPELINING, SIZE, and STARTTLS. + + +oindex:[%hosts_avoid_tls%] +`..'= +%hosts_avoid_tls%, Use: 'smtp', Type: 'host list'!!, Default: 'unset' +=== + +cindex:[TLS,avoiding for certain hosts] +Exim will not try to start a TLS session when delivering to any host that +matches this list. See chapter <<CHAPTLS>> for details of TLS. + + +oindex:[%hosts_max_try%] +`..'= +%hosts_max_try%, Use: 'smtp', Type: 'integer', Default: '5' +=== + +cindex:[host,maximum number to try] +cindex:[limit,number of hosts tried] +cindex:[limit,number of MX tried] +cindex:[MX record,maximum tried] +This option limits the number of IP addresses that are tried for any one +delivery in cases where there are temporary delivery errors. Section +<<SECTvalhosmax>> describes in detail how the value of this option is used. + + +oindex:[%hosts_max_try_hardlimit%] +`..'= +%hosts_max_try_hardlimit%, Use: 'smtp', Type: 'integer', Default: '50' +=== + +This is an additional check on the maximum number of IP addresses that Exim +tries for any one delivery. Section <<SECTvalhosmax>> describes its use and why +it exists. + + + +oindex:[%hosts_nopass_tls%] +`..'= +%hosts_nopass_tls%, Use: 'smtp', Type: 'host list'!!, Default: 'unset' +=== + +cindex:[TLS,passing connection] +cindex:[multiple SMTP deliveries] +cindex:[TLS,multiple message deliveries] +For any host that matches this list, a connection on which a TLS session has +been started will not be passed to a new delivery process for sending another +message on the same connection. See section <<SECTmulmessam>> for an explanation +of when this might be needed. + + +oindex:[%hosts_override%] +`..'= +%hosts_override%, Use: 'smtp', Type: 'boolean', Default: 'false' +=== + +If this option is set and the %hosts% option is also set, any hosts that are +attached to the address are ignored, and instead the hosts specified by the +%hosts% option are always used. This option does not apply to +%fallback_hosts%. + + +oindex:[%hosts_randomize%] +`..'= +%hosts_randomize%, Use: 'smtp', Type: 'boolean', Default: 'false' +=== + +cindex:[randomized host list] +cindex:[host,list of; randomized] +cindex:[fallback,randomized hosts] +If this option is set, and either the list of hosts is taken from the +%hosts% or the %fallback_hosts% option, or the hosts supplied by the router +were not obtained from MX records (this includes fallback hosts from the +router), and were not randomizied by the router, the order of trying the hosts +is randomized each time the transport runs. Randomizing the order of a host +list can be used to do crude load sharing. + +When %hosts_randomize% is true, a host list may be split into groups whose +order is separately randomized. This makes it possible to set up MX-like +behaviour. The boundaries between groups are indicated by an item that is just +`+` in the host list. For example: + + hosts = host1:host2:host3:+:host4:host5 + +The order of the first three hosts and the order of the last two hosts is +randomized for each use, but the first three always end up before the last two. +If %hosts_randomize% is not set, a `+` item in the list is ignored. + +oindex:[%hosts_require_auth%] +`..'= +%hosts_require_auth%, Use: 'smtp', Type: 'host list'!!, Default: 'unset' +=== + +cindex:[authentication,required by client] +This option provides a list of servers for which authentication must succeed +before Exim will try to transfer a message. If authentication fails for +servers which are not in this list, Exim tries to send unauthenticated. If +authentication fails for one of these servers, delivery is deferred. This +temporary error is detectable in the retry rules, so it can be turned into a +hard failure if required. See also %hosts_try_auth%, and chapter +<<CHAPSMTPAUTH>> for details of authentication. + + +oindex:[%hosts_require_tls%] +`..'= +%hosts_require_tls%, Use: 'smtp', Type: 'host list'!!, Default: 'unset' +=== + +cindex:[TLS,requiring for certain servers] +Exim will insist on using a TLS session when delivering to any host that +matches this list. See chapter <<CHAPTLS>> for details of TLS. +*Note*: This option affects outgoing mail only. To insist on TLS for +incoming messages, use an appropriate ACL. + +oindex:[%hosts_try_auth%] +`..'= +%hosts_try_auth%, Use: 'smtp', Type: 'host list'!!, Default: 'unset' +=== + +cindex:[authentication,optional in client] +This option provides a list of servers to which, provided they announce +authentication support, Exim will attempt to authenticate as a client when it +connects. If authentication fails, Exim will try to transfer the message +unauthenticated. See also %hosts_require_auth%, and chapter <<CHAPSMTPAUTH>> +for details of authentication. + +oindex:[%interface%] +`..'= +%interface%, Use: 'smtp', Type: 'string list'!!, Default: 'unset' +=== + +cindex:[bind IP address] +cindex:[IP address,binding] +This option specifies which interface to bind to when making an outgoing SMTP +call. The variables $host$ and $host_address$ refer to the host to which a +connection is about to be made during the expansion of the string. Forced +expansion failure, or an empty string result causes the option to be ignored. +Otherwise, after expansion, +the string must be a list of IP addresses, colon-separated by default, but the +separator can be changed in the usual way. +For example: + + interface = <; 192.168.123.123 ; 3ffe:ffff:836f::fe86:a061 + +The first interface of the correct type (IPv4 or IPv6) is used for the outgoing +connection. If none of them are the correct type, the option is ignored. If +%interface% is not set, or is ignored, the system's IP functions choose which +interface to use if the host has more than one. + + +oindex:[%keepalive%] +`..'= +%keepalive%, Use: 'smtp', Type: 'boolean', Default: 'true' +=== + +cindex:[keepalive,on outgoing connection] +This option controls the setting of SO_KEEPALIVE on outgoing TCP/IP socket +connections. When set, it causes the kernel to probe idle connections +periodically, by sending packets with ``old'' sequence numbers. The other end of +the connection should send a acknowledgement if the connection is still okay or +a reset if the connection has been aborted. The reason for doing this is that +it has the beneficial effect of freeing up certain types of connection that can +get stuck when the remote host is disconnected without tidying up the TCP/IP +call properly. The keepalive mechanism takes several hours to detect +unreachable hosts. + + +oindex:[%max_rcpt%] +`..'= +%max_rcpt%, Use: 'smtp', Type: 'integer', Default: '100' +=== + +cindex:[RCPT,maximum number of outgoing] +This option limits the number of RCPT commands that are sent in a single +SMTP message transaction. Each set of addresses is treated independently, and +so can cause parallel connections to the same host if %remote_max_parallel% +permits this. + + +oindex:[%multi_domain%] +`..'= +%multi_domain%, Use: 'smtp', Type: 'boolean', Default: 'true' +=== + +When this option is set, the ^smtp^ transport can handle a number of addresses +containing a mixture of different domains provided they all resolve to the same +list of hosts. Turning the option off restricts the transport to handling only +one domain at a time. This is useful if you want to use $domain$ in an +expansion for the transport, because it is set only when there is a single +domain involved in a remote delivery. + + +oindex:[%port%] +`..'= +%port%, Use: 'smtp', Type: 'string'!!, Default: 'see below' +=== + +cindex:[port,sending TCP/IP] +cindex:[TCP/IP,setting outgoing port] +This option specifies the TCP/IP port on the server to which Exim connects. If +it begins with a digit it is taken as a port number; otherwise it is looked up +using 'getservbyname()'. The default value is normally ``smtp'', but if +%protocol% is set to ``lmtp'', the default is ``lmtp''. +If the expansion fails, or if a port number cannot be found, delivery is +deferred. + + + +oindex:[%protocol%] +`..'= +%protocol%, Use: 'smtp', Type: 'string', Default: 'smtp' +=== + +cindex:[LMTP,over TCP/IP] +If this option is set to ``lmtp'' instead of ``smtp'', the default value for the +%port% option changes to ``lmtp'', and the transport operates the LMTP protocol +(RFC 2033) instead of SMTP. This protocol is sometimes used for local +deliveries into closed message stores. Exim also has support for running LMTP +over a pipe to a local process -- see chapter <<CHAPLMTP>>. + + +oindex:[%retry_include_ip_address%] +`..'= +%retry_include_ip_address%, Use: 'smtp', Type: 'boolean', Default: 'true' +=== + +Exim normally includes both the host name and the IP address in the key it +constructs for indexing retry data after a temporary delivery failure. This +means that when one of several IP addresses for a host is failing, it gets +tried periodically (controlled by the retry rules), but use of the other IP +addresses is not affected. + +However, in some dialup environments hosts are assigned a different IP address +each time they connect. In this situation the use of the IP address as part of +the retry key leads to undesirable behaviour. Setting this option false causes +Exim to use only the host name. This should normally be done on a separate +instance of the ^smtp^ transport, set up specially to handle the dialup hosts. + + +oindex:[%serialize_hosts%] +`..'= +%serialize_hosts%, Use: 'smtp', Type: 'host list'!!, Default: 'unset' +=== + +cindex:[serializing connections] +cindex:[host,serializing connections] +Because Exim operates in a distributed manner, if several messages for the same +host arrive at around the same time, more than one simultaneous connection to +the remote host can occur. This is not usually a problem except when there is a +slow link between the hosts. In that situation it may be helpful to restrict +Exim to one connection at a time. This can be done by setting +%serialize_hosts% to match the relevant hosts. + +cindex:[hints database,serializing deliveries to a host] +Exim implements serialization by means of a hints database in which a record is +written whenever a process connects to one of the restricted hosts. The record +is deleted when the connection is completed. Obviously there is scope for +records to get left lying around if there is a system or program crash. To +guard against this, Exim ignores any records that are more than six hours old. + +If you set up this kind of serialization, you should also arrange to delete the +relevant hints database whenever your system reboots. The names of the files +start with _misc_ and they are kept in the _spool/db_ directory. There +may be one or two files, depending on the type of DBM in use. The same files +are used for ETRN serialization. + + +oindex:[%size_addition%] +`..'= +%size_addition%, Use: 'smtp', Type: 'integer', Default: '1024' +=== + +cindex:[SMTP,SIZE] +cindex:[message,size issue for transport filter] +cindex:[size,of message] +cindex:[transport,filter] +cindex:[filter,transport filter] +If a remote SMTP server indicates that it supports the SIZE option of the +MAIL command, Exim uses this to pass over the message size at the start of +an SMTP transaction. It adds the value of %size_addition% to the value it +sends, to allow for headers and other text that may be added during delivery by +configuration options or in a transport filter. It may be necessary to increase +this if a lot of text is added to messages. + +Alternatively, if the value of %size_addition% is set negative, it disables +the use of the SIZE option altogether. + + +oindex:[%tls_certificate%] +`..'= +%tls_certificate%, Use: 'smtp', Type: 'string'!!, Default: 'unset' +=== + +cindex:[TLS client certificate, location of] +cindex:[certificate for client, location of] +The value of this option must be the absolute path to a file which contains the +client's certificate, for use when sending a message over an encrypted +connection. The values of $host$ and $host_address$ are set to the name +and address of the server during the expansion. See chapter <<CHAPTLS>> for +details of TLS. + +*Note*: This option must be set if you want Exim to use TLS when sending +messages as a client. The global option of the same name specifies the +certificate for Exim as a server; it is not automatically assumed that the same +certificate should be used when Exim is operating as a client. + + +oindex:[%tls_crl%] +`..'= +%tls_crl%, Use: 'smtp', Type: 'string'!!, Default: 'unset' +=== + +cindex:[TLS,client certificate revocation list] +cindex:[certificate,revocation list for client] +This option specifies a certificate revocation list. The expanded value must +be the name of a file that contains a CRL in PEM format. + + +oindex:[%tls_privatekey%] +`..'= +%tls_privatekey%, Use: 'smtp', Type: 'string'!!, Default: 'unset' +=== + +cindex:[TLS client private key, location of] +The value of this option must be the absolute path to a file which contains the +client's private key, for use when sending a message over an encrypted +connection. The values of $host$ and $host_address$ are set to the name +and address of the server during the expansion. +If this option is unset, the private key is assumed to be in the same file as +the certificate. +See chapter <<CHAPTLS>> for details of TLS. + + +oindex:[%tls_require_ciphers%] +`..'= +%tls_require_ciphers%, Use: 'smtp', Type: 'string'!!, Default: 'unset' +=== + +cindex:[TLS,requiring specific ciphers] +cindex:[cipher,requiring specific] +The value of this option must be a list of permitted cipher suites, for use +when setting up an outgoing encrypted connection. (There is a global option of +the same name for controlling incoming connections.) The values of $host$ and +$host_address$ are set to the name and address of the server during the +expansion. See chapter <<CHAPTLS>> for details of TLS; note that this option is +used in different ways by OpenSSL and GnuTLS (see sections <<SECTreqciphssl>> +and <<SECTreqciphgnu>>). For GnuTLS, the order of the ciphers is a preference +order. + + + +oindex:[%tls_tempfail_tryclear%] +`..'= +%tls_tempfail_tryclear%, Use: 'smtp', Type: 'boolean', Default: 'true' +=== + +When the server host is not in %hosts_require_tls%, and there is a problem in +setting up a TLS session, this option determines whether or not Exim should try +to deliver the message unencrypted. If it is set false, delivery to the +current host is deferred; if there are other hosts, they are tried. If this +option is set true, Exim attempts to deliver unencrypted after a 4##'xx' +response to STARTTLS. Also, if STARTTLS is accepted, but the subsequent +TLS negotiation fails, Exim closes the current connection (because it is in an +unknown state), opens a new one to the same host, and then tries the delivery +in clear. + + +oindex:[%tls_verify_certificates%] +`..'= +%tls_verify_certificates%, Use: 'smtp', Type: 'string'!!, Default: 'unset' +=== + +cindex:[TLS,server certificate verification] +cindex:[certificate,verification of server] +The value of this option must be the absolute path to a file containing +permitted server certificates, for use when setting up an encrypted connection. +Alternatively, if you are using OpenSSL, you can set +%tls_verify_certificates% to the name of a directory containing certificate +files. This does not work with GnuTLS; the option must be set to the name of a +single file if you are using GnuTLS. The values of $host$ and +$host_address$ are set to the name and address of the server during the +expansion of this option. See chapter <<CHAPTLS>> for details of TLS. + + + + +[[SECTvalhosmax]] +How the limits for the number of hosts to try are used +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[host,maximum number to try] +cindex:[limit,hosts; maximum number tried] +There are two options that are concerned with the number of hosts that are +tried when an SMTP delivery takes place. They are %hosts_max_try% and +%hosts_max_try_hardlimit%. + + +The %hosts_max_try% option limits the number of hosts that are tried +for a single delivery. However, despite the term ``host'' in its name, the option +actually applies to each IP address independently. In other words, a multihomed +host is treated as several independent hosts, just as it is for retrying. + +Many of the larger ISPs have multiple MX records which often point to +multihomed hosts. As a result, a list of a dozen or more IP addresses may be +created as a result of routing one of these domains. + +Trying every single IP address on such a long list does not seem sensible; if +several at the top of the list fail, it is reasonable to assume there is some +problem that is likely to affect all of them. Roughly speaking, the value of +%hosts_max_try% is the maximum number that are tried before deferring the +delivery. However, the logic cannot be quite that simple. + +Firstly, IP addresses that are skipped because their retry times have not +arrived do not count, and in addition, addresses that are past their retry +limits are also not counted, even when they are tried. This means that when +some IP addresses are past their retry limits, more than the value of +%hosts_max_retry% may be tried. The reason for this behaviour is to ensure +that all IP addresses are considered before timing out an email address (but +see below for an exception). + +Secondly, when the %hosts_max_try% limit is reached, Exim looks down the host +list to see if there is a subsequent host with a different (higher valued) MX. +If there is, that host is considered next, and the current IP address is used +but not counted. This behaviour helps in the case of a domain with a retry rule +that hardly ever delays any hosts, as is now explained: + +Consider the case of a long list of hosts with one MX value, and a few with a +higher MX value. If %hosts_max_try% is small (the default is 5) only a few +hosts at the top of the list are tried at first. With the default retry rule, +which specifies increasing retry times, the higher MX hosts are eventually +tried when those at the top of the list are skipped because they have not +reached their retry times. + +However, it is common practice to put a fixed short retry time on domains for +large ISPs, on the grounds that their servers are rarely down for very long. +Unfortunately, these are exactly the domains that tend to resolve to long lists +of hosts. The short retry time means that the lowest MX hosts are tried every +time. The attempts may be in a different order because of random sorting, but +without the special MX check, the higher MX hosts would never be tried + +until all the lower MX hosts had timed out (which might be several days), +because there are always some lower MX hosts that have reached their retry +times. With the special check, Exim considers at least one IP address from each +MX value at every delivery attempt, even if the %hosts_max_try% limit has +already been reached. + +The above logic means that %hosts_max_try% is not a hard limit, and in +particular, Exim normally eventually tries all the IP addresses before timing +out an email address. When %hosts_max_try% was implemented, this seemed a +reasonable thing to do. Recently, however, some lunatic DNS configurations have +been set up with hundreds of IP addresses for some domains. It can +take a very long time indeed for an address to time out in these cases. + +The %hosts_max_try_hardlimit% option was added to help with this problem. +Exim never tries more than this number of IP addresses; if it hits this limit +and they are all timed out, the email address is bounced, even though not all +possible IP addresses have been tried. + + + + + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// + +[[CHAPrewrite]] +Address rewriting +----------------- +cindex:[rewriting,addresses] +There are some circumstances in which Exim automatically rewrites domains in +addresses. The two most common are when an address is given without a domain +(referred to as an ``unqualified address'') or when an address contains an +abbreviated domain that is expanded by DNS lookup. + +Unqualified envelope addresses are accepted only for locally submitted +messages, or messages from hosts that match %sender_unqualified_hosts% or +%recipient_unqualified_hosts%, respectively. Unqualified addresses in header +lines are qualified if they are in locally submitted messages, or messages from +hosts that are permitted to send unqualified envelope addresses. Otherwise, +unqualified addresses in header lines are neither qualified nor rewritten. + +One situation in which Exim does 'not' automatically rewrite a domain is +when it is the name of a CNAME record in the DNS. The older RFCs suggest that +such a domain should be rewritten using the ``canonical'' name, and some MTAs do +this. The new RFCs do not contain this suggestion. + + +Explicitly configured address rewriting +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +This chapter describes the rewriting rules that can be used in the +main rewrite section of the configuration file, and also in the generic +%headers_rewrite% option that can be set on any transport. + +Some people believe that configured address rewriting is a Mortal Sin. +Others believe that life is not possible without it. Exim provides the +facility; you do not have to use it. + +The main rewriting rules that appear in the ``rewrite'' section of the +configuration file are applied to addresses in incoming messages, both envelope +addresses and addresses in header lines. Each rule specifies the types of +address to which it applies. + +Rewriting of addresses in header lines applies only to those headers that +were received with the message, and, in the case of transport rewriting, those +that were added by a system filter. That is, it applies only to those headers +that are common to all copies of the message. Header lines that are added by +individual routers or transports (and which are therefore specific to +individual recipient addresses) are not rewritten. + +In general, rewriting addresses from your own system or domain has some +legitimacy. Rewriting other addresses should be done only with great care and +in special circumstances. The author of Exim believes that rewriting should be +used sparingly, and mainly for ``regularizing'' addresses in your own domains. +Although it can sometimes be used as a routing tool, this is very strongly +discouraged. + +There are two commonly encountered circumstances where rewriting is used, as +illustrated by these examples: + +- The company whose domain is 'hitch.fict.example' has a number of hosts that +exchange mail with each other behind a firewall, but there is only a single +gateway to the outer world. The gateway rewrites '*.hitch.fict.example' as +'hitch.fict.example' when sending mail off-site. + +- A host rewrites the local parts of its own users so that, for example, +'fp42@hitch.fict.example' becomes 'Ford.Prefect@hitch.fict.example'. + + + +When does rewriting happen? +~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[rewriting,timing of] +cindex:[{ACL},rewriting addresses in] +Configured address rewriting can take place at several different stages of a +message's processing. + +At the start of an ACL for MAIL, the sender address may have been rewritten +by a special SMTP-time rewrite rule (see section <<SECTrewriteS>>), but no +ordinary rewrite rules have yet been applied. If, however, the sender address +is verified in the ACL, it is rewritten before verification, and remains +rewritten thereafter. The subsequent value of $sender_address$ is the +rewritten address. This also applies if sender verification happens in a +RCPT ACL. Otherwise, when the sender address is not verified, it is +rewritten as soon as a message's header lines have been received. + +Similarly, at the start of an ACL for RCPT, the current recipient's address +may have been rewritten by a special SMTP-time rewrite rule, but no ordinary +rewrite rules have yet been applied to it. However, the behaviour is different +from the sender address when a recipient is verified. The address is rewritten +for the verification, but the rewriting is not remembered at this stage. The +value of $local_part$ and $domain$ after verification are always the same +as they were before (that is, they contain the unrewritten -- except for +SMTP-time rewriting -- address). + +Once a message's header lines have been received, all the envelope recipient +addresses are permanently rewritten, and rewriting is also applied to the +addresses in the header lines (if configured). +cindex:['local_scan()' function,address rewriting; timing of] +Thus, all the rewriting is completed before the DATA ACL and +'local_scan()' functions are run. + +When an address is being routed, either for delivery or for verification, +rewriting is applied immediately to child addresses that are generated by +redirection, unless %no_rewrite% is set on the router. + +cindex:[envelope sender, rewriting] +cindex:[rewriting,at transport time] +At transport time, additional rewriting of addresses in header lines can be +specified by setting the generic %headers_rewrite% option on a transport. This +option contains rules that are identical in form to those in the rewrite +section of the configuration file. In addition, the outgoing envelope sender +can be rewritten by means of the %return_path% transport option. However, it +is not possible to rewrite envelope recipients at transport time. + + + + +Testing the rewriting rules that apply on input +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[rewriting,testing] +cindex:[testing,rewriting] +Exim's input rewriting configuration appears in a part of the run time +configuration file headed by ``begin rewrite''. It can be tested by the %-brw% +command line option. This takes an address (which can be a full RFC 2822 +address) as its argument. The output is a list of how the address would be +transformed by the rewriting rules for each of the different places it might +appear in an incoming message, that is, for each different header and for the +envelope sender and recipient fields. For example, + + exim -brw ph10@exim.workshop.example + +might produce the output + + sender: Philip.Hazel@exim.workshop.example + from: Philip.Hazel@exim.workshop.example + to: ph10@exim.workshop.example + cc: ph10@exim.workshop.example + bcc: ph10@exim.workshop.example + reply-to: Philip.Hazel@exim.workshop.example + env-from: Philip.Hazel@exim.workshop.example + env-to: ph10@exim.workshop.example + +which shows that rewriting has been set up for that address when used in any of +the source fields, but not when it appears as a recipient address. At the +present time, there is no equivalent way of testing rewriting rules that are +set for a particular transport. + + +Rewriting rules +~~~~~~~~~~~~~~~ +cindex:[rewriting,rules] +The rewrite section of the configuration file consists of lines of rewriting +rules in the form + + <source pattern> <replacement> <flags> + +Rewriting rules that are specified for the %headers_rewrite% generic transport +option are given as a colon-separated list. Each item in the list takes the +same form as a line in the main rewriting configuration +(except that any colons must be doubled, of course). + +The formats of source patterns and replacement strings are described below. +Each is terminated by white space, unless enclosed in double quotes, in which +case normal quoting conventions apply inside the quotes. The flags are single +characters which may appear in any order. Spaces and tabs between them are +ignored. + +For each address that could potentially be rewritten, the rules are scanned in +order, and replacements for the address from earlier rules can themselves be +replaced by later rules (but see the ``q'' and ``R'' flags). + +The order in which addresses are rewritten is undefined, may change between +releases, and must not be relied on, with one exception: when a message is +received, the envelope sender is always rewritten first, before any header +lines are rewritten. For example, the replacement string for a rewrite of an +address in 'To:' must not assume that the message's address in 'From:' has (or +has not) already been rewritten. However, a rewrite of 'From:' may assume that +the envelope sender has already been rewritten. + +The variables $local_part$ and $domain$ can be used in the replacement +string to refer to the address that is being rewritten. Note that lookup-driven +rewriting can be done by a rule of the form + + *@* ${lookup ... + +where the lookup key uses $1$ and $2$ or $local_part$ and $domain$ to +refer to the address that is being rewritten. + + +Rewriting patterns +~~~~~~~~~~~~~~~~~~ +cindex:[rewriting,patterns] +cindex:[address list,in a rewriting pattern] +The source pattern in a rewriting rule is any item which may appear in an +address list (see section <<SECTaddresslist>>). It is in fact processed as a +single-item address list, which means that it is expanded before being tested +against the address. + +Domains in patterns should be given in lower case. Local parts in patterns are +case-sensitive. If you want to do case-insensitive matching of local parts, you +can use a regular expression that starts with `^(?i)`. + +cindex:[numerical variables ($1$ $2$ etc),in rewriting rules] +After matching, the numerical variables $1$, $2$, etc. may be set, +depending on the type of match which occurred. These can be used in the +replacement string to insert portions of the incoming address. $0$ always +refers to the complete incoming address. When a regular expression is used, the +numerical variables are set from its capturing subexpressions. For other types +of pattern they are set as follows: + +- If a local part or domain starts with an asterisk, the numerical variables +refer to the character strings matched by asterisks, with $1$ associated with +the first asterisk, and $2$ with the second, if present. For example, if the +pattern + + *queen@*.fict.example ++ +is matched against the address 'hearts-queen@wonderland.fict.example' then + + $0 = hearts-queen@wonderland.fict.example + $1 = hearts- + $2 = wonderland ++ +Note that if the local part does not start with an asterisk, but the domain +does, it is $1$ that contains the wild part of the domain. + +- If the domain part of the pattern is a partial lookup, the wild and fixed parts +of the domain are placed in the next available numerical variables. Suppose, +for example, that the address 'foo@bar.baz.example' is processed by a +rewriting rule of the form + + *@partial-dbm;/some/dbm/file <replacement string> ++ +and the key in the file that matches the domain is `*.baz.example`. Then + + $1 = foo + $2 = bar + $3 = baz.example ++ +If the address 'foo@baz.example' is looked up, this matches the same +wildcard file entry, and in this case $2$ is set to the empty string, but +$3$ is still set to 'baz.example'. If a non-wild key is matched in a +partial lookup, $2$ is again set to the empty string and $3$ is set to the +whole domain. For non-partial domain lookups, no numerical variables are set. + + + +Rewriting replacements +~~~~~~~~~~~~~~~~~~~~~~ +cindex:[rewriting,replacements] +If the replacement string for a rule is a single asterisk, addresses that +match the pattern and the flags are 'not' rewritten, and no subsequent +rewriting rules are scanned. For example, + + hatta@lookingglass.fict.example * f + +specifies that 'hatta@lookingglass.fict.example' is never to be rewritten in +'From:' headers. + +If the replacement string is not a single asterisk, it is expanded, and must +yield a fully qualified address. Within the expansion, the variables +$local_part$ and $domain$ refer to the address that is being rewritten. +Any letters they contain retain their original case -- they are not lower +cased. The numerical variables are set up according to the type of pattern that +matched the address, as described above. If the expansion is forced to fail by +the presence of ``fail'' in a conditional or lookup item, rewriting by the +current rule is abandoned, but subsequent rules may take effect. Any other +expansion failure causes the entire rewriting operation to be abandoned, and an +entry written to the panic log. + + + +Rewriting flags +~~~~~~~~~~~~~~~ +There are three different kinds of flag that may appear on rewriting rules: + +- Flags that specify which headers and envelope addresses to rewrite: E, F, T, b, +c, f, h, r, s, t. + +- A flag that specifies rewriting at SMTP time: S. + +- Flags that control the rewriting process: Q, q, R, w. + +For rules that are part of the %headers_rewrite% generic transport option, +E, F, T, and S are not permitted. + + + +Flags specifying which headers and envelope addresses to rewrite +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[rewriting,flags] +If none of the following flag letters, nor the ``S'' flag (see section +<<SECTrewriteS>>) are present, a main rewriting rule applies to all headers and +to both the sender and recipient fields of the envelope, whereas a +transport-time rewriting rule just applies to all headers. Otherwise, the +rewriting rule is skipped unless the relevant addresses are being processed. + +&&& +`E` rewrite all envelope fields +`F` rewrite the envelope From field +`T` rewrite the envelope To field +`b` rewrite the 'Bcc:' header +`c` rewrite the 'Cc:' header +`f` rewrite the 'From:' header +`h` rewrite all headers +`r` rewrite the 'Reply-To:' header +`s` rewrite the 'Sender:' header +`t` rewrite the 'To:' header +&&& + +You should be particularly careful about rewriting 'Sender:' headers, and +restrict this to special known cases in your own domains. + + +[[SECTrewriteS]] +The SMTP-time rewriting flag +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[SMTP,rewriting malformed addresses] +cindex:[RCPT,rewriting argument of] +cindex:[MAIL,rewriting argument of] +The rewrite flag ``S'' specifies a rewrite of incoming envelope addresses at SMTP +time, as soon as an address is received in a MAIL or RCPT command, and +before any other processing; even before syntax checking. The pattern is +required to be a regular expression, and it is matched against the whole of the +data for the command, including any surrounding angle brackets. + +This form of rewrite rule allows for the handling of addresses that are not +compliant with RFCs 2821 and 2822 (for example, ``bang paths'' in batched SMTP +input). Because the input is not required to be a syntactically valid address, +the variables $local_part$ and $domain$ are not available during the +expansion of the replacement string. The result of rewriting replaces the +original address in the MAIL or RCPT command. + + +Flags controlling the rewriting process +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +There are four flags which control the way the rewriting process works. These +take effect only when a rule is invoked, that is, when the address is of the +correct type (matches the flags) and matches the pattern: + +- If the ``Q'' flag is set on a rule, the rewritten address is permitted to be an +unqualified local part. It is qualified with %qualify_recipient%. In the +absence of ``Q'' the rewritten address must always include a domain. + +- If the ``q'' flag is set on a rule, no further rewriting rules are considered, +even if no rewriting actually takes place because of a ``fail'' in the expansion. +The ``q'' flag is not effective if the address is of the wrong type (does not +match the flags) or does not match the pattern. + +- The ``R'' flag causes a successful rewriting rule to be re-applied to the new +address, up to ten times. It can be combined with the ``q'' flag, to stop +rewriting once it fails to match (after at least one successful rewrite). + +- cindex:[rewriting,whole addresses] +When an address in a header is rewritten, the rewriting normally applies only +to the working part of the address, with any comments and RFC 2822 ``phrase'' +left unchanged. For example, rewriting might change + + From: Ford Prefect <fp42@restaurant.hitch.fict.example> ++ +into + + From: Ford Prefect <prefectf@hitch.fict.example> ++ +Sometimes there is a need to replace the whole address item, and this can be +done by adding the flag letter ``w'' to a rule. If this is set on a rule that +causes an address in a header line to be rewritten, the entire address is +replaced, not just the working part. The replacement must be a complete RFC +2822 address, including the angle brackets if necessary. If text outside angle +brackets contains a character whose value is greater than 126 or less than 32 +(except for tab), the text is encoded according to RFC 2047. +The character set is taken from %headers_charset%, which defaults to +ISO-8859-1. ++ +When the ``w'' flag is set on a rule that causes an envelope address to be +rewritten, all but the working part of the replacement address is discarded. + + + +Rewriting examples +~~~~~~~~~~~~~~~~~~ +Here is an example of the two common rewriting paradigms: + +.... +*@*.hitch.fict.example $1@hitch.fict.example +*@hitch.fict.example ${lookup{$1}dbm{/etc/realnames}\ + {$value}fail}@hitch.fict.example bctfrF +.... + +Note the use of ``fail'' in the lookup expansion in the second rule, forcing +the string expansion to fail if the lookup does not succeed. In this context it +has the effect of leaving the original address unchanged, but Exim goes on to +consider subsequent rewriting rules, if any, because the ``q'' flag is not +present in that rule. An alternative to ``fail'' would be to supply $1$ +explicitly, which would cause the rewritten address to be the same as before, +at the cost of a small bit of processing. Not supplying either of these is an +error, since the rewritten address would then contain no local part. + +The first example above replaces the domain with a superior, more general +domain. This may not be desirable for certain local parts. If the rule + + root@*.hitch.fict.example * + +were inserted before the first rule, rewriting would be suppressed for the +local part 'root' at any domain ending in 'hitch.fict.example'. + +Rewriting can be made conditional on a number of tests, by making use of +$\{if$ in the expansion item. For example, to apply a rewriting rule only to +messages that originate outside the local host: + +.... +*@*.hitch.fict.example "${if !eq {$sender_host_address}{}\ + {$1@hitch.fict.example}fail}" +.... + +The replacement string is quoted in this example because it contains white +space. + +cindex:[rewriting,bang paths] +cindex:[bang paths,rewriting] +Exim does not handle addresses in the form of ``bang paths''. If it sees such an +address it treats it as an unqualified local part which it qualifies with the +local qualification domain (if the source of the message is local or if the +remote host is permitted to send unqualified addresses). Rewriting can +sometimes be used to handle simple bang paths with a fixed number of +components. For example, the rule + + \N^([^!]+)!(.*)@your.domain.example$\N $2@$1 + +rewrites a two-component bang path 'host.name!user' as the domain address +'user@host.name'. However, there is a security implication in using this as +a global rewriting rule for envelope addresses. It can provide a backdoor +method for using your system as a relay, because the incoming addresses appear +to be local. If the bang path addresses are received via SMTP, it is safer to +use the ``S'' flag to rewrite them as they are received, so that relay checking +can be done on the rewritten addresses. + + + + + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// + +[[CHAPretry]] +Retry configuration +------------------- +cindex:[retry configuration, description of] +cindex:[configuration file,retry section] +The ``retry'' section of the run time configuration file contains a list of retry +rules which control how often Exim tries to deliver messages that cannot be +delivered at the first attempt. If there are no retry rules, temporary errors +are treated as permanent. The %-brt% command line option can be used to test +which retry rule will be used for a given address or domain. + +The most common cause of retries is temporary failure to deliver to a remote +host because the host is down, or inaccessible because of a network problem. +Exim's retry processing in this case is applied on a per-host (strictly, per IP +address) basis, not on a per-message basis. Thus, if one message has recently +been delayed, delivery of a new message to the same host is not immediately +tried, but waits for the host's retry time to arrive. If the %retry_defer% log +selector is set, the message +cindex:[retry,time not reached] +``retry time not reached'' is written to the main log whenever a delivery is +skipped for this reason. Section <<SECToutSMTPerr>> contains more details of the +handling of errors during remote deliveries. + +Retry processing applies to routing as well as to delivering, except as covered +in the next paragraph. The retry rules do not distinguish between these +actions. It is not possible, for example, to specify different behaviour for +failures to route the domain 'snark.fict.example' and failures to deliver to +the host 'snark.fict.example'. I didn't think anyone would ever need this +added complication, so did not implement it. However, although they share the +same retry rule, the actual retry times for routing and transporting a given +domain are maintained independently. + +When a delivery is not part of a queue run (typically an immediate delivery on +receipt of a message), the routers are always run, and local deliveries are +always attempted, even if retry times are set for them. This makes for better +behaviour if one particular message is causing problems (for example, causing +quota overflow, or provoking an error in a filter file). If such a delivery +suffers a temporary failure, the retry data is updated as normal, and +subsequent delivery attempts from queue runs occur only when the retry time for +the local address is reached. + + + +Retry rules +~~~~~~~~~~~ +cindex:[retry,rules] +Each retry rule occupies one line and consists of three or four parts, +separated by white space: a pattern, an error name, an optional list of sender +addresses, and a list of retry parameters. The pattern and sender lists must be +enclosed in double quotes if they contain white space. The rules are searched in +order until one is found where the pattern, error name, and sender list (if +present) match the failing host or address, the error that occurred, and the +message's sender, respectively. + + +The pattern is any single item that may appear in an address list (see section +<<SECTaddresslist>>). It is in fact processed as a one-item address list, which +means that it is expanded before being tested against the address that has +been delayed. Address list processing treats a plain domain name as if it were +preceded by ``\*@'', which makes it possible for many retry rules to start with +just a domain. For example, + + lookingglass.fict.example * F,24h,30m; + +provides a rule for any address in the 'lookingglass.fict.example' domain, +whereas + + alice@lookingglass.fict.example * F,24h,30m; + +applies only to temporary failures involving the local part %alice%. +In practice, almost all rules start with a domain name pattern without a local +part. + +cindex:[regular expressions,in retry rules] +*Warning*: If you use a regular expression in a routing rule pattern, it +must match a complete address, not just a domain, because that is how regular +expressions work in address lists. + +&&& +`\^\Nxyz\d+\.abc\.example\\$\N \* G,1h,10m,2` %Wrong% +`\^\N[^@]+@xyz\d+\.abc\.example\\$\N \* G,1h,10m,2` %Right% +&&& + + + +Choosing which retry rule to use +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +When Exim is looking for a retry rule after a routing attempt has failed (for +example, after a DNS timeout), each line in the retry configuration is tested +against the complete address only if %retry_use_local_part% is set for the +router. Otherwise, only the domain is used, except when matching against a +regular expression, when the local part of the address is replaced with ``\*''. +A domain on its own can match a domain pattern, or a pattern that starts with +``\*@''. By default, %retry_use_local_part% is true for routers where +%check_local_user% is true, and false for other routers. + +Similarly, when Exim is looking for a retry rule after a local delivery has +failed (for example, after a mailbox full error), each line in the retry +configuration is tested against the complete address only if +%retry_use_local_part% is set for the transport (it defaults true for all +local transports). + +When Exim is looking for a retry rule after a remote delivery attempt has +failed, what happens depends on the type of failure. After a 4##'xx' SMTP +response for a recipient address, the whole address is used when searching the +retry rules. The rule that is found is used to create a retry time for the +failing address. + +For a temporary error that is not related to an individual address, +(for example, a connection timeout), each line in the retry configuration is +checked twice. First, the name of the remote host is used as a domain name +(preceded by ``\*@'' when matching a regular expression). If this does not match +the line, the domain from the email address is tried in a similar fashion. For +example, suppose the MX records for 'a.b.c.example' are + + a.b.c.example MX 5 x.y.z.example + MX 6 p.q.r.example + MX 7 m.n.o.example + +and the retry rules are + + p.q.r.example * F,24h,30m; + a.b.c.example * F,4d,45m; + +and a delivery to the host 'x.y.z.example' fails. The first rule matches +neither the host nor the domain, so Exim looks at the second rule. This does +not match the host, but it does match the domain, so it is used to calculate +the retry time for the host 'x.y.z.example'. Meanwhile, Exim tries to deliver +to 'p.q.r.example'. If this fails, the first retry rule is used, because it +matches the host. + +In other words, failures to deliver to host 'p.q.r.example' use the first +rule to determine retry times, but for all the other hosts for the domain +'a.b.c.example', the second rule is used. The second rule is also used if +routing to 'a.b.c.example' suffers a temporary failure. + + +Retry rules for specific errors +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[retry,specific errors; specifying] +The second field in a retry rule is the name of a particular error, or an +asterisk, which matches any error. The errors that can be tested for are: + +%auth_failed%:: +Authentication failed when trying to send to a host in the %hosts_require_auth% +list in an ^smtp^ transport. + +%rcpt_4xx%:: +A 4##'xx' error was received for an outgoing RCPT command. Either the first or +both of the x's can be given as specific digits, for example: `rcpt_45x` or +`rcpt_436`. For example, to recognize 452 errors given to RCPT commands by a +particular host, and have retries every ten minutes and a one-hour timeout, you +could set up a retry rule of this form: + + the.host.name rcpt_452 F,1h,10m ++ +These errors apply to both outgoing SMTP (the ^smtp^ transport) and outgoing +LMTP (either the ^lmtp^ transport, or the ^smtp^ transport in LMTP mode). +Note, however, that they apply only to responses to RCPT commands. + +%refused_MX%:: +A connection to a host obtained from an MX record was refused. + +%refused_A%:: +A connection to a host not obtained from an MX record was refused. + +%refused%:: +A connection was refused. + +%timeout_connect_MX%:: +A connection attempt to a host obtained from an MX record timed out. + +%timeout_connect_A%:: +A connection attempt to a host not obtained from an MX record timed out. + +%timeout_connect%:: +A connection attempt timed out. + +%timeout_MX%:: +There was a timeout while connecting or during an SMTP session with a host +obtained from an MX record. + +%timeout_A%:: +There was a timeout while connecting or during an SMTP session with a host not +obtained from an MX record. + +%timeout%:: +There was a timeout while connecting or during an SMTP session. + +%quota%:: +A mailbox quota was exceeded in a local delivery by the ^appendfile^ transport. + +%quota_%<'time'>:: +cindex:[quota,error testing in retry rule] +cindex:[retry,quota error testing] +A mailbox quota was exceeded in a local delivery by the ^appendfile^ transport, +and the mailbox has not been accessed for <'time'>. For example, 'quota_4d' +applies to a quota error when the mailbox has not been accessed for four days. + +/// +End of list +/// + +cindex:[mailbox,time of last read] +The idea of %quota_%<'time'> is to make it possible to have shorter timeouts +when the mailbox is full and is not being read by its owner. Ideally, it should +be based on the last time that the user accessed the mailbox. However, it is +not always possible to determine this. Exim uses the following heuristic rules: + +- If the mailbox is a single file, the time of last access (the ``atime'') is used. +As no new messages are being delivered (because the mailbox is over quota), +Exim does not access the file, so this is the time of last user access. + +- cindex:[maildir format,time of last read] +For a maildir delivery, the time of last modification of the _new_ +subdirectory is used. As the mailbox is over quota, no new files are created in +the _new_ subdirectory, because no new messages are being delivered. Any +change to the _new_ subdirectory is therefore assumed to be the result of an +MUA moving a new message to the _cur_ directory when it is first read. The +time that is used is therefore the last time that the user read a new message. + +- For other kinds of multi-file mailbox, the time of last access cannot be +obtained, so a retry rule that uses this type of error field is never matched. + +The quota errors apply both to system-enforced quotas and to Exim's own quota +mechanism in the ^appendfile^ transport. The 'quota' error also applies +when a local delivery is deferred because a partition is full (the ENOSPC +error). + + + +Retry rules for specified senders +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[retry,rules; sender-specific] +You can specify retry rules that apply only when the failing message has a +specific sender. In particular, this can be used to define retry rules that +apply only to bounce messages. The third item in a retry rule can be of this +form: + + senders=<address list> + +The retry timings themselves are then the fourth item. For example: + +.... +* * senders=: F,1h,30m +.... + +matches all temporary errors for bounce messages sent to any host. If the +address list contains white space, it must be enclosed in quotes. For example: + + a.domain timeout senders="xb.dom : yc.dom" G,8h,10m,1.5 + +When testing retry rules using %-brt%, you can supply a sender using the %-f% +command line option, like this: + + exim -f "" -brt user@dom.ain + +If you do not set %-f% with %-brt%, a retry rule that contains a senders list +is never matched. + + + + + +Retry parameters +~~~~~~~~~~~~~~~~ +cindex:[retry,parameters in rules] +The third (or fourth, if a senders list is present) field in a retry rule is a +sequence of retry parameter sets, separated by semicolons. Each set consists of + + <letter>,<cutoff time>,<arguments> + +The letter identifies the algorithm for computing a new retry time; the cutoff +time is the time beyond which this algorithm no longer applies, and the +arguments vary the algorithm's action. The cutoff time is measured from the +time that the first failure for the domain (combined with the local part if +relevant) was detected, not from the time the message was received. + +cindex:[retry,algorithms] +The available algorithms are: + +- 'F': retry at fixed intervals. There is a single time parameter specifying +the interval. + +- 'G': retry at geometrically increasing intervals. The first argument +specifies a starting value for the interval, and the second a multiplier, which +is used to increase the size of the interval at each retry. + +When computing the next retry time, the algorithm definitions are scanned in +order until one whose cutoff time has not yet passed is reached. This is then +used to compute a new retry time that is later than the current time. In the +case of fixed interval retries, this simply means adding the interval to the +current time. For geometrically increasing intervals, retry intervals are +computed from the rule's parameters until one that is greater than the previous +interval is found. The main configuration variable +cindex:[limit,retry interval] +cindex:[retry interval, maximum] +cindex:[%retry_interval_max%] +%retry_interval_max% limits the maximum interval between retries. + +A single remote domain may have a number of hosts associated with it, and each +host may have more than one IP address. Retry algorithms are selected on the +basis of the domain name, but are applied to each IP address independently. If, +for example, a host has two IP addresses and one is unusable, Exim will +generate retry times for it and will not try to use it until its next retry +time comes. Thus the good IP address is likely to be tried first most of the +time. + +cindex:[hints database,use for retrying] +Retry times are hints rather than promises. Exim does not make any attempt to +run deliveries exactly at the computed times. Instead, a queue runner process +starts delivery processes for delayed messages periodically, and these attempt +new deliveries only for those addresses that have passed their next retry time. +If a new message arrives for a deferred address, an immediate delivery attempt +occurs only if the address has passed its retry time. In the absence of new +messages, the minimum time between retries is the interval between queue runner +processes. There is not much point in setting retry times of five minutes if +your queue runners happen only once an hour, unless there are a significant +number of incoming messages (which might be the case on a system that is +sending everything to a smart host, for example). + +The data in the retry hints database can be inspected by using the +'exim_dumpdb' or 'exim_fixdb' utility programs (see chapter <<CHAPutils>>). The +latter utility can also be used to change the data. The 'exinext' utility +script can be used to find out what the next retry times are for the hosts +associated with a particular mail domain, and also for local deliveries that +have been deferred. + + +Retry rule examples +~~~~~~~~~~~~~~~~~~~ +Here are some example retry rules: + + alice@wonderland.fict.example quota_5d F,7d,3h + wonderland.fict.example quota_5d + wonderland.fict.example * F,1h,15m; G,2d,1h,2; + lookingglass.fict.example * F,24h,30m; + * refused_A F,2h,20m; + * * F,2h,15m; G,16h,1h,1.5; F,5d,8h + +The first rule sets up special handling for mail to +'alice@wonderland.fict.example' when there is an over-quota error and the +mailbox has not been read for at least 5 days. Retries continue every three +hours for 7 days. The second rule handles over-quota errors for all other local +parts at 'wonderland.fict.example'; the absence of a local part has the same +effect as supplying ``\*@''. As no retry algorithms are supplied, messages that +fail are bounced immediately if the mailbox has not been read for at least 5 +days. + +The third rule handles all other errors at 'wonderland.fict.example'; retries +happen every 15 minutes for an hour, then with geometrically increasing +intervals until two days have passed since a delivery first failed. After the +first hour there is a delay of one hour, then two hours, then four hours, and +so on (this is a rather extreme example). + +The fourth rule controls retries for the domain 'lookingglass.fict.example'. +They happen every 30 minutes for 24 hours only. The remaining two rules handle +all other domains, with special action for connection refusal from hosts that +were not obtained from an MX record. + +The final rule in a retry configuration should always have asterisks in the +first two fields so as to provide a general catch-all for any addresses that do +not have their own special handling. This example tries every 15 minutes for 2 +hours, then with intervals starting at one hour and increasing by a factor of +1.5 up to 16 hours, then every 8 hours up to 5 days. + + + +Timeout of retry data +~~~~~~~~~~~~~~~~~~~~~ +cindex:[timeout,of retry data] +cindex:[%retry_data_expire%] +cindex:[hints database,data expiry] +cindex:[retry,timeout of data] +Exim timestamps the data that it writes to its retry hints database. When it +consults the data during a delivery it ignores any that is older than the value +set in %retry_data_expire% (default 7 days). If, for example, a host hasn't +been tried for 7 days, Exim will try to deliver to it immediately a message +arrives, and if that fails, it will calculate a retry time as if it were +failing for the first time. + +This improves the behaviour for messages routed to rarely-used hosts such as MX +backups. If such a host was down at one time, and happens to be down again when +Exim tries a month later, using the old retry data would imply that it had been +down all the time, which is not a justified assumption. + +If a host really is permanently dead, this behaviour causes a burst of retries +every now and again, but only if messages routed to it are rare. It there is a +message at least once every 7 days the retry data never expires. + + + + +Long-term failures +~~~~~~~~~~~~~~~~~~ +cindex:[delivery failure, long-term] +cindex:[retry,after long-term failure] +Special processing happens when an email address has been failing for so long +that the cutoff time for the last algorithm is reached. For example, using the +default retry rule: + +.... +* * F,2h,15m; G,16h,1h,1.5; F,4d,6h +.... + +the cutoff time is four days. Reaching the retry cutoff is independent of how +long any specific message has been failing; it is the length of continuous +failure for the recipient address that counts. + +When the cutoff time is reached for a local delivery, or for all the IP +addresses associated with a remote delivery, a subsequent delivery failure +causes Exim to give up on the address, and a bounce message is generated. +In order to cater for new messages that use the failing address, a next retry +time is still computed from the final algorithm, and is used as follows: + +For local deliveries, one delivery attempt is always made for any subsequent +messages. If this delivery fails, the address fails immediately. The +post-cutoff retry time is not used. + +If the delivery is remote, there are two possibilities, controlled by the +cindex:[%delay_after_cutoff%] +%delay_after_cutoff% option of the ^smtp^ transport. The option is true by +default. Until the post-cutoff retry time for one of the IP addresses is +reached, the failing email address is bounced immediately, without a delivery +attempt taking place. After that time, one new delivery attempt is made to +those IP addresses that are past their retry times, and if that still fails, +the address is bounced and new retry times are computed. + +In other words, when all the hosts for a given email address have been failing +for a long time, Exim bounces rather then defers until one of the hosts' retry +times is reached. Then it tries once, and bounces if that attempt fails. This +behaviour ensures that few resources are wasted in repeatedly trying to deliver +to a broken destination, but if the host does recover, Exim will eventually +notice. + +If %delay_after_cutoff% is set false, Exim behaves differently. If all IP +addresses are past their final cutoff time, Exim tries to deliver to those IP +addresses that have not been tried since the message arrived. If there are +no suitable IP addresses, or if they all fail, the address is bounced. In other +words, it does not delay when a new message arrives, but tries the expired +addresses immediately, unless they have been tried since the message arrived. +If there is a continuous stream of messages for the failing domains, setting +%delay_after_cutoff% false means that there will be many more attempts to +deliver to permanently failing IP addresses than when %delay_after_cutoff% is +true. + + +Ultimate address timeout +~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[retry,ultimate address timeout] +An additional rule is needed to cope with cases where a host is intermittently +available, or when a message has some attribute that prevents its delivery when +others to the same address get through. In this situation, because some +messages are successfully delivered, the ``retry clock'' for the address keeps +getting restarted, and so a message could remain on the queue for ever. To +prevent this, if a message has been on the queue for longer than the cutoff +time of any applicable retry rule for a given address, a delivery is attempted +for that address, even if it is not yet time, and if this delivery fails, the +address is timed out. A new retry time is not computed in this case, so that +other messages for the same address are considered immediately. + + + + + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// + +[[CHAPSMTPAUTH]] +SMTP authentication +------------------- +cindex:[SMTP,authentication configuration] +cindex:[authentication] +The ``authenticators'' section of Exim's run time configuration is concerned with +SMTP authentication. This facility is an extension to the SMTP protocol, +described in RFC 2554, which allows a client SMTP host to authenticate itself +to a server. This is a common way for a server to recognize clients that +are permitted to use it as a relay. SMTP authentication is not of relevance to +the transfer of mail between servers that have no managerial connection with +each other. + +cindex:[AUTH,description of] +Very briefly, the way SMTP authentication works is as follows: + +- The server advertises a number of authentication 'mechanisms' in response to +the client's EHLO command. + +- The client issues an AUTH command, naming a specific mechanism. The command +may, optionally, contain some authentication data. + +- The server may issue one or more 'challenges', to which the client must send +appropriate responses. In simple authentication mechanisms, the challenges are +just prompts for user names and passwords. The server does not have to issue +any challenges -- in some mechanisms the relevant data may all be transmitted +with the AUTH command. + +- The server either accepts or denies authentication. + +- If authentication succeeds, the client may optionally make use of the AUTH +option on the MAIL command to pass an authenticated sender in subsequent +mail transactions. Authentication lasts for the remainder of the SMTP +connection. + +- If authentication fails, the client may give up, or it may try a different +authentication mechanism, or it may try transferring mail over the +unauthenticated connection. + +If you are setting up a client, and want to know which authentication +mechanisms the server supports, you can use Telnet to connect to port 25 (the +SMTP port) on the server, and issue an EHLO command. The response to this +includes the list of supported mechanisms. For example: + +&&& +`\$ `##*`telnet server.example 25`* +`Trying 192.168.34.25...` +`Connected to server.example.` +`Escape character is \'^]\'.` +`220 server.example ESMTP Exim 4.20 ...` +*`ehlo client.example`* +`250-server.example Hello client.example [10.8.4.5]` +`250-SIZE 52428800` +`250-PIPELINING` +`250-AUTH PLAIN` +`250 HELP` +&&& + +The second-last line of this example output shows that the server supports +authentication using the PLAIN mechanism. In Exim, the different authentication +mechanisms are configured by specifying 'authenticator' drivers. Like the +routers and transports, which authenticators are included in the binary is +controlled by build-time definitions. The following are currently available, +included by setting + + AUTH_CRAM_MD5=yes + AUTH_PLAINTEXT=yes + AUTH_SPA=yes + +in _Local/Makefile_, respectively. The first of these supports the CRAM-MD5 +authentication mechanism (RFC 2195), and the second can be configured to +support the PLAIN authentication mechanism (RFC 2595) or the LOGIN mechanism, +which is not formally documented, but used by several MUAs. The third +authenticator supports Microsoft's 'Secure Password Authentication' +mechanism. + +The authenticators are configured using the same syntax as other drivers (see +section <<SECTfordricon>>). If no authenticators are required, no authentication +section need be present in the configuration file. Each authenticator can in +principle have both server and client functions. When Exim is receiving SMTP +mail, it is acting as a server; when it is sending out messages over SMTP, it +is acting as a client. Authenticator configuration options are provided for use +in both these circumstances. + +To make it clear which options apply to which situation, the prefixes +%server_% and %client_% are used on option names that are specific to either +the server or the client function, respectively. Server and client functions +are disabled if none of their options are set. If an authenticator is to be +used for both server and client functions, a single definition, using both sets +of options, is required. For example: + + cram: + driver = cram_md5 + public_name = CRAM-MD5 + server_secret = ${if eq{$1}{ph10}{secret1}fail} + client_name = ph10 + client_secret = secret2 + +The %server_% option is used when Exim is acting as a server, and the +%client_% options when it is acting as a client. + +Descriptions of the individual authenticators are given in subsequent chapters. +The remainder of this chapter covers the generic options for the +authenticators, followed by general discussion of the way authentication works +in Exim. + + + +Generic options for authenticators +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[authentication,generic options] +cindex:[options,generic; for authenticators] + + +oindex:[%driver%] +`..'= +%driver%, Use: 'authenticators', Type: 'string', Default: 'unset' +=== + +This option must always be set. It specifies which of the available +authenticators is to be used. + + +oindex:[%public_name%] +`..'= +%public_name%, Use: 'authenticators', Type: 'string', Default: 'unset' +=== + +This option specifies the name of the authentication mechanism that the driver +implements, and by which it is known to the outside world. These names should +contain only upper case letters, digits, underscores, and hyphens (RFC 2222), +but Exim in fact matches them caselessly. If %public_name% is not set, it +defaults to the driver's instance name. + + +oindex:[%server_advertise_condition%] +`..'= +%server_advertise_condition%, Use: 'authenticators', Type: 'string'!!, Default: 'unset' +=== + +When a server is about to advertise an authentication mechanism, the condition +is expanded. If it yields the empty string, ``0'', ``no'', or ``false'', the +mechanism is not advertised. +If the expansion fails, the mechanism is not advertised. If the failure was not +forced, and was not caused by a lookup defer, the incident is logged. +See section <<SECTauthexiser>> below for further discussion. + + +oindex:[%server_debug_print%] +`..'= +%server_debug_print%, Use: 'authenticators', Type: 'string'!!, Default: 'unset' +=== + +If this option is set and authentication debugging is enabled (see the %-d% +command line option), the string is expanded and included in the debugging +output when the authenticator is run as a server. This can help with checking +out the values of variables. +If expansion of the string fails, the error message is written to the debugging +output, and Exim carries on processing. + + +oindex:[%server_set_id%] +`..'= +%server_set_id%, Use: 'authenticators', Type: 'string'!!, Default: 'unset' +=== + +When an Exim server successfully authenticates a client, this string is +expanded using data from the authentication, and preserved for any incoming +messages in the variable $authenticated_id$. It is also included in the log +lines for incoming messages. For example, a user/password authenticator +configuration might preserve the user name that was used to authenticate, and +refer to it subsequently during delivery of the message. +If expansion fails, the option is ignored. + + +oindex:[%server_mail_auth_condition%] +`..'= +%server_mail_auth_condition%, Use: 'authenticators', Type: 'string'!!, Default: 'unset' +=== + +This option allows a server to discard authenticated sender addresses supplied +as part of MAIL commands in SMTP connections that are authenticated by the +driver on which %server_mail_auth_condition% is set. The option is not used +as part of the authentication process; instead its (unexpanded) value is +remembered for later use. +How it is used is described in the following section. + + + + + +[[SECTauthparamail]] +The AUTH parameter on MAIL commands +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[authentication,sender; authenticated] +cindex:[AUTH,on MAIL command] +When a client supplied an AUTH= item on a MAIL command, Exim applies +the following checks before accepting it as the authenticated sender of the +message: + +- If the connection is not using extended SMTP (that is, HELO was used rather +than EHLO), the use of AUTH= is a syntax error. + +- If the value of the AUTH= parameter is ``<>'', it is ignored. + +- If %acl_smtp_mailauth% is defined, the ACL it specifies is run. While it is +running, the value of $authenticated_sender$ is set to the value obtained +from the AUTH= parameter. If the ACL does not yield ``accept'', the value of +$authenticated_sender$ is deleted. The %acl_smtp_mailauth% ACL may not +return ``drop'' or ``discard''. If it defers, a temporary error code (451) is given +for the MAIL command. + +- If %acl_smtp_mailauth% is not defined, the value of the AUTH= parameter +is accepted and placed in $authenticated_sender$ only if the client has +authenticated. + +- If the AUTH= value was accepted by either of the two previous rules, and +the client has authenticated, and the authenticator has a setting for the +%server_mail_auth_condition%, the condition is checked at this point. The +valued that was saved from the authenticator is expanded. If the expansion +fails, or yields an empty string, ``0'', ``no'', or ``false'', the value of +$authenticated_sender$ is deleted. If the expansion yields any other value, +the value of $authenticated_sender$ is retained and passed on with the +message. + + +When $authenticated_sender$ is set for a message, it is passed on to other +hosts to which Exim authenticates as a client. Do not confuse this value with +$authenticated_id$, which is a string obtained from the authentication +process, and which is not usually a complete email address. + +Whenever an AUTH= value is ignored, the incident is logged. The ACL for +MAIL, if defined, is run after AUTH= is accepted or ignored. It can +therefore make use of $authenticated_sender$. The converse is not true: the +value of $sender_address$ is not yet set up when the %acl_smtp_mailauth% +ACL is run. + + + +[[SECTauthexiser]] +Authentication on an Exim server +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[authentication,on an Exim server] +When Exim receives an EHLO command, it advertises the public names of those +authenticators that are configured as servers, subject to the following +conditions: + +- The client host must match %auth_advertise_hosts% (default \*). + +- It the %server_advertise_condition% option is set, its expansion must not +yield the empty string, ``0'', ``no'', or ``false''. + +The order in which the authenticators are defined controls the order in which +the mechanisms are advertised. + +Some mail clients (for example, some versions of Netscape) require the user to +provide a name and password for authentication whenever AUTH is advertised, +even though authentication may not in fact be needed (for example, Exim may be +set up to allow unconditional relaying from the client by an IP address check). +You can make such clients more friendly by not advertising AUTH to them. +For example, if clients on the 10.9.8.0/24 network are permitted (by the ACL +that runs for RCPT) to relay without authentication, you should set + + auth_advertise_hosts = ! 10.9.8.0/24 + +so that no authentication mechanisms are advertised to them. + +The %server_advertise_condition% controls the advertisement of individual +authentication mechanisms. For example, it can be used to restrict the +advertisement of a patricular mechanism to encrypted connections, by a setting +such as: + + server_advertise_condition = ${if eq{$tls_cipher}{}{no}{yes}} + +If the session is encrypted, $tls_cipher$ is not empty, and so the expansion +yields ``yes'', which allows the advertisement to happen. + +When an Exim server receives an AUTH command from a client, it rejects it +immediately if AUTH was not advertised in response to an earlier EHLO +command. This is the case if + +- The client host does not match %auth_advertise_hosts%; or + +- No authenticators are configured with server options; or + +- Expansion of %server_advertise_condition% blocked the advertising of all the +server authenticators. + + +Otherwise, Exim runs the ACL specified by %acl_smtp_auth% in order +to decide whether to accept the command. If %acl_smtp_auth% is not set, +AUTH is accepted from any client host. + +If AUTH is not rejected by the ACL, Exim searches its configuration for a +server authentication mechanism that was advertised in response to EHLO and +that matches the one named in the AUTH command. If it finds one, it runs +the appropriate authentication protocol, and authentication either succeeds or +fails. If there is no matching advertised mechanism, the AUTH command is +rejected with a 504 error. + +When a message is received from an authenticated host, the value of +$received_protocol$ is set to ``esmtpa'' instead of ``esmtp'', and +$sender_host_authenticated$ contains the name (not the public name) of the +authenticator driver that successfully authenticated the client from which the +message was received. This variable is empty if there was no successful +authentication. + + + + +Testing server authentication +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[authentication,testing a server] +cindex:[AUTH,testing a server] +cindex:[base64 encoding,creating authentication test data] +Exim's %-bh% option can be useful for testing server authentication +configurations. The data for the AUTH command has to be sent using base64 +encoding. A quick way to produce such data for testing is the following Perl +script: + + use MIME::Base64; + printf ("%s", encode_base64(eval "\"$ARGV[0]\"")); + +cindex:[binary zero,in authentication data] +This interprets its argument as a Perl string, and then encodes it. The +interpretation as a Perl string allows binary zeros, which are required for +some kinds of authentication, to be included in the data. For example, a +command line to run this script on such data might be + + encode '\0user\0password' + +Note the use of single quotes to prevent the shell interpreting the +backslashes, so that they can be interpreted by Perl to specify characters +whose code value is zero. + +*Warning 1*: If either of the user or password strings starts with an octal +digit, you must use three zeros instead of one after the leading backslash. If +you do not, the octal digit that starts your string will be incorrectly +interpreted as part of the code for the first character. + +*Warning 2*: If there are characters in the strings that Perl interprets +specially, you must use a Perl escape to prevent them being misinterpreted. For +example, a command such as + + encode '\0user@domain.com\0pas$$word' + +gives an incorrect answer because of the unescaped ``@'' and ``\$'' characters. + +If you have the %mimencode% command installed, another way to do produce +base64-encoded strings is to run the command + + echo -e -n `\0user\0password' | mimencode + +The %-e% option of %echo% enables the interpretation of backslash escapes in +the argument, and the %-n% option specifies no newline at the end of its +output. However, not all versions of %echo% recognize these options, so you +should check your version before relying on this suggestion. + + + +Authentication by an Exim client +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[authentication,on an Exim client] +The ^smtp^ transport has two options called %hosts_require_auth% and +%hosts_try_auth%. When the ^smtp^ transport connects to a server that +announces support for authentication, and the host matches an entry in either +of these options, Exim (as a client) tries to authenticate as follows: + +- For each authenticator that is configured as a client, it searches the +authentication mechanisms announced by the server for one whose name +matches the public name of the authenticator. + +- When it finds one that matches, it runs the authenticator's client code. +The variables $host$ and $host_address$ are available for any string +expansions that the client might do. They are set to the server's name and +IP address. If any expansion is forced to fail, the authentication attempt +is abandoned, +and Exim moves on to the next authenticator. +Otherwise an expansion failure causes delivery to be +deferred. + +- If the result of the authentication attempt is a temporary error or a timeout, +Exim abandons trying to send the message to the host for the moment. It will +try again later. If there are any backup hosts available, they are tried in the +usual way. + +- If the response to authentication is a permanent error (5xx code), Exim carries +on searching the list of authenticators and tries another one if possible. If +all authentication attempts give permanent errors, or if there are no attempts +because no mechanisms match +(or option expansions force failure), +what happens depends on whether the host matches %hosts_require_auth% or +%hosts_try_auth%. In the first case, a temporary error is generated, and +delivery is deferred. The error can be detected in the retry rules, and thereby +turned into a permanent error if you wish. In the second case, Exim tries to +deliver the message unauthenticated. + +cindex:[AUTH,on MAIL command] +When Exim has authenticated itself to a remote server, it adds the AUTH +parameter to the MAIL commands it sends, if it has an authenticated sender +for the message. +If the message came from a remote host, the authenticated sender is the one +that was receiving on an incoming MAIL command, provided that the incoming +connection was authenticated and the %server_mail_auth% condition allowed the +authenticated sender to be retained. If a local process calls Exim to send a +message, the sender address that is built from the login name and +%qualify_domain% is treated as authenticated. However, if the +%authenticated_sender% option is set on the ^smtp^ transport, it overrides +the authenticated sender that was received with the message. + + + + + + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// + +[[CHAPplaintext]] +The plaintext authenticator +--------------------------- +cindex:[^plaintext^ authenticator] +cindex:[authenticators,^plaintext^] +The ^plaintext^ authenticator can be configured to support the PLAIN and +LOGIN authentication mechanisms, both of which transfer authentication data as +plain (unencrypted) text (though base64 encoded). The use of plain text is a +security risk. If you use one of these mechanisms without also making use of +SMTP encryption (see chapter <<CHAPTLS>>) you should not use the same passwords +for SMTP connections as you do for login accounts. + + +Using plaintext in a server +~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[options,^plaintext^ authenticator (server)] +When running as a server, ^plaintext^ performs the authentication test by +expanding a string. It has the following options: + +oindex:[%server_prompts%] +`..'= +%server_prompts%, Use: 'plaintext', Type: 'string'!!, Default: 'unset' +=== + +The contents of this option, after expansion, must be a colon-separated list of +prompt strings. If expansion fails, a temporary authentication rejection is +given. + +oindex:[%server_condition%] +`..'= +%server_condition%, Use: 'plaintext', Type: 'string'!!, Default: 'unset' +=== + +This option must be set in order to configure the driver as a server. Its use +is described below. + +cindex:[AUTH,in ^plaintext^ authenticator] +cindex:[binary zero,in ^plaintext^ authenticator] +cindex:[numerical variables ($1$ $2$ etc),in ^plaintext^ authenticator] +cindex:[base64 encoding,in ^plaintext^ authenticator] +The data sent by the client with the AUTH command, or in response to +subsequent prompts, is base64 encoded, and so may contain any byte values +when decoded. If any data is supplied with the command, it is treated as a +list of strings, separated by NULs (binary zeros), which are placed in the +expansion variables $1$, $2$, etc. If there are more strings in +%server_prompts% than the number of strings supplied with the AUTH +command, the remaining prompts are used to obtain more data. Each response from +the client may be a list of NUL-separated strings. + +Once a sufficient number of data strings have been received, +%server_condition% is expanded. +If the expansion is forced to fail, authentication fails. Any other expansion +failure causes a temporary error code to be returned. +If the result of a successful expansion is an empty string, ``0'', ``no'', or +``false'', authentication fails. If the result of the expansion is ``1'', ``yes'', or +``true'', authentication succeeds and the generic %server_set_id% option is +expanded and saved in $authenticated_id$. For any other result, a temporary +error code is returned, with the expanded string as the error text. + +*Warning*: If you use a lookup in the expansion to find the user's +password, be sure to make the authentication fail if the user is unknown. +There are good and bad examples at the end of the next section. + + + +The PLAIN authentication mechanism +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[PLAIN authentication mechanism] +cindex:[authentication,PLAIN mechanism] +cindex:[binary zero,in ^plaintext^ authenticator] +The PLAIN authentication mechanism (RFC 2595) specifies that three strings be +sent as one item of data (that is, one combined string containing two NUL +separators). The data is sent either as part of the AUTH command, or +subsequently in response to an empty prompt from the server. + +The second and third strings are a user name and a corresponding password. +Using a single fixed user name and password as an example, this could be +configured as follows: + +.... +fixed_plain: + driver = plaintext + public_name = PLAIN + server_prompts = : + server_condition = \ + ${if and {{eq{$2}{username}}{eq{$3}{mysecret}}}{yes}{no}} + server_set_id = $2 +.... + +The %server_prompts% setting specifies a single, empty prompt (empty items at +the end of a string list are ignored). If all the data comes as part of the +AUTH command, as is commonly the case, the prompt is not used. This +authenticator is advertised in the response to EHLO as + + 250-AUTH PLAIN + +and a client host can authenticate itself by sending the command + + AUTH PLAIN AHVzZXJuYW1lAG15c2VjcmV0 + +As this contains three strings (more than the number of prompts), no further +data is required from the client. Alternatively, the client may just send + + AUTH PLAIN + +to initiate authentication, in which case the server replies with an empty +prompt. The client must respond with the combined data string. + +The data string is base64 encoded, as required by the RFC. This example, +when decoded, is <'NUL'>`username`<'NUL'>`mysecret`, where <'NUL'> represents a +zero byte. This is split up into three strings, the first of which is empty. +The %server_condition% option in the authenticator checks that the second two +are `username` and `mysecret` respectively. + +Having just one fixed user name and password, as in this example, is not very +realistic, though for a small organization with only a handful of +authenticating clients it could make sense. + +A more sophisticated instance of this authenticator could use the user name in +$2$ to look up a password in a file or database, and maybe do an encrypted +comparison (see %crypteq% in chapter <<CHAPexpand>>). Here is a example of this +approach, where the passwords are looked up in a DBM file. *Warning*: This +is an incorrect example: + +.... +server_condition = \ + ${if eq{$3}{${lookup{$2}dbm{/etc/authpwd}}}{yes}{no}} +.... + +The expansion uses the user name ($2$) as the key to look up a password, +which it then compares to the supplied password ($3$). Why is this example +incorrect? It works fine for existing users, but consider what happens if a +non-existent user name is given. The lookup fails, but as no success/failure +strings are given for the lookup, it yields an empty string. Thus, to defeat +the authentication, all a client has to do is to supply a non-existent user +name and an empty password. The correct way of writing this test is: + +.... +server_condition = ${lookup{$2}dbm{/etc/authpwd}\ + {${if eq{$value}{$3}{yes}{no}}}{no}} +.... + +In this case, if the lookup succeeds, the result is checked; if the lookup +fails, authentication fails. If %crypteq% is being used instead of %eq%, the +first example is in fact safe, because %crypteq% always fails if its second +argument is empty. However, the second way of writing the test makes the logic +clearer. + + + +The LOGIN authentication mechanism +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[LOGIN authentication mechanism] +cindex:[authentication,LOGIN mechanism] +The LOGIN authentication mechanism is not documented in any RFC, but is in use +in a number of programs. No data is sent with the AUTH command. Instead, a +user name and password are supplied separately, in response to prompts. The +plaintext authenticator can be configured to support this as in this example: + +.... +fixed_login: + driver = plaintext + public_name = LOGIN + server_prompts = User Name : Password + server_condition = \ + ${if and {{eq{$1}{username}}{eq{$2}{mysecret}}}{yes}{no}} + server_set_id = $1 +.... + +Because of the way plaintext operates, this authenticator accepts data supplied +with the AUTH command (in contravention of the specification of LOGIN), but +if the client does not supply it (as is the case for LOGIN clients), the prompt +strings are used to obtain two data items. + +Some clients are very particular about the precise text of the prompts. For +example, Outlook Express is reported to recognize only ``Username:'' and +``Password:''. Here is an example of a LOGIN authenticator which uses those +strings, and which uses the %ldapauth% expansion condition to check the user +name and password by binding to an LDAP server: + +.... +login: + driver = plaintext + public_name = LOGIN + server_prompts = Username:: : Password:: + server_condition = ${if ldapauth \ + {user="cn=${quote_ldap_dn:$1},ou=people,o=example.org" \ + pass=${quote:$2} \ + ldap://ldap.example.org/}{yes}{no}} + server_set_id = uid=$1,ou=people,o=example.org +.... + +Note the use of the %quote_ldap_dn% operator to correctly quote the DN for +authentication. However, the basic %quote% operator, rather than any of the +LDAP quoting operators, is the correct one to use for the password, because +quoting is needed only to make the password conform to the Exim syntax. At the +LDAP level, the password is an uninterpreted string. + + + +Support for different kinds of authentication +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +A number of string expansion features are provided for the purpose of +interfacing to different ways of user authentication. These include checking +traditionally encrypted passwords from _/etc/passwd_ (or equivalent), PAM, +Radius, %ldapauth%, and 'pwcheck'. For details see section <<SECTexpcond>>. + + + + +Using plaintext in a client +~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[options,^plaintext^ authenticator (client)] +The ^plaintext^ authenticator has just one client option: + + + +oindex:[%client_send%] +`..'= +%client_send%, Use: 'plaintext', Type: 'string'!!, Default: 'unset' +=== + +The string is a colon-separated list of authentication data strings. Each +string is independently expanded before being sent to the server. The first +string is sent with the AUTH command; any more strings are sent in response +to prompts from the server. + +*Note*: you cannot use expansion to create multiple strings, because +splitting takes priority and happens first. + +Because the PLAIN authentication mechanism requires NUL (binary zero) bytes in +the data, further processing is applied to each string before it is sent. If +there are any single circumflex characters in the string, they are converted to +NULs. Should an actual circumflex be required as data, it must be doubled in +the string. + +This is an example of a client configuration that implements the PLAIN +authentication mechanism with a fixed user name and password: + + fixed_plain: + driver = plaintext + public_name = PLAIN + client_send = ^username^mysecret + +The lack of colons means that the entire text is sent with the AUTH +command, with the circumflex characters converted to NULs. A similar example +that uses the LOGIN mechanism is: + + fixed_login: + driver = plaintext + public_name = LOGIN + client_send = : username : mysecret + +The initial colon means that the first string is empty, so no data is sent with +the AUTH command itself. The remaining strings are sent in response to +prompts. + + + + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// + +The cram_md5 authenticator +-------------------------- +cindex:[^cram_md5^ authenticator] +cindex:[authenticators,^cram_md5^] +cindex:[CRAM-MD5 authentication mechanism] +cindex:[authentication,CRAM-MD5 mechanism] +The CRAM-MD5 authentication mechanism is described in RFC 2195. The server +sends a challenge string to the client, and the response consists of a user +name and the CRAM-MD5 digest of the challenge string combined with a secret +string (password) which is known to both server and client. Thus, the secret +is not sent over the network as plain text, which makes this authenticator more +secure than ^plaintext^. However, the downside is that the secret has to be +available in plain text at either end. + + +Using cram_md5 as a server +~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[options,^cram_md5^ authenticator (server)] +This authenticator has one server option, which must be set to configure the +authenticator as a server: + +oindex:[%server_secret%] +`..'= +%server_secret%, Use: 'cram_md5', Type: 'string'!!, Default: 'unset' +=== + +cindex:[numerical variables ($1$ $2$ etc),in ^cram_md5^ authenticator] +When the server receives the client's response, the user name is placed in +the expansion variable $1$, and %server_secret% is expanded to obtain the +password for that user. The server then computes the CRAM-MD5 digest that the +client should have sent, and checks that it received the correct string. If the +expansion of %server_secret% is forced to fail, authentication fails. If the +expansion fails for some other reason, a temporary error code is returned to +the client. + +For example, the following authenticator checks that the user name given by the +client is ``ph10'', and if so, uses ``secret'' as the password. For any other user +name, authentication fails. + + fixed_cram: + driver = cram_md5 + public_name = CRAM-MD5 + server_secret = ${if eq{$1}{ph10}{secret}fail} + server_set_id = $1 + +If authentication succeeds, the setting of %server_set_id% preserves the user +name in $authenticated_id$. +A more tyical configuration might look up the secret string in a file, using +the user name as the key. For example: + + lookup_cram: + driver = cram_md5 + public_name = CRAM-MD5 + server_secret = ${lookup{$1}lsearch{/etc/authpwd}{$value}fail} + server_set_id = $1 + +Note that this expansion explicitly forces failure if the lookup fails +because $1$ contains an unknown user name. + + +Using cram_md5 as a client +~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[options,^cram_md5^ authenticator (client)] +When used as a client, the ^cram_md5^ authenticator has two options: + + + +oindex:[%client_name%] +`..'= +%client_name%, Use: 'cram_md5', Type: 'string'!!, Default: 'the primary host name' +=== + +This string is expanded, and the result used as the user name data when +computing the response to the server's challenge. + + +oindex:[%client_secret%] +`..'= +%client_secret%, Use: 'cram_md5', Type: 'string'!!, Default: 'unset' +=== + +This option must be set for the authenticator to work as a client. Its value is +expanded and the result used as the secret string when computing the response. + + +Different user names and secrets can be used for different servers by referring +to $host$ or $host_address$ in the options. + +Forced failure of either expansion string is treated as an indication that this +authenticator is not prepared to handle this case. Exim moves on to the next +configured client authenticator. Any other expansion failure causes Exim to +give up trying to send the message to the current server. + +A simple example configuration of a ^cram_md5^ authenticator, using fixed +strings, is: + + fixed_cram: + driver = cram_md5 + public_name = CRAM-MD5 + client_name = ph10 + client_secret = secret + + + + + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// + +The cyrus_sasl authenticator +---------------------------- +cindex:[^cyrus_sasl^ authenticator] +cindex:[authenticators,^cyrus_sasl^] +cindex:[Cyrus, SASL library] +The code for this authenticator was provided by Matthew Byng-Maddick of A L +Digital Ltd (*http://www.aldigital.co.uk[]*). + +The ^cyrus_sasl^ authenticator provides server support for the Cyrus SASL +library implementation of the RFC 2222 (``Simple Authentication and Security +Layer''). This library supports a number of authentication mechanisms, including +PLAIN and LOGIN, but also several others that Exim does not support directly. +In particular, there is support for Kerberos authentication. + +The ^cyrus_sasl^ authenticator provides a gatewaying mechanism directly to +the Cyrus interface, so if your Cyrus library can do, for example, CRAM-MD5, +then so can the ^cyrus_sasl^ authenticator. By default it uses the public +name of the driver to determine which mechanism to support. + +Where access to some kind of secret file is required, for example in GSSAPI +or CRAM-MD5, it is worth noting that the authenticator runs as the 'exim' +user, and that the Cyrus SASL library has no way of escalating privileges +by default. You may also find you need to set environment variables, +depending on the driver you are using. + + +Using cyrus_sasl as a server +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +The ^cyrus_sasl^ authenticator has four private options. It puts the +username (on a successful authentication) into $1$. + +oindex:[%server_hostname%] +`..'= +%server_hostname%, Use: 'cyrus_sasl', Type: 'string'!!, Default: `$primary_hostname` +=== + +This option selects the hostname that is used when communicating with +the library. It is up to the underlying SASL plug-in what it does with +this data. + + +oindex:[%server_mech%] +`..'= +%server_mech%, Use: 'cyrus_sasl', Type: 'string', Default: `public_name` +=== + +This option selects the authentication mechanism this driver should +use. It allows you to use a different underlying mechanism from the +advertised name. For example: + + sasl: + driver = cyrus_sasl + public_name = X-ANYTHING + server_mech = CRAM-MD5 + server_set_id = $1 + + + +oindex:[%server_realm%] +`..'= +%server_realm%, Use: 'cyrus_sasl', Type: 'string', Default: 'unset' +=== + +This specifies the SASL realm that the server claims to be in. + + +oindex:[%server_service%] +`..'= +%server_service%, Use: 'cyrus_sasl', Type: 'string', Default: `smtp` +=== + +This is the SASL service that the server claims to implement. + + +For straightforward cases, you do not need to set any of the authenticator's +private options. All you need to do is to specify an appropriate mechanism as +the public name. Thus, if you have a SASL library that supports CRAM-MD5 and +PLAIN, you could have two authenticators as follows: + + sasl_cram_md5: + driver = cyrus_sasl + public_name = CRAM-MD5 + server_set_id = $1 + + sasl_plain: + driver = cyrus_sasl + public_name = PLAIN + server_set_id = $1 + + +Cyrus SASL does implement the LOGIN authentication method, even though it is +not a standard method. It is disabled by default in the source distribution, +but it is present in many binary distributions. + + + + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// + +The spa authenticator +--------------------- +cindex:[^spa^ authenticator] +cindex:[authenticators,^spa^] +cindex:[authentication,Microsoft Secure Password] +cindex:[authentication,NTLM] +cindex:[Microsoft Secure Password Authentication] +cindex:[NTLM authentication] +The ^spa^ authenticator provides client support for Microsoft's 'Secure +Password Authentication' mechanism, +which is also sometimes known as NTLM (NT LanMan). The code for client side of +this authenticator was contributed by Marc Prud'hommeaux, and much of it is +taken from the Samba project (*http://www.samba.org[]*). The code for the +server side was subsequently contributed by Tom Kistner. The mechanism works as +follows: + +- After the AUTH command has been accepted, the client sends an SPA +authentication request based on the user name and optional domain. + +- The server sends back a challenge. + +- The client builds a challenge response which makes use of the user's password +and sends it to the server, which then accepts or rejects it. + +Encryption is used to protect the password in transit. + + + +Using spa as a server +~~~~~~~~~~~~~~~~~~~~~ +cindex:[options,^spa^ authenticator (server)] +The ^spa^ authenticator has just one server option: + +oindex:[%server_password%] +`..'= +%server_password%, Use: 'spa', Type: 'string'!!, Default: 'unset' +=== + +cindex:[numerical variables ($1$ $2$ etc),in ^spa^ authenticator] +This option is expanded, and the result must be the cleartext password for the +authenticating user, whose name is at this point in $1$. For example: + + spa: + driver = spa + public_name = NTLM + server_password = ${lookup{$1}lsearch{/etc/exim/spa_clearpass}} + +If the expansion is forced to fail, authentication fails. Any other expansion +failure causes a temporary error code to be returned. + + + + + +Using spa as a client +~~~~~~~~~~~~~~~~~~~~~ +cindex:[options,^spa^ authenticator (client)] +The ^spa^ authenticator has the following client options: + + + +oindex:[%client_domain%] +`..'= +%client_domain%, Use: 'spa', Type: 'string'!!, Default: 'unset' +=== + +This option specifies an optional domain for the authentication. + + +oindex:[%client_password%] +`..'= +%client_password%, Use: 'spa', Type: 'string'!!, Default: 'unset' +=== + +This option specifies the user's password, and must be set. + + +oindex:[%client_username%] +`..'= +%client_username%, Use: 'spa', Type: 'string'!!, Default: 'unset' +=== + +This option specifies the user name, and must be set. + + +Here is an example of a configuration of this authenticator for use with the +mail servers at 'msn.com': + + msn: + driver = spa + public_name = MSN + client_username = msn/msn_username + client_password = msn_plaintext_password + client_domain = DOMAIN_OR_UNSET + + + + + + + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// + +[[CHAPTLS]] +[titleabbrev="Encrypted SMTP connections"] +Encrypted SMTP connections using TLS/SSL +---------------------------------------- +cindex:[encryption,on SMTP connection] +cindex:[SMTP,encryption] +cindex:[TLS,on SMTP connection] +cindex:[OpenSSL] +cindex:[GnuTLS] +Support for TLS (Transport Layer Security), formerly known as SSL (Secure +Sockets Layer), is implemented by making use of the OpenSSL library or the +GnuTLS library (Exim requires GnuTLS release 1.0 or later). There is no +cryptographic code in the Exim distribution itself for implementing TLS. In +order to use this feature you must install OpenSSL or GnuTLS, and then build a +version of Exim that includes TLS support (see section <<SECTinctlsssl>>). You +also need to understand the basic concepts of encryption at a managerial level, +and in particular, the way that public keys, private keys, and certificates are +used. + +RFC 2487 defines how SMTP connections can make use of encryption. Once a +connection is established, the client issues a STARTTLS command. If the +server accepts this, the client and the server negotiate an encryption +mechanism. If the negotiation succeeds, the data that subsequently passes +between them is encrypted. + +Exim's ACLs can detect whether the current SMTP session is encrypted or not, +and if so, what cipher suite is in use, whether the client supplied a +certificate, and whether or not that certificate was verified. This makes it +possible for an Exim server to deny or accept certain commands based on the +encryption state. + +*Warning*: certain types of firewall and certain anti-virus products can +disrupt TLS connections. You need to turn off SMTP scanning for these products +in order to get TLS to work. + + + +Support for the legacy ``ssmtp'' (aka ``smtps'') protocol +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[ssmtp protocol] +cindex:[smtps protocol] +cindex:[SMTP,ssmtp protocol] +cindex:[SMTP,smtps protocol] +Early implementations of encrypted SMTP used a different TCP port from normal +SMTP, and expected an encryption negotiation to start immediately, instead of +waiting for a STARTTLS command from the client using the standard SMTP +port. The protocol was called ``ssmtp'' or ``smtps'', and port 465 was allocated +for this purpose. + +This approach was abandoned when encrypted SMTP was standardised, but there are +still some legacy clients that use it. Exim supports these clients by means of +the %tls_on_connect_ports% global option. Its value must be a list of port +numbers; the most common use is expected to be: + + tls_on_connect_ports = 465 + +The port numbers specified by this option apply to all SMTP connections, both +via the daemon and via 'inetd'. You still need to specify all the ports that +the daemon uses (by setting %daemon_smtp_ports% or %local_interfaces% or the +%-oX% command line option) because %tls_on_connect_ports% does not add an +extra port -- rather, it specifies different behaviour on a port that is +defined elsewhere. + +There is also a %-tls-on-connect% command line option. This overrides +%tls_on_connect_ports%; it forces the legacy behaviour for all ports. + + + + + + +[[SECTopenvsgnu]] +OpenSSL vs GnuTLS +~~~~~~~~~~~~~~~~~ +cindex:[TLS,OpenSSL 'vs' GnuTLS] +The first TLS support in Exim was implemented using OpenSSL. Support for GnuTLS +followed later, when the first versions of GnuTLS were released. To build Exim +to use GnuTLS, you need to set + + USE_GNUTLS=yes + +in Local/Makefile, in addition to + + SUPPORT_TLS=yes + +You must also set TLS_LIBS and TLS_INCLUDE appropriately, so that the +include files and libraries for GnuTLS can be found. + +There are some differences in usage when using GnuTLS instead of OpenSSL: + +- The %tls_verify_certificates% option must contain the name of a file, not the +name of a directory (for OpenSSL it can be either). + +- The %tls_dhparam% option is ignored, because early versions of GnuTLS had no +facility for varying its Diffie-Hellman parameters. I understand that this has +changed, but Exim has not been updated to provide this facility. + +- GnuTLS uses RSA and D-H parameters that take a substantial amount of +time to compute. It is unreasonable to re-compute them for every TLS +session. Therefore, Exim keeps this data in a file in its spool +directory, called _gnutls-params_. The file is owned by the Exim user and is +readable only by its owner. Every Exim process that start up GnuTLS reads the +RSA and D-H parameters from this file. If the file does not exist, the first +Exim process that needs it computes the data and writes it to a temporary file +which is renamed once it is complete. It does not matter if several Exim +processes do this simultaneously (apart from wasting a few resources). Once a +file is in place, new Exim processes immediately start using it. ++ +For maximum security, the parameters that are stored in this file should be +recalculated periodically, the frequency depending on your paranoia level. +Arranging this is easy; just delete the file when you want new values to be +computed. + +- Distinguished Name (DN) strings reported by the OpenSSL library use a slash for +separating fields; GnuTLS uses commas, in accordance with RFC 2253. This +affects the value of the $tls_peerdn$ variable. + +- OpenSSL identifies cipher suites using hyphens as separators, for example: +DES-CBC3-SHA. GnuTLS uses underscores, for example: RSA_ARCFOUR_SHA. What is +more, OpenSSL complains if underscores are present in a cipher list. To make +life simpler, Exim changes underscores to hyhens for OpenSSL and hyphens to +underscores for GnuTLS when processing lists of cipher suites in the +%tls_require_ciphers% options (the global option and the ^smtp^ transport +option). + +- The %tls_require_ciphers% options operate differently, as described in the +following sections. + + + +[[SECTreqciphssl]] +Requiring specific ciphers in OpenSSL +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[TLS,requiring specific ciphers (OpenSSL)] +cindex:[%tls_require_ciphers%,OpenSSL] +There is a function in the OpenSSL library that can be passed a list of cipher +suites before the cipher negotiation takes place. This specifies which ciphers +are acceptable. The list is colon separated and may contain names like +DES-CBC3-SHA. Exim passes the expanded value of %tls_require_ciphers% +directly to this function call. The following quotation from the OpenSSL +documentation specifies what forms of item are allowed in the cipher string: + +- It can consist of a single cipher suite such as RC4-SHA. + +- It can represent a list of cipher suites containing a certain algorithm, +or cipher suites of a certain type. For example SHA1 represents all +ciphers suites using the digest algorithm SHA1 and SSLv3 represents all +SSL v3 algorithms. + +- Lists of cipher suites can be combined in a single cipher string using +the + character. This is used as a logical and operation. For example +SHA1+DES represents all cipher suites containing the SHA1 and the DES +algorithms. + +- Each cipher string can be optionally preceded by the characters `!`, `-` or +`+`. ++ +If `!` is used then the ciphers are permanently deleted from the list. The +ciphers deleted can never reappear in the list even if they are explicitly +stated. ++ +If `-` is used then the ciphers are deleted from the list, but some or all +of the ciphers can be added again by later options. ++ +If `+` is used then the ciphers are moved to the end of the list. This +option doesn't add any new ciphers it just moves matching existing ones. ++ +If none of these characters is present then the string is just interpreted as +a list of ciphers to be appended to the current preference list. If the list +includes any ciphers already present they will be ignored: that is, they will +not moved to the end of the list. + + + + +[[SECTreqciphgnu]] +Requiring specific ciphers in GnuTLS +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[TLS,requiring specific ciphers (GnuTLS)] +cindex:[%tls_require_ciphers%,GnuTLS] +The GnuTLS library does not have a combined function like OpenSSL. Instead, +it allows the caller to specify separate lists of key-exchange methods, +main cipher algorithms, and MAC algorithms. Unfortunately, these lists are +numerical, and the library does not have a function for turning names into +numbers. Consequently, the list of recognized names has to be built into +the application. + +At present, Exim permits only the list of main cipher algorithms to be +changed. The %tls_require_ciphers% option is in the same format as for +OpenSSL. Exim searches each item for the name of available algorithm. For +example, if the list contains RSA_AES_SHA then AES is recognized. + +The cipher algorithms list starts out with a default set of algorithms. If +the first item in %tls_require_ciphers% does 'not' start with an +exclamation mark, all the default items are deleted. Thus, only those specified +can be used. If the first item in %tls_require_ciphers% 'does' start with +an exclamation mark, the defaults are left on the list. + +Then, any item that starts with an exclamation mark causes the relevent +algorithms to be removed from the list, and any item that does not start +with an exclamation mark causes the relevant algorithms to be added to the +list. Thus, + + tls_require_ciphers = !RSA_ARCFOUR_SHA + +allows all the defaults except those that use ARCFOUR, whereas + + tls_require_ciphers = AES : 3DES + +allows only cipher suites that use AES and 3DES. The currently recognized +algorithms are: AES_256, AES_128, AES (both of the preceding), 3DES, and +ARCFOUR_128. Unrecognized algorithms are ignored. In a server, the order of the +list is unimportant; the server will advertise the availability of all the +relevant cipher suites. However, in a client, the order of the list specifies a +preference order for the algorithms. The first one in the client's list that is +also advertised by the server is tried first. The default order is as listed +above. + + + + +Configuring an Exim server to use TLS +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[TLS,configuring an Exim server] +When Exim has been built with TLS support, it advertises the availability of +the STARTTLS command to client hosts that match %tls_advertise_hosts%, +but not to any others. The default value of this option is unset, which means +that STARTTLS is not advertised at all. This default is chosen because you +need to set some other options in order to make TLS avaliable, and also it is +sensible for systems that want to use TLS only as a client. + +If a client issues a STARTTLS command and there is some configuration +problem in the server, the command is rejected with a 454 error. If the client +persists in trying to issue SMTP commands, all except QUIT are rejected +with the error + + 554 Security failure + +If a STARTTLS command is issued within an existing TLS session, it is +rejected with a 554 error code. + +To enable TLS operations on a server, you must set %tls_advertise_hosts% to +match some hosts. You can, of course, set it to \* to match all hosts. +However, this is not all you need to do. TLS sessions to a server won't work +without some further configuration at the server end. + +It is rumoured that all existing clients that support TLS/SSL use RSA +encryption. To make this work you need to set, in the server, + + tls_certificate = /some/file/name + tls_privatekey = /some/file/name + +The first file contains the server's X509 certificate, and the second contains +the private key that goes with it. These files need to be readable by the Exim +user, and must always be given as full path names. They can be the same file if +both the certificate and the key are contained within it. If %tls_privatekey% +is not set, this is assumed to be the case. The certificate file may also +contain intermediate certificates that need to be sent to the client to enable +it to authenticate the server's certificate. + +If you do not understand about certificates and keys, please try to find a +source of this background information, which is not Exim-specific. (There are a +few comments below in section <<SECTcerandall>>.) + +*Note*: These options do not apply when Exim is operating as a client -- +they apply only in the case of a server. For a client, you must set the options +of the same name in an ^smtp^ transport. + +With just these options, Exim will work as a server with clients such as +Netscape. It does not require the client to have a certificate (but see below +for how to insist on this). There is one other option that may be needed in +other situations. If + + tls_dhparam = /some/file/name + +is set, the SSL library is initialized for the use of Diffie-Hellman ciphers +with the parameters contained in the file. This increases the set of cipher +suites that the server supports. See the command + + openssl dhparam + +for a way of generating this data. +At present, %tls_dhparam% is used only when Exim is linked with OpenSSL. It is +ignored if GnuTLS is being used. + +The strings supplied for these three options are expanded every time a client +host connects. It is therefore possible to use different certificates and keys +for different hosts, if you so wish, by making use of the client's IP address +in $sender_host_address$ to control the expansion. If a string expansion is +forced to fail, Exim behaves as if the option is not set. + +cindex:[cipher,logging] +cindex:[log,TLS cipher] +The variable $tls_cipher$ is set to the cipher suite that was negotiated for +an incoming TLS connection. It is included in the 'Received:' header of an +incoming message (by default -- you can, of course, change this), and it is +also included in the log line that records a message's arrival, keyed by ``X='', +unless the %tls_cipher% log selector is turned off. +The %encrypted% condition can be used to test for specific cipher suites in +ACLs. + +The ACLs that run for subsequent SMTP commands can check the name of the cipher +suite and vary their actions accordingly. The cipher suite names are those used +by OpenSSL. These may differ from the names used elsewhere. For example, +OpenSSL uses the name DES-CBC3-SHA for the cipher suite which in other contexts +is known as TLS_RSA_WITH_3DES_EDE_CBC_SHA. Check the OpenSSL +documentation for more details. + + + +Requesting and verifying client certificates +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[certificate,verification of client] +cindex:[TLS,client certificate verification] +If you want an Exim server to request a certificate when negotiating a TLS +session with a client, you must set either %tls_verify_hosts% or +%tls_try_verify_hosts%. You can, of course, set either of them to \* to +apply to all TLS connections. For any host that matches one of these options, +Exim requests a certificate as part of the setup of the TLS session. The +contents of the certificate are verified by comparing it with a list of +expected certificates. These must be available in a file or, +for OpenSSL only (not GnuTLS), a directory, identified by +%tls_verify_certificates%. + +A file can contain multiple certificates, concatenated end to end. If a +directory is used +(OpenSSL only), +each certificate must be in a separate file, with a name (or a symbolic link) +of the form <'hash'>.0, where <'hash'> is a hash value constructed from the +certificate. You can compute the relevant hash by running the command + + openssl x509 -hash -noout -in /cert/file + +where _/cert/file_ contains a single certificate. + +The difference between %tls_verify_hosts% and %tls_try_verify_hosts% is +what happens if the client does not supply a certificate, or if the certificate +does not match any of the certificates in the collection named by +%tls_verify_certificates%. If the client matches %tls_verify_hosts%, the +attempt to set up a TLS session is aborted, and the incoming connection is +dropped. If the client matches %tls_try_verify_hosts%, the (encrypted) SMTP +session continues. ACLs that run for subsequent SMTP commands can detect the +fact that no certificate was verified, and vary their actions accordingly. For +example, you can insist on a certificate before accepting a message for +relaying, but not when the message is destined for local delivery. + +When a client supplies a certificate (whether it verifies or not), the value of +the Distinguished Name of the certificate is made available in the variable +$tls_peerdn$ during subsequent processing of the message. + +cindex:[log,distinguished name] +Because it is often a long text string, it is not included in the log line or +'Received:' header by default. You can arrange for it to be logged, keyed by +``DN='', by setting the %tls_peerdn% log selector, and you can use +%received_header_text% to change the 'Received:' header. When no certificate +is supplied, $tls_peerdn$ is empty. + + +Revoked certificates +~~~~~~~~~~~~~~~~~~~~ +cindex:[TLS,revoked certificates] +cindex:[revocation list] +cindex:[certificate,revocation list] +Certificate issuing authorities issue Certificate Revocation Lists (CRLs) when +certificates are revoked. If you have such a list, you can pass it to an Exim +server using the global option called %tls_crl% and to an Exim client using an +identically named option for the ^smtp^ transport. In each case, the value of +the option is expanded and must then be the name of a file that contains a CRL +in PEM format. + + +Configuring an Exim client to use TLS +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[cipher,logging] +cindex:[log,TLS cipher] +cindex:[log,distinguished name] +cindex:[TLS,configuring an Exim client] +The %tls_cipher% and %tls_peerdn% log selectors apply to outgoing SMTP +deliveries as well as to incoming, the latter one causing logging of the +server certificate's DN. The remaining client configuration for TLS is all +within the ^smtp^ transport. + +It is not necessary to set any options to have TLS work in the ^smtp^ +transport. If Exim is built with TLS support, and TLS is advertised by a +server, the ^smtp^ transport always tries to start a TLS session. However, +this can be prevented by setting %hosts_avoid_tls% (an option of the +transport) to a list of server hosts for which TLS should not be used. + +If you do not want Exim to attempt to send messages unencrypted when an attempt +to set up an encrypted connection fails in any way, you can set +%hosts_require_tls% to a list of hosts for which encryption is mandatory. For +those hosts, delivery is always deferred if an encrypted connection cannot be +set up. If there are any other hosts for the address, they are tried in the +usual way. + +When the server host is not in %hosts_require_tls%, Exim may try to deliver +the message unencrypted. It always does this if the response to STARTTLS is +a 5##'xx' code. For a temporary error code, or for a failure to negotiate a TLS +session after a success response code, what happens is controlled by the +%tls_tempfail_tryclear% option of the ^smtp^ transport. If it is false, +delivery to this host is deferred, and other hosts (if available) are tried. If +it is true, Exim attempts to deliver unencrypted after a 4##'xx' response to +STARTTLS, and if STARTTLS is accepted, but the subsequent TLS +negotiation fails, Exim closes the current connection (because it is in an +unknown state), opens a new one to the same host, and then tries the delivery +unencrypted. + + +The %tls_certificate% and %tls_privatekey% options of the ^smtp^ transport +provide the client with a certificate, which is passed to the server if it +requests it. If the server is Exim, it will request a certificate only if +%tls_verify_hosts% or %tls_try_verify_hosts% matches the client. +*Note*: these options must be set in the ^smtp^ transport for Exim to use +TLS when it is operating as a client. Exim does not assume that a server +certificate (set by the global options of the same name) should also be used +when operating as a client. + +If %tls_verify_certificates% is set, it must name a file or, +for OpenSSL only (not GnuTLS), a directory, that contains a collection of +expected server certificates. The client verifies the server's certificate +against this collection, taking into account any revoked certificates that are +in the list defined by %tls_crl%. + +If +%tls_require_ciphers% is set on the ^smtp^ transport, it must contain a +list of permitted cipher suites. If either of these checks fails, delivery to +the current host is abandoned, and the ^smtp^ transport tries to deliver to +alternative hosts, if any. + +All the TLS options in the ^smtp^ transport are expanded before use, with +$host$ and $host_address$ containing the name and address of the server to +which the client is connected. Forced failure of an expansion causes Exim to +behave as if the relevant option were unset. + + + +[[SECTmulmessam]] +Multiple messages on the same encrypted TCP/IP connection +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[multiple SMTP deliveries with TLS] +cindex:[TLS,multiple message deliveries] +Exim sends multiple messages down the same TCP/IP connection by starting up +an entirely new delivery process for each message, passing the socket from +one process to the next. This implementation does not fit well with the use +of TLS, because there is quite a lot of state information associated with a TLS +connection, not just a socket identification. Passing all the state information +to a new process is not feasible. Consequently, Exim shuts down an existing TLS +session before passing the socket to a new process. The new process may then +try to start a new TLS session, and if successful, may try to re-authenticate +if AUTH is in use, before sending the next message. + +The RFC is not clear as to whether or not an SMTP session continues in clear +after TLS has been shut down, or whether TLS may be restarted again later, as +just described. However, if the server is Exim, this shutdown and +reinitialization works. It is not known which (if any) other servers operate +successfully if the client closes a TLS session and continues with unencrypted +SMTP, but there are certainly some that do not work. For such servers, Exim +should not pass the socket to another process, because the failure of the +subsequent attempt to use it would cause Exim to record a temporary host error, +and delay other deliveries to that host. + +To test for this case, Exim sends an EHLO command to the server after +closing down the TLS session. If this fails in any way, the connection is +closed instead of being passed to a new delivery process, but no retry +information is recorded. + +There is also a manual override; you can set %hosts_nopass_tls% on the +^smtp^ transport to match those hosts for which Exim should not pass +connections to new processes if TLS has been used. + + + + +[[SECTcerandall]] +Certificates and all that +~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[certificate,references to discussion] +In order to understand fully how TLS works, you need to know about +certificates, certificate signing, and certificate authorities. This is not the +place to give a tutorial, especially as I do not know very much about it +myself. Some helpful introduction can be found in the FAQ for the SSL addition +to Apache, currently at + +&&& +*http://www.modssl.org/docs/2.7/ssl_faq.html#ToC24[]* +&&& + +Other parts of the 'modssl' documentation are also helpful, and have +links to further files. +Eric Rescorla's book, 'SSL and TLS', published by Addison-Wesley (ISBN +0-201-61598-3), contains both introductory and more in-depth descriptions. +Some sample programs taken from the book are available from + +&&& +*http://www.rtfm.com/openssl-examples/[]* +&&& + + + +Certificate chains +~~~~~~~~~~~~~~~~~~ +The file named by %tls_certificate% may contain more than one +certificate. This is useful in the case where the certificate that is being +sent is validated by an intermediate certificate which the other end does +not have. Multiple certificates must be in the correct order in the file. +First the host's certificate itself, then the first intermediate +certificate to validate the issuer of the host certificate, then the next +intermediate certificate to validate the issuer of the first intermediate +certificate, and so on, until finally (optionally) the root certificate. +The root certificate must already be trusted by the recipient for +validation to succeed, of course, but if it's not preinstalled, sending the +root certificate along with the rest makes it available for the user to +install if the receiving end is a client MUA that can interact with a user. + + +Self-signed certificates +~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[certificate,self-signed] +You can create a self-signed certificate using the 'req' command provided +with OpenSSL, like this: + +.... +openssl req -x509 -newkey rsa:1024 -keyout file1 -out file2 \ + -days 9999 -nodes +.... + +_file1_ and _file2_ can be the same file; the key and the certificate are +delimited and so can be identified independently. The %-days% option +specifies a period for which the certificate is valid. The %-nodes% option is +important: if you do not set it, the key is encrypted with a passphrase +that you are prompted for, and any use that is made of the key causes more +prompting for the passphrase. This is not helpful if you are going to use +this certificate and key in an MTA, where prompting is not possible. + +A self-signed certificate made in this way is sufficient for testing, and +may be adequate for all your requirements if you are mainly interested in +encrypting transfers, and not in secure identification. + +However, many clients require that the certificate presented by the server be a +user (also called ``leaf'' or ``site'') certificate, and not a self-signed +certificate. In this situation, the self-signed certificate described above +must be installed on the client host as a trusted root 'certification +authority' (CA), and the certificate used by Exim must be a user certificate +signed with that self-signed certificate. + +For information on creating self-signed CA certificates and using them to sign +user certificates, see the 'General implementation overview' chapter of the +Open-source PKI book, available online at *http://ospkibook.sourceforge.net/[]*. + + + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// + +[[CHAPACL]] +Access control lists +-------------------- +cindex:[{ACL},description] +cindex:[control of incoming mail] +cindex:[message,controlling incoming] +cindex:[policy control,access control lists] +Access Control Lists (ACLs) are defined in a separate section of the run time +configuration file, headed by ``begin acl''. Each ACL definition starts with a +name, terminated by a colon. Here is a complete ACL section that contains just +one very small ACL: + + begin acl + + small_acl: + accept hosts = one.host.only + +You can have as many lists as you like in the ACL section, and the order in +which they appear does not matter. The lists are self-terminating. + +The majority of ACLs are used to control Exim's behaviour when it receives +certain SMTP commands. This applies both to incoming TCP/IP connections, and +when a local process submits a message using SMTP by specifying the %-bs% +option. The most common use is for controlling which recipients are accepted +in incoming messages. In addition, you can define an ACL that is used to check +local non-SMTP messages. The default configuration file contains an example of +a realistic ACL for checking RCPT commands. This is discussed in chapter +<<CHAPdefconfil>>. + + +Testing ACLs +~~~~~~~~~~~~ +The %-bh% command line option provides a way of testing your ACL configuration +locally by running a fake SMTP session with which you interact. The host +'relay-test.mail-abuse.org' provides a service for checking your relaying +configuration (see section <<SECTcheralcon>> for more details). + + + +Specifying when ACLs are used +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[{ACL},options for specifying] +In order to cause an ACL to be used, you have to name it in one of the relevant +options in the main part of the configuration. These options are: +cindex:[AUTH,ACL for] +cindex:[DATA, ACLs for] +cindex:[ETRN,ACL for] +cindex:[EXPN,ACL for] +cindex:[HELO,ACL for] +cindex:[EHLO,ACL for] +cindex:[MAIL,ACL for] +cindex:[QUIT, ACL for] +cindex:[RCPT,ACL for] +cindex:[STARTTLS, ACL for] +cindex:[VRFY,ACL for] +cindex:[SMTP connection, ACL for] +cindex:[non-smtp message, ACL for] + +[frame="none"] +`--`--------------------`--------------------------------------- + %acl_not_smtp% ACL for non-SMTP messages + %acl_smtp_auth% ACL for AUTH + %acl_smtp_connect% ACL for start of SMTP connection + %acl_smtp_data% ACL after DATA is complete + %acl_smtp_etrn% ACL for ETRN + %acl_smtp_expn% ACL for EXPN + %acl_smtp_helo% ACL for HELO or EHLO + %acl_smtp_mail% ACL for MAIL + %acl_smtp_mailauth% ACL for the AUTH parameter of MAIL + %acl_smtp_mime% ACL for content-scanning MIME parts + %acl_smtp_predata% ACL at start of DATA command + %acl_smtp_quit% ACL for QUIT + %acl_smtp_rcpt% ACL for RCPT + %acl_smtp_starttls% ACL for STARTTLS + %acl_smtp_vrfy% ACL for VRFY +---------------------------------------------------------------- + +For example, if you set + + acl_smtp_rcpt = small_acl + +the little ACL defined above is used whenever Exim receives a RCPT command +in an SMTP dialogue. The majority of policy tests on incoming messages can be +done when RCPT commands arrive. A rejection of RCPT should cause the +sending MTA to give up on the recipient address contained in the RCPT +command, whereas rejection at other times may cause the client MTA to keep on +trying to deliver the message. It is therefore recommended that you do as much +testing as possible at RCPT time. + + +The non-SMTP ACL +~~~~~~~~~~~~~~~~ +cindex:[non-smtp message, ACL for] +The non-SMTP ACL applies to all non-interactive incoming messages, that is, it +applies to batch SMTP as well as to non-SMTP messages. (Batch SMTP is not +really SMTP.) This ACL is run just before the 'local_scan()' function. Any +kind of rejection is treated as permanent, because there is no way of sending a +temporary error for these kinds of message. Many of the ACL conditions (for +example, host tests, and tests on the state of the SMTP connection such as +encryption and authentication) are not relevant and are forbidden in this ACL. + + +The connect ACL +~~~~~~~~~~~~~~~ +cindex:[SMTP connection, ACL for] +The ACL test specified by %acl_smtp_connect% happens after the test specified +by %host_reject_connection% (which is now an anomaly) and any TCP Wrappers +testing (if configured). + + +The DATA ACLs +~~~~~~~~~~~~~ +cindex:[DATA, ACLs for] +Two ACLs are associated with the DATA command, because it is two-stage +command, with two responses being sent to the client. +When the DATA command is received, the ACL defined by %acl_smtp_predata% +is obeyed. This gives you control after all the RCPT commands, but before +the message itself is received. It offers the opportunity to give a negative +response to the DATA command before the data is transmitted. Header lines +added by MAIL or RCPT ACLs are not visible at this time, but any that +are defined here are visible when the %acl_smtp_data% ACL is run. + +You cannot test the contents of the message, for example, to verify addresses +in the headers, at RCPT time or when the DATA command is received. Such +tests have to appear in the ACL that is run after the message itself has been +received, before the final response to the DATA command is sent. This is +the ACL specified by %acl_smtp_data%, which is the second ACL that is +associated with the DATA command. + +For both of these ACLs, it is not possible to reject individual recipients. An +error response rejects the entire message. Unfortunately, it is known that some +MTAs do not treat hard (5##'xx') responses to the DATA command (either +before or after the data) correctly -- they keep the message on their queues +and try again later, but that is their problem, though it does waste some of +your resources. + + +The MIME ACL +~~~~~~~~~~~~ +The %acl_smtp_mime% option is available only when Exim is compiled with the +content-scanning extension. For details, see chapter <<CHAPexiscan>>. + + +[[SECTQUITACL]] +The QUIT ACL +~~~~~~~~~~~~ +cindex:[QUIT, ACL for] +The ACL for the SMTP QUIT command is anomalous, in that the +outcome of the ACL does not affect the response code to QUIT, +which is always 221. Thus, the ACL does not in fact control any access. +For this reason, the only verbs that are permitted are %accept% and %warn%. + +This ACL can be used for tasks such as custom logging at the end of an SMTP +session. For example, you can use ACL variables in other ACLs to count +messages, recipients, etc., and log the totals at QUIT time using one or +more %logwrite% modifiers on a %warn% verb. + +You do not need to have a final %accept%, but if you do, you can use a +%message% modifier to specify custom text that is sent as part of the 221 +response to QUIT. + +This ACL is run only for a ``normal'' QUIT. For certain kinds of disastrous +failure (for example, failure to open a log file, or when Exim is bombing out +because it has detected an unrecoverable error), all SMTP commands from the +client are given temporary error responses until QUIT is received or the +connection is closed. In these special cases, the QUIT ACL does not run. + + + +Finding an ACL to use +~~~~~~~~~~~~~~~~~~~~~ +cindex:[{ACL},finding which to use] +The value of an %acl_smtp_'xxx'% option is expanded before use, so you can +use different ACLs in different circumstances. The resulting string does not +have to be the name of an ACL in the configuration file; there are other +possibilities. Having expanded the string, Exim searches for an ACL as follows: + +- If the string begins with a slash, Exim uses it as a file name, and reads its +contents as an ACL. The lines are processed in the same way as lines in the +Exim configuration file. In particular, continuation lines are supported, blank +lines are ignored, as are lines whose first non-whitespace character is ``#''. +If the file does not exist or cannot be read, an error occurs (typically +causing a temporary failure of whatever caused the ACL to be run). For example: ++ +.... +acl_smtp_data = /etc/acls/\ + ${lookup{$sender_host_address}lsearch\ + {/etc/acllist}{$value}{default}} +.... ++ +This looks up an ACL file to use on the basis of the host's IP address, falling +back to a default if the lookup fails. If an ACL is successfully read from a +file, it is retained in memory for the duration of the Exim process, so that it +can be re-used without having to re-read the file. + +- If the string does not start with a slash, and does not contain any spaces, +Exim searches the ACL section of the configuration for an ACL whose name +matches the string. + +- If no named ACL is found, or if the string contains spaces, Exim parses +the string as an inline ACL. This can save typing in cases where you just +want to have something like ++ + acl_smtp_vrfy = accept ++ +in order to allow free use of the VRFY command. Such a string may contain +newlines; it is processed in the same way as an ACL that is read from a file. + + + + +ACL return codes +~~~~~~~~~~~~~~~~ +cindex:[{ACL},return codes] +Except for the QUIT ACL, which does not affect the SMTP return code (see +section <<SECTQUITACL>> above), the + +result of running an ACL is either ``accept'' or ``deny'', or, if some test +cannot be completed (for example, if a database is down), ``defer''. These +results cause 2##'xx', 5##'xx', and 4##'xx' return codes, respectively, to be +used in the SMTP dialogue. A fourth return, ``error'', occurs when there is an +error such as invalid syntax in the ACL. This also causes a 4'##xx' return +code. + +For the non-SMTP ACL, ``defer'' and ``error'' are treated in the same way as +``deny'', because there is no mechanism for passing temporary errors to the +submitters of non-SMTP messages. + + +ACLs that are relevant to message reception may also return ``discard''. This +has the effect of ``accept'', but causes either the entire message or an +individual recipient address to be discarded. In other words, it is a +blackholing facility. Use it with care. + +If the ACL for MAIL returns ``discard'', all recipients are discarded, and no +ACL is run for subsequent RCPT commands. The effect of ``discard'' in a +RCPT ACL is to discard just the one recipient address. If there are no +recipients left when the message's data is received, the DATA ACL is not +run. A ``discard'' return from the DATA or the non-SMTP ACL discards all the +remaining recipients. + +The ``discard'' return is not permitted for the %acl_smtp_predata% ACL. + + +cindex:['local_scan()' function,when all recipients discarded] +The 'local_scan()' function is always run, even if there are no remaining +recipients; it may create new recipients. + + + +Unset ACL options +~~~~~~~~~~~~~~~~~ +cindex:[{ACL},unset options] +The default actions when any of the %acl_'xxx'% options are unset are not +all the same. *Note*: These defaults apply only when the relevant ACL is +not defined at all. For any defined ACL, the default action when control reaches +the end of the ACL statements is ``deny''. + +For %acl_not_smtp%, %acl_smtp_auth%, %acl_smtp_connect%, %acl_smtp_data%, +%acl_smtp_helo%, %acl_smtp_mail%, %acl_smtp_mailauth%, %acl_smtp_mime%, +%acl_smtp_predata%, %acl_smtp_quit%, and %acl_smtp_starttls%, the action when +the ACL is not defined is ``accept''. + +For the others (%acl_smtp_etrn%, %acl_smtp_expn%, %acl_smtp_rcpt%, and +%acl_smtp_vrfy%), the action when the ACL is not defined is ``deny''. +This means that %acl_smtp_rcpt% must be defined in order to receive any +messages over an SMTP connection. For an example, see the ACL in the default +configuration file. + + + + +Data for message ACLs +~~~~~~~~~~~~~~~~~~~~~ +cindex:[{ACL},data for message ACL] +When a MAIL or RCPT ACL, or either of the DATA ACLs, is running, +the variables that contain information about the host and the message's sender +(for example, $sender_host_address$ and $sender_address$) are set, and +can be used in ACL statements. In the case of RCPT (but not MAIL or +DATA), $domain$ and $local_part$ are set from the argument address. + +When an ACL for the AUTH parameter of MAIL is running, the variables that +contain information about the host are set, but $sender_address$ is not yet +set. Section <<SECTauthparamail>> contains a discussion of this parameter and +how it is used. + +The $message_size$ variable is set to the value of the SIZE parameter on +the MAIL command at MAIL, RCPT and pre-data time, or to -1 if +that parameter is not given. The value is updated to the true message size by +the time the final DATA ACL is run (after the message data has been +received). + +The $rcpt_count$ variable increases by one for each RCPT command +received. The $recipients_count$ variable increases by one each time a +RCPT command is accepted, so while an ACL for RCPT is being processed, +it contains the number of previously accepted recipients. At DATA time (for +both the DATA ACLs), $rcpt_count$ contains the total number of RCPT +commands, and $recipients_count$ contains the total number of accepted +recipients. + + + + + +[[SECTdatfornon]] +Data for non-message ACLs +~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[{ACL},data for non-message ACL] +When an ACL is being run for AUTH, EHLO, ETRN, EXPN, HELO, STARTTLS, or VRFY, +the remainder of the SMTP command line is placed in $smtp_command_argument$. +This can be tested using a %condition% condition. For example, here is an ACL +for use with AUTH, which insists that either the session is encrypted, or the +CRAM-MD5 authentication method is used. In other words, it does not permit +authentication methods that use cleartext passwords on unencrypted connections. + +.... +acl_check_auth: + accept encrypted = * + accept condition = ${if eq{${uc:$smtp_command_argument}}\ + {CRAM-MD5}} + deny message = TLS encryption or CRAM-MD5 required +.... + +(Another way of applying this restriction is to arrange for the authenticators +that use cleartext passwords not to be advertised when the connection is not +encrypted. You can use the generic %server_advertise_condition% authenticator +option to do this.) + + + +Format of an ACL +~~~~~~~~~~~~~~~~ +cindex:[{ACL},format of] +cindex:[{ACL},verbs; definition of] +An individual ACL consists of a number of statements. Each statement starts +with a verb, optionally followed by a number of conditions and ``modifiers''. +Modifiers can change the way the verb operates, define error and log messages, +set variables, insert delays, and vary the processing of accepted messages. + +If all the conditions are met, the verb is obeyed. The same condition may be +used (with different arguments) more than once in the same statement. This +provides a means of specifying an ``and'' conjunction between conditions. For +example: + + deny dnslists = list1.example + dnslists = list2.example + +If there are no conditions, the verb is always obeyed. Exim stops evaluating +the conditions and modifiers when it reaches a condition that fails. What +happens then depends on the verb (and in one case, on a special modifier). Not +all the conditions make sense at every testing point. For example, you cannot +test a sender address in the ACL that is run for a VRFY command. + + +ACL verbs +~~~~~~~~~ +The ACL verbs are as follows: + +- cindex:[%accept%, ACL verb] +%accept%: If all the conditions are met, the ACL returns ``accept''. If any of +the conditions are not met, what happens depends on whether %endpass% appears +among the conditions (for syntax see below). If the failing condition is before +%endpass%, control is passed to the next ACL statement; if it is after +%endpass%, the ACL returns ``deny''. Consider this statement, used to check a +RCPT command: + + accept domains = +local_domains + endpass + verify = recipient ++ +If the recipient domain does not match the %domains% condition, control passes +to the next statement. If it does match, the recipient is verified, and the +command is accepted if verification succeeds. However, if verification fails, +the ACL yields ``deny'', because the failing condition is after %endpass%. + +- cindex:[%defer%, ACL verb] +%defer%: If all the conditions are met, the ACL returns ``defer'' which, in an +SMTP session, causes a 4##'xx' response to be given. For a non-SMTP ACL, +%defer% is the same as %deny%, because there is no way of sending a temporary +error. For a RCPT command, %defer% is much the same as using a +^redirect^ router and `:defer:` while verifying, but the %defer% verb can +be used in any ACL, and even for a recipient it might be a simpler approach. + +- cindex:[%deny%, ACL verb] +%deny%: If all the conditions are met, the ACL returns ``deny''. If any of the +conditions are not met, control is passed to the next ACL statement. For +example, + + deny dnslists = blackholes.mail-abuse.org ++ +rejects commands from hosts that are on a DNS black list. + +- cindex:[%discard%, ACL verb] +%discard%: This verb behaves like %accept%, except that it returns ``discard'' +from the ACL instead of ``accept''. It is permitted only on ACLs that are +concerned with receiving messages, and it causes recipients to be discarded. +If the %log_message% modifier is set when %discard% operates, its contents are +added to the line that is automatically written to the log. ++ +If %discard% is used in an ACL for RCPT, just the one recipient is +discarded; if used for MAIL, DATA or in the non-SMTP ACL, all the +message's recipients are discarded. Recipients that are discarded before +DATA do not appear in the log line when the %log_recipients% log selector +is set. + +- cindex:[%drop%, ACL verb] +%drop%: This verb behaves like %deny%, except that an SMTP connection is +forcibly closed after the 5##'xx' error message has been sent. For example: + + drop message = I don't take more than 20 RCPTs + + condition = ${if > {$rcpt_count}{20}} ++ +There is no difference between %deny% and %drop% for the connect-time ACL. The +connection is always dropped after sending a 550 response. + +- cindex:[%require%, ACL verb] +%require%: If all the conditions are met, control is passed to the next ACL +statement. If any of the conditions are not met, the ACL returns ``deny''. For +example, when checking a RCPT command, + + require verify = sender ++ +passes control to subsequent statements only if the message's sender can be +verified. Otherwise, it rejects the command. + +- cindex:[%warn%, ACL verb] +%warn%: If all the conditions are met, a header line is added to an incoming +message and/or a line is written to Exim's main log. In all cases, control +passes to the next ACL statement. The text of the added header line and the log +line are specified by modifiers; if they are not present, a %warn% verb just +checks its conditions and obeys any ``immediate'' modifiers such as %set% and +%logwrite%. There is more about adding header lines in section +<<SECTaddheadwarn>>. ++ +If any condition on a %warn% statement cannot be completed (that is, there is +some sort of defer), no header lines are added and the configured log line is +not written. No further conditions or modifiers in the %warn% statement are +processed. The incident is logged, but the ACL continues to be processed, from +the next statement onwards. ++ +If a %message% modifier is present on a %warn% verb in an ACL that is not +testing an incoming message, it is ignored, and the incident is logged. ++ +A %warn% statement may use the %log_message% modifier to cause a line to be +written to the main log when the statement's conditions are true. +If an identical log line is requested several times in the same message, only +one copy is actually written to the log. If you want to force duplicates to be +written, use the %logwrite% modifier instead. ++ +When one of the %warn% conditions is an address verification that fails, the +text of the verification failure message is in $acl_verify_message$. If you +want this logged, you must set it up explicitly. For example: + + warn !verify = sender + log_message = sender verify failed: $acl_verify_message + +At the end of each ACL there is an implicit unconditional %deny%. + +As you can see from the examples above, the conditions and modifiers are +written one to a line, with the first one on the same line as the verb, and +subsequent ones on following lines. If you have a very long condition, you can +continue it onto several physical lines by the usual backslash continuation +mechanism. It is conventional to align the conditions vertically. + + + +[[SECTaclvariables]] +ACL variables +~~~~~~~~~~~~~ +cindex:[{ACL},variables] +There are some special variables that can be set during ACL processing. They +can be used to pass information between different ACLs, different invocations +of the same ACL in the same SMTP connection, and between ACLs and the routers, +transports, and filters that are used to deliver a message. There are two sets +of these variables: + +- The values of $acl_c0$ to $acl_c9$ persist throughout an SMTP connection. +They are never reset. Thus, a value that is set while receiving one message is +still available when receiving the next message on the same SMTP connection. + +- The values of $acl_m0$ to $acl_m9$ persist only while a message is being +received. They are reset afterwards. They are also reset by MAIL, RSET, +EHLO, HELO, and after starting up a TLS session. + +When a message is accepted, the current values of all the ACL variables are +preserved with the message and are subsequently made available at delivery +time. The ACL variables are set by modifier called %set%. For example: + + accept hosts = whatever + set acl_m4 = some value + +*Note*: a leading dollar sign is not used when naming a variable that is to +be set. If you want to set a variable without taking any action, you can use a +%warn% verb without any other modifiers or conditions. + + + +Condition and modifier processing +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[{ACL},conditions; processing] +cindex:[{ACL},modifiers; processing] +An exclamation mark preceding a condition negates its result. For example, + + deny domains = *.dom.example + !verify = recipient + +causes the ACL to return ``deny'' if the recipient domain ends in +'dom.example' and the recipient address cannot be verified. + +The arguments of conditions and modifiers are expanded. A forced failure +of an expansion causes a condition to be ignored, that is, it behaves as if the +condition is true. Consider these two statements: + +.... +accept senders = ${lookup{$host_name}lsearch\ + {/some/file}{$value}fail} +accept senders = ${lookup{$host_name}lsearch\ + {/some/file}{$value}{}} +.... + +Each attempts to look up a list of acceptable senders. If the lookup succeeds, +the returned list is searched, but if the lookup fails the behaviour is +different in the two cases. The %fail% in the first statement causes the +condition to be ignored, leaving no further conditions. The %accept% verb +therefore succeeds. The second statement, however, generates an empty list when +the lookup fails. No sender can match an empty list, so the condition fails, +and therefore the %accept% also fails. + +ACL modifiers appear mixed in with conditions in ACL statements. Some of them +specify actions that are taken as the conditions for a statement are checked; +others specify text for messages that are used when access is denied or a +warning is generated. The %control% modifier affects the way an incoming +message is handled. + +The positioning of the modifiers in an ACL statement important, because the +processing of a verb ceases as soon as its outcome is known. Only those +modifiers that have already been encountered will take effect. For example, +consider this use of the %message% modifier: + + require message = Can't verify sender + verify = sender + message = Can't verify recipient + verify = recipient + message = This message cannot be used + +If sender verification fails, Exim knows that the result of the statement is +``deny'', so it goes no further. The first %message% modifier has been seen, so +its text is used as the error message. If sender verification succeeds, but +recipient verification fails, the second message is used. If recipient +verification succeeds, the third message becomes ``current'', but is never used +because there are no more conditions to cause failure. + +For the %deny% verb, on the other hand, it is always the last %message% +modifier that is used, because all the conditions must be true for rejection to +happen. Specifying more than one %message% modifier does not make sense, and +the message can even be specified after all the conditions. For example: + + deny hosts = ... + !senders = *@my.domain.example + message = Invalid sender from client host + +The ``deny'' result does not happen until the end of the statement is reached, +by which time Exim has set up the message. + + + +[[SECTACLmodi]] +ACL modifiers +~~~~~~~~~~~~~ +cindex:[{ACL},modifiers; list of] +The ACL modifiers are as follows: + +*control*~=~<'text'>:: +cindex:[%control%, ACL modifier] +This modifier affects the subsequent processing of the SMTP connection or of an +incoming message that is accepted. The effect of the first type of control +lasts for the duration of the connection, whereas the effect of the second type +lasts only until the current message has been received. The message-specific +controls always apply to the whole message, not to individual recipients, +even if the %control% modifier appears in a RCPT ACL. ++ +As there are now quite a few controls that can be applied, they are described +separately in section <<SECTcontrols>>. The %control% modifier can be used in +several different ways. For example: ++ +- It can be at the end of an %accept% statement: ++ +.... + accept ...some conditions + control = queue_only +.... ++ +In this case, the control is applied when this statement yields ``accept'', in +other words, when the conditions are all true. + +- It can be in the middle of an %accept% statement: ++ +.... + accept ...some conditions... + control = queue_only + ...some more conditions... +.... ++ +If the first set of conditions are true, the control is applied, even if the +statement does not accept because one of the second set of conditions is false. +In this case, some subsequent statement must yield ``accept'' for the control to +be relevant. + +- It can be used with %warn% to apply the control, leaving the +decision about accepting or denying to a subsequent verb. For +example: ++ +.... + warn ...some conditions... + control = freeze + accept ... +.... ++ +This example of %warn% does not contain %message%, %log_message%, or +%logwrite%, so it does not add anything to the message and does not write a log +entry. + +- If you want to apply a control unconditionally, you can use it with a +%require% verb. For example: ++ +.... + require control = no_multiline_response +.... + +/// +End of bulleted list, continue with variable list +/// + + +*delay*~=~<'time'>:: +cindex:[%delay%, ACL modifier] +cindex:[%-bh% option] +This modifier causes Exim to wait for the time interval before proceeding. The +time is given in the usual Exim notation. This modifier may appear in any ACL. +The delay happens as soon as the modifier is processed. However, when testing +Exim using the %-bh% option, the delay is not actually imposed (an appropriate +message is output instead). ++ +Like %control%, %delay% can be used with %accept% or +%deny%, for example: + + deny ...some conditions... + delay = 30s ++ +The delay happens if all the conditions are true, before the statement returns +``deny''. Compare this with: + + deny delay = 30s + ...some conditions... ++ +which waits for 30s before processing the conditions. The %delay% modifier can +also be used with %warn% and together with %control%: + + warn ...some conditions... + delay = 2m + control = freeze + accept ... + +*endpass*:: +cindex:[%endpass%, ACL modifier] +This modifier, which has no argument, is recognized only in %accept% +statements. It marks the boundary between the conditions whose failure causes +control to pass to the next statement, and the conditions whose failure causes +the ACL to return ``deny''. See the description of %accept% above. + +*log_message*~=~<'text'>:: +cindex:[%log_message%, ACL modifier] +This modifier sets up a message that is used as part of the log message if the +ACL denies access or a %warn% statement's conditions are true. For example: + + require log_message = wrong cipher suite $tls_cipher + encrypted = DES-CBC3-SHA ++ +%log_message% adds to any underlying error message that may exist because of +the condition failure. For example, while verifying a recipient address, a +':fail:' redirection might have already set up a message. Although the message +is usually defined before the conditions to which it applies, the expansion +does not happen until Exim decides that access is to be denied. This means that +any variables that are set by the condition are available for inclusion in the +message. For example, the $dnslist_$<'xxx'> variables are set after a DNS +black list lookup succeeds. If the expansion of %log_message% fails, or if the +result is an empty string, the modifier is ignored. ++ +If you want to use a %warn% statement to log the result of an address +verification, you can use $acl_verify_message$ to include the verification +error message. ++ +If %log_message% is used with a %warn% statement, ``Warning:'' is added to the +start of the logged message. If the same warning log message is requested more +than once while receiving a single email message, only one copy is actually +logged. If you want to log multiple copies, use %logwrite% instead of +%log_message%. In the absence of %log_message% and %logwrite%, nothing is +logged for a succesful %warn% statement. ++ +If %log_message% is not present and there is no underlying error message (for +example, from the failure of address verification), but %message% is present, +the %message% text is used for logging rejections. However, if any text for +logging contains newlines, only the first line is logged. In the absence of +both %log_message% and %message%, a default built-in message is used for +logging rejections. + +*logwrite*~=~<'text'>:: +cindex:[%logwrite%, ACL modifier] +cindex:[logging in ACL, immediate] +This modifier writes a message to a log file as soon as it is encountered when +processing an ACL. (Compare %log_message%, which, except in the case of +%warn%, is used only if the ACL statement denies access.) The %logwrite% +modifier can be used to log special incidents in ACLs. For example: + + accept <some special conditions> + control = freeze + logwrite = froze message because ... ++ +By default, the message is written to the main log. However, it may begin +with a colon, followed by a comma-separated list of log names, and then +another colon, to specify exactly which logs are to be written. For +example: + + logwrite = :main,reject: text for main and reject logs + logwrite = :panic: text for panic log only + +*message*~=~<'text'>:: +cindex:[%message%, ACL modifier] +This modifier sets up a text string that is expanded and used as an error +message if the current statement causes the ACL to deny access. The expansion +happens at the time Exim decides that access is to be denied, not at the time +it processes %message%. If the expansion fails, or generates an empty string, +the modifier is ignored. For ACLs that are triggered by SMTP commands, the +message is returned as part of the SMTP error response. ++ +The %message% modifier is also used with the %warn% verb to specify one or more +header lines to be added to an incoming message when all the conditions are +true. See section <<SECTaddheadwarn>> for more details. If %message% is used +with %warn% in an ACL that is not concerned with receiving a message, it has no +effect. ++ +The text is literal; any quotes are taken as literals, but because the string +is expanded, backslash escapes are processed anyway. If the message contains +newlines, this gives rise to a multi-line SMTP response. Like %log_message%, +the contents of %message% are not expanded until after a condition has failed. ++ +If %message% is used on a statement that verifies an address, the message +specified overrides any message that is generated by the verification process. +However, the original message is available in the variable +$acl_verify_message$, so you can incorporate it into your message if you +wish. In particular, if you want the text from %:fail:% items in ^redirect^ +routers to be passed back as part of the SMTP response, you should either not +use a %message% modifier, or make use of $acl_verify_message$. + +*set*~<'acl_name'>~=~<'value'>:: +cindex:[%set%, ACL modifier] +This modifier puts a value into one of the ACL variables (see section +<<SECTaclvariables>>). + + + +[[SECTcontrols]] +Use of the control modifier +~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[%control%, ACL modifier] +The %control% modifier supports the following settings: + +*control~=~caseful_local_part*:: +See below. + +*control~=~caselower_local_part*:: +cindex:[{ACL},case of local part in] +cindex:[case of local parts] +These two controls are permitted only in the ACL specified by %acl_smtp_rcpt% +(that is, during RCPT processing). By default, the contents of $local_part$ are +lower cased before ACL processing. If ``caseful_local_part'' is specified, any +uppercase letters in the original local part are restored in $local_part$ for +the rest of the ACL, or until a control that sets ``caselower_local_part'' is +encountered. ++ +These controls affect only the current recipient. Moreover, they apply only to +local part handling that takes place directly in the ACL (for example, as a key +in lookups). If a test to verify the recipient is obeyed, the case-related +handling of the local part during the verification is controlled by the router +configuration (see the %caseful_local_part% generic router option). ++ +This facility could be used, for example, to add a spam score to local parts +containing upper case letters. For example, using $acl_m4$ to accumulate the +spam score: ++ +.... +warn control = caseful_local_part + set acl_m4 = ${eval:\ + $acl_m4 + \ + ${if match{$local_part}{[A-Z]}{1}{0}}\ + } + control = caselower_local_part +.... ++ +Notice that we put back the lower cased version afterwards, assuming that +is what is wanted for subsequent tests. + +*control~=~enforce_sync*:: +See below. + +*control~=~no_enforce_sync*:: +cindex:[SMTP,synchronization checking] +cindex:[synchronization checking in SMTP] +These controls make it possible to be selective about when SMTP synchronization +is enforced. The global option %smtp_enforce_sync% specifies the initial +state of the switch (it is true by default). See the description of this option +in chapter <<CHAPmainconfig>> for details of SMTP synchronization checking. ++ +The effect of these two controls lasts for the remainder of the SMTP +connection. They can appear in any ACL except the one for the non-SMTP +messages. The most straightforward place to put them is in the ACL defined by +%acl_smtp_connect%, which is run at the start of an incoming SMTP connection, +before the first synchronization check. The expected use is to turn off the +synchronization checks for badly-behaved hosts that you nevertheless need to +work with. + +*control~=~fakereject/*<'message'>:: +cindex:[fake rejection] +cindex:[rejection, fake] +This control is permitted only for the MAIL, RCPT, and DATA ACLs, in other +words, only when an SMTP message is being received. If Exim accepts the +message, instead the final 250 response, a 550 rejection message is sent. +However, Exim proceeds to deliver the message as normal. The control applies +only to the current message, not to any subsequent ones that may be received in +the same SMTP connection. ++ +The text for the 550 response is taken from the %control% modifier. If no +message is supplied, the following is used: + + 550-Your message has been rejected but is being + 550-kept for evaluation. + 550-If it was a legitimate message, it may still be + 550 delivered to the target recipient(s). ++ +This facilty should be used with extreme caution. + +*control~=~freeze*:: +cindex:[frozen messages,forcing in ACL] +This control is permitted only for the MAIL, RCPT, DATA, and non-SMTP ACLs, in +other words, only when a message is being received. If the message is accepted, +it is placed on Exim's queue and frozen. The control applies only to the +current message, not to any subsequent ones that may be received in the same +SMTP connection. + +*control~=~no_mbox_unspool*:: +This control is available when Exim is compiled with the content scanning +extension. Content scanning may require a copy of the current message, or parts +of it, to be written in ``mbox format'' to a spool file, for passing to a virus +or spam scanner. Normally, such copies are deleted when they are no longer +needed. If this control is set, the copies are not deleted. The control applies +only to the current message, not to any subsequent ones that may be received in +the same SMTP connection. It is provided for debugging purposes and is unlikely +to be useful in production. + +*control~=~no_multiline_response*:: +cindex:[multiline responses, suppressing] +This control is permitted for any ACL except the one for non-SMTP messages. +It seems that there are broken clients in use that cannot handle multiline +SMTP responses, despite the fact that RFC 821 defined them over 20 years ago. ++ +If this control is set, multiline SMTP responses from ACL rejections are +suppressed. One way of doing this would have been to put out these responses as +one long line. However, RFC 2821 specifies a maximum of 512 bytes per response +(``use multiline responses for more'' it says -- ha!), and some of the responses +might get close to that. So this facility, which is after all only a sop to +broken clients, is implemented by doing two very easy things: ++ +-- +. Extra information that is normally output as part of a rejection caused by +sender verification failure is omitted. Only the final line (typically ``sender +verification failed'') is sent. + +. If a %message% modifier supplies a multiline response, only the first +line is output. +-- ++ +The setting of the switch can, of course, be made conditional on the +calling host. Its effect lasts until the end of the SMTP connection. + +*control~=~queue_only*:: +cindex:[%queue_only%] +cindex:[queueing incoming messages] +This control is permitted only for the MAIL, RCPT, DATA, and non-SMTP ACLs, in +other words, only when a message is being received. If the message is accepted, +it is placed on Exim's queue and left there for delivery by a subsequent queue +runner. No immediate delivery process is started. In other words, it has the +effect as the %queue_only% global option. However, the control applies only to +the current message, not to any subsequent ones that may be received in the +same SMTP connection. + +*control~=~submission/*<'options'>:: +cindex:[message,submission] +cindex:[submission mode] +This control is permitted only for the MAIL, RCPT, and start of data ACLs (the +latter is the one defined by %acl_smtp_predata%). Setting it tells Exim that +the current message is a submission from a local MUA. In this case, Exim +operates in ``submission mode'', and applies certain fixups to the message if +necessary. For example, it add a 'Date:' header line if one is not present. +This control is not permitted in the %acl_smtp_data% ACL, because that is too +late (the message has already been created). ++ +Chapter <<CHAPmsgproc>> describes the processing that Exim applies to messages. +Section <<SECTsubmodnon>> covers the processing that happens in submission mode; +the available options for this control are described there. The control applies +only to the current message, not to any subsequent ones that may be received in +the same SMTP connection. + + + +[[SECTaddheadwarn]] +Adding header lines with the warn verb +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[header lines,adding in an ACL] +cindex:[header lines,position of added lines] +cindex:[%warn%, ACL verb] +cindex:[%message%, ACL modifier] +The %message% modifier can be used on a %warn% statement to add an extra header +line to an incoming message, as in this example: + +.... +warn message = X-blacklisted-at: $dnslist_domain + dnslists = sbl.spamhaus.org : \ + dialup.mail-abuse.org +.... + +If an identical header line is requested several times (provoked, for example, +by multiple RCPT commands), only one copy is actually added to the message. +If the text of the %message% modifier contains one or more newlines that are +not followed by a space or a tab, it is assumed to contain multiple header +lines. Each one is checked for valid syntax; `X-ACL-Warn:` is added to the +front of any line that is not a valid header line. + +By default, new lines are added at the end of the existing header lines. +However, you can specify that any particular header line should be added right +at the start (before all the 'Received:' lines), immediately after the first +block of 'Received:' lines, or immediately before any line that is not a +'Received:' or 'Resent-something:' header. + +This is done by specifying ``:at_start:'', ``:after_received:'', or +``:at_start_rfc:'' (or, for completeness, ``:at_end:'') before the text of the +header line, respectively. (Header text cannot start with a colon, as there has +to be a header name first.) For example: + + warn message = :after_received:X-My-Header: something or other... + + +If more than one header is supplied in a single warn statement, each one is +treated independently and can therefore be placed differently. If you add +more than one line at the start, or after the Received: block, they will +end up in reverse order. + +*Warning*: This facility currently applies only to header lines that are +added in an ACL. It does NOT work for header lines that are added in a +system filter or in a router or transport. + +cindex:[header lines,added; visibility of] +Header lines that are added by an ACL at MAIL or RCPT time are not +visible in string expansions in ACLs for subsequent RCPT commands or in the +%acl_smtp_predata% ACL. However, they are visible in string expansions in the +ACL that is run after DATA is complete (the %acl_smtp_data% ACL). This is +also true for header lines that are added in the %acl_smtp_predata% ACL. +If a message is rejected after DATA, all added header lines are included in +the entry that is written to the reject log. + +If you want to preserve data between MAIL, RCPT, and the +%acl_smtp_predata% ACLs, you can use ACL variables, as described in section +<<SECTaclvariables>>. + + + + + +[[SECTaclconditions]] +ACL conditions +~~~~~~~~~~~~~~ +cindex:[{ACL},conditions; list of] +Some of conditions listed in this section are available only when Exim is +compiled with the content-scanning extension. They are included here briefly +for completeness. More detailed descriptions can be found in the discussion on +content scanning in chapter <<CHAPexiscan>>. + +Not all conditions are relevant in all circumstances. For example, testing +senders and recipients does not make sense in an ACL that is being run as the +result of the arrival of an ETRN command, and checks on message headers can be +done only in the ACLs specified by %acl_smtp_data% and %acl_not_smtp%. You can +use the same condition (with different parameters) more than once in the same +ACL statement. This provides a way of specifying an ``and'' conjunction. The +conditions are as follows: + + +*acl~=~*<'name~of~acl~or~ACL~string~or~file~name~'>:: +cindex:[{ACL},nested] +cindex:[{ACL},indirect] +cindex:[%acl%, ACL condition] +The possible values of the argument are the same as for the %acl_smtp_%##'xxx' +options. The named or inline ACL is run. If it returns ``accept'' the condition +is true; if it returns ``deny'' the condition is false. If it returns +``defer'', the current ACL returns ``defer'' unless the condition is on a +%warn% verb. In that case, a ``defer'' return makes the condition false. This +means that further processing of the %warn% verb ceases, but processing of the +ACL continues. ++ +If the nested %acl% returns ``drop'' and the outer condition denies access, the +connection is dropped. If it returns ``discard'', the verb must be %accept% or +%discard%, and the action is taken immediately -- no further conditions are +tested. ++ +ACLs may be nested up to 20 deep; the limit exists purely to catch runaway +loops. This condition allows you to use different ACLs in different +circumstances. For example, different ACLs can be used to handle RCPT commands +for different local users or different local domains. + +*authenticated~=~*<'string~list'>:: +cindex:[%authenticated%, ACL condition] +cindex:[authentication,ACL checking] +cindex:[{ACL},testing for authentication] +If the SMTP connection is not authenticated, the condition is false. Otherwise, +the name of the authenticator is tested against the list. To test for +authentication by any authenticator, you can set + + authenticated = * + +*condition~=~*<'string'>:: +cindex:[%condition%, ACL condition] +cindex:[customizing,ACL condition] +cindex:[{ACL},customized test] +cindex:[{ACL},testing; customized] +This feature allows you to make up custom conditions. If the result of +expanding the string is an empty string, the number zero, or one of the strings +``no'' or ``false'', the condition is false. If the result is any non-zero +number, or one of the strings ``yes'' or ``true'', the condition is true. For +any other values, some error is assumed to have occured, and the ACL returns +``defer''. + +*decode~=~*<'location'>:: +cindex:[%decode%, ACL condition] +This condition is available only when Exim is compiled with the +content-scanning extension, and it is allowed only the the ACL defined by +%acl_smtp_mime%. It causes the current MIME part to be decoded into a file. For +details, see chapter <<CHAPexiscan>>. + +*dnslists~=~*<'list~of~domain~names~and~other~data'>:: +cindex:[%dnslists%, ACL condition] +cindex:[DNS list,in ACL] +cindex:[black list (DNS)] +cindex:[{ACL},testing a DNS list] +This condition checks for entries in DNS black lists. These are also known as +``RBL lists'', after the original Realtime Blackhole List, but note that the +use of the lists at 'mail-abuse.org' now carries a charge. There are too many +different variants of this condition to describe briefly here. See sections +<<SECTmorednslists>>--<<SECTmorednslistslast>> for details. + +*domains~=~*<'domain~list'>:: +cindex:[%domains%, ACL condition] +cindex:[domain,ACL checking] +cindex:[{ACL},testing a recipient domain] +This condition is relevant only after a RCPT command. It checks that the domain +of the recipient address is in the domain list. If percent-hack processing is +enabled, it is done before this test is done. If the check succeeds with a +lookup, the result of the lookup is placed in $domain_data$ until the next +%domains% test. + +*encrypted~=~*<'string~list'>:: +cindex:[%encrypted%, ACL condition] +cindex:[encryption,checking in an ACL] +cindex:[{ACL},testing for encryption] +If the SMTP connection is not encrypted, the condition is false. Otherwise, the +name of the cipher suite in use is tested against the list. To test for +encryption without testing for any specific cipher suite(s), set + + encrypted = * + +*hosts~=~*<'~host~list'>:: +cindex:[%hosts%, ACL condition] +cindex:[host,ACL checking] +cindex:[{ACL},testing the client host] +This condition tests that the calling host matches the host list. If you have +name lookups or wildcarded host names and IP addresses in the same host list, +you should normally put the IP addresses first. For example, you could have: + + accept hosts = 10.9.8.7 : dbm;/etc/friendly/hosts ++ +The reason for this lies in the left-to-right way that Exim processes lists. +It can test IP addresses without doing any DNS lookups, but when it reaches an +item that requires a host name, it fails if it cannot find a host name to +compare with the pattern. If the above list is given in the opposite order, the +%accept% statement fails for a host whose name cannot be found, even if its +IP address is 10.9.8.7. ++ +If you really do want to do the name check first, and still recognize the IP +address even if the name lookup fails, you can rewrite the ACL like this: + + accept hosts = dbm;/etc/friendly/hosts + accept hosts = 10.9.8.7 ++ +The default action on failing to find the host name is to assume that the host +is not in the list, so the first %accept% statement fails. The second statement +can then check the IP address. ++ +If a %hosts% condition is satisfied by means of a lookup, the result +of the lookup is made available in the $host_data$ variable. This +allows you, for example, to set up a statement like this: + + deny hosts = net-lsearch;/some/file + message = $host_data ++ +which gives a custom error message for each denied host. + +*local_parts~=~*<'local~part~list'>:: +cindex:[%local_parts%, ACL condition] +cindex:[local part,ACL checking] +cindex:[{ACL},testing a local part] +This condition is relevant only after a RCPT command. It checks that the local +part of the recipient address is in the list. If percent-hack processing is +enabled, it is done before this test. If the check succeeds with a lookup, the +result of the lookup is placed in $local_part_data$ until the next +%local_parts% test. + +*malware~=~*<'option'>:: +cindex:[%malware%, ACL condition] +cindex:[{ACL},virus scanning] +cindex:[{ACL},scanning for viruses] +This condition is available only when Exim is compiled with the +content-scanning extension. It causes the incoming message to be scanned for +viruses. For details, see chapter <<CHAPexiscan>>. + +*mime_regex~=~*<'list~of~regular~expressions'>:: +cindex:[%mime_regex%, ACL condition] +cindex:[{ACL},testing by regex matching] +This condition is available only when Exim is compiled with the +content-scanning extension, and it is allowed only the the ACL defined by +%acl_smtp_mime%. It causes the current MIME part to be scanned for a match with +any of the regular expressions. For details, see chapter <<CHAPexiscan>>. + +*recipients~=~*<'address~list'>:: +cindex:[%recipients%, ACL condition] +cindex:[recipient,ACL checking] +cindex:[{ACL},testing a recipient] +This condition is relevant only after a RCPT command. It checks the entire +recipient address against a list of recipients. + +*regex~=~*<'list~of~regular~expressions'>:: +cindex:[%regex%, ACL condition] +cindex:[{ACL},testing by regex matching] +This condition is available only when Exim is compiled with the +content-scanning extension. It causes the incoming message to be scanned for a +match with any of the regular expressions. For details, see chapter +<<CHAPexiscan>>. + +*sender_domains~=~*<'domain~list'>:: +cindex:[%sender_domains%, ACL condition] +cindex:[sender,ACL checking] +cindex:[{ACL},testing a sender domain] +This condition tests the domain of the sender of the message against the given +domain list. *Note*: the domain of the sender address is in +$sender_address_domain$. It is 'not' put in $domain$ during the testing of this +condition. This is an exception to the general rule for testing domain lists. +It is done this way so that, if this condition is used in an ACL for a RCPT +command, the recipient's domain (which is in $domain$) can be used to influence +the sender checking. + +*senders~=~*<'address~list'>:: +cindex:[%senders%, ACL condition] +cindex:[sender,ACL checking] +cindex:[{ACL},testing a sender] +This condition tests the sender of the message against the given list. To test +for a bounce message, which has an empty sender, set + + senders = : + +*spam~=~*<'username'>:: +cindex:[%spam%, ACL condition] +cindex:[{ACL},scanning for spam] +This condition is available only when Exim is compiled with the +content-scanning extension. It causes the incoming message to be scanned by +SpamAssassin. For details, see chapter <<CHAPexiscan>>. + +*verify~=~certificate*:: +cindex:[%verify%, ACL condition] +cindex:[TLS,client certificate verification] +cindex:[certificate,verification of client] +cindex:[{ACL},certificate verification] +cindex:[{ACL},testing a TLS certificate] +This condition is true in an SMTP session if the session is encrypted, and a +certificate was received from the client, and the certificate was verified. The +server requests a certificate only if the client matches %tls_verify_hosts% or +%tls_try_verify_hosts% (see chapter <<CHAPTLS>>). + +*verify~=~header_sender/*<'options'>:: +cindex:[%verify%, ACL condition] +cindex:[{ACL},verifying sender in the header] +cindex:[header lines,verifying the sender in] +cindex:[sender,verifying in header] +cindex:[verifying,sender in header] +This condition is relevant only in an ACL that is run after a message has been +received, that is, in an ACL specified by %acl_smtp_data% or %acl_not_smtp%. It +checks that there is a verifiable address in at least one of the 'Sender:', +'Reply-To:', or 'From:' header lines. Such an address is loosely thought of as +a ``sender'' address (hence the name of the test). However, an address that +appears in one of these headers need not be an address that accepts bounce +messages; only sender addresses in envelopes are required to accept bounces. +Therefore, if you use the callout option on this check, you might want to +arrange for a non-empty address in the MAIL command. ++ +Details of address verification and the options are given later, starting at +section <<SECTaddressverification>> (callouts are described in section +<<SECTcallver>>). You can combine this condition with the %senders% condition to +restrict it to bounce messages only: + + deny senders = : + message = A valid sender header is required for bounces + !verify = header_sender + +*verify~=~header_syntax*:: +cindex:[%verify%, ACL condition] +cindex:[{ACL},verifying header syntax] +cindex:[header lines,verifying syntax] +cindex:[verifying,header syntax] +This condition is relevant only in an ACL that is run after a message has been +received, that is, in an ACL specified by %acl_smtp_data% or %acl_not_smtp%. It +checks the syntax of all header lines that can contain lists of addresses +('Sender:', 'From:', 'Reply-To:', 'To:', 'Cc:', and 'Bcc:'). Unqualified +addresses (local parts without domains) are permitted only in locally generated +messages and from hosts that match %sender_unqualified_hosts% or +%recipient_unqualified_hosts%, as appropriate. ++ +Note that this condition is a syntax check only. However, a common spamming +ploy used to be to send syntactically invalid headers such as + + To: @ ++ +and this condition can be used to reject such messages, though they are not as +common as they used to be. + +*verify~=~helo*:: +cindex:[%verify%, ACL condition] +cindex:[{ACL},verifying HELO/EHLO] +cindex:[HELO,verifying] +cindex:[EHLO,verifying] +cindex:[verifying,EHLO] +cindex:[verifying,HELO] +This condition is true if a HELO or EHLO command has been received from the +client host, and its contents have been verified. Verification of these +commands does not happen by default. See the description of the +%helo_verify_hosts% and %helo_try_verify_hosts% options for details of how to +request it. + +*verify~=~recipient/*<'options'>:: +cindex:[%verify%, ACL condition] +cindex:[{ACL},verifying recipient] +cindex:[recipient,verifying] +cindex:[verifying,recipient] +This condition is relevant only after a RCPT command. It verifies the current +recipient. Details of address verification are given later, starting at section +<<SECTaddressverification>>. After a recipient has been verified, the value of +$address_data$ is the last value that was set while routing the address. This +applies even if the verification fails. When an address that is being verified +is redirected to a single address, verification continues with the new address, +and in that case, the subsequent value of $address_data$ is the value for the +child address. + +*verify~=~reverse_host_lookup*:: +cindex:[%verify%, ACL condition] +cindex:[{ACL},verifying host reverse lookup] +cindex:[host,verifying reverse lookup] +This condition ensures that a verified host name has been looked up from the IP +address of the client host. (This may have happened already if the host name +was needed for checking a host list, or if the host matched %host_lookup%.) +Verification ensures that the host name obtained from a reverse DNS lookup, or +one of its aliases, does, when it is itself looked up in the DNS, yield the +original IP address. ++ +If this condition is used for a locally generated message (that is, when there +is no client host involved), it always succeeds. + +*verify~=~sender/*<'options'>:: +cindex:[%verify%, ACL condition] +cindex:[{ACL},verifying sender] +cindex:[sender,verifying] +cindex:[verifying,sender] +This condition is relevant only after a MAIL or RCPT command, or after a +message has been received (the %acl_smtp_data% or %acl_not_smtp% ACLs). If the +message's sender is empty (that is, this is a bounce message), the condition is +true. Otherwise, the sender address is verified. ++ +If there is data in the $address_data$ variable at the end of routing, its +value is placed in $sender_address_data$ at the end of verification. This +value can be used in subsequent conditions and modifiers in the same ACL +statement. It does not persist after the end of the current statement. If you +want to preserve the value for longer, you can save it in an ACL variable. ++ +Details of verification are given later, starting at section +<<SECTaddressverification>>. Exim caches the result of sender verification, to +avoid doing it more than once per message. + +*verify~=~sender=*<'address'>*/*<'options'>:: +cindex:[%verify%, ACL condition] +This is a variation of the previous option, in which a modified address is +verified as a sender. + + + +[[SECTmorednslists]] +Using DNS lists +~~~~~~~~~~~~~~~ +cindex:[DNS list,in ACL] +cindex:[black list (DNS)] +cindex:[{ACL},testing a DNS list] +In its simplest form, the %dnslists% condition tests whether the calling host +is on at least one of a number of DNS lists by looking up the inverted IP +address in one or more DNS domains. For example, if the calling host's IP +address is 192.168.62.43, and the ACL statement is + +.... +deny dnslists = blackholes.mail-abuse.org : \ + dialups.mail-abuse.org +.... + +the following records are looked up: + + 43.62.168.192.blackholes.mail-abuse.org + 43.62.168.192.dialups.mail-abuse.org + +As soon as Exim finds an existing DNS record, processing of the list stops. +Thus, multiple entries on the list provide an ``or'' conjunction. If you want to +test that a host is on more than one list (an ``and'' conjunction), you can use +two separate conditions: + + deny dnslists = blackholes.mail-abuse.org + dnslists = dialups.mail-abuse.org + +If a DNS lookup times out or otherwise fails to give a decisive answer, Exim +behaves as if the host does not match the list item, that is, as if the DNS +record does not exist. If there are further items in the DNS list, they are +processed. + +This is usually the required action when %dnslists% is used with %deny% (which +is the most common usage), because it prevents a DNS failure from blocking +mail. However, you can change this behaviour by putting one of the following +special items in the list: + +cindex:[`+include_unknown`] +cindex:[`+exclude_unknown`] +cindex:[`+defer_unknown`] +&&& +`+include_unknown ` behave as if the item is on the list +`+exclude_unknown ` behave as if the item is not on the list (default) +`+defer_unknown ` give a temporary error +&&& +Each of these applies to any subsequent items on the list. For example: + + deny dnslists = +defer_unknown : foo.bar.example + + +Testing the list of domains stops as soon as a match is found. If you want to +warn for one list and block for another, you can use two different statements: + + deny dnslists = blackholes.mail-abuse.org + warn message = X-Warn: sending host is on dialups list + dnslists = dialups.mail-abuse.org + + +DNS list lookups are cached by Exim for the duration of the SMTP session, +so a lookup based on the IP address is done at most once for any incoming +connection. Exim does not share information between multiple incoming +connections (but your local name server cache should be active). + + + +Specifying the IP address for a DNS list lookup +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[DNS list,keyed by explicit IP address] +By default, the IP address that is used in a DNS list lookup is the IP address +of the calling host. However, you can specify another IP address by listing it +after the domain name, introduced by a slash. For example: + + deny dnslists = black.list.tls/192.168.1.2 + +This feature is not very helpful with explicit IP addresses; it is intended for +use with IP addresses that are looked up, for example, the IP addresses of the +MX hosts or nameservers of an email sender address. For an example, see section +<<SECTmulkeyfor>> below. + + + + +DNS lists keyed on domain names +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[DNS list,keyed by domain name] +There are some lists that are keyed on domain names rather than inverted IP +addresses (see for example the 'domain based zones' link at +*http://www.rfc-ignorant.org/[]*). No reversing of components is used with +these lists. You can change the name that is looked up in a DNS list by listing +it after the domain name, introduced by a slash. For example, + + deny message = Sender's domain is listed at $dnslist_domain + dnslists = dsn.rfc-ignorant.org/$sender_address_domain + +This particular example is useful only in ACLs that are obeyed after the +RCPT or DATA commands, when a sender address is available. If (for +example) the message's sender is 'user@tld.example' the name that is looked +up by this example is + + tld.example.dsn.rfc-ignorant.org + +A single %dnslists% condition can contain entries for both names and IP +addresses. For example: + +.... +deny dnslists = sbl.spamhaus.org : \ + dsn.rfc-ignorant.org/$sender_address_domain +.... + +The first item checks the sending host's IP address; the second checks a domain +name. The whole condition is true if either of the DNS lookups succeeds. + + + + +[[SECTmulkeyfor]] +Multiple explicit keys for a DNS list +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[DNS list,multiple keys for] +The syntax described above for looking up explicitly-defined values (either +names or IP addresses) in a DNS blacklist is a simplification. After the domain +name for the DNS list, what follows the slash can in fact be a list of items. +As with all lists in Exim, the default separator is a colon. However, because +this is a sublist within the list of DNS blacklist domains, it is necessary +either to double the separators like this: + + dnslists = black.list.tld/name.1::name.2 + +or to change the separator character, like this: + + dnslists = black.list.tld/<;name.1;name.2 + +If an item in the list is an IP address, it is inverted before the DNS +blacklist domain is appended. If it is not an IP address, no inversion +occurs. Consider this condition: + + dnslists = black.list.tld/<;192.168.1.2;a.domain + +The DNS lookups that occur are: + + 2.1.168.192.black.list.tld + a.domain.black.list.tld + +Once a DNS record has been found (that matches a specific IP return +address, if specified -- see section <<SECTaddmatcon>>), no further lookups are +done. If there is a temporary DNS error, the rest of the sublist of domains or +IP addresses is tried. A temporary error for the whole dnslists item occurs +only if no other DNS lookup in this sublist succeeds. In other words, a +successful lookup for any of the items in the sublist overrides a temporary +error for a previous item. + +The ability to supply a list of items after the slash is in some sense just a +syntactic convenience. These two examples have the same effect: + + dnslists = black.list.tld/a.domain : black.list.tld/b.domain + dnslists = black.list.tld/a.domain::b.domain + +However, when the data for the list is obtained from a lookup, the second form +is usually much more convenient. Consider this example: + +.... +deny message = The mail servers for the domain \ + $sender_address_domain \ + are listed at $dnslist_domain ($dnslist_value); \ + see $dnslist_text. + dnslists = sbl.spamhaus.org/<|${lookup dnsdb {>|a=<|\ + ${lookup dnsdb {>|mxh=\ + $sender_address_domain} }} } +.... + +Note the use of `>|` in the dnsdb lookup to specify the separator for +multiple DNS records. The inner dnsdb lookup produces a list of MX hosts +and the outer dnsdb lookup finds the IP addresses for these hosts. The result +of expanding the condition might be something like this: + + dnslists = sbl.spahmaus.org/<|192.168.2.3|192.168.5.6|... + +Thus, this example checks whether or not the IP addresses of the sender +domain's mail servers are on the Spamhaus black list. + + + + + +Data returned by DNS lists +~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[DNS list,data returned from] +DNS lists are constructed using address records in the DNS. The original RBL +just used the address 127.0.0.1 on the right hand side of each record, but the +RBL+ list and some other lists use a number of values with different meanings. +The values used on the RBL+ list are: + +&&& +127.1.0.1 RBL +127.1.0.2 DUL +127.1.0.3 DUL and RBL +127.1.0.4 RSS +127.1.0.5 RSS and RBL +127.1.0.6 RSS and DUL +127.1.0.7 RSS and DUL and RBL +&&& + +Some DNS lists may return more than one address record. + + +Variables set from DNS lists +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[DNS list,variables set from] +When an entry is found in a DNS list, the variable $dnslist_domain$ +contains the name of the domain that matched, $dnslist_value$ contains the +data from the entry, and $dnslist_text$ contains the contents of any +associated TXT record. If more than one address record is returned by the DNS +lookup, all the IP addresses are included in $dnslist_value$, separated by +commas and spaces. + +You can use these variables in %message% or %log_message% modifiers -- +although these appear before the condition in the ACL, they are not expanded +until after it has failed. For example: + +.... +deny hosts = !+local_networks + message = $sender_host_address is listed \ + at $dnslist_domain + dnslists = rbl-plus.mail-abuse.example +.... + + + + +[[SECTaddmatcon]] +Additional matching conditions for DNS lists +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[DNS list,matching specific returned data] +You can add an equals sign and an IP address after a %dnslists% domain name in +order to restrict its action to DNS records with a matching right hand side. +For example, + + deny dnslists = rblplus.mail-abuse.org=127.0.0.2 + +rejects only those hosts that yield 127.0.0.2. Without this additional data, +any address record is considered to be a match. If more than one address record +is found on the list, they are all checked for a matching right-hand side. + +More than one IP address may be given for checking, using a comma as a +separator. These are alternatives -- if any one of them matches, the %dnslists% +condition is true. For example: + + deny dnslists = a.b.c=127.0.0.2,127.0.0.3 + + +If you want to specify a constraining address list and also specify names or IP +addresses to be looked up, the constraining address list must be specified +first. For example: + +.... +deny dnslists = dsn.rfc-ignorant.org\ + =127.0.0.2/$sender_address_domain +.... + + +If the character ``&'' is used instead of ``='', the comparison for each listed +IP address is done by a bitwise ``and'' instead of by an equality test. In +other words, the listed addresses are used as bit masks. The comparison is +true if all the bits in the mask are present in the address that is being +tested. For example: + + dnslists = a.b.c&0.0.0.3 + +matches if the address is 'x.x.x.'3, 'x.x.x.'7, 'x.x.x.'11, etc. If you +want to test whether one bit or another bit is present (as opposed to both +being present), you must use multiple values. For example: + + dnslists = a.b.c&0.0.0.1,0.0.0.2 + +matches if the final component of the address is an odd number or two times +an odd number. + + + +Negated DNS matching conditions +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +You can supply a negative list of IP addresses as part of a %dnslists% +condition. Whereas + + deny dnslists = a.b.c=127.0.0.2,127.0.0.3 + +means ``deny if the host is in the black list at the domain 'a.b.c' and the IP +address yielded by the list is either 127.0.0.2 or 127.0.0.3'', + + deny dnslists = a.b.c!=127.0.0.2,127.0.0.3 + +means ``deny if the host is in the black list at the domain 'a.b.c' and the IP +address yielded by the list is not 127.0.0.2 and not 127.0.0.3''. In other +words, the result of the test is inverted if an exclamation mark appears before +the ``='' (or the ``&'') sign. + +*Note*: this kind of negation is not the same as negation in a domain, +host, or address list (which is why the syntax is different). + +If you are using just one list, the negation syntax does not gain you much. The +previous example is precisely equivalent to + + deny dnslists = a.b.c + !dnslists = a.b.c=127.0.0.2,127.0.0.3 + +However, if you are using multiple lists, the negation syntax is clearer. +Consider this example: + +.... +deny dnslists = sbl.spamhaus.org : \ + list.dsbl.org : \ + dnsbl.njabl.org!=127.0.0.3 : \ + relays.ordb.org +.... + +Using only positive lists, this would have to be: + +.... +deny dnslists = sbl.spamhaus.org : \ + list.dsbl.org +deny dnslists = dnsbl.njabl.org + !dnslists = dnsbl.njabl.org=127.0.0.3 +deny dnslists = relays.ordb.org +.... + +which is less clear, and harder to maintain. + + + + +[[SECTmorednslistslast]] +DNS lists and IPv6 +~~~~~~~~~~~~~~~~~~ +cindex:[IPv6,DNS black lists] +cindex:[DNS list,IPv6 usage] +If Exim is asked to do a dnslist lookup for an IPv6 address, it inverts it +nibble by nibble. For example, if the calling host's IP address is +3ffe:ffff:836f:0a00:000a:0800:200a:c031, Exim might look up + + 1.3.0.c.a.0.0.2.0.0.8.0.a.0.0.0.0.0.a.0.f.6.3.8. + f.f.f.f.e.f.f.3.blackholes.mail-abuse.org + +(split over two lines here to fit on the page). Unfortunately, some of the DNS +lists contain wildcard records, intended for IPv4, that interact badly with +IPv6. For example, the DNS entry + + *.3.some.list.example. A 127.0.0.1 + +is probably intended to put the entire 3.0.0.0/8 IPv4 network on the list. +Unfortunately, it also matches the entire 3::/4 IPv6 network. + +You can exclude IPv6 addresses from DNS lookups by making use of a suitable +%condition% condition, as in this example: + + deny condition = ${if isip4{$sender_host_address}} + dnslists = some.list.example + + + + +[[SECTaddressverification]] +Address verification +~~~~~~~~~~~~~~~~~~~~ +cindex:[verifying address, options for] +cindex:[policy control,address verification] +Several of the %verify% conditions described in section <<SECTaclconditions>> +cause addresses to be verified. These conditions can be followed by options +that modify the verification process. The options are separated from the +keyword and from each other by slashes, and some of them contain parameters. +For example: + + verify = sender/callout + verify = recipient/defer_ok/callout=10s,defer_ok + +The first stage of address verification, which always happens, is to run the +address through the routers, in ``verify mode''. Routers can detect the +difference between verification and routing for delivery, and their actions can +be varied by a number of generic options such as %verify% and %verify_only% +(see chapter <<CHAProutergeneric>>). If routing fails, verification fails. +The available options are as follows: + +- If the %callout% option is specified, successful routing to one or more remote +hosts is followed by a ``callout'' to those hosts as an additional check. +Callouts and their sub-options are discussed in the next section. + +- If there is a defer error while doing verification routing, the ACL +normally returns ``defer''. However, if you include %defer_ok% in the options, +the condition is forced to be true instead. Note that this is a main +verification option as well as a suboption for callouts. + +- The %no_details% option is covered in section <<SECTsenaddver>>, which discusses +the reporting of sender address verification failures. + +cindex:[verifying address, differentiating failures] +After an address verification failure, $sender_verify_failure$ or +$recipient_verify_failure$ (as appropriate) contains one of the following +words: + +- %qualify%: The address was unqualified (no domain), and the message +was neither local nor came from an exempted host. + +- %route%: Routing failed. + +- %mail%: Routing succeeded, and a callout was attempted; rejection +occurred at or before the MAIL command (that is, on initial +connection, HELO, or MAIL). + +- %recipient%: The RCPT command in a callout was rejected. + +- %postmaster%: The postmaster check in a callout was rejected. + + +The main use of these variables is expected to be to distinguish between +rejections of MAIL and rejections of RCPT in callouts. + + + + +[[SECTcallver]] +Callout verification +~~~~~~~~~~~~~~~~~~~~ +cindex:[verifying address, by callout] +cindex:[callout,verification] +cindex:[SMTP,callout verification] +For non-local addresses, routing verifies the domain, but is unable to do any +checking of the local part. There are situations where some means of verifying +the local part is desirable. One way this can be done is to make an SMTP +'callback' to the sending host (for a sender address) or a 'callforward' to +a subsequent host (for a recipient address), to see if the host accepts the +address. We use the term 'callout' to cover both cases. This facility should +be used with care, because it can add a lot of resource usage to the cost of +verifying an address. However, Exim does cache the results of callouts, which +helps to reduce the cost. Details of caching are in the next section. + +Recipient callouts are usually used only between hosts that are controlled by +the same administration. For example, a corporate gateway host could use +callouts to check for valid recipients on an internal mailserver. +A successful callout does not guarantee that a real delivery to the address +would succeed; on the other hand, a failing callout does guarantee that +a delivery would fail. + +If the %callout% option is present on a condition that verifies an address, a +second stage of verification occurs if the address is successfully routed to +one or more remote hosts. The usual case is routing by a ^dnslookup^ or a +^manualroute^ router, where the router specifies the hosts. However, if a +router that does not set up hosts routes to an ^smtp^ transport with a +%hosts% setting, the transport's hosts are used. If an ^smtp^ transport has +%hosts_override% set, its hosts are always used, whether or not the router +supplies a host list. + +The port that is used is taken from the transport, if it is specified and is a +remote transport. (For routers that do verification only, no transport need be +specified.) Otherwise, the default SMTP port is used. If a remote transport +specifies an outgoing interface, this is used; otherwise the interface is not +specified. + +For a sender callout check, Exim makes SMTP connections to the remote hosts, to +test whether a bounce message could be delivered to the sender address. The +following SMTP commands are sent: + +&&& +`HELO `<'smtp active host name'> +`MAIL FROM:<>` +`RCPT TO:`<'the address to be tested'> +`QUIT` +&&& + +LHLO is used instead of HELO if the transport's %protocol% option is +set to ``lmtp''. + +A recipient callout check is similar. By default, it also uses an empty address +for the sender. This default is chosen because most hosts do not make use of +the sender address when verifying a recipient. Using the same address means +that a single cache entry can be used for each recipient. Some sites, however, +do make use of the sender address when verifying. These are catered for by the +%use_sender% and %use_postmaster% options, described in the next section. + +If the response to the RCPT command is a 2'##xx' code, the verification +succeeds. If it is 5##'xx', the verification fails. For any other condition, +Exim tries the next host, if any. If there is a problem with all the remote +hosts, the ACL yields ``defer'', unless the %defer_ok% parameter of the +%callout% option is given, in which case the condition is forced to succeed. + + + + + +[[CALLaddparcall]] +Additional parameters for callouts +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[callout,additional parameters for] +The %callout% option can be followed by an equals sign and a number of optional +parameters, separated by commas. For example: + + verify = recipient/callout=10s,defer_ok + +The old syntax, which had %callout_defer_ok% and %check_postmaster% as +separate verify options, is retained for backwards compatibility, but is now +deprecated. The additional parameters for %callout% are as follows: + + +<'a~time~interval'>:: +cindex:[callout timeout, specifying] +This specifies the timeout that applies for the callout attempt to each host. +For example: + + verify = sender/callout=5s ++ +The default is 30 seconds. The timeout is used for each response from the +remote host. It is also used for the intial connection, unless overridden by +the %connect% parameter. + + +*connect~=~*<'time~interval'>:: +cindex:[callout connection timeout, specifying] +This parameter makes it possible to set a different (usually smaller) timeout +for making the SMTP connection. For example: + + verify = sender/callout=5s,connect=1s ++ +If not specified, this timeout defaults to the general timeout value. + +*defer_ok*:: +cindex:[callout defer, action on] +When this parameter is present, failure to contact any host, or any other kind +of temporary error, is treated as success by the ACL. However, the cache is not +updated in this circumstance. + +*mailfrom~=~*<'email~address'>:: +cindex:[callout,sender when verifying header] +When verifying addresses in header lines using the %header_sender% verification +option, Exim behaves by default as if the addresses are envelope sender +addresses from a message. Callout verification therefore tests to see whether a +bounce message could be delivered, by using an empty address in the MAIL +command. However, it is arguable that these addresses might never be used as +envelope senders, and could therefore justifiably reject bounce messages (empty +senders). The %mailfrom% callout parameter allows you to specify what address +to use in the MAIL command. For example: + + require verify = header_sender/callout=mailfrom=abcd@x.y.z ++ +This parameter is available only for the %header_sender% verification option. + + +*maxwait~=~*<'time~interval'>:: +cindex:[callout overall timeout, specifying] +This parameter sets an overall timeout for performing a callout verification. +For example: + + verify = sender/callout=5s,maxwait=30s ++ +This timeout defaults to four times the callout timeout for individual SMTP +commands. The overall timeout applies when there is more than one host that can +be tried. The timeout is checked before trying the next host. This prevents +very long delays if there are a large number of hosts and all are timing out +(for example, when network connections are timing out). + + +*no_cache*:: +cindex:[callout cache, suppressing] +cindex:[caching callout, suppressing] +When this parameter is given, the callout cache is neither read nor updated. + +*postmaster*:: +cindex:[callout,postmaster; checking] +When this parameter is set, a sucessful callout check is followed by a similar +check for the local part 'postmaster' at the same domain. If this address is +rejected, the callout fails. The result of the postmaster check is recorded in +a cache record; if it is a failure, this is used to fail subsequent callouts +for the domain without a connection being made, until the cache record expires. + +*postmaster_mailfrom~=~*<'email~address'>:: +The postmaster check uses an empty sender in the MAIL command by default. +You can use this parameter to do a postmaster check using a different address. +For example: + + require verify = sender/callout=postmaster_mailfrom=abc@x.y.z ++ +If both %postmaster% and %postmaster_mailfrom% are present, the rightmost one +overrides. The %postmaster% parameter is equivalent to this example: + + require verify = sender/callout=postmaster_mailfrom= ++ +*Warning*: The caching arrangements for postmaster checking do not take +account of the sender address. It is assumed that either the empty address or +a fixed non-empty address will be used. All that Exim remembers is that the +postmaster check for the domain succeeded or failed. + + +*random*:: +cindex:[callout,``random'' check] +When this parameter is set, before doing the normal callout check, Exim does a +check for a ``random'' local part at the same domain. The local part is not +really random -- it is defined by the expansion of the option +%callout_random_local_part%, which defaults to + + $primary_host_name-$tod_epoch-testing ++ +The idea here is to try to determine whether the remote host accepts all local +parts without checking. If it does, there is no point in doing callouts for +specific local parts. If the ``random'' check succeeds, the result is saved in +a cache record, and used to force the current and subsequent callout checks to +succeed without a connection being made, until the cache record expires. + +*use_postmaster*:: +cindex:[callout,sender for recipient check] +This parameter applies to recipient callouts only. For example: + + deny !verify = recipient/callout=use_postmaster ++ +It causes a non-empty postmaster address to be used in the MAIL command +when performing the callout. The local part of the address is `postmaster` +and the domain is the contents of $qualify_domain$. + +*use_sender*:: +This option applies to recipient callouts only. For example: + + require verify = recipient/callout=use_sender ++ +It causes the message's actual sender address to be used in the MAIL +command when performing the callout, instead of an empty address. There is no +need to use this option unless you know that the called hosts make use of the +sender when checking recipients. If used indiscriminately, it reduces the +usefulness of callout caching. + +/// +End of list +/// + +If you use any of the parameters that set a non-empty sender for the MAIL +command (%mailfrom%, %postmaster_mailfrom%, %use_postmaster%, or +%use_sender%), you should think about possible loops. Recipient checking is +usually done between two hosts that are under the same management, and the host +that receives the callouts is not normally configured to do callouts itself. +Therefore, it is normally safe to use %use_postmaster% or %use_sender% in +these circumstances. + +However, if you use a non-empty sender address for a callout to an arbitrary +host, there is the likelihood that the remote host will itself initiate a +callout check back to your host. As it is checking what appears to be a message +sender, it is likely to use an empty address in MAIL, thus avoiding a +callout loop. However, to be on the safe side it would be best to set up your +own ACLs so that they do not do sender verification checks when the recipient +is the address you use for header sender or postmaster callout checking. + +Another issue to think about when using non-empty senders for callouts is +caching. When you set %mailfrom% or %use_sender%, the cache record is keyed by +the sender/recipient combination; thus, for any given recipient, many more +actual callouts are performed than when an empty sender or postmaster is used. + + + + +[[SECTcallvercache]] +Callout caching +~~~~~~~~~~~~~~~ +cindex:[hints database,callout cache] +cindex:[callout,caching] +cindex:[caching,callout] +Exim caches the results of callouts in order to reduce the amount of resources +used, unless you specify the %no_cache% parameter with the %callout% option. +A hints database called ``callout'' is used for the cache. Two different record +types are used: one records the result of a callout check for a specific +address, and the other records information that applies to the entire domain +(for example, that it accepts the local part 'postmaster'). + +When an original callout fails, a detailed SMTP error message is given about +the failure. However, for subsequent failures use the cache data, this message +is not available. + +The expiry times for negative and positive address cache records are +independent, and can be set by the global options %callout_negative_expire% +(default 2h) and %callout_positive_expire% (default 24h), respectively. + +If a host gives a negative response to an SMTP connection, or rejects any +commands up to and including + + MAIL FROM:<> + +(but not including the MAIL command with a non-empty address), +any callout attempt is bound to fail. Exim remembers such failures in a +domain cache record, which it uses to fail callouts for the domain without +making new connections, until the domain record times out. There are two +separate expiry times for domain cache records: +%callout_domain_negative_expire% (default 3h) and +%callout_domain_positive_expire% (default 7d). + +Domain records expire when the negative expiry time is reached if callouts +cannot be made for the domain, or if the postmaster check failed. +Otherwise, they expire when the positive expiry time is reached. This +ensures that, for example, a host that stops accepting ``random'' local parts +will eventually be noticed. + +The callout caching mechanism is based on the domain of the address that is +being tested. If the domain routes to several hosts, it is assumed that their +behaviour will be the same. + + + +[[SECTsenaddver]] +Sender address verification reporting +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[verifying,suppressing error details] +When sender verification fails in an ACL, the details of the failure are +given as additional output lines before the 550 response to the relevant +SMTP command (RCPT or DATA). For example, if sender callout is in use, +you might see: + + MAIL FROM:<xyz@abc.example> + 250 OK + RCPT TO:<pqr@def.example> + 550-Verification failed for <xyz@abc.example> + 550-Called: 192.168.34.43 + 550-Sent: RCPT TO:<xyz@abc.example> + 550-Response: 550 Unknown local part xyz in <xyz@abc.example> + 550 Sender verification failed + +If more than one RCPT command fails in the same way, the details are given +only for the first of them. However, some administrators do not want to send +out this much information. You can suppress the details by adding +``/no_details'' to the ACL statement that requests sender verification. For +example: + + verify = sender/no_details + + + + +Redirection while verifying +~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[verifying,redirection while] +cindex:[address redirection,while verifying] +A dilemma arises when a local address is redirected by aliasing or forwarding +during verification: should the generated addresses themselves be verified, +or should the successful expansion of the original address be enough to verify +it? Exim takes the following pragmatic approach: + +- When an incoming address is redirected to just one child address, verification +continues with the child address, and if that fails to verify, the original +verification also fails. + +- When an incoming address is redirected to more than one child address, +verification does not continue. A success result is returned. + +This seems the most reasonable behaviour for the common use of aliasing as a +way of redirecting different local parts to the same mailbox. It means, for +example, that a pair of alias entries of the form + + A.Wol: aw123 + aw123: :fail: Gone away, no forwarding address + +work as expected, with both local parts causing verification failure. When a +redirection generates more than one address, the behaviour is more like a +mailing list, where the existence of the alias itself is sufficient for +verification to succeed. + + + +[[SECTrelaycontrol]] +Using an ACL to control relaying +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[{ACL},relay control] +cindex:[relaying,control by ACL] +cindex:[policy control,relay control] +An MTA is said to 'relay' a message if it receives it from some host and +delivers it directly to another host as a result of a remote address contained +within it. Redirecting a local address via an alias or forward file and then +passing the message on to another host is not relaying, + +cindex:[``percent hack''] +but a redirection as a result of the ``percent hack'' is. + +Two kinds of relaying exist, which are termed ``incoming'' and ``outgoing''. +A host which is acting as a gateway or an MX backup is concerned with incoming +relaying from arbitrary hosts to a specific set of domains. On the other hand, +a host which is acting as a smart host for a number of clients is concerned +with outgoing relaying from those clients to the Internet at large. Often the +same host is fulfilling both functions, +/// +as illustrated in the diagram below, +/// +but in principle these two kinds of relaying are entirely independent. What is +not wanted is the transmission of mail from arbitrary remote hosts through your +system to arbitrary domains. + + +You can implement relay control by means of suitable statements in the ACL that +runs for each RCPT command. For convenience, it is often easiest to use +Exim's named list facility to define the domains and hosts involved. For +example, suppose you want to do the following: + +- Deliver a number of domains to mailboxes on the local host (or process them +locally in some other way). Let's say these are 'my.dom1.example' and +'my.dom2.example'. + +- Relay mail for a number of other domains for which you are the secondary MX. +These might be 'friend1.example' and 'friend2.example'. + +- Relay mail from the hosts on your local LAN, to whatever domains are involved. +Suppose your LAN is 192.168.45.0/24. + + +In the main part of the configuration, you put the following definitions: + + domainlist local_domains = my.dom1.example : my.dom2.example + domainlist relay_domains = friend1.example : friend2.example + hostlist relay_hosts = 192.168.45.0/24 + +Now you can use these definitions in the ACL that is run for every RCPT +command: + + acl_check_rcpt: + accept domains = +local_domains : +relay_domains + accept hosts = +relay_hosts + +The first statement accepts any RCPT command that contains an address in +the local or relay domains. For any other domain, control passes to the second +statement, which accepts the command only if it comes from one of the relay +hosts. In practice, you will probably want to make your ACL more sophisticated +than this, for example, by including sender and recipient verification. The +default configuration includes a more comprehensive example, which is described +in chapter <<CHAPdefconfil>>. + + + +[[SECTcheralcon]] +Checking a relay configuration +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[relaying,checking control of] +You can check the relay characteristics of your configuration in the same way +that you can test any ACL behaviour for an incoming SMTP connection, by using +the %-bh% option to run a fake SMTP session with which you interact. + +For specifically testing for unwanted relaying, the host +'relay-test.mail-abuse.org' provides a useful service. If you telnet to this +host from the host on which Exim is running, using the normal telnet port, you +will see a normal telnet connection message and then quite a long delay. Be +patient. The remote host is making an SMTP connection back to your host, and +trying a number of common probes to test for open relay vulnerability. The +results of the tests will eventually appear on your terminal. + + + + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// + +[[CHAPexiscan]] +Content scanning +---------------- +cindex:[content scanning] +The content-scanning extension of Exim, formerly known as ``exiscan'', was +originally implemented as a patch by Tom Kistner. The code was integrated into +the main source for Exim release 4.50, and Tom continues to maintain it. Most +of the wording of this chapter is taken from Tom's specification. + +If you want to include the content-scanning features when you compile Exim, you +need to arrange for WITH_CONTENT_SCAN to be defined in your +_Local/Makefile_. When you do that, the Exim binary is built with: + +- An additional ACL (%acl_smtp_mime%) that is run for all MIME parts. + +- Additional ACL conditions and modifiers: %decode%, %malware%, %mime_regex%, +%regex%, and %spam%. These can be used in the ACL that is run at the end of +message reception (the %acl_smtp_data% ACL). + +- An additional control feature (``no_mbox_unspool'') that saves spooled copies +of messages, or parts of messages, for debugging purposes. + +- Additional expansion variables that are set in the new ACL and by the new +conditions. + +- Two new main configuration options: %av_scanner% and %spamd_address%. + +There is another content-scanning configuration option for _Local/Makefile_, +called WITH_OLD_DEMIME. If this is set, the old, deprecated %demime% ACL +condition is compiled, in addition to all the other content-scanning features. + +Content-scanning is continually evolving, and new features are still being +added. While such features are still unstable and liable to incompatible +changes, they are made available in Exim by setting options whose names begin +EXPERIMENTAL_ in _Local/Makefile_. Such features are not documented in +this manual. You can find out about them by reading the file called +_doc/experimental.txt_. + +All the content-scanning facilites work on a MBOX copy of the message that is +temporarily created in a file called: + + <spool_directory>/scan/<message_id>/<message_id>.eml + +The _.eml_ extension is a friendly hint to virus scanners that they can +expect an MBOX-like structure inside that file. The file is created when the +first content scanning facility is called. Subsequent calls to content +scanning conditions open the same file again. The directory is recursively +removed when the %acl_smtp_data% ACL has finished running, unless + + control = no_mbox_unspool + +has been encountered. When the MIME ACL decodes files, they are put into the +same directory by default. + + + +[[SECTscanvirus]] +Scanning for viruses +~~~~~~~~~~~~~~~~~~~~ +cindex:[virus scanning] +cindex:[content scanning,for viruses] +cindex:[content scanning,the %malware% condition] +The %malware% ACL condition lets you connect virus scanner software to Exim. It +supports a ``generic'' interface to scanners called via the shell, and +specialized interfaces for ``daemon'' type virus scanners, which are resident in +memory and thus are much faster. + +cindex:[%av_scanner%] +You can set the %av_scanner% option in first part of the Exim configuration +file to specify which scanner to use, together with any additional options that +are needed. The basic syntax is as follows: + + av_scanner = <scanner-type>:<option1>:<option2>:[...] + +If you do not set %av_scanner%, it defaults to + + av_scanner = sophie:/var/run/sophie + +If the value of %av_scanner% starts with dollar character, it is expanded +before use. + +The following scanner types are supported in this release: + +%aveserver%:: +cindex:[virus scanners,Kaspersky] +This is the scanner daemon of Kaspersky Version 5. You can get a trial version +at *http://www.kaspersky.com[]*. This scanner type takes one option, which is +the path to the daemon's UNIX socket. The default is shown in this example: + + av_scanner = aveserver:/var/run/aveserver + +%clamd%:: +cindex:[virus scanners,clamd] +This daemon-type scanner is GPL and free. You can get it at +*http://www.clamav.net/[]*. Clamd does not seem to unpack MIME containers, so +it is recommended to unpack MIME attachments in the MIME ACL. It takes one +option: either the path and name of a UNIX socket file, or a hostname or IP +number, and a port, separated by space, as in the second of these examples: + + av_scanner = clamd:/opt/clamd/socket + av_scanner = clamd:192.168.2.100 1234 ++ +If the option is unset, the default is _/tmp/clamd_. Thanks to David Saez for +contributing the code for this scanner. + +%cmdline%:: +cindex:[virus scanners,command line interface] +This is the keyword for the generic command line scanner interface. It can be +used to attach virus scanners that are invoked from the shell. This scanner +type takes 3 mandatory options: ++ +-- +. The full path and name of the scanner binary, with all command line options, +and a placeholder (%s) for the directory to scan. + +. A regular expression to match against the STDOUT and STDERR output of the +virus scanner. If the expression matches, a virus was found. You must make +absolutely sure that this expression matches on ``virus found''. This is called +the ``trigger'' expression. + +. Another regular expression, containing exactly one pair of parentheses, to +match the name of the virus found in the scanners output. This is called the +``name'' expression. +-- ++ +For example, Sophos Sweep reports a virus on a line like this: + + Virus 'W32/Magistr-B' found in file ./those.bat ++ +For the trigger expression, we can just match the word ``found''. For the name +expression, we want to extract the W32/Magistr-B string, so we can match for +the single quotes left and right of it. Altogether, this makes the +configuration setting: ++ +.... +av_scanner = cmdline:\ + /path/to/sweep -all -rec -archive %s:\ + found:'(.+)' +.... + + +%drweb%:: +cindex:[virus scanners,DrWeb] +The DrWeb daemon scanner (*http://www.sald.com/[]*) interface takes one +argument, either a full path to a UNIX socket, or an IP address and port +separated by whitespace, as in these examples: + + av_scanner = drweb:/var/run/drwebd.sock + av_scanner = drweb:192.168.2.20 31337 ++ +If you omit the argument, the default path _/usr/local/drweb/run/drwebd.sock_ +is used. Thanks to Alex Miller for contributing the code for this scanner. + +%fsecure%:: +cindex:[virus scanners,F-Secure] +The F-Secure daemon scanner (*http://www.f-secure.com[]*) takes one argument +which is the path to a UNIX socket. For example: + + av_scanner = fsecure:/path/to/.fsav ++ +If no argument is given, the default is _/var/run/.fsav_. Thanks to Johan +Thelmen for contributing the code for this scanner. + +%kavdaemon%:: +cindex:[virus scanners,Kaspersky] +This is the scanner daemon of Kaspersky Version 4. This version of the +Kaspersky scanner is outdated. Please upgrade (see %aveserver% above). This +scanner type takes one option, which is the path to the daemon's UNIX socket. +For example: + + av_scanner = kavdaemon:/opt/AVP/AvpCtl ++ +The default path is _/var/run/AvpCtl_. + +%mksd%:: +cindex:[virus scanners,mksd] +This is a daemon type scanner that is aimed mainly at Polish users, though some +parts of documentation are now available in English. You can get it at +*http://linux.mks.com.pl/[]*. The only option for this scanner type is the +maximum number of processes used simultaneously to scan the attachments, +provided that the demime facility is employed and also provided that mksd has +been run with at least the same number of child processes. For example: + + av_scanner = mksd:2 ++ +You can safely omit this option (the default value is 1). + +%sophie%:: +cindex:[virus scanners,Sophos and Sophie] +Sophie is a daemon that uses Sophos' %libsavi% library to scan for viruses. You +can get Sophie at *http://www.vanja.com/tools/sophie/[]*. The only option for +this scanner type is the path to the UNIX socket that Sophie uses for client +communication. For example: + + av_scanner = sophie:/tmp/sophie ++ +The default path is _/var/run/sophie_, so if you are using this, you can omit +the option. + +/// +End of list +/// + +When %av_scanner% is correctly set, you can use the %malware% condition in the +DATA ACL. The %av_scanner% option is expanded each time %malware% is +called. This makes it possible to use different scanners. See further below for +an example. The %malware% condition caches its results, so when you use it +multiple times for the same message, the actual scanning process is only +carried out once. However, using expandable items in %av_scanner% disables +this caching, in which case each use of the %malware% condition causes a new +scan of the message. + +The %malware% condition takes a right-hand argument that is expanded before +use. It can then be one of + +- ``true'', ``\*'', or ``1'', in which case the message is scanned for viruses. +The condition succeeds if a virus was found, and fail otherwise. This is the +recommended usage. + +- ``false'' or ``0'', in which case no scanning is done and the condition fails +immediately. + +- A regular expression, in which case the message is scanned for viruses. The +condition succeeds if a virus is found and its name matches the regular +expression. This allows you to take special actions on certain types of virus. + +You can append `/defer_ok` to the %malware% condition to accept messages even +if there is a problem with the virus scanner. + +cindex:[$malware_name$] +When a virus is found, the condition sets up an expansion variable called +$malware_name$ that contains the name of the virus. You can use it in a +%message% modifier that specifies the error returned to the sender, and/or in +logging data. + +If your virus scanner cannot unpack MIME and TNEF containers itself, you should +use the %demime% condition (see section <<SECTdemimecond>>) before the %malware% +condition. + +Here is a very simple scanning example: + + deny message = This message contains malware ($malware_name) + demime = * + malware = * + +The next example accepts messages when there is a problem with the scanner: + + deny message = This message contains malware ($malware_name) + demime = * + malware = */defer_ok + +The next example shows how to use an ACL variable to scan with both sophie and +aveserver. It assumes you have set: + + av_scanner = $acl_m0 + +in the main Exim configuration. + + deny message = This message contains malware ($malware_name) + set acl_m0 = sophie + malware = * + + deny message = This message contains malware ($malware_name) + set acl_m0 = aveserver + malware = * + + + + +[[SECTscanspamass]] +Scanning with SpamAssassin +~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[content scanning,for spam] +cindex:[spam scanning] +cindex:[SpamAssassin, scanning with] +The %spam% ACL condition calls SpamAssassin's %spamd% daemon to get a spam +score and a report for the message. You can get SpamAssassin at +*http://www.spamassassin.org[]*, or, if you have a working Perl installation, +you can use CPAN by running: + + perl -MCPAN -e 'install Mail::SpamAssassin' + +SpamAssassin has its own set of configuration files. Please review its +documentation to see how you can tweak it. The default installation should work +nicely, however. + +cindex:[%spamd_address%] +After having installed and configured SpamAssassin, start the %spamd% daemon. +By default, it listens on 127.0.0.1, TCP port 783. If you use another host or +port for %spamd%, you must set the %spamd_address% option in the global part +of the Exim configuration as follows (example): + + spamd_address = 192.168.99.45 387 + +You do not need to set this option if you use the default. As of version 2.60, +%spamd% also supports communication over UNIX sockets. If you want to use +these, supply %spamd_address% with an absolute file name instead of a +address/port pair: + + spamd_address = /var/run/spamd_socket + + +You can have multiple %spamd% servers to improve scalability. These can reside +on other hardware reachable over the network. To specify multiple %spamd% +servers, put multiple address/port pairs in the %spamd_address% option, +separated with colons: + +.... +spamd_address = 192.168.2.10 783 : \ + 192.168.2.11 783 : \ + 192.168.2.12 783 +.... + +Up to 32 %spamd% servers are supported. The servers are +queried in a random fashion. When a server fails to respond +to the connection attempt, all other servers are tried +until one succeeds. If no server responds, the %spam% +condition defers. + +*Warning*: It is not possible to use the UNIX socket connection method with +multiple %spamd% servers. + +Here is a simple example of the use of the %spam% condition in a DATA ACL: + + deny message = This message was classified as SPAM + spam = joe + +The right-hand side of the %spam% condition specifies the username that +SpamAssassin should scan for. If you do not want to scan for a particular user, +but rather use the SpamAssassin system-wide default profile, you can scan for +an unknown user, or simply use ``nobody''. However, you must put something on the +right-hand side. + +The username allows you to use per-domain or per-user antispam profiles. The +right-hand side is expanded before being used, so you can put lookups or +conditions there. When the right-hand side evaluates to ``0'' or ``false'', no +scanning is done and the condition fails immediately. + +The %spam% condition returns true if the threshold specified in the user's +SpamAssassin profile has been matched or exceeded. If you want to use the +%spam% condition for its side effects (see the variables below), you can make +it always return ``true'' by appending `:true` to the username. + +cindex:[spam scanning,returned variables] +When the %spam% condition is run, it sets up the following expansion +variables: + +$spam_score$:: +The spam score of the message, for example ``3.4'' or ``30.5''. This is useful +for inclusion in log or reject messages. + +$spam_score_int$:: +The spam score of the message, multiplied by ten, as an integer value. For +example ``34'' or ``305''. This is useful for numeric comparisons in +conditions. This variable is special; it is saved with the message, and written +to Exim's spool file. This means that it can be used during the whole life of +the message on your Exim system, in particular, in routers or transports during +the later delivery phase. + +$spam_bar$:: +A string consisting of a number of ``+'' or ``-'' characters, representing the +integer part of the spam score value. A spam score of 4.4 would have a +$spam_bar$ value of ``++++''. This is useful for inclusion in warning headers, +since MUAs can match on such strings. + +$spam_report$:: +A multiline text table, containing the full SpamAssassin report for the +message. Useful for inclusion in headers or reject messages. + +/// +End of list +/// + +The %spam% condition caches its results. If you call it again with the same +user name, it does not scan again, but rather returns the same values as +before. + +The %spam% condition returns DEFER if there is any error while running the +message through SpamAssassin. If you want to treat DEFER as FAIL (to pass on to +the next ACL statement block), append `/defer_ok` to the right-hand side of +the spam condition, like this: + + deny message = This message was classified as SPAM + spam = joe/defer_ok + +This causes messages to be accepted even if there is a +problem with %spamd%. + +Here is a longer, commented example of the use of the %spam% +condition: + + # put headers in all messages (no matter if spam or not) + warn message = X-Spam-Score: $spam_score ($spam_bar) + spam = nobody:true + warn message = X-Spam-Report: $spam_report + spam = nobody:true + + # add second subject line with *SPAM* marker when message + # is over threshold + warn message = Subject: *SPAM* $h_Subject: + spam = nobody + + # reject spam at high scores (> 12) + deny message = This message scored $spam_score spam points. + spam = nobody:true + condition = ${if >{$spam_score_int}{120}{1}{0}} + + + + + +[[SECTscanmimepart]] +Scanning MIME parts +~~~~~~~~~~~~~~~~~~~ +cindex:[content scanning,MIME parts] +cindex:[MIME content scanning] +cindex:[%acl_smtp_mime%] +The %acl_smtp_mime% global option defines an ACL that is called once for each +MIME part of a message, including multipart types, in the sequence of their +position in the message. + +This ACL is called (possibly many times) just before the %acl_smtp_data% ACL, +but only if the message has a 'MIME-Version:' header. When a call to the MIME +ACL does not yield ``accept'', ACL processing is aborted and the appropriate +result code is sent to the remote client. The %acl_smtp_data% ACL is not +called in this circumstance. + +At the start of the MIME ACL, a number of variables are set from the header +information for the relevant MIME part. These are described below. The contents +of the MIME part are not by default decoded into a disk file except for MIME +parts whose content-type is ``message/rfc822''. If you want to decode a MIME part +into a disk file, you can use the %decode% modifier. The general syntax is: + + decode = [/<path>/]<filename> + +The right hand side is expanded before use. After expansion, +the value can be: + +. ``0'' or ``false'', in which case no decoding is done. + +. The string ``default''. In that case, the file is put in the temporary +``default'' directory <'spool_directory'>_/scan/_<'message_id'>_/_ with a +sequential file name consisting of the message id and a sequence number. The +full path and name is available in $mime_decoded_filename$ after decoding. + +. A full path name starting with a slash. If the full name is an existing +directory, it is used as a replacement for the default directory. The filename +is then sequentially assigned. If the path does not exist, it is used as +the full path and file name. + +. If the string does not start with a slash, it is used as the +filename, and the default path is then used. + +/// +End of list +/// + +You can easily decode a file with its original, proposed filename using + + decode = $mime_filename + +However, you should keep in mind that $mime_filename$ might contain +anything. If you place files outside of the default path, they are not +automatically unlinked. + +For RFC822 attachments (these are messages attached to messages, with a +content-type of ``message/rfc822''), the ACL is called again in the same manner +as for the primary message, only that the $mime_is_rfc822$ expansion +variable is set (see below). Attached messages are always decoded to disk +before being checked, and the files are unlinked once the check is done. + +The MIME ACL supports the %regex% and %mime_regex% conditions. These can be +used to match regular expressions against raw and decoded MIME parts, +respectively. They are described in section <<SECTscanregex>>. + +cindex:[MIME content scanning,returned variables] +The following list describes all expansion variables that are +available in the MIME ACL: + +$mime_boundary$:: +If the current part is a multipart (see $mime_is_multipart$) below, it should +have a boundary string, which is stored in this variable. If the current part +has no boundary parameter in the 'Content-Type:' header, this variable contains +the empty string. + +$mime_charset$:: +This variable contains the character set identifier, if one was found in the +'Content-Type:' header. Examples for charset identifiers are: + + us-ascii + gb2312 (Chinese) + iso-8859-1 ++ +Please note that this value is not normalized, so you should do matches +case-insensitively. + +$mime_content_description$:: +This variable contains the normalized content of the 'Content-Description:' +header. It can contain a human-readable description of the parts content. Some +implementations repeat the filename for attachments here, but they are usually +only used for display purposes. + +$mime_content_disposition$:: +This variable contains the normalized content of the 'Content-Disposition:' +header. You can expect strings like ``attachment'' or ``inline'' here. + +$mime_content_id$:: +This variable contains the normalized content of the 'Content-ID:' header. +This is a unique ID that can be used to reference a part from another part. + +$mime_content_size$:: +This variable is set only after the %decode% modifier (see above) has been +successfully run. It contains the size of the decoded part in kilobytes. The +size is always rounded up to full kilobytes, so only a completely empty part +has a $mime_content_size$ of zero. + +$mime_content_transfer_encoding$:: +This variable contains the normalized content of the +'Content-transfer-encoding:' header. This is a symbolic name for an encoding +type. Typical values are ``base64'' and ``quoted-printable''. + +$mime_content_type$:: +If the MIME part has a 'Content-Type:' header, this variable contains its +value, lowercased, and without any options (like ``name'' or ``charset''). Here +are some examples of popular MIME types, as they may appear in this variable: + + text/plain + text/html + application/octet-stream + image/jpeg + audio/midi ++ +If the MIME part has no 'Content-Type:' header, this variable contains the +empty string. + +$mime_decoded_filename$:: +This variable is set only after the %decode% modifier (see above) has been +successfully run. It contains the full path and file name of the file +containing the decoded data. + +$mime_filename$:: +This is perhaps the most important of the MIME variables. It contains a +proposed filename for an attachment, if one was found in either the +'Content-Type:' or 'Content-Disposition:' headers. The filename will be RFC2047 +decoded, but no additional sanity checks are done. If no filename was found, +this variable contains the empty string. + +$mime_is_coverletter$:: +This variable attempts to differentiate the ``cover letter'' of an e-mail from +attached data. It can be used to clamp down on flashy or unneccessarily encoded +content in the cover letter, while not restricting attachments at all. ++ +The variable contains 1 (true) for a MIME part believed to be part of the +cover letter, and 0 (false) for an attachment. At present, the algorithm is as +follows: ++ +-- +. The outermost MIME part of a message is always a cover letter. + +. If a multipart/alternative or multipart/related MIME part is a cover letter, so +are all MIME subparts within that multipart. + +. If any other multipart is a cover letter, the first subpart is a cover letter, +and the rest are attachments. + +. All parts contained within an attachment multipart are attachments. +-- ++ +As an example, the following will ban ``HTML mail'' (including that sent with +alternative plain text), while allowing HTML files to be attached. HTML +coverletter mail attached to non-HMTL coverletter mail will also be allowed: + + deny message = HTML mail is not accepted here + !condition = $mime_is_rfc822 + condition = $mime_is_coverletter + condition = ${if eq{$mime_content_type}{text/html}{1}{0}} + +$mime_is_multipart$:: +This variable has the value 1 (true) when the current part has the main type +``multipart'', for example ``multipart/alternative'' or ``multipart/mixed''. +Since multipart entities only serve as containers for other parts, you may not +want to carry out specific actions on them. + +$mime_is_rfc822$:: +This variable has the value 1 (true) if the current part is not a part of the +checked message itself, but part of an attached message. Attached message +decoding is fully recursive. + +$mime_part_count$:: +This variable is a counter that is raised for each processed MIME part. It +starts at zero for the very first part (which is usually a multipart). The +counter is per-message, so it is reset when processing RFC822 attachments (see +$mime_is_rfc822$). The counter stays set after %acl_smtp_mime% is +complete, so you can use it in the DATA ACL to determine the number of MIME +parts of a message. For non-MIME messages, this variable contains the value -1. + + + +[[SECTscanregex]] +Scanning with regular expressions +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[content scanning,with regular expressions] +cindex:[regular expressions,content scanning with] +You can specify your own custom regular expression matches on the full body of +the message, or on individual MIME parts. + +The %regex% condition takes one or more regular expressions as arguments and +matches them against the full message (when called in the DATA ACL) or a raw +MIME part (when called in the MIME ACL). The %regex% condition matches +linewise, with a maximum line length of 32K characters. That means you cannot +have multiline matches with the %regex% condition. + +The %mime_regex% condition can be called only in the MIME ACL. It matches up +to 32K of decoded content (the whole content at once, not linewise). If the +part has not been decoded with the %decode% modifier earlier in the ACL, it is +decoded automatically when %mime_regex% is executed (using default path and +filename values). If the decoded data is larger than 32K, only the first 32K +characters are checked. + +The regular expressions are passed as a colon-separated list. To include a +literal colon, you must double it. Since the whole right-hand side string is +expanded before being used, you must also escape dollar signs and backslashes +with more backslashes, or use the `\N` facility to disable expansion. +Here is a simple example that contains two regular expressions: + + deny message = contains blacklisted regex ($regex_match_string) + regex = [Mm]ortgage : URGENT BUSINESS PROPOSAL + +The conditions returns true if any one of the regular expressions matches. The +$regex_match_string$ expansion variable is then set up and contains the +matching regular expression. + +*Warning*: With large messages, these conditions can be fairly +CPU-intensive. + + + + +[[SECTdemimecond]] +The demime condition +~~~~~~~~~~~~~~~~~~~~ +cindex:[content scanning,MIME checking] +cindex:[MIME content scanning] +The %demime% ACL condition provides MIME unpacking, sanity checking and file +extension blocking. It uses a simpler interface to MIME decoding than the MIME +ACL functionality, but provides no additional facilities. Please note that this +condition is deprecated and kept only for for backward compatibility. You must +set the WITH_OLD_DEMIME option in _Local/Makefile_ at build time to be +able to use the %demime% condition. + +The %demime% condition unpacks MIME containers in the message. It detects +errors in MIME containers and can match file extensions found in the message +against a list. Using this facility produces files containing the unpacked MIME +parts of the message in the temporary scan directory. If you do antivirus +scanning, it is recommened that you use the %demime% condition before the +antivirus (%malware%) condition. + +On the right-hand side of the %demime% condition you can pass a colon-separated +list of file extensions that it should match against. For example: + + deny message = Found blacklisted file attachment + demime = vbs:com:bat:pif:prf:lnk + +If one of the file extensions is found, the condition is true, otherwise it is +false. If there is a temporary error while demimeing (for example, ``disk +full''), the condition defers, and the message is temporarily rejected (unless +the condition is on a %warn% verb). + +The right-hand side is expanded before being treated as a list, so you can have +conditions and lookups there. If it expands to an empty string, ``false'', or +zero (``0''), no demimeing is done and the condition is false. + +The %demime% condition set the following variables: + +$demime_errorlevel$:: +When an error is detected in a MIME container, this variable contains the +severity of the error, as an integer number. The higher the value, the more +severe the error. If this variable is unset or zero, no error occurred. + +$demime_reason$:: +When $demime_errorlevel$ is greater than zero, this variable contains a +human-readable text string describing the MIME error that occurred. + +$found_extension$:: +When the %demime% condition is true, this variable contains the file extension +it found. + +/// +End of list +/// + +Both $demime_errorlevel$ and $demime_reason$ are set by the first call of +the %demime% condition, and are not changed on subsequent calls. + +If you do not want to check for file extensions, but rather use the %demime% +condition for unpacking or error checking purposes, pass ``\*'' as the +right-hand side value. Here is a more elaborate example of how to use this +facility: + + # Reject messages with serious MIME container errors + deny message = Found MIME error ($demime_reason). + demime = * + condition = ${if >{$demime_errorlevel}{2}{1}{0}} + + # Reject known virus spreading file extensions. + # Accepting these is pretty much braindead. + deny message = contains $found_extension file (blacklisted). + demime = com:vbs:bat:pif:scr + + # Freeze .exe and .doc files. Postmaster can + # examine them and eventually thaw them. + deny log_message = Another $found_extension file. + demime = exe:doc + control = freeze + + + + + + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// + +[[CHAPlocalscan]] +[titleabbrev="Local scan function"] +Adding a local scan function to Exim +------------------------------------ +cindex:['local_scan()' function,description of] +cindex:[customizing,input scan using C function] +cindex:[policy control,by local scan function] +In these days of email worms, viruses, and ever-increasing spam, some sites +want to apply a lot of checking to messages before accepting them. + +The content scanning extension (chapter <<CHAPexiscan>>) has facilities for +passing messages to external virus and spam scanning software. You can also do + +a certain amount in Exim itself through string expansions and the %condition% +condition in the ACL that runs after the SMTP DATA command or the ACL for +non-SMTP messages (see chapter <<CHAPACL>>), but this has its limitations. + +To allow for further customization to a site's own requirements, there is the +possibility of linking Exim with a private message scanning function, written +in C. If you want to run code that is written in something other than C, you +can of course use a little C stub to call it. + +The local scan function is run once for every incoming message, at the point +when Exim is just about to accept the message. +It can therefore be used to control non-SMTP messages from local processes as +well as messages arriving via SMTP. + +Exim applies a timeout to calls of the local scan function, and there is an +option called %local_scan_timeout% for setting it. The default is 5 minutes. +Zero means ``no timeout''. +Exim also sets up signal handlers for SIGSEGV, SIGILL, SIGFPE, and SIGBUS +before calling the local scan function, so that the most common types of crash +are caught. If the timeout is exceeded or one of those signals is caught, the +incoming message is rejected with a temporary error if it is an SMTP message. +For a non-SMTP message, the message is dropped and Exim ends with a non-zero +code. The incident is logged on the main and reject logs. + + + +Building Exim to use a local scan function +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:['local_scan()' function,building Exim to use] +To make use of the local scan function feature, you must tell Exim where your +function is before building Exim, by setting LOCAL_SCAN_SOURCE in your +_Local/Makefile_. A recommended place to put it is in the _Local_ +directory, so you might set + + LOCAL_SCAN_SOURCE=Local/local_scan.c + +for example. The function must be called 'local_scan()'. It is called by +Exim after it has received a message, when the success return code is about to +be sent. This is after all the ACLs have been run. The return code from your +function controls whether the message is actually accepted or not. There is a +commented template function (that just accepts the message) in the file +_src/local_scan.c_. + +If you want to make use of Exim's run time configuration file to set options +for your 'local_scan()' function, you must also set + + LOCAL_SCAN_HAS_OPTIONS=yes + +in _Local/Makefile_ (see section <<SECTconoptloc>> below). + + + + +[[SECTapiforloc]] +API for local_scan() +~~~~~~~~~~~~~~~~~~~~ +cindex:['local_scan()' function,API description] +You must include this line near the start of your code: + + #include "local_scan.h" + +This header file defines a number of variables and other values, and the +prototype for the function itself. Exim is coded to use unsigned char values +almost exclusively, and one of the things this header defines is a shorthand +for `unsigned char` called `uschar`. +It also contains the following macro definitions, to simplify casting character +strings and pointers to character strings: + + #define CS (char *) + #define CCS (const char *) + #define CSS (char **) + #define US (unsigned char *) + #define CUS (const unsigned char *) + #define USS (unsigned char **) + + +The function prototype for 'local_scan()' is: + + extern int local_scan(int fd, uschar **return_text); + +The arguments are as follows: + +- %fd% is a file descriptor for the file that contains the body of the message +(the -D file). The file is open for reading and writing, but updating it is not +recommended. *Warning*: You must 'not' close this file descriptor. ++ +The descriptor is positioned at character 19 of the file, which is the first +character of the body itself, because the first 19 characters are the message +id followed by `-D` and a newline. If you rewind the file, you should use the +macro SPOOL_DATA_START_OFFSET to reset to the start of the data, just in +case this changes in some future version. + +- %return_text% is an address which you can use to return a pointer to a text +string at the end of the function. The value it points to on entry is NULL. + +The function must return an %int% value which is one of the following macros: + +`LOCAL_SCAN_ACCEPT`:: +The message is accepted. If you pass back a string of text, it is saved with +the message, and made available in the variable $local_scan_data$. No +newlines are permitted (if there are any, they are turned into spaces) and the +maximum length of text is 1000 characters. + +`LOCAL_SCAN_ACCEPT_FREEZE`:: +This behaves as LOCAL_SCAN_ACCEPT, except that the accepted message is +queued without immediate delivery, and is frozen. + +`LOCAL_SCAN_ACCEPT_QUEUE`:: +This behaves as LOCAL_SCAN_ACCEPT, except that the accepted message is +queued without immediate delivery. + +`LOCAL_SCAN_REJECT`:: +The message is rejected; the returned text is used as an error message which is +passed back to the sender and which is also logged. Newlines are permitted -- +they cause a multiline response for SMTP rejections, but are converted to `\n` +in log lines. If no message is given, ``Administrative prohibition'' is used. + +`LOCAL_SCAN_TEMPREJECT`:: +The message is temporarily rejected; the returned text is used as an error +message as for LOCAL_SCAN_REJECT. If no message is given, ``Temporary local +problem'' is used. + +`LOCAL_SCAN_REJECT_NOLOGHDR`:: +This behaves as LOCAL_SCAN_REJECT, except that the header of the rejected +message is not written to the reject log. It has the effect of unsetting the +%rejected_header% log selector for just this rejection. If %rejected_header% +is already unset (see the discussion of the %log_selection% option in section +<<SECTlogselector>>), this code is the same as LOCAL_SCAN_REJECT. + +`LOCAL_SCAN_TEMPREJECT_NOLOGHDR`:: +This code is a variation of LOCAL_SCAN_TEMPREJECT in the same way that +LOCAL_SCAN_REJECT_NOLOGHDR is a variation of LOCAL_SCAN_REJECT. + +/// +End of list +/// + +If the message is not being received by interactive SMTP, rejections are +reported by writing to %stderr% or by sending an email, as configured by the +%-oe% command line options. + + + +[[SECTconoptloc]] +Configuration options for local_scan() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:['local_scan()' function,configuration options] +It is possible to have option settings in the main configuration file +that set values in static variables in the 'local_scan()' module. If you +want to do this, you must have the line + + LOCAL_SCAN_HAS_OPTIONS=yes + +in your _Local/Makefile_ when you build Exim. (This line is in +_OS/Makefile-Default_, commented out). Then, in the 'local_scan()' source +file, you must define static variables to hold the option values, and a table to +define them. + +The table must be a vector called %local_scan_options%, of type +`optionlist`. Each entry is a triplet, consisting of a name, an option type, +and a pointer to the variable that holds the value. The entries must appear in +alphabetical order. Following %local_scan_options% you must also define a +variable called %local_scan_options_count% that contains the number of +entries in the table. Here is a short example, showing two kinds of option: + + static int my_integer_option = 42; + static uschar *my_string_option = US"a default string"; + + optionlist local_scan_options[] = { + { "my_integer", opt_int, &my_integer_option }, + { "my_string", opt_stringptr, &my_string_option } + }; + int local_scan_options_count = + sizeof(local_scan_options)/sizeof(optionlist); + +The values of the variables can now be changed from Exim's runtime +configuration file by including a local scan section as in this example: + + begin local_scan + my_integer = 99 + my_string = some string of text... + +The available types of option data are as follows: + +*opt_bool*:: +This specifies a boolean (true/false) option. The address should point to a +variable of type `BOOL`, which will be set to TRUE or FALSE, which are macros +that are defined as ``1'' and ``0'', respectively. If you want to detect +whether such a variable has been set at all, you can initialize it to +TRUE_UNSET. (BOOL variables are integers underneath, so can hold more than two +values.) + +*opt_fixed*:: +This specifies a fixed point number, such as is used for load averages. +The address should point to a variable of type `int`. The value is stored +multiplied by 1000, so, for example, 1.4142 is truncated and stored as 1414. + +*opt_int*:: +This specifies an integer; the address should point to a variable of type +`int`. The value may be specified in any of the integer formats accepted by +Exim. + +*opt_mkint*:: +This is the same as %opt_int%, except that when such a value is output in a +%-bP% listing, if it is an exact number of kilobytes or megabytes, it is +printed with the suffix K or M. + +*opt_octint*:: +This also specifies an integer, but the value is always interpeted as an +octal integer, whether or not it starts with the digit zero, and it is +always output in octal. + +*opt_stringptr*:: +This specifies a string value; the address must be a pointer to a +variable that points to a string (for example, of type `uschar \*`). + +*opt_time*:: +This specifies a time interval value. The address must point to a variable of +type `int`. The value that is placed there is a number of seconds. + +/// +End of list +/// + +If the %-bP% command line option is followed by `local_scan`, Exim prints +out the values of all the 'local_scan()' options. + + + +Available Exim variables +~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:['local_scan()' function,available Exim variables] +The header _local_scan.h_ gives you access to a number of C variables. These +are the only ones that are guaranteed to be maintained from release to release. +Note, however, that you can obtain the value of any Exim variable by calling +'expand_string()'. The exported variables are as follows: + +*unsigned~int~debug_selector*:: +This variable is set to zero when no debugging is taking place. Otherwise, it +is a bitmap of debugging selectors. Two bits are identified for use in +'local_scan()'; they are defined as macros: ++ +-- +- The `D_v` bit is set when %-v% was present on the command line. This is a +testing option that is not privileged -- any caller may set it. All the +other selector bits can be set only by admin users. + +- The `D_local_scan` bit is provided for use by 'local_scan()'; it is set +by the `+local_scan` debug selector. It is not included in the default set +of debugging bits. +-- ++ +Thus, to write to the debugging output only when `+local_scan` has been +selected, you should use code like this: + + if ((debug_selector & D_local_scan) != 0) + debug_printf("xxx", ...); + + +*uschar~\*expand_string_message*:: +After a failing call to 'expand_string()' (returned value NULL), the +variable %expand_string_message% contains the error message, zero-terminated. + +*header_line~\*header_list*:: +A pointer to a chain of header lines. The %header_line% structure is discussed +below. + +*header_line~\*header_last*:: +A pointer to the last of the header lines. + +*uschar~\*headers_charset*:: +The value of the %headers_charset% configuration option. + +*BOOL~host_checking*:: +This variable is TRUE during a host checking session that is initiated by the +%-bh% command line option. + +*uschar~\*interface_address*:: +The IP address of the interface that received the message, as a string. This +is NULL for locally submitted messages. + +*int~interface_port*:: +The port on which this message was received. + +*uschar~\*message_id*:: +This variable contains the message id for the incoming message as a +zero-terminated string. + +*uschar~\*received_protocol*:: +The name of the protocol by which the message was received. + +*int~recipients_count*:: +The number of accepted recipients. + +*recipient_item~\*recipients_list*:: +cindex:[recipient,adding in local scan] +cindex:[recipient,removing in local scan] +The list of accepted recipients, held in a vector of length %recipients_count%. +The %recipient_item% structure is discussed below. You can add additional +recipients by calling 'receive_add_recipient()' (see below). You can delete +recipients by removing them from the vector and adusting the value in +%recipients_count%. In particular, by setting %recipients_count% to zero you +remove all recipients. If you then return the value `LOCAL_SCAN_ACCEPT`, the +message is accepted, but immediately blackholed. To replace the recipients, set +%recipients_count% to zero and then call 'receive_add_recipient()' as often as +needed. + +*uschar~\*sender_address*:: +The envelope sender address. For bounce messages this is the empty string. + +*uschar~\*sender_host_address*:: +The IP address of the sending host, as a string. This is NULL for +locally-submitted messages. + +*uschar~\*sender_host_authenticated*:: +The name of the authentication mechanism that was used, or NULL if the message +was not received over an authenticated SMTP connection. + +*uschar~\*sender_host_name*:: +The name of the sending host, if known. + +*int~sender_host_port*:: +The port on the sending host. + +*BOOL~smtp_input*:: +This variable is TRUE for all SMTP input, including BSMTP. + +*BOOL~smtp_batched_input*:: +This variable is TRUE for BSMTP input. + +*int~store_pool*:: +The contents of this variable control which pool of memory is used for new +requests. See section <<SECTmemhanloc>> for details. + +/// +End of list +/// + + + +Structure of header lines +~~~~~~~~~~~~~~~~~~~~~~~~~ +The %header_line% structure contains the members listed below. +You can add additional header lines by calling the 'header_add()' function +(see below). You can cause header lines to be ignored (deleted) by setting +their type to \*. + + +*struct~header_line~\*next*:: +A pointer to the next header line, or NULL for the last line. + +*int~type*:: +A code identifying certain headers that Exim recognizes. The codes are printing +characters, and are documented in chapter <<CHAPspool>> of this manual. Notice +in particular that any header line whose type is \* is not transmitted with the +message. This flagging is used for header lines that have been rewritten, or +are to be removed (for example, 'Envelope-sender:' header lines.) Effectively, +\* means ``deleted''. + +*int~slen*:: +The number of characters in the header line, including the terminating and any +internal newlines. + +*uschar~\*text*:: +A pointer to the text of the header. It always ends with a newline, followed by +a zero byte. Internal newlines are preserved. + + + +Structure of recipient items +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +The %recipient_item% structure contains these members: + +*uschar~\*address*:: +This is a pointer to the recipient address as it was received. + +*int~pno*:: +This is used in later Exim processing when top level addresses are created by +the %one_time% option. It is not relevant at the time 'local_scan()' is run and +must always contain -1 at this stage. + +*uschar~\*errors_to*:: +If this value is not NULL, bounce messages caused by failing to deliver to the +recipient are sent to the address it contains. In other words, it overrides the +envelope sender for this one recipient. (Compare the %errors_to% generic router +option.) If a 'local_scan()' function sets an %errors_to% field to an +unqualified address, Exim qualifies it using the domain from +%qualify_recipient%. When 'local_scan()' is called, the %errors_to% field is +NULL for all recipients. + + + +Available Exim functions +~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:['local_scan()' function,available Exim functions] +The header _local_scan.h_ gives you access to a number of Exim functions. +These are the only ones that are guaranteed to be maintained from release to +release: + +*pid_t~child_open(uschar~{star}{star}argv,~uschar~{star}{star}envp,~int~newumask,~int~{star}infdptr,~int~{star}outfdptr,~BOOL~make_leader)*:: + +This function creates a child process that runs the command specified by +%argv%. The environment for the process is specified by %envp%, which can be +NULL if no environment variables are to be passed. A new umask is supplied for +the process in %newumask%. ++ +Pipes to the standard input and output of the new process are set up +and returned to the caller via the %infdptr% and %outfdptr% arguments. The +standard error is cloned to the standard output. If there are any file +descriptors ``in the way'' in the new process, they are closed. If the final +argument is TRUE, the new process is made into a process group leader. ++ +The function returns the pid of the new process, or -1 if things go wrong. + +*int~child_close(pid_t~pid,~int~timeout)*:: +This function waits for a child process to terminate, or for a timeout (in +seconds) to expire. A timeout value of zero means wait as long as it takes. The +return value is as follows: ++ +- >= 0 ++ +The process terminated by a normal exit and the value is the process ending +status. + +- < 0 and > --256 ++ +The process was terminated by a signal and the value is the negation of the +signal number. + +- --256 ++ +The process timed out. + +- --257 ++ +The was some other error in wait(); %errno% is still set. + + +*pid_t~child_open_exim(int~{star}fd)*:: +This function provide you with a means of submitting a new message to +Exim. (Of course, you can also call _/usr/sbin/sendmail_ yourself if you +want, but this packages it all up for you.) The function creates a pipe, +forks a subprocess that is running + + exim -t -oem -oi -f <> ++ +and returns to you (via the `int *` argument) a file descriptor for the pipe +that is connected to the standard input. The yield of the function is the PID +of the subprocess. You can then write a message to the file descriptor, with +recipients in 'To:', 'Cc:', and/or 'Bcc:' header lines. ++ +When you have finished, call 'child_close()' to wait for the process to +finish and to collect its ending status. A timeout value of zero is usually +fine in this circumstance. Unless you have made a mistake with the recipient +addresses, you should get a return code of zero. + +*void~debug_printf(char~{star},~...)*:: +This is Exim's debugging function, with arguments as for '(printf()'. The +output is written to the standard error stream. If no debugging is selected, +calls to 'debug_printf()' have no effect. Normally, you should make calls +conditional on the `local_scan` debug selector by coding like this: + + if ((debug_selector & D_local_scan) != 0) + debug_printf("xxx", ...); + +*uschar~{star}expand_string(uschar~{star}string)*:: +This is an interface to Exim's string expansion code. The return value is the +expanded string, or NULL if there was an expansion failure. +The C variable %expand_string_message% contains an error message after an +expansion failure. If expansion does not change the string, the return value is +the pointer to the input string. Otherwise, the return value points to a new +block of memory that was obtained by a call to 'store_get()'. See section +<<SECTmemhanloc>> below for a discussion of memory handling. + +*void~header_add(int~type,~char~{star}format,~...)*:: +This function allows you to an add additional header line at the end of the +existing ones. The first argument is the type, and should normally be a space +character. The second argument is a format string and any number of +substitution arguments as for 'sprintf()'. You may include internal newlines if +you want, and you must ensure that the string ends with a newline. + +*void~header_add_at_position(BOOL~after,~uschar~{star}name,~BOOL~topnot,~int~type,~char~{star}format,~...)*:: +This function adds a new header line at a specified point in the header +chain. The header itself is specified as for 'header_add()'. ++ +If %name% is NULL, the new header is added at the end of the chain if %after% +is true, or at the start if %after% is false. If %name% is not NULL, the header +lines are searched for the first non-deleted header that matches the name. If +one is found, the new header is added before it if %after% is false. If %after% +is true, the new header is added after the found header and any adjacent +subsequent ones with the same name (even if marked ``deleted''). If no matching +non-deleted header is found, the %topnot% option controls where the header is +added. If it is true, addition is at the top; otherwise at the bottom. Thus, to +add a header after all the 'Received:' headers, or at the top if there are no +'Received:' headers, you could use + + header_add_at_position(TRUE, US"Received", TRUE, + ' ', "X-xxx: ..."); ++ +Normally, there is always at least one non-deleted 'Received:' header, but +there may not be if %received_header_text% expands to an empty string. + + +*void~header_remove(int~occurrence,~uschar~{star}name)*:: +This function removes header lines. If %occurrence% is zero or negative, all +occurrences of the header are removed. If occurrence is greater than zero, that +particular instance of the header is removed. If no header(s) can be found that +match the specification, the function does nothing. + + +*BOOL~header_testname(header_line~{star}hdr,~uschar~{star}name,~int~length,~BOOL~notdel)*:: +This function tests whether the given header has the given name. It is not just +a string comparison, because whitespace is permitted between the name and the +colon. If the %notdel% argument is true, a false return is forced for all +``deleted'' headers; otherwise they are not treated specially. For example: + + if (header_testname(h, US"X-Spam", 6, TRUE)) ... + + +*uschar~{star}lss_b64encode(uschar~{star}cleartext,~int~length)*:: +cindex:[base64 encoding,functions for 'local_scan()' use] +This function base64-encodes a string, which is passed by address and length. +The text may contain bytes of any value, including zero. The result is passed +back in dynamic memory that is obtained by calling 'store_get()'. It is +zero-terminated. + +*int~lss_b64decode(uschar~{star}codetext,~uschar~{star}{star}cleartext)*:: +This function decodes a base64-encoded string. Its arguments are a +zero-terminated base64-encoded string and the address of a variable that is set +to point to the result, which is in dynamic memory. The length of the decoded +string is the yield of the function. If the input is invalid base64 data, the +yield is -1. A zero byte is added to the end of the output string to make it +easy to interpret as a C string (assuming it contains no zeros of its own). The +added zero byte is not included in the returned count. + +*int~lss_match_domain(uschar~{star}domain,~uschar~{star}list)*:: +This function checks for a match in a domain list. Domains are always +matched caselessly. The return value is one of the following: ++ +&&& +`OK ` match succeeded +`FAIL ` match failed +`DEFER ` match deferred +&&& ++ +DEFER is usually caused by some kind of lookup defer, such as the +inability to contact a database. + +*int~lss_match_local_part(uschar~{star}localpart,~uschar~{star}list,~BOOL~caseless)*:: +This function checks for a match in a local part list. The third argument +controls case-sensitivity. The return values are as for +'lss_match_domain()'. + +*int~lss_match_address(uschar~{star}address,~uschar~{star}list,~BOOL~caseless)*:: +This function checks for a match in an address list. The third argument +controls the case-sensitivity of the local part match. The domain is always +matched caselessly. The return values are as for 'lss_match_domain()'. + +*int~lss_match_host(uschar~{star}host_name,~uschar~{star}host_address,~uschar~{star}list)*:: +This function checks for a match in a host list. The most common usage is +expected to be + + lss_match_host(sender_host_name, sender_host_address, ...) ++ +An empty address field matches an empty item in the host list. If the +host name is NULL, the name corresponding to $sender_host_address$ is +automatically looked up if a host name is required to match an item in the +list. The return values are as for 'lss_match_domain()', but in addition, +'lss_match_host()' returns ERROR in the case when it had to look up a host +name, but the lookup failed. + +*void~log_write(unsigned~int~selector,~int~which,~char~{star}format,~...)*:: +This function writes to Exim's log files. The first argument should be zero (it +is concerned with %log_selector%). The second argument can be `LOG_MAIN` or +`LOG_REJECT` or `LOG_PANIC` or the inclusive ``or'' of any combination of them. +It specifies to which log or logs the message is written. The remaining +arguments are a format and relevant insertion arguments. The string should not +contain any newlines, not even at the end. + + +*void~receive_add_recipient(uschar~{star}address,~int~pno)*:: +This function adds an additional recipient to the message. The first argument +is the recipient address. If it is unqualified (has no domain), it is qualified +with the %qualify_recipient% domain. The second argument must always be -1. ++ +This function does not allow you to specify a private %errors_to% address (as +described with the structure of %recipient_item% above), because it pre-dates +the addition of that field to the structure. However, it is easy to add such a +value afterwards. For example: + + receive_add_recipient(US"monitor@mydom.example", -1); + recipients_list[recipients_count-1].errors_to = + US"postmaster@mydom.example"; + +*BOOL~receive_remove_recipient(uschar~{star}recipient)*:: +This is a convenience function to remove a named recipient from the list of +recipients. It returns true if a recipient was removed, and false if no +matching recipient could be found. The argument must be a complete email +address. + + +*uschar~*rfc2047_decode(uschar~{star}string,~BOOL~lencheck,~uschar~{star}target,~int~zeroval,~int~{star}lenptr,~uschar~{star}{star}error)*:: +This function decodes strings that are encoded according to RFC 2047. Typically +these are the contents of header lines. First, each encoded ``word'' is decoded +from the Q or B encoding into a byte-string. Then, if provided with the name of +a charset encoding, and if the 'iconv()' function is available, an attempt is +made to translate the result to the named character set. If this fails, the +binary string is returned with an error message. ++ +The first argument is the string to be decoded. If %lencheck% is TRUE, the +maximum MIME word length is enforced. The third argument is the target +encoding, or NULL if no translation is wanted. ++ +cindex:[binary zero,in RFC 2047 decoding] +If a binary zero is encountered in the decoded string, it is replaced by the +contents of the %zeroval% argument. For use with Exim headers, the value must +not be 0 because header lines are handled as zero-terminated strings. ++ +The function returns the result of processing the string, zero-terminated; if +%lenptr% is not NULL, the length of the result is set in the variable to which +it points. When %zeroval% is 0, %lenptr% should not be NULL. ++ +If an error is encountered, the function returns NULL and uses the %error% +argument to return an error message. The variable pointed to by %error% is set +to NULL if there is no error; it may be set non-NULL even when the function +returns a non-NULL value if decoding was successful, but there was a problem +with translation. + + +*int~smtp_fflush(void)*:: +This function is used in conjunction with 'smtp_printf()', as described +below. + +*void~smtp_printf(char~{star},~...)*:: +The arguments of this function are like 'printf()'; it writes to the SMTP +output stream. You should use this function only when there is an SMTP output +stream, that is, when the incoming message is being received via interactive +SMTP. This is the case when %smtp_input% is TRUE and %smtp_batched_input% is +FALSE. If you want to test for an incoming message from another host (as +opposed to a local process that used the %-bs% command line option), you can +test the value of %sender_host_address%, which is non-NULL when a remote host +is involved. ++ +If an SMTP TLS connection is established, 'smtp_printf()' uses the TLS +output function, so it can be used for all forms of SMTP connection. ++ +Strings that are written by 'smtp_printf()' from within 'local_scan()' +must start with an appropriate response code: 550 if you are going to return +LOCAL_SCAN_REJECT, 451 if you are going to return +LOCAL_SCAN_TEMPREJECT, and 250 otherwise. Because you are writing the +initial lines of a multi-line response, the code must be followed by a hyphen +to indicate that the line is not the final response line. You must also ensure +that the lines you write terminate with CRLF. For example: + + smtp_printf("550-this is some extra info\r\n"); + return LOCAL_SCAN_REJECT; ++ +Note that you can also create multi-line responses by including newlines in +the data returned via the %return_text% argument. The added value of using +'smtp_printf()' is that, for instance, you could introduce delays between +multiple output lines. ++ +The 'smtp_printf()' function does not return any error indication, because it +does not automatically flush pending output, and therefore does not test +the state of the stream. (In the main code of Exim, flushing and error +detection is done when Exim is ready for the next SMTP input command.) If +you want to flush the output and check for an error (for example, the +dropping of a TCP/IP connection), you can call 'smtp_fflush()', which has no +arguments. It flushes the output stream, and returns a non-zero value if there +is an error. + +*void~{star}store_get(int)*:: +This function accesses Exim's internal store (memory) manager. It gets a new +chunk of memory whose size is given by the argument. Exim bombs out if it ever +runs out of memory. See the next section for a discussion of memory handling. + +*void~{star}store_get_perm(int)*:: +This function is like 'store_get()', but it always gets memory from the +permanent pool. See the next section for a discussion of memory handling. + +*uschar~{star}string_copy(uschar~{star}string)*:: +See below. + +*uschar~{star}string_copyn(uschar~{star}string,~int~length)*:: +See below. + +*uschar~{star}string_sprintf(char~{star}format,~...)*:: +These three functions create strings using Exim's dynamic memory facilities. +The first makes a copy of an entire string. The second copies up to a maximum +number of characters, indicated by the second argument. The third uses a format +and insertion arguments to create a new string. In each case, the result is a +pointer to a new string in the current memory pool. See the next section for +more discussion. + +/// +End of list +/// + + + + +[[SECTmemhanloc]] +More about Exim's memory handling +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:['local_scan()' function,memory handling] +No function is provided for freeing memory, because that is never needed. +The dynamic memory that Exim uses when receiving a message is automatically +recycled if another message is received by the same process (this applies only +to incoming SMTP connections -- other input methods can supply only one message +at a time). After receiving the last message, a reception process terminates. + +Because it is recycled, the normal dynamic memory cannot be used for holding +data that must be preserved over a number of incoming messages on the same SMTP +connection. However, Exim in fact uses two pools of dynamic memory; the second +one is not recycled, and can be used for this purpose. + +If you want to allocate memory that remains available for subsequent messages +in the same SMTP connection, you should set + + store_pool = POOL_PERM + +before calling the function that does the allocation. There is no need to +restore the value if you do not need to; however, if you do want to revert to +the normal pool, you can either restore the previous value of %store_pool% or +set it explicitly to POOL_MAIN. + +The pool setting applies to all functions that get dynamic memory, including +'expand_string()', 'store_get()', and the 'string_xxx()' functions. +There is also a convenience function called 'store_get_perm()' that gets a +block of memory from the permanent pool while preserving the value of +%store_pool%. + + + + + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// + +[[CHAPsystemfilter]] +System-wide message filtering +----------------------------- +cindex:[filter,system filter] +cindex:[filtering all mail] +cindex:[system filter] +The previous chapters (on ACLs and the local scan function) describe checks +that can be applied to messages before they are accepted by a host. There is +also a mechanism for checking messages once they have been received, but before +they are delivered. This is called the 'system filter'. + +The system filter operates in a similar manner to users' filter files, but it +is run just once per message (however many recipients the message has). +It should not normally be used as a substitute for routing, because %deliver% +commands in a system router provide new envelope recipient addresses. +The system filter must be an Exim filter. It cannot be a Sieve filter. + +The system filter is run at the start of a delivery attempt, before any routing +is done. If a message fails to be completely delivered at the first attempt, +the system filter is run again at the start of every retry. +If you want your filter to do something only once per message, you can make use +of the %first_delivery% condition in an %if% command in the filter to prevent +it happening on retries. + +*Warning*: Because the system filter runs just once, variables that are +specific to individual recipient addresses, such as $local_part$ and +$domain$, are not set, and the ``personal'' condition is not meaningful. If you +want to run a centrally-specified filter for each recipient address +independently, you can do so by setting up a suitable ^redirect^ router, as +described in section <<SECTperaddfil>> below. + + +Specifying a system filter +~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[uid (user id),system filter] +cindex:[gid (group id),system filter] +The name of the file that contains the system filter must be specified by +setting %system_filter%. If you want the filter to run under a uid and gid +other than root, you must also set %system_filter_user% and +%system_filter_group% as appropriate. For example: + + system_filter = /etc/mail/exim.filter + system_filter_user = exim + +If a system filter generates any deliveries directly to files or pipes (via the +%save% or %pipe% commands), transports to handle these deliveries must be +specified by setting %system_filter_file_transport% and +%system_filter_pipe_transport%, respectively. Similarly, +%system_filter_reply_transport% must be set to handle any messages generated +by the %reply% command. + + +Testing a system filter +~~~~~~~~~~~~~~~~~~~~~~~ +You can run simple tests of a system filter in the same way as for a user +filter, but you should use %-bF% rather than %-bf%, so that features that +are permitted only in system filters are recognized. + +If you want to test the combined effect of a system filter and a user filter, +you can use both %-bF% and %-bf% on the same command line. + + + +Contents of a system filter +~~~~~~~~~~~~~~~~~~~~~~~~~~~ +The language used to specify system filters is the same as for users' filter +files. It is described in the separate end-user document 'Exim's interface to +mail filtering'. However, there are some additional features that are +available only in system filters; these are described in subsequent sections. +If they are encountered in a user's filter file or when testing with %-bf%, +they cause errors. + +cindex:[frozen messages,manual thaw; testing in filter] +There are two special conditions which, though available in users' filter +files, are designed for use in system filters. The condition %first_delivery% +is true only for the first attempt at delivering a message, and +%manually_thawed% is true only if the message has been frozen, and +subsequently thawed by an admin user. An explicit forced delivery counts as a +manual thaw, but thawing as a result of the %auto_thaw% setting does not. + +*Warning*: If a system filter uses the %first_delivery% condition to +specify an ``unseen'' (non-significant) delivery, and that delivery does not +succeed, it will not be tried again. +If you want Exim to retry an unseen delivery until it succeeds, you should +arrange to set it up every time the filter runs. + +When a system filter finishes running, the values of the variables $n0$ -- +$n9$ are copied into $sn0$ -- $sn9$ and are thereby made available to +users' filter files. Thus a system filter can, for example, set up ``scores'' to +which users' filter files can refer. + + + +Additional variable for system filters +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +The expansion variable $recipients$, containing a list of all the recipients +of the message (separated by commas and white space), is available in system +filters. It is not available in users' filters for privacy reasons. + + + +Defer, freeze, and fail commands for system filters +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[freezing messages] +cindex:[message,freezing] +cindex:[message,forced failure] +cindex:[%fail%,in system filter] +cindex:[%freeze% in system filter] +cindex:[%defer% in system filter] +There are three extra commands (%defer%, %freeze% and %fail%) which are always +available in system filters, but are not normally enabled in users' filters. +(See the %allow_defer%, +%allow_freeze% and %allow_fail% options for the ^redirect^ router.) These +commands can optionally be followed by the word %text% and a string containing +an error message, for example: + + fail text "this message looks like spam to me" + +The keyword %text% is optional if the next character is a double quote. + +The %defer% command defers delivery of the original recipients of the message. +The %fail% command causes all the original recipients to be failed, and a +bounce message to be created. The %freeze% command suspends all delivery +attempts for the original recipients. In all cases, any new deliveries that are +specified by the filter are attempted as normal after the filter has run. + +The %freeze% command is ignored if the message has been manually unfrozen and +not manually frozen since. This means that automatic freezing by a system +filter can be used as a way of checking out suspicious messages. If a message +is found to be all right, manually unfreezing it allows it to be delivered. + +cindex:[log,%fail% command log line] +cindex:[%fail%,log line; reducing] +The text given with a fail command is used as part of the bounce message as +well as being written to the log. If the message is quite long, this can fill +up a lot of log space when such failures are common. To reduce the size of the +log message, Exim interprets the text in a special way if it starts with the +two characters `<<` and contains `>>` later. The text between these two +strings is written to the log, and the rest of the text is used in the bounce +message. For example: + +.... +fail "<<filter test 1>>Your message is rejected \ + because it contains attachments that we are \ + not prepared to receive." +.... + + +cindex:[loop,caused by %fail%] +Take great care with the %fail% command when basing the decision to fail on the +contents of the message, because the bounce message will of course include the +contents of the original message and will therefore trigger the %fail% command +again (causing a mail loop) unless steps are taken to prevent this. Testing the +%error_message% condition is one way to prevent this. You could use, for +example + + if $message_body contains "this is spam" and not error_message + then fail text "spam is not wanted here" endif + +though of course that might let through unwanted bounce messages. The +alternative is clever checking of the body and/or headers to detect bounces +generated by the filter. + +The interpretation of a system filter file ceases after a +%defer%, +%freeze%, or %fail% command is obeyed. However, any deliveries that were set up +earlier in the filter file are honoured, so you can use a sequence such as + + mail ... + freeze + +to send a specified message when the system filter is freezing (or deferring or +failing) a message. The normal deliveries for the message do not, of course, +take place. + + + +[[SECTaddremheasys]] +Adding and removing headers in a system filter +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[header lines,adding; in system filter] +cindex:[header lines,removing; in system filter] +cindex:[filter,header lines; adding/removing] +Two filter commands that are available only in system filters are: + + headers add <string> + headers remove <string> + +The argument for the %headers add% is a string that is expanded and then added +to the end of the message's headers. It is the responsibility of the filter +maintainer to make sure it conforms to RFC 2822 syntax. Leading white space is +ignored, and if the string is otherwise empty, or if the expansion is forced to +fail, the command has no effect. + +You can use ``\n'' within the string, followed by white space, to specify +continued header lines. More than one header may be added in one command by +including ``\n'' within the string without any following white space. For +example: + +.... +headers add "X-header-1: ....\n \ + continuation of X-header-1 ...\n\ + X-header-2: ...." +.... + +Note that the header line continuation white space after the first newline must +be placed before the backslash that continues the input string, because white +space after input continuations is ignored. + +The argument for %headers remove% is a colon-separated list of header names. +This command applies only to those headers that are stored with the message; +those that are added at delivery time (such as 'Envelope-To:' and +'Return-Path:') cannot be removed by this means. If there is more than one +header with the same name, they are all removed. + +The %headers% command in a system filter makes an immediate change to the set +of header lines that was received with the message (with possible additions +from ACL processing). Subsequent commands in the system filter operate on the +modified set, which also forms the basis for subsequent message delivery. +Unless further modified during routing or transporting, this set of headers is +used for all recipients of the message. + +During routing and transporting, the variables that refer to the contents of +header lines refer only to those lines that are in this set. Thus, header lines +that are added by a system filter are visible to users' filter files and to all +routers and transports. This contrasts with the manipulation of header lines by +routers and transports, which is not immediate, but which instead is saved up +until the message is actually being written (see section <<SECTheadersaddrem>>). + +If the message is not delivered at the first attempt, header lines that were +added by the system filter are stored with the message, and so are still +present at the next delivery attempt. Header lines that were removed are still +present, but marked ``deleted'' so that they are not transported with the +message. For this reason, it is usual to make the %headers% command conditional +on %first_delivery% so that the set of header lines is not modified more than +once. + +Because header modification in a system filter acts immediately, you have to +use an indirect approach if you want to modify the contents of a header line. +For example: + + headers add "Old-Subject: $h_subject:" + headers remove "Subject" + headers add "Subject: new subject (was: $h_old-subject:)" + headers remove "Old-Subject" + + + + + +Setting an errors address in a system filter +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[envelope sender] +In a system filter, if a %deliver% command is followed by + + errors_to <some address> + +in order to change the envelope sender (and hence the error reporting) for that +delivery, any address may be specified. (In a user filter, only the current +user's address can be set.) For example, if some mail is being monitored, you +might use + + unseen deliver monitor@spying.example errors_to root@local.example + +to take a copy which would not be sent back to the normal error reporting +address if its delivery failed. + + + +[[SECTperaddfil]] +Per-address filtering +~~~~~~~~~~~~~~~~~~~~~ +In contrast to the system filter, which is run just once per message for each +delivery attempt, it is also possible to set up a system-wide filtering +operation that runs once for each recipient address. In this case, variables +such as $local_part$ and $domain$ can be used, and indeed, the choice of +filter file could be made dependent on them. This is an example of a router +which implements such a filter: + + central_filter: + check_local_user + driver = redirect + domains = +local_domains + file = /central/filters/$local_part + no_verify + allow_filter + allow_freeze + +The filter is run in a separate process under its own uid. Therefore, either +%check_local_user% must be set (as above), in which case the filter is run as +the local user, or the %user% option must be used to specify which user to use. +If both are set, %user% overrides. + +Care should be taken to ensure that none of the commands in the filter file +specify a significant delivery if the message is to go on to be delivered to +its intended recipient. The router will not then claim to have dealt with the +address, so it will be passed on to subsequent routers to be delivered in the +normal way. + + + + + + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// + +[[CHAPmsgproc]] +Message processing +------------------ +cindex:[message,general processing] +Exim performs various transformations on the sender and recipient addresses of +all messages that it handles, and also on the messages' header lines. Some of +these are optional and configurable, while others always take place. All of +this processing, except rewriting as a result of routing, and the addition or +removal of header lines while delivering, happens when a message is received, +before it is placed on Exim's queue. + +Some of the automatic processing takes place by default only for +``locally-originated'' messages. This adjective is used to describe messages that +are not received over TCP/IP, but instead are passed to an Exim process on its +standard input. This includes the interactive ``local SMTP'' case that is set up +by the %-bs% command line option. + +*Note*: messages received over TCP/IP on the loopback interface (127.0.0.1 +or ::1) are not considered to be locally-originated. Exim does not treat the +loopback interface specially in any way. + +If you want the loopback interface to be treated specially, you must ensure +that there are appropriate entries in your ACLs. + + + + +[[SECTsubmodnon]] +Submission mode for non-local messages +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[message,submission] +cindex:[submission mode] +Processing that happens automatically for locally-originated messages can also +be requested for other messages. The term ``submission mode'' is used to describe +this state. Submisssion mode is set by the modifier + + control = submission + +in a MAIL, RCPT, or pre-data ACL for an incoming SMTP message (see +sections <<SECTACLmodi>> and <<SECTcontrols>>). This makes Exim treat the message +as a local submission, and is normally used when the source of the message is +known to be an MUA running on a client host (as opposed to an MTA). For +example, to set submission mode for messages originating on the IPv4 loopback +interface, you could include the following in the MAIL ACL: + + warn hosts = 127.0.0.1 + control = submission + +There are some options that can be used when setting submission mode. A slash +is used to separate options. For example: + + control = submission/sender_retain + +Specifying %sender_retain% has the effect of setting %local_sender_retain% +true and %local_from_check% false for the current incoming message. The first +of these allows an existing 'Sender:' header in the message to remain, and the +second suppresses the check to ensure that 'From:' matches the authenticated +sender. With this setting, Exim still fixes up messages by adding 'Date:' and +'Message-ID:' header lines if they are missing, but makes no attempt to check +sender authenticity in header lines. + +A submission mode setting may also specify a domain to be used when generating +a 'From:' or 'Sender:' header. For example: + + control = submission/domain=some.domain + +The domain may be empty. How this value is used is described in sections +<<SECTthefrohea>> and <<SECTthesenhea>>. + + + + + +[[SECTlineendings]] +Line endings +~~~~~~~~~~~~ +cindex:[line endings] +cindex:[carriage return] +cindex:[linefeed] +RFC 2821 specifies that CRLF (two characters: carriage-return, followed by +linefeed) is the line ending for messages transmitted over the Internet using +SMTP over TCP/IP. However, within individual operating systems, different +conventions are used. For example, Unix-like systems use just LF, but others +use CRLF or just CR. + +Exim was designed for Unix-like systems, and internally, it stores messages +using the system's convention of a single LF as a line terminator. When +receiving a message, all line endings are translated to this standard format. +Originally, it was thought that programs that passed messages directly to an +MTA within an operating system would use that system's convention. Experience +has shown that this is not the case; for example, there are Unix applications +that use CRLF in this circumstance. For this reason, and for compatibility with +other MTAs, the way Exim handles line endings for all messages is now as +follows: + +- LF not preceded by CR is treated as a line ending. + +- CR is treated as a line ending; if it is immediately followed by LF, the LF +is ignored. + +- The sequence ``CR, dot, CR'' does not terminate an incoming SMTP message, +nor a local message in the state where a line containing only a dot is a +terminator. + +- If a bare CR is encountered within a header line, an extra space is added after +the line terminator so as not to end the header line. The reasoning behind this +is that bare CRs in header lines are most likely either to be mistakes, or +people trying to play silly games. + +- If the first header line received in a message ends with CRLF, a subsequent +bare LF in a header line is treated in the same way as a bare CR in a header +line. + + + + + +Unqualified addresses +~~~~~~~~~~~~~~~~~~~~~ +cindex:[unqualified addresses] +cindex:[address,qualification] +By default, Exim expects every envelope address it receives from an external +host to be fully qualified. Unqualified addresses cause negative responses to +SMTP commands. However, because SMTP is used as a means of transporting +messages from MUAs running on personal workstations, there is sometimes a +requirement to accept unqualified addresses from specific hosts or IP networks. + +Exim has two options that separately control which hosts may send unqualified +sender or receipient addresses in SMTP commands, namely +%sender_unqualified_hosts% and %recipient_unqualified_hosts%. In both +cases, if an unqualified address is accepted, it is qualified by adding the +value of %qualify_domain% or %qualify_recipient%, as appropriate. + +cindex:[%qualify_domain%] +cindex:[%qualify_recipient%] +Unqualified addresses in header lines are automatically qualified for messages +that are locally originated, unless the %-bnq% option is given on the command +line. For messages received over SMTP, unqualified addresses in header lines +are qualified only if unqualified addresses are permitted in SMTP commands. In +other words, such qualification is also controlled by +%sender_unqualified_hosts% and %recipient_unqualified_hosts%, + + + + +The UUCP From line +~~~~~~~~~~~~~~~~~~ +cindex:[``From'' line] +cindex:[UUCP,``From'' line] +cindex:[sender,address] +cindex:[%uucp_from_pattern%] +cindex:[%uucp_from_sender%] +cindex:[envelope sender] +cindex:[Sendmail compatibility,``From'' line] +Messages that have come from UUCP (and some other applications) often begin +with a line containing the envelope sender and a timestamp, following the word +``From''. Examples of two common formats are: + + From a.oakley@berlin.mus Fri Jan 5 12:35 GMT 1996 + From f.butler@berlin.mus Fri, 7 Jan 97 14:00:00 GMT + +This line precedes the RFC 2822 header lines. For compatibility with Sendmail, +Exim recognizes such lines at the start of messages that are submitted to it +via the command line (that is, on the standard input). It does not recognize +such lines in incoming SMTP messages, unless the sending host matches +%ignore_fromline_hosts% or the %-bs% option was used for a local message and +%ignore_fromline_local% is set. The recognition is controlled by a regular +expression that is defined by the %uucp_from_pattern% option, whose default +value matches the two common cases shown above and puts the address that +follows ``From'' into $1$. + +cindex:[numerical variables ($1$ $2$ etc),in ``From '' line handling] +When the caller of Exim for a non-SMTP message that contains a ``From'' line is a +trusted user, the message's sender address is constructed by expanding the +contents of %uucp_sender_address%, whose default value is ``\$1''. This is then +parsed as an RFC 2822 address. If there is no domain, the local part is +qualified with %qualify_domain% unless it is the empty string. However, if the +command line %-f% option is used, it overrides the ``From'' line. + +If the caller of Exim is not trusted, the ``From'' line is recognized, but the +sender address is not changed. This is also the case for incoming SMTP messages +that are permitted to contain ``From'' lines. + +Only one ``From'' line is recognized. If there is more than one, the second is +treated as a data line that starts the body of the message, as it is not valid +as a header line. This also happens if a ``From'' line is present in an incoming +SMTP message from a source that is not permitted to send them. + + + +Resent- header lines +~~~~~~~~~~~~~~~~~~~~ +cindex:[%Resent-% header lines] +RFC 2822 makes provision for sets of header lines starting with the string +`Resent-` to be added to a message when it is resent by the original +recipient to somebody else. These headers are 'Resent-Date:', 'Resent-From:', +'Resent-Sender:', 'Resent-To:', 'Resent-Cc:', 'Resent-Bcc:' and +'Resent-Message-ID:'. The RFC says: + +'Resent fields are strictly informational. They MUST NOT be used in the normal +processing of replies or other such automatic actions on messages.' + +This leaves things a bit vague as far as other processing actions such as +address rewriting are concerned. Exim treats %Resent-% header lines as +follows: + +- A 'Resent-From:' line that just contains the login id of the submitting user +is automatically rewritten in the same way as 'From:' (see below). + +- If there's a rewriting rule for a particular header line, it is also applied to +%Resent-% header lines of the same type. For example, a rule that rewrites +'From:' also rewrites 'Resent-From:'. + +- For local messages, if 'Sender:' is removed on input, 'Resent-Sender:' is also +removed. + +- For a locally-submitted message, +if there are any %Resent-% header lines but no 'Resent-Date:', +'Resent-From:', or 'Resent-Message-Id:', they are added as necessary. It is +the contents of 'Resent-Message-Id:' (rather than 'Message-Id:') which are +included in log lines in this case. + +- The logic for adding 'Sender:' is duplicated for 'Resent-Sender:' when any +%Resent-% header lines are present. + + + + +The Auto-Submitted: header line +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Whenever Exim generates a bounce or a delay warning message, it includes the +header line + + Auto-Submitted: auto-generated + + + + +The Bcc: header line +~~~~~~~~~~~~~~~~~~~~ +cindex:['Bcc:' header line] +If Exim is called with the %-t% option, to take recipient addresses from a +message's header, it removes any 'Bcc:' header line that may exist (after +extracting its addresses). If %-t% is not present on the command line, any +existing 'Bcc:' is not removed. + + +The Date: header line +~~~~~~~~~~~~~~~~~~~~~ +cindex:['Date:' header line] +If a locally-generated +or submission-mode +message has no 'Date:' header line, Exim adds one, using the current date and +time. + + +The Delivery-date: header line +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:['Delivery-date:' header line] +cindex:[%delivery_date_remove%] +'Delivery-date:' header lines are not part of the standard RFC 2822 header +set. Exim can be configured to add them to the final delivery of messages. (See +the generic %delivery_date_add% transport option.) They should not be present +in messages in transit. If the %delivery_date_remove% configuration option is +set (the default), Exim removes 'Delivery-date:' header lines from incoming +messages. + + +The Envelope-to: header line +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:['Envelope-to:' header line] +cindex:[%envelope_to_remove%] +'Envelope-to:' header lines are not part of the standard RFC 2822 header set. +Exim can be configured to add them to the final delivery of messages. (See the +generic %envelope_to_add% transport option.) They should not be present in +messages in transit. If the %envelope_to_remove% configuration option is set +(the default), Exim removes 'Envelope-to:' header lines from incoming +messages. + + +[[SECTthefrohea]] +The From: header line +~~~~~~~~~~~~~~~~~~~~~ +cindex:['From:' header line] +cindex:[Sendmail compatibility,``From'' line] +cindex:[message,submission] +cindex:[submission mode] +If a submission-mode message does not contain a 'From:' header line, Exim adds +one if either of the following conditions is true: + +- The envelope sender address is not empty (that is, this is not a bounce +message). The added header line copies the envelope sender address. + +- The SMTP session is authenticated and $authenticated_id$ is not empty. + +.. If no domain is specified by the submission control, the local part is +$authenticated_id$ and the domain is $qualify_domain$. + +.. If a non-empty domain is specified by the submission control, the local +part is $authenticated_id$, and the the domain is the specified domain. + +.. If an empty domain is specified by the submission control, +$authenticated_id$ is assumed to be the complete address. + +A non-empty envelope sender takes precedence. + +If a locally-generated incoming message does not contain a 'From:' header +line, Exim adds one containing the sender's address. The calling user's login +name and full name are used to construct the address, as described in section +<<SECTconstr>>. They are obtained from the password data by calling +'getpwuid()' (but see the %unknown_login% configuration option). The address +is qualified with %qualify_domain%. + +For compatibility with Sendmail, if an incoming, non-SMTP message has a +'From:' header line containing just the unqualified login name of the calling +user, this is replaced by an address containing the user's login name and full +name as described in section <<SECTconstr>>. + + +The Message-ID: header line +~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:['Message-ID:' header line] +cindex:[message,submission] +If a locally-generated or submission-mode incoming message does not contain a +'Message-ID:' or 'Resent-Message-ID:' header line, Exim adds one to the +message. If there are any 'Resent-:' headers in the message, it creates +'Resent-Message-ID:'. The id is constructed from Exim's internal message id, +preceded by the letter E to ensure it starts with a letter, and followed by @ +and the primary host name. Additional information can be included in this +header line by setting the +cindex:[%message_id_header_text%] +%message_id_header_text% and/or %message_id_header_domain% options. + + + +The Received: header line +~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:['Received:' header line] +A 'Received:' header line is added at the start of every message. The contents +are defined by the %received_header_text% configuration option, and Exim +automatically adds a semicolon and a timestamp to the configured string. + +The 'Received:' header is generated as soon as the message's header lines have +been received. At this stage, the timestamp in the 'Received:' header line is +the time that the message started to be received. This is the value that is +seen by the DATA ACL and by the 'local_scan()' function. + +Once a message is accepted, the timestamp in the 'Received:' header line is +changed to the time of acceptance, which is (apart from a small delay while the +-H spool file is written) the earliest time at which delivery could start. + + + +The Return-path: header line +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:['Return-path:' header line] +cindex:[%return_path_remove%] +'Return-path:' header lines are defined as something an MTA may insert when +it does the final delivery of messages. (See the generic %return_path_add% +transport option.) Therefore, they should not be present in messages in +transit. If the %return_path_remove% configuration option is set (the +default), Exim removes 'Return-path:' header lines from incoming messages. + + + +[[SECTthesenhea]] +The Sender: header line +~~~~~~~~~~~~~~~~~~~~~~~ +cindex:['Sender:' header line] +cindex:[message,submission] +For a locally-originated message from an untrusted user, Exim may remove an +existing 'Sender:' header line, and it may add a new one. You can modify these +actions by setting %local_sender_retain% true or %local_from_check% false. + +When a local message is received from an untrusted user and +%local_from_check% is true (the default), a check is made to see if the +address given in the 'From:' header line is the correct (local) sender of the +message. The address that is expected has the login name as the local part and +the value of %qualify_domain% as the domain. Prefixes and suffixes for the +local part can be permitted by setting %local_from_prefix% and +%local_from_suffix% appropriately. If 'From:' does not contain the correct +sender, a 'Sender:' line is added to the message. + +If you set %local_from_check% false, this checking does not occur. However, +the removal of an existing 'Sender:' line still happens, unless you also set +%local_sender_retain% to be true. It is not possible to set both of these +options true at the same time. + +cindex:[submission mode] +By default, no processing of 'Sender:' header lines is done for messages +received over TCP/IP or for messages submitted by trusted users. However, when +a message is received over TCP/IP in submission mode, and %sender_retain% is +not specified on the submission control, the following processing takes place: + +First, any existing 'Sender:' lines are removed. Then, if the SMTP session is +authenticated, and $authenticated_id$ is not empty, a sender address is +created as follows: + +- If no domain is specified by the submission control, the local part is +$authenticated_id$ and the domain is $qualify_domain$. + +- If a non-empty domain is specified by the submission control, the local part is +$authenticated_id$, and the the domain is the specified domain. + +- If an empty domain is specified by the submission control, +$authenticated_id$ is assumed to be the complete address. + +This address is compared with the address in the 'From:' header line. If they +are different, a 'Sender:' header line containing the created address is +added. Prefixes and suffixes for the local part in 'From:' can be permitted by +setting %local_from_prefix% and %local_from_suffix% appropriately. + + + + +[[SECTheadersaddrem]] +Adding and removing header lines in routers and transports +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[header lines,adding; in router or transport] +cindex:[header lines,removing; in router or transport] +When a message is delivered, the addition and removal of header lines can be +specified in a system filter, or on any of the routers and transports that +process the message. Section <<SECTaddremheasys>> contains details about +modifying headers in a system filter. + +In contrast to what happens in a system filter, header modifications that are +specified on routers and transports apply only to the particular recipient +addresses that are being processed by those routers and transports. These +changes do not actually take place until a copy of the message is being +transported. Therefore, they do not affect the basic set of header lines, and +they do not affect the values of the variables that refer to header lines. + +For both routers and transports, the result of expanding a %headers_add% +option must be in the form of one or more RFC 2822 header lines, separated by +newlines (coded as ``\n''). For example: + +.... +headers_add = X-added-header: added by $primary_hostname\n\ + X-added-second: another added header line +.... + +Exim does not check the syntax of these added header lines. + +The result of expanding %headers_remove% must consist of a colon-separated +list of header names. This is confusing, because header names themselves are +often terminated by colons. In this case, the colons are the list separators, +not part of the names. For example: + + headers_remove = return-receipt-to:acknowledge-to + +When %headers_add% or %headers_remove% is specified on a router, its value is +expanded at routing time, and then associated with all addresses that are +accepted by that router, and also with any new addresses that it generates. If +an address passes through several routers as a result of aliasing or +forwarding, the changes are cumulative. + +cindex:[%unseen% option] +However, this does not apply to multiple routers that result from the use of +the %unseen% option. Any header modifications that were specified by the +``unseen'' router or its predecessors apply only to the ``unseen'' delivery. + +Addresses that end up with different %headers_add% or %headers_remove% +settings cannot be delivered together in a batch, so a transport is always +dealing with a set of addresses that have the same header-processing +requirements. + +The transport starts by writing the original set of header lines that arrived +with the message, possibly modified by the system filter. As it writes out +these lines, it consults the list of header names that were attached to the +recipient address(es) by %headers_remove% options in routers, and it also +consults the transport's own %headers_remove% option. Header lines whose names +are on either of these lists are not written out. If there are multiple +instances of any listed header, they are all skipped. + +After the remaining original header lines have been written, new header +lines that were specified by routers' %headers_add% options are written, in +the order in which they were attached to the address. These are followed by any +header lines specified by the transport's %headers_add% option. + +This way of handling header line modifications in routers and transports has +the following consequences: + +- The original set of header lines, possibly modified by the system filter, +remains ``visible'', in the sense that the $header_$'xxx' variables refer to +it, at all times. + +- Header lines that are added by a router's +%headers_add% option are not accessible by means of the $header_$'xxx' +expansion syntax in subsequent routers or the transport. + +- Conversely, header lines that are specified for removal by %headers_remove% in +a router remain visible to subsequent routers and the transport. + +- Headers added to an address by %headers_add% in a router cannot be removed by +a later router or by a transport. + +- An added header can refer to the contents of an original header that is to be +removed, even it has the same name as the added header. For example: + + headers_remove = subject + headers_add = Subject: new subject (was: $h_subject:) + + +*Warning*: The %headers_add% and %headers_remove% options cannot be used +for a ^redirect^ router that has the %one_time% option set. + + + + + +[[SECTconstr]] +Constructed addresses +~~~~~~~~~~~~~~~~~~~~~ +cindex:[address,constructed] +cindex:[constructed address] +When Exim constructs a sender address for a locally-generated message, it uses +the form + + <user name> <<login>@<qualify_domain>> + +For example: + + Zaphod Beeblebrox <zaphod@end.univ.example> + +The user name is obtained from the %-F% command line option if set, or +otherwise by looking up the calling user by 'getpwuid()' and extracting the +``gecos'' field from the password entry. If the ``gecos'' field contains an +ampersand character, this is replaced by the login name with the first letter +upper cased, as is conventional in a number of operating systems. See the +%gecos_name% option for a way to tailor the handling of the ``gecos'' field. The +%unknown_username% option can be used to specify user names in cases when +there is no password file entry. + +In all cases, the user name is made to conform to RFC 2822 by quoting all or +parts of it if necessary. In addition, if it contains any non-printing +characters, it is encoded as described in RFC 2047, which defines a way of +including non-ASCII characters in header lines. +The value of the %headers_charset% option specifies the name of the encoding +that is used (the characters are assumed to be in this encoding). +The setting of %print_topbitchars% controls whether characters with the top +bit set (that is, with codes greater than 127) count as printing characters or +not. + + + +Case of local parts +~~~~~~~~~~~~~~~~~~~ +cindex:[case of local parts] +cindex:[local part,case of] +RFC 2822 states that the case of letters in the local parts of addresses cannot +be assumed to be non-significant. Exim preserves the case of local parts of +addresses, but by default it uses a lower-cased form when it is routing, +because on most Unix systems, usernames are in lower case and case-insensitive +routing is required. However, any particular router can be made to use the +original case for local parts by setting the %caseful_local_part% generic +router option. + +cindex:[mixed-case login names] +If you must have mixed-case user names on your system, the best way to proceed, +assuming you want case-independent handling of incoming email, is to set up +your first router to convert incoming local parts in your domains to the +correct case by means of a file lookup. For example: + +.... +correct_case: + driver = redirect + domains = +local_domains + data = ${lookup{$local_part}cdb\ + {/etc/usercased.cdb}{$value}fail}\ + @$domain +.... + +For this router, the local part is forced to lower case by the default action +(%caseful_local_part% is not set). The lower-cased local part is used to look +up a new local part in the correct case. If you then set %caseful_local_part% +on any subsequent routers which process your domains, they will operate on +local parts with the correct case in a case-sensitive manner. + + + +Dots in local parts +~~~~~~~~~~~~~~~~~~~ +cindex:[dot,in local part] +cindex:[local part,dots in] +RFC 2822 forbids empty components in local parts. That is, an unquoted local +part may not begin or end with a dot, nor have two consecutive dots in the +middle. However, it seems that many MTAs do not enforce this, so Exim permits +empty components for compatibility. + + + +Rewriting addresses +~~~~~~~~~~~~~~~~~~~ +cindex:[rewriting,addresses] +Rewriting of sender and recipient addresses, and addresses in headers, can +happen automatically, or as the result of configuration options, as described +in chapter <<CHAPrewrite>>. The headers that may be affected by this are 'Bcc:', +'Cc:', 'From:', 'Reply-To:', 'Sender:', and 'To:'. + +Automatic rewriting includes qualification, as mentioned above. The other case +in which it can happen is when an incomplete non-local domain is given. The +routing process may cause this to be expanded into the full domain name. For +example, a header such as + + To: hare@teaparty + +might get rewritten as + + To: hare@teaparty.wonderland.fict.example + +Rewriting as a result of routing is the one kind of message processing that +does not happen at input time, as it cannot be done until the address has +been routed. + +Strictly, one should not do 'any' deliveries of a message until all its +addresses have been routed, in case any of the headers get changed as a +result of routing. However, doing this in practice would hold up many +deliveries for unreasonable amounts of time, just because one address could not +immediately be routed. Exim therefore does not delay other deliveries when +routing of one or more addresses is deferred. + + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// + +[[CHAPSMTP]] +SMTP processing +--------------- +cindex:[SMTP,processing details] +cindex:[LMTP,processing details] +Exim supports a number of different ways of using the SMTP protocol, and its +LMTP variant, which is an interactive protocol for transferring messages into a +closed mail store application. This chapter contains details of how SMTP is +processed. For incoming mail, the following are available: + +- SMTP over TCP/IP (Exim daemon or 'inetd'); + +- SMTP over the standard input and output (the %-bs% option); + +- Batched SMTP on the standard input (the %-bS% option). + +For mail delivery, the following are available: + +- SMTP over TCP/IP (the ^smtp^ transport); + +- LMTP over TCP/IP (the ^smtp^ transport with the %protocol% option set to +``lmtp''); + +- LMTP over a pipe to a process running in the local host (the ^lmtp^ +transport); + +- Batched SMTP to a file or pipe (the ^appendfile^ and ^pipe^ transports with +the %use_bsmtp% option set). + +'Batched SMTP' is the name for a process in which batches of messages are +stored in or read from files (or pipes), in a format in which SMTP commands are +used to contain the envelope information. + + + +[[SECToutSMTPTCP]] +Outgoing SMTP and LMTP over TCP/IP +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[SMTP,outgoing over TCP/IP] +cindex:[outgoing SMTP over TCP/IP] +cindex:[LMTP,over TCP/IP] +cindex:[outgoing LMTP over TCP/IP] +cindex:[EHLO] +cindex:[HELO] +cindex:[SIZE option on MAIL command] +Outgoing SMTP and LMTP over TCP/IP is implemented by the ^smtp^ transport. +The %protocol% option selects which protocol is to be used, but the actual +processing is the same in both cases. + +If, in response to its EHLO command, Exim is told that the SIZE +parameter is supported, it adds SIZE=<'n'> to each subsequent MAIL +command. The value of <'n'> is the message size plus the value of the +%size_addition% option (default 1024) to allow for additions to the message +such as per-transport header lines, or changes made in a +cindex:[transport,filter] +cindex:[filter,transport filter] +transport filter. If %size_addition% is set negative, the use of SIZE is +suppressed. + +If the remote server advertises support for PIPELINING, Exim uses the +pipelining extension to SMTP (RFC 2197) to reduce the number of TCP/IP packets +required for the transaction. + +If the remote server advertises support for the STARTTLS command, and Exim +was built to support TLS encryption, it tries to start a TLS session unless the +server matches %hosts_avoid_tls%. See chapter <<CHAPTLS>> for more details. + +If the remote server advertises support for the AUTH command, Exim scans +the authenticators configuration for any suitable client settings, as described +in chapter <<CHAPSMTPAUTH>>. + +cindex:[carriage return] +cindex:[linefeed] +Responses from the remote host are supposed to be terminated by CR followed by +LF. However, there are known to be hosts that do not send CR characters, so in +order to be able to interwork with such hosts, Exim treats LF on its own as a +line terminator. + +If a message contains a number of different addresses, all those with the same +characteristics (for example, the same envelope sender) that resolve to the +same set of hosts, in the same order, are sent in a single SMTP transaction, +even if they are for different domains, unless there are more than the setting +of the %max_rcpts% option in the ^smtp^ transport allows, in which case they +are split into groups containing no more than %max_rcpts% addresses each. If +%remote_max_parallel% is greater than one, such groups may be sent in +parallel sessions. The order of hosts with identical MX values is not +significant when checking whether addresses can be batched in this way. + +When the ^smtp^ transport suffers a temporary failure that is not +message-related, Exim updates its transport-specific database, which contains +records indexed by host name that remember which messages are waiting for each +particular host. It also updates the retry database with new retry times. + +cindex:[hints database,retry keys] +Exim's retry hints are based on host name plus IP address, so if one address of +a multi-homed host is broken, it will soon be skipped most of the time. +See the next section for more detail about error handling. + +cindex:[SMTP,passed connection] +cindex:[SMTP,batching over TCP/IP] +When a message is successfully delivered over a TCP/IP SMTP connection, Exim +looks in the hints database for the transport to see if there are any queued +messages waiting for the host to which it is connected. If it finds one, it +creates a new Exim process using the %-MC% option (which can only be used by a +process running as root or the Exim user) and passes the TCP/IP socket to it so +that it can deliver another message using the same socket. The new process does +only those deliveries that are routed to the connected host, and may in turn +pass the socket on to a third process, and so on. + +The %connection_max_messages% option of the ^smtp^ transport can be used to +limit the number of messages sent down a single TCP/IP connection. + +cindex:[asterisk,after IP address] +The second and subsequent messages delivered down an existing connection are +identified in the main log by the addition of an asterisk after the closing +square bracket of the IP address. + + + + +[[SECToutSMTPerr]] +Errors in outgoing SMTP +~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[error,in outgoing SMTP] +cindex:[SMTP,errors in outgoing] +cindex:[host,error] +Three different kinds of error are recognized for outgoing SMTP: host errors, +message errors, and recipient errors. + +. A host error is not associated with a particular message or with a +particular recipient of a message. The host errors are: ++ +-- +- Connection refused or timed out, + +- Any error response code on connection, + +- Any error response code to EHLO or HELO, + +- Loss of connection at any time, except after ``.'', + +- I/O errors at any time, + +- Timeouts during the session, other than in response to MAIL, RCPT or +the ``.'' at the end of the data. +-- ++ +For a host error, a permanent error response on connection, or in response to +EHLO, causes all addresses routed to the host to be failed. Any other host +error causes all addresses to be deferred, and retry data to be created for the +host. It is not tried again, for any message, until its retry time arrives. If +the current set of addresses are not all delivered in this run (to some +alternative host), the message is added to the list of those waiting for this +host, so if it is still undelivered when a subsequent successful delivery is +made to the host, it will be sent down the same SMTP connection. + +. cindex:[message,error] +A message error is associated with a particular message when sent to a +particular host, but not with a particular recipient of the message. The +message errors are: ++ +-- +- Any error response code to MAIL, DATA, or the ``.'' that terminates +the data, + +- Timeout after MAIL, + +- Timeout or loss of connection after the ``.'' that terminates the data. A +timeout after the DATA command itself is treated as a host error, as is loss of +connection at any other time. +-- ++ +For a message error, a permanent error response (5##'xx') causes all addresses +to be failed, and a delivery error report to be returned to the sender. A +temporary error response (4##'xx'), or one of the timeouts, causes all +addresses to be deferred. Retry data is not created for the host, but instead, +a retry record for the combination of host plus message id is created. The +message is not added to the list of those waiting for this host. This ensures +that the failing message will not be sent to this host again until the retry +time arrives. However, other messages that are routed to the host are not +affected, so if it is some property of the message that is causing the error, +it will not stop the delivery of other mail. ++ +If the remote host specified support for the SIZE parameter in its response +to EHLO, Exim adds SIZE='nnn' to the MAIL command, so an +over-large message will cause a message error because the error arrives as a +response to MAIL. + +. cindex:[recipient,error] +A recipient error is associated with a particular recipient of a message. The +recipient errors are: ++ +-- +- Any error response to RCPT, + +- Timeout after RCPT. +-- ++ +For a recipient error, a permanent error response (5##'xx') causes the +recipient address to be failed, and a bounce message to be returned to the +sender. A temporary error response (4##'xx') or a timeout causes the failing +address to be deferred, and routing retry data to be created for it. This is +used to delay processing of the address in subsequent queue runs, until its +routing retry time arrives. This applies to all messages, but because it +operates only in queue runs, one attempt will be made to deliver a new message +to the failing address before the delay starts to operate. This ensures that, +if the failure is really related to the message rather than the recipient +(``message too big for this recipient'' is a possible example), other messages +have a chance of getting delivered. If a delivery to the address does succeed, +the retry information gets cleared, so all stuck messages get tried again, and +the retry clock is reset. ++ +The message is not added to the list of those waiting for this host. Use of the +host for other messages is unaffected, and except in the case of a timeout, +other recipients are processed independently, and may be successfully delivered +in the current SMTP session. After a timeout it is of course impossible to +proceed with the session, so all addresses get deferred. However, those other +than the one that failed do not suffer any subsequent retry delays. Therefore, +if one recipient is causing trouble, the others have a chance of getting +through when a subsequent delivery attempt occurs before the failing +recipient's retry time. + +/// +End of list +/// + +In all cases, if there are other hosts (or IP addresses) available for the +current set of addresses (for example, from multiple MX records), they are +tried in this run for any undelivered addresses, subject of course to their +own retry data. In other words, recipient error retry data does not take effect +until the next delivery attempt. + +Some hosts have been observed to give temporary error responses to every +MAIL command at certain times (``insufficient space'' has been seen). It +would be nice if such circumstances could be recognized, and defer data for the +host itself created, but this is not possible within the current Exim design. +What actually happens is that retry data for every (host, message) combination +is created. + +The reason that timeouts after MAIL and RCPT are treated specially is that +these can sometimes arise as a result of the remote host's verification +procedures. Exim makes this assumption, and treats them as if a temporary error +response had been received. A timeout after ``.'' is treated specially because +it is known that some broken implementations fail to recognize the end of the +message if the last character of the last line is a binary zero. Thus, it is +helpful to treat this case as a message error. + +Timeouts at other times are treated as host errors, assuming a problem with the +host, or the connection to it. If a timeout after MAIL, RCPT, +or ``.'' is really a connection problem, the assumption is that at the next try +the timeout is likely to occur at some other point in the dialogue, causing it +then to be treated as a host error. + +There is experimental evidence that some MTAs drop the connection after the +terminating ``.'' if they do not like the contents of the message for some +reason, in contravention of the RFC, which indicates that a 5##'xx' response +should be given. That is why Exim treats this case as a message rather than a +host error, in order not to delay other messages to the same host. + + + + + +Variable Envelope Return Paths (VERP) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[VERP] +cindex:[Variable Envelope Return Paths] +cindex:[envelope sender] +Variable Envelope Return Paths -- see +*ftp://koobera.math.uic.edu/www/proto/verp.txt[]* -- can be supported in Exim +by using the %return_path% generic transport option to rewrite the return path +at transport time. For example, the following could be used on an ^smtp^ +transport: + +.... +return_path = \ + ${if match {$return_path}{^(.+?)-request@your.dom.example\$}\ + {$1-request=$local_part%$domain@your.dom.example}fail} +.... + +This has the effect of rewriting the return path (envelope sender) on all +outgoing SMTP messages, if the local part of the original return path ends in +``-request'', and the domain is 'your.dom.example'. The rewriting inserts the +local part and domain of the recipient into the return path. Suppose, for +example, that a message whose return path has been set to +'somelist-request@your.dom.example' is sent to +'subscriber@other.dom.example'. In the transport, the return path is +rewritten as + + somelist-request=subscriber%other.dom.example@your.dom.example + +For this to work, you must arrange for outgoing messages that have ``-request'' +in their return paths to have just a single recipient. This can be done by +setting + + max_rcpt = 1 + +in the ^smtp^ transport. Otherwise a single copy of a message might be +addressed to several different recipients in the same domain, in which case +$local_part$ is not available (because it is not unique). Of course, if you +do start sending out messages with this kind of return path, you must also +configure Exim to accept the bounce messages that come back to those paths. +Typically this would be done by setting an %local_part_suffix% option for a +suitable router. + +The overhead incurred in using VERP depends very much on the size of the +message, the number of recipient addresses that resolve to the same remote +host, and the speed of the connection over which the message is being sent. If +a lot of addresses resolve to the same host and the connection is slow, sending +a separate copy of the message for each address may take substantially longer +than sending a single copy with many recipients (for which VERP cannot be +used). + + + +Incoming SMTP messages over TCP/IP +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[SMTP,incoming over TCP/IP] +cindex:[incoming SMTP over TCP/IP] +cindex:[inetd] +cindex:[daemon] +Incoming SMTP messages can be accepted in one of two ways: by running a +listening daemon, or by using 'inetd'. In the latter case, the entry in +_/etc/inetd.conf_ should be like this: + + smtp stream tcp nowait exim /opt/exim/bin/exim in.exim -bs + +Exim distinguishes between this case and the case of a locally running user +agent using the %-bs% option by checking whether or not the standard input is +a socket. When it is, either the port must be privileged (less than 1024), or +the caller must be root or the Exim user. If any other user passes a socket +with an unprivileged port number, Exim prints a message on the standard error +stream and exits with an error code. + +By default, Exim does not make a log entry when a remote host connects or +disconnects (either via the daemon or 'inetd'), unless the disconnection is +unexpected. It can be made to write such log entries by setting the +%smtp_connection% log selector. + +cindex:[carriage return] +cindex:[linefeed] +Commands from the remote host are supposed to be terminated by CR followed by +LF. However, there are known to be hosts that do not send CR characters. In +order to be able to interwork with such hosts, Exim treats LF on its own as a +line terminator. +Furthermore, because common code is used for receiving messages from all +sources, a CR on its own is also interpreted as a line terminator. However, the +sequence ``CR, dot, CR'' does not terminate incoming SMTP data. + +cindex:[EHLO,invalid data] +cindex:[HELO,invalid data] +One area that sometimes gives rise to problems concerns the EHLO or +HELO commands. Some clients send syntactically invalid versions of these +commands, which Exim rejects by default. (This is nothing to do with verifying +the data that is sent, so %helo_verify_hosts% is not relevant.) You can tell +Exim not to apply a syntax check by setting %helo_accept_junk_hosts% to +match the broken hosts that send invalid commands. + +cindex:[SIZE option on MAIL command] +cindex:[MAIL,SIZE option] +The amount of disk space available is checked whenever SIZE is received on +a MAIL command, independently of whether %message_size_limit% or +%check_spool_space% is configured, unless %smtp_check_spool_space% is set +false. A temporary error is given if there is not enough space. If +%check_spool_space% is set, the check is for that amount of space plus the +value given with SIZE, that is, it checks that the addition of the incoming +message will not reduce the space below the threshold. + +When a message is successfully received, Exim includes the local message id in +its response to the final ``.'' that terminates the data. If the remote host logs +this text it can help with tracing what has happened to a message. + +The Exim daemon can limit the number of simultaneous incoming connections it is +prepared to handle (see the %smtp_accept_max% option). It can also limit the +number of simultaneous incoming connections from a single remote host (see the +%smtp_accept_max_per_host% option). Additional connection attempts are +rejected using the SMTP temporary error code 421. + +The Exim daemon does not rely on the SIGCHLD signal to detect when a +subprocess has finished, as this can get lost at busy times. Instead, it looks +for completed subprocesses every time it wakes up. Provided there are other +things happening (new incoming calls, starts of queue runs), completed +processes will be noticed and tidied away. On very quiet systems you may +sometimes see a ``defunct'' Exim process hanging about. This is not a problem; it +will be noticed when the daemon next wakes up. + +When running as a daemon, Exim can reserve some SMTP slots for specific hosts, +and can also be set up to reject SMTP calls from non-reserved hosts at times of +high system load -- for details see the %smtp_accept_reserve%, +%smtp_load_reserve%, and %smtp_reserve_hosts% options. The load check +applies in both the daemon and 'inetd' cases. + +Exim normally starts a delivery process for each message received, though this +can be varied by means of the %-odq% command line option and the +%queue_only%, %queue_only_file%, and %queue_only_load% options. The number +of simultaneously running delivery processes started in this way from SMTP +input can be limited by the %smtp_accept_queue% and +%smtp_accept_queue_per_connection% options. When either limit is reached, +subsequently received messages are just put on the input queue without starting +a delivery process. + +The controls that involve counts of incoming SMTP calls (%smtp_accept_max%, +%smtp_accept_queue%, %smtp_accept_reserve%) are not available when Exim is +started up from the 'inetd' daemon, because in that case each connection is +handled by an entirely independent Exim process. Control by load average is, +however, available with 'inetd'. + +Exim can be configured to verify addresses in incoming SMTP commands as they +are received. See chapter <<CHAPACL>> for details. It can also be configured to +rewrite addresses at this time -- before any syntax checking is done. See +section <<SECTrewriteS>>. + +Exim can also be configured to limit the rate at which a client host submits +MAIL and RCPT commands in a single SMTP session. See the +%smtp_ratelimit_hosts% option. + + + +Unrecognized SMTP commands +~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[SMTP,unrecognized commands] +If Exim receives more than %smtp_max_unknown_commands% unrecognized SMTP +commands during a single SMTP connection, it drops the connection after sending +the error response to the last command. The default value for +%smtp_max_unknown_commands% is 3. This is a defence against some kinds of +abuse that subvert web servers into making connections to SMTP ports; in these +circumstances, a number of non-SMTP lines are sent first. + + +Syntax and protocol errors in SMTP commands +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[SMTP,syntax errors] +cindex:[SMTP,protocol errors] +A syntax error is detected if an SMTP command is recognized, but there is +something syntactically wrong with its data, for example, a malformed email +address in a RCPT command. Protocol errors include invalid command +sequencing such as RCPT before MAIL. If Exim receives more than +%smtp_max_synprot_errors% such commands during a single SMTP connection, it +drops the connection after sending the error response to the last command. The +default value for %smtp_max_synprot_errors% is 3. This is a defence against +broken clients that loop sending bad commands (yes, it has been seen). + + + +Use of non-mail SMTP commands +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[SMTP,non-mail commands] +The ``non-mail'' SMTP commands are those other than MAIL, RCPT, and +DATA. Exim counts such commands, and drops the connection if there are too +many of them in a single SMTP session. This action catches some +denial-of-service attempts and things like repeated failing AUTHs, or a mad +client looping sending EHLO. The global option %smtp_accept_max_nonmail% +defines what ``too many'' means. Its default value is 10. + +When a new message is expected, one occurrence of RSET is not counted. This +allows a client to send one RSET between messages (this is not necessary, +but some clients do it). Exim also allows one uncounted occurence of HELO +or EHLO, and one occurrence of STARTTLS between messages. After +starting up a TLS session, another EHLO is expected, and so it too is not +counted. + +The first occurrence of AUTH in a connection, or immediately following +STARTTLS is also not counted. Otherwise, all commands other than MAIL, +RCPT, DATA, and QUIT are counted. + +You can control which hosts are subject to the limit set by +%smtp_accept_max_nonmail% by setting +%smtp_accept_max_nonmail_hosts%. The default value is `\*`, which makes +the limit apply to all hosts. This option means that you can exclude any +specific badly-behaved hosts that you have to live with. + + + + +The VRFY and EXPN commands +~~~~~~~~~~~~~~~~~~~~~~~~~~ +When Exim receives a VRFY or EXPN command on a TCP/IP connection, it +runs the ACL specified by %acl_smtp_vrfy% or %acl_smtp_expn% (as +appropriate) in order to decide whether the command should be accepted or not. +If no ACL is defined, the command is rejected. + +cindex:[VRFY,processing] +When VRFY is accepted, it runs exactly the same code as when Exim is +called with the %-bv% option. + +cindex:[EXPN,processing] +When EXPN is accepted, a single-level expansion of the address is done. +EXPN is treated as an ``address test'' (similar to the %-bt% option) rather +than a verification (the %-bv% option). If an unqualified local part is given +as the argument to EXPN, it is qualified with %qualify_domain%. Rejections +of VRFY and EXPN commands are logged on the main and reject logs, and +VRFY verification failures are logged on the main log for consistency with +RCPT failures. + + + +[[SECTETRN]] +The ETRN command +~~~~~~~~~~~~~~~~ +cindex:[ETRN,processing] +RFC 1985 describes an SMTP command called ETRN that is designed to +overcome the security problems of the TURN command (which has fallen into +disuse). When Exim receives an ETRN command on a TCP/IP connection, it runs +the ACL specified by %acl_smtp_etrn% in order to decide whether the command +should be accepted or not. If no ACL is defined, the command is rejected. + +The ETRN command is concerned with ``releasing'' messages that are awaiting +delivery to certain hosts. As Exim does not organize its message queue by host, +the only form of ETRN that is supported by default is the one where the +text starts with the ``#'' prefix, in which case the remainder of the text is +specific to the SMTP server. A valid ETRN command causes a run of Exim with +the %-R% option to happen, with the remainder of the ETRN text as its +argument. For example, + + ETRN #brigadoon + +runs the command + + exim -R brigadoon + +which causes a delivery attempt on all messages with undelivered addresses +containing the text ``brigadoon''. When %smtp_etrn_serialize% is set (the +default), Exim prevents the simultaneous execution of more than one queue run +for the same argument string as a result of an ETRN command. This stops +a misbehaving client from starting more than one queue runner at once. + +cindex:[hints database,ETRN serialization] +Exim implements the serialization by means of a hints database in which a +record is written whenever a process is started by ETRN, and deleted when +the process completes. However, Exim does not keep the SMTP session waiting for +the ETRN process to complete. Once ETRN is accepted, the client is sent +a ``success'' return code. Obviously there is scope for hints records to get left +lying around if there is a system or program crash. To guard against this, Exim +ignores any records that are more than six hours old. + +cindex:[%smtp_etrn_command%] +For more control over what ETRN does, the %smtp_etrn_command% option can +used. This specifies a command that is run whenever ETRN is received, +whatever the form of its argument. For +example: + + smtp_etrn_command = /etc/etrn_command $domain $sender_host_address + +The string is split up into arguments which are independently expanded. The +expansion variable $domain$ is set to the argument of the ETRN command, +and no syntax checking is done on the contents of this argument. Exim does not +wait for the command to complete, so its status code is not checked. Exim runs +under its own uid and gid when receiving incoming SMTP, so it is not possible +for it to change them before running the command. + + + +Incoming local SMTP +~~~~~~~~~~~~~~~~~~~ +cindex:[SMTP,local incoming] +Some user agents use SMTP to pass messages to their local MTA using the +standard input and output, as opposed to passing the envelope on the command +line and writing the message to the standard input. This is supported by the +%-bs% option. This form of SMTP is handled in the same way as incoming +messages over TCP/IP (including the use of ACLs), except that the envelope +sender given in a MAIL command is ignored unless the caller is trusted. In +an ACL you can detect this form of SMTP input by testing for an empty host +identification. It is common to have this as the first line in the ACL that +runs for RCPT commands: + + accept hosts = : + +This accepts SMTP messages from local processes without doing any other tests. + + + +[[SECTbatchSMTP]] +Outgoing batched SMTP +~~~~~~~~~~~~~~~~~~~~~ +cindex:[SMTP,batched outgoing] +cindex:[batched SMTP output] +Both the ^appendfile^ and ^pipe^ transports can be used for handling batched +SMTP. Each has an option called %use_bsmtp% which causes messages to be output +in BSMTP format. No SMTP responses are possible for this form of delivery. All +it is doing is using SMTP commands as a way of transmitting the envelope along +with the message. + +The message is written to the file or pipe preceded by the SMTP commands +MAIL and RCPT, and followed by a line containing a single dot. Lines in +the message that start with a dot have an extra dot added. The SMTP command +HELO is not normally used. If it is required, the %message_prefix% option +can be used to specify it. + +Because ^appendfile^ and ^pipe^ are both local transports, they accept only +one recipient address at a time by default. However, you can arrange for them +to handle several addresses at once by setting the %batch_max% option. When +this is done for BSMTP, messages may contain multiple RCPT commands. See +chapter <<CHAPbatching>> for more details. + +When one or more addresses are routed to a BSMTP transport by a router that +sets up a host list, the name of the first host on the list is available to the +transport in the variable $host$. Here is an example of such a transport and +router: + + begin routers + route_append: + driver = manualroute + transport = smtp_appendfile + route_list = domain.example batch.host.example + + begin transports + smtp_appendfile: + driver = appendfile + directory = /var/bsmtp/$host + batch_max = 1000 + use_bsmtp + user = exim + +This causes messages addressed to 'domain.example' to be written in BSMTP +format to _/var/bsmtp/batch.host.example_, with only a single copy of each +message (unless there are more than 1000 recipients). + + + +[[SECTincomingbatchedSMTP]] +Incoming batched SMTP +~~~~~~~~~~~~~~~~~~~~~ +cindex:[SMTP,batched incoming] +cindex:[batched SMTP input] +The %-bS% command line option causes Exim to accept one or more messages by +reading SMTP on the standard input, but to generate no responses. If the caller +is trusted, the senders in the MAIL commands are believed; otherwise the +sender is always the caller of Exim. Unqualified senders and receivers are not +rejected (there seems little point) but instead just get qualified. HELO +and EHLO act as RSET; VRFY, EXPN, ETRN and HELP, act +as NOOP; QUIT quits. + +No policy checking is done for BSMTP input. That is, no ACL is run at anytime. +In this respect it is like non-SMTP local input. + +If an error is detected while reading a message, including a missing ``.'' at +the end, Exim gives up immediately. It writes details of the error to the +standard output in a stylized way that the calling program should be able to +make some use of automatically, for example: + + 554 Unexpected end of file + Transaction started in line 10 + Error detected in line 14 + +It writes a more verbose version, for human consumption, to the standard error +file, for example: + + An error was detected while processing a file of BSMTP input. + The error message was: + + 501 '>' missing at end of address + + The SMTP transaction started in line 10. + The error was detected in line 12. + The SMTP command at fault was: + + rcpt to:<malformed@in.com.plete + + 1 previous message was successfully processed. + The rest of the batch was abandoned. + +The return code from Exim is zero only if there were no errors. It is 1 if some +messages were accepted before an error was detected, and 2 if no messages were +accepted. + + + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// + +[[CHAPemsgcust]] +[titleabbrev="Customizing messages"] +Customizing bounce and warning messages +--------------------------------------- +When a message fails to be delivered, or remains on the queue for more than a +configured amount of time, Exim sends a message to the original sender, or +to an alternative configured address. The text of these messages is built into +the code of Exim, but it is possible to change it, either by adding a single +string, or by replacing each of the paragraphs by text supplied in a file. + +The 'From:' and 'To:' header lines are automatically generated; you can cause +a 'Reply-To:' line to be added by setting the %errors_reply_to% option. Exim +also adds the line + + Auto-Submitted: auto-generated + +to all warning and bounce messages, + + +Customizing bounce messages +~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[customizing,bounce message] +cindex:[bounce message,customizing] +If %bounce_message_text% is set, its contents are included in the default +message immediately after ``This message was created automatically by mail +delivery software.'' The string is not expanded. It is not used if +%bounce_message_file% is set. + +When %bounce_message_file% is set, it must point to a template file for +constructing error messages. The file consists of a series of text items, +separated by lines consisting of exactly four asterisks. If the file cannot be +opened, default text is used and a message is written to the main and panic +logs. If any text item in the file is empty, default text is used for that +item. + +Each item of text that is read from the file is expanded, and there are two +expansion variables which can be of use here: $bounce_recipient$ is set to +the recipient of an error message while it is being created, and +$return_size_limit$ contains the value of the %return_size_limit% option, +rounded to a whole number. + +The items must appear in the file in the following order: + +- The first item is included in the headers, and should include at least a +'Subject:' header. Exim does not check the syntax of these headers. + +- The second item forms the start of the error message. After it, Exim lists the +failing addresses with their error messages. + +- The third item is used to introduce any text from pipe transports that is to be +returned to the sender. It is omitted if there is no such text. + +- The fourth item is used to introduce the copy of the message that is returned +as part of the error report. + +- The fifth item is added after the fourth one if the returned message is +truncated because it is bigger than %return_size_limit%. + +- The sixth item is added after the copy of the original message. + +The default state (%bounce_message_file% unset) is equivalent to the +following file, in which the sixth item is empty. The 'Subject:' line has been +split into two here in order to fit it on the page: + + Subject: Mail delivery failed + ${if eq{$sender_address}{$bounce_recipient}{: returning message to sender}} + **** + This message was created automatically by mail delivery software. + + A message ${if eq{$sender_address}{$bounce_recipient}{that you sent }{sent by + + <$sender_address> + + }}could not be delivered to all of its recipients. + The following address(es) failed: + **** + The following text was generated during the delivery attempt(s): + **** + ------ This is a copy of the message, including all the headers. ------ + **** + ------ The body of the message is $message_size characters long; only the first + ------ $return_size_limit or so are included here. + **** + + +[[SECTcustwarn]] +Customizing warning messages +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[customizing,warning message] +cindex:[warning of delay,customizing the message] +The option %warn_message_file% can be pointed at a template file for use when +warnings about message delays are created. In this case there are only three +text sections: + +- The first item is included in the headers, and should include at least a +'Subject:' header. Exim does not check the syntax of these headers. + +- The second item forms the start of the warning message. After it, Exim lists +the delayed addresses. + +- The third item then ends the message. + +The default state is equivalent to the following file, except that the line +starting ``A message'' has been split here, in order to fit it on the page: + + Subject: Warning: message $message_id delayed $warn_message_delay + **** + This message was created automatically by mail delivery software. + + A message ${if eq{$sender_address}{$warn_message_recipients} + {that you sent }{sent by + + <$sender_address> + + }}has not been delivered to all of its recipients after + more than $warn_message_delay on the queue on $primary_hostname. + + The message identifier is: $message_id + The subject of the message is: $h_subject + The date of the message is: $h_date + + The following address(es) have not yet been delivered: + **** + No action is required on your part. Delivery attempts will continue for + some time, and this warning may be repeated at intervals if the message + remains undelivered. Eventually the mail delivery software will give up, + and when that happens, the message will be returned to you. + +except that in the default state the subject and date lines are omitted if no +appropriate headers exist. During the expansion of this file, +$warn_message_delay$ is set to the delay time in one of the forms ``<''n'> +minutes' or ``<''n'> hours', and $warn_message_recipients$ contains a list of +recipients for the warning message. There may be more than one if there are +multiple addresses with different %errors_to% settings on the routers that +handled them. + + + + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// + +[[CHAPcomconreq]] +[titleabbrev="Common configuration settings"] +Some common configuration settings +---------------------------------- +This chapter discusses some configuration settings that seem to be fairly +common. More examples and discussion can be found in the Exim book. + + + +Sending mail to a smart host +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[smart host,example router] +If you want to send all mail for non-local domains to a ``smart host'', you +should replace the default ^dnslookup^ router with a router which does the +routing explicitly: + + send_to_smart_host: + driver = manualroute + route_list = !+local_domains smart.host.name + transport = remote_smtp + +You can use the smart host's IP address instead of the name if you wish. + +If you are using Exim only to submit messages to a smart host, and not for +receiving incoming messages, you can arrange for it to do the submission +synchronously by setting the %mua_wrapper% option (see chapter +<<CHAPnonqueueing>>). + + + + +[[SECTmailinglists]] +Using Exim to handle mailing lists +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[mailing lists] +Exim can be used to run simple mailing lists, but for large and/or complicated +requirements, the use of additional specialized mailing list software such as +Majordomo or Mailman is recommended. + +The ^redirect^ router can be used to handle mailing lists where each list +is maintained in a separate file, which can therefore be managed by an +independent manager. The %domains% router option can be used to run these +lists in a separate domain from normal mail. For example: + + lists: + driver = redirect + domains = lists.example + file = /usr/lists/$local_part + forbid_pipe + forbid_file + errors_to = $local_part-request@lists.example + no_more + +This router is skipped for domains other than 'lists.example'. For addresses +in that domain, it looks for a file that matches the local part. If there is no +such file, the router declines, but because %no_more% is set, no subsequent +routers are tried, and so the whole delivery fails. + +The %forbid_pipe% and %forbid_file% options prevent a local part from being +expanded into a file name or a pipe delivery, which is usually inappropriate in +a mailing list. + +cindex:[%errors_to%] +The %errors_to% option specifies that any delivery errors caused by addresses +taken from a mailing list are to be sent to the given address rather than the +original sender of the message. However, before acting on this, Exim verifies +the error address, and ignores it if verification fails. + +For example, using the configuration above, mail sent to +'dicts@lists.example' is passed on to those addresses contained in +_/usr/lists/dicts_, with error reports directed to +'dicts-request@lists.example', provided that this address can be verified. +There could be a file called _/usr/lists/dicts-request_ containing +the address(es) of this particular list's manager(s), but other approaches, +such as setting up an earlier router (possibly using the %local_part_prefix% +or %local_part_suffix% options) to handle addresses of the form %owner-xxx% +or %xxx-request%, are also possible. + + + +Syntax errors in mailing lists +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[mailing lists,syntax errors in] +If an entry in redirection data contains a syntax error, Exim normally defers +delivery of the original address. That means that a syntax error in a mailing +list holds up all deliveries to the list. This may not be appropriate when a +list is being maintained automatically from data supplied by users, and the +addresses are not rigorously checked. + +If the %skip_syntax_errors% option is set, the ^redirect^ router just skips +entries that fail to parse, noting the incident in the log. If in addition +%syntax_errors_to% is set to a verifiable address, a message is sent to it +whenever a broken address is skipped. It is usually appropriate to set +%syntax_errors_to% to the same address as %errors_to%. + + + +Re-expansion of mailing lists +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[mailing lists,re-expansion of] +Exim remembers every individual address to which a message has been delivered, +in order to avoid duplication, but it normally stores only the original +recipient addresses with a message. If all the deliveries to a mailing list +cannot be done at the first attempt, the mailing list is re-expanded when the +delivery is next tried. This means that alterations to the list are taken into +account at each delivery attempt, so addresses that have been added to +the list since the message arrived will therefore receive a copy of the +message, even though it pre-dates their subscription. + +If this behaviour is felt to be undesirable, the %one_time% option can be set +on the ^redirect^ router. If this is done, any addresses generated by the +router that fail to deliver at the first attempt are added to the message as +``top level'' addresses, and the parent address that generated them is marked +``delivered''. Thus, expansion of the mailing list does not happen again at the +subsequent delivery attempts. The disadvantage of this is that if any of the +failing addresses are incorrect, correcting them in the file has no effect on +pre-existing messages. + +The original top-level address is remembered with each of the generated +addresses, and is output in any log messages. However, any intermediate parent +addresses are not recorded. This makes a difference to the log only if the +%all_parents% selector is set, but for mailing lists there is normally only +one level of expansion anyway. + + + +Closed mailing lists +~~~~~~~~~~~~~~~~~~~~ +cindex:[mailing lists,closed] +The examples so far have assumed open mailing lists, to which anybody may +send mail. It is also possible to set up closed lists, where mail is accepted +from specified senders only. This is done by making use of the generic +%senders% option to restrict the router that handles the list. + +The following example uses the same file as a list of recipients and as a list +of permitted senders. It requires three routers: + +.... +lists_request: + driver = redirect + domains = lists.example + local_part_suffix = -request + file = /usr/lists/$local_part$local_part_suffix + no_more + +lists_post: + driver = redirect + domains = lists.example + senders = ${if exists {/usr/lists/$local_part}\ + {lsearch;/usr/lists/$local_part}{*}} + file = /usr/lists/$local_part + forbid_pipe + forbid_file + errors_to = $local_part-request@lists.example + no_more + +lists_closed: + driver = redirect + domains = lists.example + allow_fail + data = :fail: $local_part@lists.example is a closed mailing list +.... + +All three routers have the same %domains% setting, so for any other domains, +they are all skipped. The first router runs only if the local part ends in +%-request%. It handles messages to the list manager(s) by means of an open +mailing list. + +The second router runs only if the %senders% precondition is satisfied. It +checks for the existence of a list that corresponds to the local part, and then +checks that the sender is on the list by means of a linear search. It is +necessary to check for the existence of the file before trying to search it, +because otherwise Exim thinks there is a configuration error. If the file does +not exist, the expansion of %senders% is \*, which matches all senders. This +means that the router runs, but because there is no list, declines, and +%no_more% ensures that no further routers are run. The address fails with an +``unrouteable address'' error. + +The third router runs only if the second router is skipped, which happens when +a mailing list exists, but the sender is not on it. This router forcibly fails +the address, giving a suitable error message. + + + + +[[SECTvirtualdomains]] +Virtual domains +~~~~~~~~~~~~~~~ +cindex:[virtual domains] +cindex:[domain,virtual] +The phrase 'virtual domain' is unfortunately used with two rather different +meanings: + +- A domain for which there are no real mailboxes; all valid local parts are +aliases for other email addresses. Common examples are organizational +top-level domains and ``vanity'' domains. + +- One of a number of independent domains that are all handled by the same host, +with mailboxes on that host, but where the mailbox owners do not necessarily +have login accounts on that host. + +The first usage is probably more common, and does seem more ``virtual'' than the +second. This kind of domain can be handled in Exim with a straightforward +aliasing router. One approach is to create a separate alias file for each +virtual domain. Exim can test for the existence of the alias file to determine +whether the domain exists. The ^dsearch^ lookup type is useful here, leading +to a router of this form: + + virtual: + driver = redirect + domains = dsearch;/etc/mail/virtual + data = ${lookup{$local_part}lsearch{/etc/mail/virtual/$domain}} + no_more + +The %domains% option specifies that the router is to be skipped, unless there +is a file in the _/etc/mail/virtual_ directory whose name is the same as the +domain that is being processed. When the router runs, it looks up the local +part in the file to find a new address (or list of addresses). The %no_more% +setting ensures that if the lookup fails (leading to %data% being an empty +string), Exim gives up on the address without trying any subsequent routers. + +This one router can handle all the virtual domains because the alias file names +follow a fixed pattern. Permissions can be arranged so that appropriate people +can edit the different alias files. A successful aliasing operation results in +a new envelope recipient address, which is then routed from scratch. + +The other kind of ``virtual'' domain can also be handled in a straightforward +way. One approach is to create a file for each domain containing a list of +valid local parts, and use it in a router like this: + + my_domains: + driver = accept + domains = dsearch;/etc/mail/domains + local_parts = lsearch;/etc/mail/domains/$domain + transport = my_mailboxes + +The address is accepted if there is a file for the domain, and the local part +can be found in the file. The %domains% option is used to check for the file's +existence because %domains% is tested before the %local_parts% option (see +section <<SECTrouprecon>>). You can't use %require_files%, because that option +is tested after %local_parts%. The transport is as follows: + + my_mailboxes: + driver = appendfile + file = /var/mail/$domain/$local_part + user = mail + +This uses a directory of mailboxes for each domain. The %user% setting is +required, to specify which uid is to be used for writing to the mailboxes. + +The configuration shown here is just one example of how you might support this +requirement. There are many other ways this kind of configuration can be set +up, for example, by using a database instead of separate files to hold all the +information about the domains. + + + +[[SECTmulbox]] +Multiple user mailboxes +~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[multiple mailboxes] +cindex:[mailbox,multiple] +cindex:[local part,prefix] +cindex:[local part,suffix] +Heavy email users often want to operate with multiple mailboxes, into which +incoming mail is automatically sorted. A popular way of handling this is to +allow users to use multiple sender addresses, so that replies can easily be +identified. Users are permitted to add prefixes or suffixes to their local +parts for this purpose. The wildcard facility of the generic router options +%local_part_prefix% and %local_part_suffix% can be used for this. For +example, consider this router: + + userforward: + driver = redirect + check_local_user + file = $home/.forward + local_part_suffix = -* + local_part_suffix_optional + allow_filter + +It runs a user's _.forward_ file for all local parts of the form +'username-\*'. Within the filter file the user can distinguish different +cases by testing the variable $local_part_suffix$. For example: + + if $local_part_suffix contains -special then + save /home/$local_part/Mail/special + endif + +If the filter file does not exist, or does not deal with such addresses, they +fall through to subsequent routers, and, assuming no subsequent use of the +%local_part_suffix% option is made, they presumably fail. Thus, users have +control over which suffixes are valid. + +Alternatively, a suffix can be used to trigger the use of a different +_.forward_ file -- which is the way a similar facility is implemented in +another MTA: + + userforward: + driver = redirect + check_local_user + file = $home/.forward$local_part_suffix + local_part_suffix = -* + local_part_suffix_optional + allow_filter + +If there is no suffix, _.forward_ is used; if the suffix is '-special', for +example, _.forward-special_ is used. Once again, if the appropriate file +does not exist, or does not deal with the address, it is passed on to +subsequent routers, which could, if required, look for an unqualified +_.forward_ file to use as a default. + + + +Simplified vacation processing +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[vacation processing] +The traditional way of running the 'vacation' program is for a user to set up +a pipe command in a _.forward_ file +(see section <<SECTspecitredli>> for syntax details). +This is prone to error by inexperienced users. There are two features of Exim +that can be used to make this process simpler for users: + +- A local part prefix such as ``vacation-'' can be specified on a router which +can cause the message to be delivered directly to the 'vacation' program, or +alternatively can use Exim's ^autoreply^ transport. The contents of a user's +_.forward_ file are then much simpler. For example: + + spqr, vacation-spqr + +- The %require_files% generic router option can be used to trigger a +vacation delivery by checking for the existence of a certain file in the +user's home directory. The %unseen% generic option should also be used, to +ensure that the original delivery also proceeds. In this case, all the user has +to do is to create a file called, say, _.vacation_, containing a vacation +message. + +Another advantage of both these methods is that they both work even when the +use of arbitrary pipes by users is locked out. + + + +Taking copies of mail +~~~~~~~~~~~~~~~~~~~~~ +cindex:[message,copying every] +Some installations have policies that require archive copies of all messages to +be made. A single copy of each message can easily be taken by an appropriate +command in a system filter, which could, for example, use a different file for +each day's messages. + +There is also a shadow transport mechanism that can be used to take copies of +messages that are successfully delivered by local transports, one copy per +delivery. This could be used, 'inter alia', to implement automatic +notification of delivery by sites that insist on doing such things. + + + +Intermittently connected hosts +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[intermittently connected hosts] +It has become quite common (because it is cheaper) for hosts to connect to the +Internet periodically rather than remain connected all the time. The normal +arrangement is that mail for such hosts accumulates on a system that is +permanently connected. + +Exim was designed for use on permanently connected hosts, and so it is not +particularly well-suited to use in an intermittently connected environment. +Nevertheless there are some features that can be used. + + +Exim on the upstream server host +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +It is tempting to arrange for incoming mail for the intermittently connected +host to remain on Exim's queue until the client connects. However, this +approach does not scale very well. Two different kinds of waiting message are +being mixed up in the same queue -- those that cannot be delivered because of +some temporary problem, and those that are waiting for their destination host +to connect. This makes it hard to manage the queue, as well as wasting +resources, because each queue runner scans the entire queue. + +A better approach is to separate off those messages that are waiting for an +intermittently connected host. This can be done by delivering these messages +into local files in batch SMTP, ``mailstore'', or other envelope-preserving +format, from where they are transmitted by other software when their +destination connects. This makes it easy to collect all the mail for one host +in a single directory, and to apply local timeout rules on a per-message basis +if required. + +On a very small scale, leaving the mail on Exim's queue can be made to work. If +you are doing this, you should configure Exim with a long retry period for the +intermittent host. For example: + + cheshire.wonderland.fict.example * F,5d,24h + +This stops a lot of failed delivery attempts from occurring, but Exim remembers +which messages it has queued up for that host. Once the intermittent host comes +online, forcing delivery of one message (either by using the %-M% or %-R% +options, or by using the ETRN SMTP command (see section <<SECTETRN>>) +causes all the queued up messages to be delivered, often down a single SMTP +connection. While the host remains connected, any new messages get delivered +immediately. + +If the connecting hosts do not have fixed IP addresses, that is, if a host is +issued with a different IP address each time it connects, Exim's retry +mechanisms on the holding host get confused, because the IP address is normally +used as part of the key string for holding retry information. This can be +avoided by unsetting %retry_include_ip_address% on the ^smtp^ transport. +Since this has disadvantages for permanently connected hosts, it is best to +arrange a separate transport for the intermittently connected ones. + + + +Exim on the intermittently connected client host +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +The value of %smtp_accept_queue_per_connection% should probably be +increased, or even set to zero (that is, disabled) on the intermittently +connected host, so that all incoming messages down a single connection get +delivered immediately. + +cindex:[SMTP,passed connection] +cindex:[SMTP,multiple deliveries] +cindex:[multiple SMTP deliveries] +Mail waiting to be sent from an intermittently connected host will probably +not have been routed, because without a connection DNS lookups are not +possible. This means that if a normal queue run is done at connection time, +each message is likely to be sent in a separate SMTP session. This can be +avoided by starting the queue run with a command line option beginning with +%-qq% instead of %-q%. In this case, the queue is scanned twice. In the first +pass, routing is done but no deliveries take place. The second pass is a normal +queue run; since all the messages have been previously routed, those destined +for the same host are likely to get sent as multiple deliveries in a single +SMTP connection. + + + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// + +[[CHAPnonqueueing]] +[titleabbrev="Exim as a non-queueing client"] +Using Exim as a non-queueing client +----------------------------------- +cindex:[client, non-queueing] +cindex:[smart host,queueing; suppressing] +On a personal computer, it is a common requirement for all +email to be sent to a ``smart host''. There are plenty of MUAs that can be +configured to operate that way, for all the popular operating systems. +However, there are some MUAs for Unix-like systems that cannot be so +configured: they submit messages using the command line interface of +_/usr/sbin/sendmail_. Furthermore, utility programs such as 'cron' submit +messages this way. + +If the personal computer runs continuously, there is no problem, because it can +run a conventional MTA that handles delivery to the smart host, and deal with +any delays via its queueing mechanism. However, if the computer does not run +continuously or runs different operating systems at different times, queueing +email is not desirable. + +There is therefore a requirement for something that can provide the +_/usr/sbin/sendmail_ interface but deliver messages to a smart host without +any queueing or retrying facilities. Furthermore, the delivery to the smart +host should be synchronous, so that if it fails, the sending MUA is immediately +informed. In other words, we want something that extends an MUA that submits +to a local MTA via the command line so that it behaves like one that submits +to a remote smart host using TCP/SMTP. + +There are a number of applications (for example, there is one called 'ssmtp') +that do this job. However, people have found them to be lacking in various +ways. For instance, you might want to allow aliasing and forwarding to be done +before sending a message to the smart host. + +Exim already had the necessary infrastructure for doing this job. Just a few +tweaks were needed to make it behave as required, though it is somewhat of an +overkill to use a fully-featured MTA for this purpose. + +cindex:[%mua_wrapper%] +There is a Boolean global option called %mua_wrapper%, defaulting false. +Setting %mua_wrapper% true causes Exim to run in a special mode where it +assumes that it is being used to ``wrap'' a command-line MUA in the manner +just described. As well as setting %mua_wrapper%, you also need to provide a +compatible router and transport configuration. Typically there will be just one +router and one transport, sending everything to a smart host. + +When run in MUA wrapping mode, the behaviour of Exim changes in the +following ways: + +- A daemon cannot be run, nor will Exim accept incoming messages from 'inetd'. +In other words, the only way to submit messages is via the command line. + +- Each message is synchonously delivered as soon as it is received (%-odi% is +assumed). All queueing options (%queue_only%, %queue_smtp_domains%, +%control% in an ACL, etc.) are quietly ignored. The Exim reception process does +not finish until the delivery attempt is complete. If the delivery is +successful, a zero return code is given. + +- Address redirection is permitted, but the final routing for all addresses must +be to the same remote transport, and to the same list of hosts. Furthermore, +the return address (envelope sender) must be the same for all recipients, as +must any added or deleted header lines. In other words, it must be possible to +deliver the message in a single SMTP transaction, however many recipients there +are. + +- If these conditions are not met, or if routing any address results in a +failure or defer status, or if Exim is unable to deliver all the recipients +successfully to one of the smart hosts, delivery of the entire message fails. + +- Because no queueing is allowed, all failures are treated as permanent; there +is no distinction between 4##'xx' and 5##'xx' SMTP response codes from the +smart host. Furthermore, because only a single yes/no response can be given to +the caller, it is not possible to deliver to some recipients and not others. If +there is an error (temporary or permanent) for any recipient, all are failed. + +- If more than one smart host is listed, Exim will try another host after a +connection failure or a timeout, in the normal way. However, if this kind of +failure happens for all the hosts, the delivery fails. + +- When delivery fails, an error message is written to the standard error stream +(as well as to Exim's log), and Exim exits to the caller with a return code +value 1. The message is expunged from Exim's spool files. No bounce messages +are ever generated. + +- No retry data is maintained, and any retry rules are ignored. + +- A number of Exim options are overridden: %deliver_drop_privilege% is forced +true, %max_rcpt% in the smtp transport is forced to ``unlimited'', +%remote_max_parallel% is forced to one, and fallback hosts are ignored. + +The overall effect is that Exim makes a single synchronous attempt to deliver +the message, failing if there is any kind of problem. Because no local +deliveries are done and no daemon can be run, Exim does not need root +privilege. It should be possible to run it setuid to 'exim' instead of setuid +to 'root'. See section <<SECTrunexiwitpri>> for a general discussion about the +advantages and disadvantages of running without root privilege. + + + + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// + +[[CHAPlog]] +Log files +--------- +cindex:[log,types of] +cindex:[log,general description] +Exim writes three different logs, referred to as the main log, the reject log, +and the panic log: + +- cindex:[main log] +The main log records the arrival of each message and each delivery in a single +line in each case. The format is as compact as possible, in an attempt to keep +down the size of log files. Two-character flag sequences make it easy to pick +out these lines. A number of other events are recorded in the main log. Some of +them are optional, in which case the %log_selector% option controls whether +they are included or not. A Perl script called 'eximstats', which does simple +analysis of main log files, is provided in the Exim distribution (see section +<<SECTmailstat>>). + +- cindex:[reject log] +The reject log records information from messages that are rejected as a result +of a configuration option (that is, for policy reasons). +The first line of each rejection is a copy of the line that is also written to +the main log. Then, if the message's header has been read at the time the log +is written, its contents are written to this log. Only the original header +lines are available; header lines added by ACLs are not logged. You can use the +reject log to check that your policy controls are working correctly; on a busy +host this may be easier than scanning the main log for rejection messages. You +can suppress the writing of the reject log by setting %write_rejectlog% false. + +- cindex:[panic log] +cindex:[system log] +When certain serious errors occur, Exim writes entries to its panic log. If the +error is sufficiently disastrous, Exim bombs out afterwards. Panic log entries +are usually written to the main log as well, but can get lost amid the mass of +other entries. The panic log should be empty under normal circumstances. It is +therefore a good idea to check it (or to have a 'cron' script check it) +regularly, in order to become aware of any problems. When Exim cannot open its +panic log, it tries as a last resort to write to the system log (syslog). This +is opened with LOG_PID+LOG_CONS and the facility code of LOG_MAIL. The +message itself is written at priority LOG_CRIT. + +Every log line starts with a timestamp, in the format shown in this example: + + 2001-09-16 16:09:47 SMTP connection from [127.0.0.1] closed by QUIT + +By default, the timestamps are in the local timezone. There are two +ways of changing this: + +- You can set the %timezone% option to a different time zone; in particular, if +you set ++ + timezone = UTC ++ +the timestamps will be in UTC (aka GMT). + +- If you set %log_timezone% true, the time zone is added to the timestamp, for +example: ++ + 2003-04-25 11:17:07 +0100 Start queue run: pid=12762 + + + + + +[[SECTwhelogwri]] +Where the logs are written +~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[log,destination] +cindex:[log,to file] +cindex:[log,to syslog] +cindex:[syslog] +The logs may be written to local files, or to syslog, or both. However, it +should be noted that many syslog implementations use UDP as a transport, and +are therefore unreliable in the sense that messages are not guaranteed to +arrive at the loghost, nor is the ordering of messages necessarily maintained. +It has also been reported that on large log files (tens of megabytes) you may +need to tweak syslog to prevent it syncing the file with each write -- on Linux +this has been seen to make syslog take 90% plus of CPU time. + +The destination for Exim's logs is configured by setting LOG_FILE_PATH in +_Local/Makefile_ or by setting %log_file_path% in the run time +configuration. This latter string is expanded, so it can contain, for example, +references to the host name: + + log_file_path = /var/log/$primary_hostname/exim_%slog + +It is generally advisable, however, to set the string in _Local/Makefile_ +rather than at run time, because then the setting is available right from the +start of Exim's execution. Otherwise, if there's something it wants to log +before it has read the configuration file (for example, an error in the +configuration file) it will not use the path you want, and may not be able to +log at all. + +The value of LOG_FILE_PATH or %log_file_path% is a colon-separated +list, currently limited to at most two items. This is one option where the +facility for changing a list separator may not be used. The list must always be +colon-separated. If an item in the list is ``syslog'' then syslog is used; +otherwise the item must either be an absolute path, containing `%s` at the +point where ``main'', ``reject'', or ``panic'' is to be inserted, or be empty, +implying the use of a default path. + +When Exim encounters an empty item in the list, it searches the list defined by +LOG_FILE_PATH, and uses the first item it finds that is neither empty nor +``syslog''. This means that an empty item in %log_file_path% can be used to +mean ``use the path specified at build time''. It no such item exists, log files +are written in the _log_ subdirectory of the spool directory. This is +equivalent to the setting: + + log_file_path = $spool_directory/log/%slog + +If you do not specify anything at build time or run time, that is where the +logs are written. + +A log file path may also contain `%D` if datestamped log file names are in +use -- see section <<SECTdatlogfil>> below. + +Here are some examples of possible settings: + +&&& +`LOG_FILE_PATH=syslog ` syslog only +`LOG_FILE_PATH=:syslog ` syslog and default path +`LOG_FILE_PATH=syslog : /usr/log/exim_%s ` syslog and specified path +`LOG_FILE_PATH=/usr/log/exim_%s ` specified path only +&&& + +If there are more than two paths in the list, the first is used and a panic +error is logged. + + + +Logging to local files that are periodically ``cycled'' +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[log,cycling local files] +cindex:[cycling logs] +cindex:['exicyclog'] +cindex:[log,local files; writing to] +Some operating systems provide centralized and standardised methods for cycling +log files. For those that do not, a utility script called 'exicyclog' is +provided (see section <<SECTcyclogfil>>). This renames and compresses the main +and reject logs each time it is called. The maximum number of old logs to keep +can be set. It is suggested this script is run as a daily 'cron' job. + +An Exim delivery process opens the main log when it first needs to write to it, +and it keeps the file open in case subsequent entries are required -- for +example, if a number of different deliveries are being done for the same +message. However, remote SMTP deliveries can take a long time, and this means +that the file may be kept open long after it is renamed if 'exicyclog' or +something similar is being used to rename log files on a regular basis. To +ensure that a switch of log files is noticed as soon as possible, Exim calls +'stat()' on the main log's name before reusing an open file, and if the file +does not exist, or its inode has changed, the old file is closed and Exim +tries to open the main log from scratch. Thus, an old log file may remain open +for quite some time, but no Exim processes should write to it once it has been +renamed. + + + +[[SECTdatlogfil]] +Datestamped log files +~~~~~~~~~~~~~~~~~~~~~ +cindex:[log,datestamped files] +Instead of cycling the main and reject log files by renaming them +periodically, some sites like to use files whose names contain a datestamp, +for example, _mainlog-20031225_. The datestamp is in the form _yyyymmdd_. +Exim has support for this way of working. It is enabled by setting the +%log_file_path% option to a path that includes `%D` at the point where the +datestamp is required. For example: + + log_file_path = /var/spool/exim/log/%slog-%D + log_file_path = /var/log/exim-%s-%D.log + log_file_path = /var/spool/exim/log/%D-%slog + +As before, `%s` is replaced by ``main'' or ``reject''; the following are examples +of names generated by the above examples: + + /var/spool/exim/log/mainlog-20021225 + /var/log/exim-reject-20021225.log + /var/spool/exim/log/20021225-mainlog + +When this form of log file is specified, Exim automatically switches to new +files at midnight. It does not make any attempt to compress old logs; you +will need to write your own script if you require this. You should not +run 'exicyclog' with this form of logging. + +The location of the panic log is also determined by %log_file_path%, but it +is not datestamped, because rotation of the panic log does not make sense. +When generating the name of the panic log, `%D` is removed from the string. +In addition, if it immediately follows a slash, a following non-alphanumeric +character is removed; otherwise a preceding non-alphanumeric character is +removed. Thus, the three examples above would give these panic log names: + + /var/spool/exim/log/paniclog + /var/log/exim-panic.log + /var/spool/exim/log/paniclog + + + + +Logging to syslog +~~~~~~~~~~~~~~~~~ +cindex:[log,syslog; writing to] +The use of syslog does not change what Exim logs or the format of its messages, +except in one respect. If %syslog_timestamp% is set false, the timestamps on +Exim's log lines are omitted when these lines are sent to syslog. Apart from +that, the same strings are written to syslog as to log files. The syslog +``facility'' is set to LOG_MAIL, and the program name to ``exim'' +by default, but you can change these by setting the %syslog_facility% and +%syslog_processname% options, respectively. If Exim was compiled with +SYSLOG_LOG_PID set in _Local/Makefile_ (this is the default in +_src/EDITME_), then, on systems that permit it (all except ULTRIX), the +LOG_PID flag is set so that the 'syslog()' call adds the pid as well as +the time and host name to each line. +The three log streams are mapped onto syslog priorities as follows: + +- 'mainlog' is mapped to LOG_INFO + +- 'rejectlog' is mapped to LOG_NOTICE + +- 'paniclog' is mapped to LOG_ALERT + +Many log lines are written to both 'mainlog' and 'rejectlog', and some are +written to both 'mainlog' and 'paniclog', so there will be duplicates if +these are routed by syslog to the same place. You can suppress this duplication +by setting %syslog_duplication% false. + +Exim's log lines can sometimes be very long, and some of its 'rejectlog' +entries contain multiple lines when headers are included. To cope with both +these cases, entries written to syslog are split into separate 'syslog()' +calls at each internal newline, and also after a maximum of +870 data characters. (This allows for a total syslog line length of 1024, when +additions such as timestamps are added.) If you are running a syslog +replacement that can handle lines longer than the 1024 characters allowed by +RFC 3164, you should set + + SYSLOG_LONG_LINES=yes + +in _Local/Makefile_ before building Exim. That stops Exim from splitting long +lines, but it still splits at internal newlines in 'reject' log entries. + +To make it easy to re-assemble split lines later, each component of a split +entry starts with a string of the form ``[<''n'>/<'m'>]' or ``[<''n'>\<'m'>]' +where <'n'> is the component number and <'m'> is the total number of components +in the entry. The / delimiter is used when the line was split because it was +too long; if it was split because of an internal newline, the \ delimiter is +used. For example, supposing the length limit to be 70 instead of 1000, the +following would be the result of a typical rejection message to 'mainlog' +(LOG_INFO), each line in addition being preceded by the time, host name, and +pid as added by syslog: + + $smc\{[1/3] 2002-09-16 16:09:43 16RdAL-0006pc-00 rejected from [127.0.0.1] (ph10): + [2/3] syntax error in 'From' header when scanning for sender: missing or ma + [3/3] lformed local part in "<>" (envelope sender is <ph10@cam.example>)\} + +The same error might cause the following lines to be written to ``rejectlog'' +(LOG_NOTICE): + + $smc\{[1/14] 2002-09-16 16:09:43 16RdAL-0006pc-00 rejected from [127.0.0.1] (ph10): + [2/14] syntax error in 'From' header when scanning for sender: missing or ma + [3\14] lformed local part in "<>" (envelope sender is <ph10@cam.example>) + [4\14] Recipients: ph10@some.domain.cam.example + [5\14] P Received: from [127.0.0.1] (ident=ph10) + [6\14] by xxxxx.cam.example with smtp (Exim 4.00) + [7\14] id 16RdAL-0006pc-00 + [8\14] for ph10@cam.example; Mon, 16 Sep 2002 16:09:43 +0100 + [9\14] F From: <> + [10\14] Subject: this is a test header + [11\14] X-something: this is another header + [12\14] I Message-Id: <E16RdAL-0006pc-00@xxxxx.cam.example> + [13\14] B Bcc: + [14/14] Date: Mon, 16 Sep 2002 16:09:43 +0100\} + +Log lines that are neither too long nor contain newlines are written to syslog +without modification. + +If only syslog is being used, the Exim monitor is unable to provide a log tail +display, unless syslog is routing 'mainlog' to a file on the local host and +the environment variable EXIMON_LOG_FILE_PATH is set to tell the monitor +where it is. + + + +Log line flags +~~~~~~~~~~~~~~ +One line is written to the main log for each message received, and for each +successful, unsuccessful, and delayed delivery. These lines can readily be +picked out by the distinctive two-character flags that immediately follow the +timestamp. The flags are: + +&&& +`<=` message arrival +`=>` normal message delivery +`->` additional address in same delivery +`\*>` delivery suppressed by %-N% +`\*\*` delivery failed; address bounced +`==` delivery deferred; temporary problem +&&& + + + +Logging message reception +~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[log,reception line] +The format of the single-line entry in the main log that is written for every +message received is shown in the basic example below, which is split over +several lines in order to fit it on the page: + + 2002-10-31 08:57:53 16ZCW1-0005MB-00 <= kryten@dwarf.fict.example + H=mailer.fict.example [192.168.123.123] U=exim + P=smtp S=5678 id=<incoming message id> + +The address immediately following ``<='' is the envelope sender address. A bounce +message is shown with the sender address ``<>'', and if it is locally generated, +this is followed by an item of the form + + R=<message id> + +which is a reference to the message that caused the bounce to be sent. + +cindex:[HELO] +cindex:[EHLO] +For messages from other hosts, the H and U fields identify the remote host and +record the RFC 1413 identity of the user that sent the message, if one was +received. The number given in square brackets is the IP address of the sending +host. If there is a single, unparenthesized host name in the H field, as +above, it has been verified to correspond to the IP address (see the +%host_lookup% option). If the name is in parentheses, it was the name quoted +by the remote host in the SMTP HELO or EHLO command, and has not been +verified. If verification yields a different name to that given for HELO or +EHLO, the verified name appears first, followed by the HELO or EHLO +name in parentheses. + +Misconfigured hosts (and mail forgers) sometimes put an IP address, with or +without brackets, in the HELO or EHLO command, leading to entries in +the log containing text like these examples: + + H=(10.21.32.43) [192.168.8.34] + H=([10.21.32.43]) [192.168.8.34] + +This can be confusing. Only the final address in square brackets can be relied +on. + +For locally generated messages (that is, messages not received over TCP/IP), +the H field is omitted, and the U field contains the login name of the caller +of Exim. + +cindex:[authentication,logging] +cindex:[AUTH,logging] +For all messages, the P field specifies the protocol used to receive the +message. This is set to ``esmtpa'' for messages received from hosts that have +authenticated themselves using the SMTP AUTH command. In this case there is an +additional item A= followed by the name of the authenticator that was used. If +an authenticated identification was set up by the authenticator's +%server_set_id% option, this is logged too, separated by a colon from the +authenticator name. + +The id field records the existing message id, if present. +cindex:[size,of message] +The size of the received message is given by the S field. When the message is +delivered, headers may get removed or added, so that the size of delivered +copies of the message may not correspond with this value (and indeed may be +different to each other). + +The %log_selector% option can be used to request the logging of additional +data when a message is received. See section <<SECTlogselector>> below. + + + +Logging deliveries +~~~~~~~~~~~~~~~~~~ +cindex:[log,delivery line] +The format of the single-line entry in the main log that is written for every +delivery is shown in one of the examples below, for local and remote deliveries, +respectively. Each example has been split into two lines in order to fit +it on the page: + + 2002-10-31 08:59:13 16ZCW1-0005MB-00 => marv <marv@hitch.fict.example> + R=localuser T=local_delivery + 2002-10-31 09:00:10 16ZCW1-0005MB-00 => monk@holistic.fict.example + R=dnslookup T=remote_smtp H=holistic.fict.example [192.168.234.234] + +For ordinary local deliveries, the original address is given in angle brackets +after the final delivery address, which might be a pipe or a file. If +intermediate address(es) exist between the original and the final address, the +last of these is given in parentheses after the final address. The R and T +fields record the router and transport that were used to process the address. + +If a shadow transport was run after a successful local delivery, the log line +for the successful delivery has an item added on the end, of the form + + ST=<shadow transport name> + +If the shadow transport did not succeed, the error message is put in +parentheses afterwards. + +When more than one address is included in a single delivery (for example, two +SMTP RCPT commands in one transaction) the second and subsequent +addresses are flagged with `->` instead of `=>`. When two or more +messages are delivered down a single SMTP connection, an asterisk follows the +IP address in the log lines for the second and subsequent messages. + +The generation of a reply message by a filter file gets logged as a ``delivery'' +to the addressee, preceded by ``>''. + +The %log_selector% option can be used to request the logging of additional +data when a message is delivered. See section <<SECTlogselector>> below. + + + +Discarded deliveries +~~~~~~~~~~~~~~~~~~~~ +cindex:[discarded messages] +cindex:[message,discarded] +cindex:[delivery,discarded; logging] +When a message is discarded as a result of the command ``seen finish'' being +obeyed in a filter file which generates no deliveries, a log entry of the form + + 2002-12-10 00:50:49 16auJc-0001UB-00 => discarded + <low.club@bridge.example> R=userforward + +is written, to record why no deliveries are logged. When a message is discarded +because it is aliased to ``:blackhole:'' the log line is like this: + + 1999-03-02 09:44:33 10HmaX-0005vi-00 => :blackhole: + <hole@nowhere.example> R=blackhole_router + + + + +Deferred deliveries +~~~~~~~~~~~~~~~~~~~ +When a delivery is deferred, a line of the following form is logged: + + 2002-12-19 16:20:23 16aiQz-0002Q5-00 == marvin@endrest.example + R=dnslookup T=smtp defer (146): Connection refused + +In the case of remote deliveries, the error is the one that was given for the +last IP address that was tried. Details of individual SMTP failures are also +written to the log, so the above line would be preceded by something like + + 2002-12-19 16:20:23 16aiQz-0002Q5-00 Failed to connect to + mail1.endrest.example [192.168.239.239]: Connection refused + +When a deferred address is skipped because its retry time has not been reached, +a message is written to the log, but this can be suppressed by setting an +appropriate value in %log_selector%. + + + +Delivery failures +~~~~~~~~~~~~~~~~~ +cindex:[delivery,failure; logging] +If a delivery fails because an address cannot be routed, a line of the +following form is logged: + + 1995-12-19 16:20:23 0tRiQz-0002Q5-00 ** jim@trek99.example + <jim@trek99.example>: unknown mail domain + +If a delivery fails at transport time, the router and transport are shown, and +the response from the remote host is included, as in this example: + + 2002-07-11 07:14:17 17SXDU-000189-00 ** ace400@pb.example R=dnslookup + T=remote_smtp: SMTP error from remote mailer after pipelined + RCPT TO:<ace400@pb.example>: host pbmail3.py.example + [192.168.63.111]: 553 5.3.0 <ace400@pb.example>... + Addressee unknown + +The word ``pipelined'' indicates that the SMTP PIPELINING extension was being +used. See %hosts_avoid_esmtp% in the ^smtp^ transport for a way of +disabling PIPELINING. + +The log lines for all forms of delivery failure are flagged with `\*\*`. + + + +Fake deliveries +~~~~~~~~~~~~~~~ +cindex:[delivery,fake; logging] +If a delivery does not actually take place because the %-N% option has been +used to suppress it, a normal delivery line is written to the log, except that +``=>'' is replaced by ``\*>''. + + + +Completion +~~~~~~~~~~ +A line of the form + + 2002-10-31 09:00:11 16ZCW1-0005MB-00 Completed + +is written to the main log when a message is about to be removed from the spool +at the end of its processing. + + + + +Summary of Fields in Log Lines +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[log,summary of fields] +A summary of the field identifiers that are used in log lines is shown in +the following table: + +&&& +`A ` authenticator name (and optional id) +`C ` SMTP confirmation on delivery +`CV ` certificate verification status +`DN ` distinguished name from peer certificate +`DT ` on `=>` lines: time taken for a delivery +`F ` sender address (on delivery lines) +`H ` host name and IP address +`I ` local interface used +`id ` message id for incoming message +`P ` on `<=` lines: protocol used +` ` on `=>` and `\*\*` lines: return path +`QT ` on `=>` lines: time spent on queue so far +` ` on ``Completed'' lines: time spent on queue +`R ` on `<=` lines: reference for local bounce +` ` on `=>` `\*\*` and `==` lines: router name +`S ` size of message +`ST ` shadow transport name +`T ` on `<=` lines: message subject (topic) +` ` on `=>` `\*\*` and `==` lines: transport name +`U ` local user or RFC 1413 identity +`X ` TLS cipher suite +&&& + + + +Other log entries +~~~~~~~~~~~~~~~~~ +Various other types of log entry are written from time to time. Most should be +self-explanatory. Among the more common are: + +- cindex:[retry,time not reached] +'retry time not reached'~~An address previously suffered a temporary error +during routing or local delivery, and the time to retry has not yet arrived. +This message is not written to an individual message log file unless it happens +during the first delivery attempt. + +- 'retry time not reached for any host'~~An address previously suffered +temporary errors during remote delivery, and the retry time has not yet arrived +for any of the hosts to which it is routed. + +- cindex:[spool directory,file locked] +'spool file locked'~~An attempt to deliver a message cannot proceed because +some other Exim process is already working on the message. This can be quite +common if queue running processes are started at frequent intervals. The +'exiwhat' utility script can be used to find out what Exim processes are +doing. + +- cindex:[error,ignored] +'error ignored'~~There are several circumstances that give rise to this +message: + +. Exim failed to deliver a bounce message whose age was greater than +%ignore_bounce_errors_after%. The bounce was discarded. + +. A filter file set up a delivery using the ``noerror'' option, and the delivery +failed. The delivery was discarded. + +. A delivery set up by a router configured with ++ + errors_to = <> ++ +failed. The delivery was discarded. + + + + + +[[SECTlogselector]] +Reducing or increasing what is logged +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[log,selectors] +By setting the %log_selector% global option, you can disable some of Exim's +default logging, or you can request additional logging. The value of +%log_selector% is made up of names preceded by plus or minus characters. For +example: + + log_selector = +arguments -retry_defer + +The list of optional log items is in the following table, with the default +selection marked by asterisks: + +&&& +` address_rewrite ` address rewriting +` all_parents ` all parents in => lines +` arguments ` command line arguments +`\*connection_reject ` connection rejections +`\*delay_delivery ` immediate delivery delayed +` deliver_time ` time taken to perform delivery +` delivery_size ` add S=nnn to => lines +`\*dnslist_defer ` defers of DNS list (aka RBL) lookups +`\*etrn ` ETRN commands +`\*host_lookup_failed ` as it says +` ident_timeout ` timeout for ident connection +` incoming_interface ` incoming interface on <= lines +` incoming_port ` incoming port on <= lines +`\*lost_incoming_connection ` as it says (includes timeouts) +` outgoing_port ` add remote port to => lines +`\*queue_run ` start and end queue runs +` queue_time ` time on queue for one recipient +` queue_time_overall ` time on queue for whole message +` received_recipients ` recipients on <= lines +` received_sender ` sender on <= lines +`\*rejected_header ` header contents on reject log +`\*retry_defer ` ``retry time not reached'' +` return_path_on_delivery ` put return path on => and \*\ lines +` sender_on_delivery ` add sender to => lines +`\*size_reject ` rejection because too big +`\*skip_delivery ` delivery skipped in a queue run +` smtp_confirmation ` SMTP confirmation on => lines +` smtp_connection ` SMTP connections +` smtp_incomplete_transaction` incomplete SMTP transactions +` smtp_protocol_error ` SMTP protocol errors +` smtp_syntax_error ` SMTP syntax errors +` subject ` contents of 'Subject:' on <= lines +` tls_certificate_verified ` certificate verification status +`\*tls_cipher ` TLS cipher suite on <= and => lines +` tls_peerdn ` TLS peer DN on <= and => lines + +` all ` all of the above +&&& + +More details on each of these items follows: + +- cindex:[log,rewriting] +cindex:[rewriting,logging] +%address_rewrite%: This applies both to global rewrites and per-transport +rewrites, +but not to rewrites in filters run as an unprivileged user (because such users +cannot access the log). + +- cindex:[log,full parentage] +%all_parents%: Normally only the original and final addresses are logged on +delivery lines; with this selector, intermediate parents are given in +parentheses between them. + +- cindex:[log,Exim arguments] +cindex:[Exim arguments, logging] +%arguments%: This causes Exim to write the arguments with which it was called +to the main log, preceded by the current working directory. This is a debugging +feature, added to make it easier to find out how certain MUAs call +_/usr/sbin/sendmail_. The logging does not happen if Exim has given up root +privilege because it was called with the %-C% or %-D% options. Arguments that +are empty or that contain whitespace are quoted. Non-printing characters are +shown as escape sequences. This facility cannot log unrecognized arguments, +because the arguments are checked before the configuration file is read. The +only way to log such cases is to interpose a script such as _util/logargs.sh_ +between the caller and Exim. + +- cindex:[log,connection rejections] +%connection_reject%: A log entry is written whenever an incoming SMTP +connection is rejected, for whatever reason. + +- cindex:[log,delayed delivery] +cindex:[delayed delivery, logging] +%delay_delivery%: A log entry is written whenever a delivery process is not +started for an incoming message because the load is too high or too many +messages were received on one connection. Logging does not occur if no delivery +process is started because %queue_only% is set or %-odq% was used. + +- cindex:[log,delivery duration] +%deliver_time%: For each delivery, the amount of real time it has taken to +perform the actual delivery is logged as DT=<'time'>, for example, `DT=1s`. + +- cindex:[log,message size on delivery] +cindex:[size,of message] +%delivery_size%: For each delivery, the size of message delivered is added to +the ``=>'' line, tagged with S=. + +- cindex:[log,dnslist defer] +cindex:[DNS list,logging defer] +cindex:[black list (DNS)] +%dnslist_defer%: A log entry is written if an attempt to look up a host in a +DNS black list suffers a temporary error. + +- cindex:[log,ETRN commands] +cindex:[ETRN,logging] +%etrn%: Every legal ETRN command that is received is logged, before the ACL is +run to determine whether or not it is actually accepted. An invalid ETRN +command, or one received within a message transaction is not logged by this +selector (see %smtp_syntax_error% and %smtp_protocol_error%). + +- cindex:[log,host lookup failure] +%host_lookup_failed%: When a lookup of a host's IP addresses fails to find +any addresses, or when a lookup of an IP address fails to find a host name, a +log line is written. This logging does not apply to direct DNS lookups when +routing email addresses, but it does apply to ``byname'' lookups. + +- cindex:[log,ident timeout] +cindex:[RFC 1413,logging timeout] +%ident_timeout%: A log line is written whenever an attempt to connect to a +client's ident port times out. + +- cindex:[log,incoming interface] +cindex:[interface,logging] +%incoming_interface%: The interface on which a message was received is added to +the ``<='' line as an IP address in square brackets, tagged by I= and followed +by a colon and the port number. The local interface and port are also added to +other SMTP log lines, for example ``SMTP connection from'', and to rejection +lines. + +- cindex:[log,incoming remote port] +cindex:[port,logging remote] +cindex:[TCP/IP,logging incoming remote port] +%incoming_port%: The remote port number from which a message was received is +added to log entries and 'Received:' header lines, following the IP address in +square brackets, and separated from it by a colon. This is implemented by +changing the value that is put in the $sender_fullhost$ and +$sender_rcvhost$ variables. Recording the remote port number has become more +important with the widening use of NAT (see RFC 2505). + +- cindex:[log,dropped connection] +%lost_incoming_connection%: A log line is written when an incoming SMTP +connection is unexpectedly dropped. + +- cindex:[log,outgoing remote port] +cindex:[port,logging outgoint remote] +cindex:[TCP/IP,logging ougtoing remote port] +%outgoing_port%: The remote port number is added to delivery log lines (those +containing => tags) following the IP address. This option is not included in +the default setting, because for most ordinary configurations, the remote port +number is always 25 (the SMTP port). + +- cindex:[log,queue run] +cindex:[queue runner,logging] +%queue_run%: The start and end of every queue run are logged. + +- cindex:[log,queue time] +%queue_time%: The amount of time the message has been in the queue on the local +host is logged as QT=<'time'> on delivery (`=>`) lines, for example, +`QT=3m45s`. The clock starts when Exim starts to receive the message, so it +includes reception time as well as the delivery time for the current address. +This means that it may be longer than the difference between the arrival and +delivery log line times, because the arrival log line is not written until the +message has been successfully received. + +- %queue_time_overall%: The amount of time the message has been in the queue on +the local host is logged as QT=<'time'> on ``Completed'' lines, for +example, `QT=3m45s`. The clock starts when Exim starts to receive the +message, so it includes reception time as well as the total delivery time. + +- cindex:[log,recipients] +%received_recipients%: The recipients of a message are listed in the main log +as soon as the message is received. The list appears at the end of the log line +that is written when a message is received, preceded by the word ``for''. The +addresses are listed after they have been qualified, but before any rewriting +has taken place. +Recipients that were discarded by an ACL for MAIL or RCPT do not appear +in the list. + +- cindex:[log,sender reception] +%received_sender%: The unrewritten original sender of a message is added to +the end of the log line that records the message's arrival, after the word +``from'' (before the recipients if %received_recipients% is also set). + +- cindex:[log,header lines for rejection] +%rejected_header%: If a message's header has been received at the time a +rejection is written to the reject log, the complete header is added to the +log. Header logging can be turned off individually for messages that are +rejected by the 'local_scan()' function (see section <<SECTapiforloc>>). + +- cindex:[log,retry defer] +%retry_defer%: A log line is written if a delivery is deferred because a retry +time has not yet been reached. However, this ``retry time not reached'' message +is always omitted from individual message logs after the first delivery +attempt. + +- cindex:[log,return path] +%return_path_on_delivery%: The return path that is being transmitted with +the message is included in delivery and bounce lines, using the tag P=. +This is omitted if no delivery actually happens, for example, if routing fails, +or if delivery is to _/dev/null_ or to `:blackhole:`. + +- cindex:[log,sender on delivery] +%sender_on_delivery%: The message's sender address is added to every delivery +and bounce line, tagged by F= (for ``from''). +This is the original sender that was received with the message; it is not +necessarily the same as the outgoing return path. + +- cindex:[log,size rejection] +%size_reject%: A log line is written whenever a message is rejected because it +is too big. + +- cindex:[log,frozen messages; skipped] +cindex:[frozen messages,logging skipping] +%skip_delivery%: A log line is written whenever a message is skipped during a +queue run because it is frozen or because another process is already delivering +it. +cindex:[``spool file is locked''] +The message that is written is ``spool file is locked''. + +- cindex:[log,smtp confirmation] +cindex:[SMTP,logging confirmation] +%smtp_confirmation%: The response to the final ``.'' in the SMTP dialogue for +outgoing messages is added to delivery log lines in the form ``C="<''text'>"'. A +number of MTAs (including Exim) return an identifying string in this response. + +- cindex:[log,SMTP connections] +cindex:[SMTP,logging connections] +%smtp_connection%: A log line is written whenever an SMTP connection is +established or closed, unless the connection is from a host that matches +%hosts_connection_nolog%. (In contrast, %lost_incoming_connection% applies only +when the closure is unexpected.) This applies to connections from local +processes that use %-bs% as well as to TCP/IP connections. If a connection is +dropped in the middle of a message, a log line is always written, whether or +not this selector is set, but otherwise nothing is written at the start and end +of connections unless this selector is enabled. ++ +For TCP/IP connections to an Exim daemon, the current number of connections is +included in the log message for each new connection, but note that the count is +reset if the daemon is restarted. +Also, because connections are closed (and the closure is logged) in +subprocesses, the count may not include connections that have been closed but +whose termination the daemon has not yet noticed. Thus, while it is possible to +match up the opening and closing of connections in the log, the value of the +logged counts may not be entirely accurate. + +- cindex:[log,SMTP transaction; incomplete] +cindex:[SMTP,logging incomplete transactions] +%smtp_incomplete_transaction%: When a mail transaction is aborted by +RSET, QUIT, loss of connection, or otherwise, the incident is logged, +and the message sender plus any accepted recipients are included in the log +line. This can provide evidence of dictionary attacks. + +- cindex:[log,SMTP protocol error] +cindex:[SMTP,logging protocol error] +%smtp_protocol_error%: A log line is written for every SMTP protocol error +encountered. Exim does not have perfect detection of all protocol errors +because of transmission delays and the use of pipelining. If PIPELINING has +been advertised to a client, an Exim server assumes that the client will use +it, and therefore it does not count ``expected'' errors (for example, RCPT +received after rejecting MAIL) as protocol errors. + +- cindex:[SMTP,logging syntax errors] +cindex:[SMTP,syntax errors; logging] +cindex:[SMTP,unknown command; logging] +cindex:[log,unknown SMTP command] +cindex:[log,SMTP syntax error] +%smtp_syntax_error%: A log line is written for every SMTP syntax error +encountered. An unrecognized command is treated as a syntax error. For an +external connection, the host identity is given; for an internal connection +using %-bs% the sender identification (normally the calling user) is given. + +- cindex:[log,subject] +cindex:[subject, logging] +%subject%: The subject of the message is added to the arrival log line, +preceded by ``T='' (T for ``topic'', since S is already used for ``size''). +Any MIME ``words'' in the subject are decoded. The %print_topbitchars% option +specifies whether characters with values greater than 127 should be logged +unchanged, or whether they should be rendered as escape sequences. + +- cindex:[log,certificate verification] +%tls_certificate_verified%: An extra item is added to <= and => log lines +when TLS is in use. The item is `CV=yes` if the peer's certificate was +verified, and `CV=no` if not. + +- cindex:[log,TLS cipher] +cindex:[TLS,logging cipher] +%tls_cipher%: When a message is sent or received over an encrypted connection, +the cipher suite used is added to the log line, preceded by X=. + +- cindex:[log,TLS peer DN] +cindex:[TLS,logging peer DN] +%tls_peerdn%: When a message is sent or received over an encrypted connection, +and a certificate is supplied by the remote host, the peer DN is added to the +log line, preceded by DN=. + + + +Message log +~~~~~~~~~~~ +cindex:[message,log file for] +cindex:[log,message log; description of] +In addition to the general log files, Exim writes a log file for each message +that it handles. The names of these per-message logs are the message ids, and + +cindex:[_msglog_ directory] +they are kept in the _msglog_ sub-directory of the spool directory. Each +message log contains copies of the log lines that apply to the message. This +makes it easier to inspect the status of an individual message without having +to search the main log. A message log is deleted when processing of the message +is complete, + +cindex:[%preserve_message_logs%] +unless %preserve_message_logs% is set, but this should be used only with +great care because they can fill up your disk very quickly. + +On a heavily loaded system, it may be desirable to disable the use of +per-message logs, in order to reduce disk I/O. This can be done by setting the +%message_logs% option false. + + + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// + +[[CHAPutils]] +Exim utilities +-------------- +cindex:[utilities] +A number of utility scripts and programs are supplied with Exim and are +described in this chapter. There is also the Exim Monitor, which is covered in +the next chapter. The utilities described here are: + +[frame="none"] +`2`8`30`40~ +,<<SECTfinoutwha>> , 'exiwhat' , list what Exim processes are doing +,<<SECTgreptheque>> , 'exiqgrep' , grep the queue +,<<SECTsumtheque>> , 'exiqsumm' , summarize the queue +,<<SECTextspeinf>> , 'exigrep' , search the main log +,<<SECTexipick>> , 'exipick' , select messages on various criteria +,<<SECTcyclogfil>> , 'exicyclog' , cycle (rotate) log files +,<<SECTmailstat>> , 'eximstats' , extract statistics from the log +,<<SECTcheckaccess>> , 'exim_checkaccess', check address acceptance from given IP +,<<SECTdbmbuild>> , 'exim_dbmbuild' , build a DBM file +,<<SECTfinindret>> , 'exinext' , extract retry information +,<<SECThindatmai>> , 'exim_dumpdb' , dump a hints database +,<<SECThindatmai>> , 'exim_tidydb' , clean up a hints database +,<<SECThindatmai>> , 'exim_fixdb' , patch a hints database +,<<SECTmailboxmaint>>, 'exim_lock' , lock a mailbox file +~~~~~ + + +[[SECTfinoutwha]] +Finding out what Exim processes are doing (exiwhat) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:['exiwhat'] +cindex:[process, querying] +cindex:[SIGUSR1] +On operating systems that can restart a system call after receiving a signal +(most modern OS), an Exim process responds to the SIGUSR1 signal by writing +a line describing what it is doing to the file _exim-process.info_ in the +Exim spool directory. The 'exiwhat' script sends the signal to all Exim +processes it can find, having first emptied the file. It then waits for one +second to allow the Exim processes to react before displaying the results. In +order to run 'exiwhat' successfully you have to have sufficient privilege to +send the signal to the Exim processes, so it is normally run as root. + +*Warning*: This is not an efficient process. It is intended for occasional +use by system administrators. It is not sensible, for example, to set up a +script that sends SIGUSR1 signals to Exim processes at short intervals. + + +Unfortunately, the 'ps' command that 'exiwhat' uses to find Exim processes +varies in different operating systems. Not only are different options used, +but the format of the output is different. For this reason, there are some +system configuration options that configure exactly how 'exiwhat' works. If it +doesn't seem to be working for you, check the following compile-time options: + +&&& +`EXIWHAT_PS_CMD ` the command for running 'ps' +`EXIWHAT_PS_ARG ` the argument for 'ps' +`EXIWHAT_EGREP_ARG ` the argument for 'egrep' to select from 'ps' output +`EXIWHAT_KILL_ARG ` the argument for the 'kill' command +&&& + +An example of typical output from 'exiwhat' is + + 164 daemon: -q1h, listening on port 25 + 10483 running queue: waiting for 0tAycK-0002ij-00 (10492) + 10492 delivering 0tAycK-0002ij-00 to mail.ref.example [10.19.42.42] + (editor@ref.example) + 10592 handling incoming call from [192.168.243.242] + 10628 accepting a local non-SMTP message + +The first number in the output line is the process number. The third line has +been split here, in order to fit it on the page. + + + +[[SECTgreptheque]] +Selective queue listing (exiqgrep) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:['exiqgrep'] +cindex:[queue,grepping] +This utility is a Perl script contributed by Matt Hubbard. It runs + + exim -bpu + +to obtain a queue listing with undelivered recipients only, and then greps the +output to select messages that match given criteria. The following selection +options are available: + +*-f*~<'regex'>:: +Match the sender address. The field that is tested is enclosed in angle +brackets, so you can test for bounce messages with + + exiqgrep -f '^<>$' + +*-r*~<'regex'>:: +Match a recipient address. The field that is tested is not enclosed in angle +brackets. + +*-s*~<'regex'>:: +Match against the size field. + +*-y*~<'seconds'>:: +Match messages that are younger than the given time. + +*-o*~<'seconds'>:: +Match messages that are older than the given time. + +*-z*:: +Match only frozen messages. + +*-x*:: +Match only non-frozen messages. + +/// +End of list +/// + +The following options control the format of the output: + +*-c*:: +Display only the count of matching messages. + +*-l*:: +Long format -- display the full message information as output by Exim. This is +the default. + +*-i*:: +Display message ids only. + +*-b*:: +Brief format -- one line per message. + +*-R*:: +Display messages in reverse order. + +/// +End of list +/// + +There is one more option, %-h%, which outputs a list of options. + + + +[[SECTsumtheque]] +Summarising the queue (exiqsumm) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:['exiqsumm'] +cindex:[queue,summary] +The 'exiqsumm' utility is a Perl script which reads the output of 'exim +-bp' and produces a summary of the messages on the queue. Thus, you use it by +running a command such as + + exim -bp | exiqsumm + +The output consists of one line for each domain that has messages waiting for +it, as in the following example: + + 3 2322 74m 66m msn.com.example + +Each line lists the number of +pending deliveries for a domain, their total volume, and the length of time +that the oldest and the newest messages have been waiting. Note that the number +of pending deliveries is greater than the number of messages when messages +have more than one recipient. + +A summary line is output at the end. By default the output is sorted on the +domain name, but 'exiqsumm' has the options %-a% and %-c%, which cause the +output to be sorted by oldest message and by count of messages, respectively. + +The output of 'exim -bp' contains the original addresses in the message, so +this also applies to the output from 'exiqsumm'. No domains from addresses +generated by aliasing or forwarding are included (unless the %one_time% option +of the ^redirect^ router has been used to convert them into ``top level'' +addresses). + + + + +[[SECTextspeinf]] +Extracting specific information from the log (exigrep) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:['exigrep'] +cindex:[log,extracts; grepping for] +The 'exigrep' utility is a Perl script that searches one or more main log +files for entries that match a given pattern. When it finds a match, it +extracts all the log entries for the relevant message, not just those that +match the pattern. Thus, 'exigrep' can extract complete log entries for a +given message, or all mail for a given user, or for a given host, for example. + +If a matching log line is not associated with a specific message, it is always +included in 'exigrep''s output. +The usage is: + + exigrep [-l] [-t<n>] <pattern> [<log file>] ... + +The %-t% argument specifies a number of seconds. It adds an additional +condition for message selection. Messages that are complete are shown only if +they spent more than <'n'> seconds on the queue. + +The %-l% flag means ``literal'', that is, treat all characters in the +pattern as standing for themselves. Otherwise the pattern must be a Perl +regular expression. The pattern match is case-insensitive. If no file names are +given on the command line, the standard input is read. + +If the location of a 'zcat' command is known from the definition of +ZCAT_COMMAND in _Local/Makefile_, 'exigrep' automatically passes any +file whose name ends in COMPRESS_SUFFIX through 'zcat' as it searches +it. + + +[[SECTexipick]] +Selecting messages by various criteria (exipick) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:['exipick'] +John Jetmore's 'exipick' utility is included in the Exim distribution. It +lists messages from the queue according to a variety of criteria. For details, +run: + + exipick --help + + + + +[[SECTcyclogfil]] +Cycling log files (exicyclog) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[log,cycling local files] +cindex:[cycling logs] +cindex:['exicyclog'] +The 'exicyclog' script can be used to cycle (rotate) 'mainlog' and +'rejectlog' files. This is not necessary if only syslog is being used, or if +you are using log files with datestamps in their names (see section +<<SECTdatlogfil>>). Some operating systems have their own standard mechanisms for +log cycling, and these can be used instead of 'exicyclog' if preferred. + +Each time 'exicyclog' is run the file names get ``shuffled down'' by one. If +the main log file name is _mainlog_ (the default) then when 'exicyclog' is +run _mainlog_ becomes _mainlog.01_, the previous _mainlog.01_ becomes +_mainlog.02_ and so on, up to a limit which is set in the script, and which +defaults to 10. Log files whose numbers exceed the limit are discarded. Reject +logs are handled similarly. + +If the limit is greater than 99, the script uses 3-digit numbers such as +_mainlog.001_, _mainlog.002_, etc. If you change from a number less than 99 +to one that is greater, or 'vice versa', you will have to fix the names of +any existing log files. + + +If no _mainlog_ file exists, the script does nothing. Files that ``drop off'' +the end are deleted. All files with numbers greater than 01 are compressed, +using a compression command which is configured by the COMPRESS_COMMAND +setting in _Local/Makefile_. It is usual to run 'exicyclog' daily from a +root %crontab% entry of the form + + 1 0 * * * su exim -c /usr/exim/bin/exicyclog + +assuming you have used the name ``exim'' for the Exim user. You can run +'exicyclog' as root if you wish, but there is no need. + + + +[[SECTmailstat]] +Mail statistics (eximstats) +~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[statistics] +cindex:['eximstats'] +A Perl script called 'eximstats' is provided for extracting statistical +information from log files. The output is either plain text, or HTML. +Exim log files are also suported by the 'Lire' system produced by the +LogReport Foundation (*http://www.logreport.org[]*). + +The 'eximstats' script has been hacked about quite a bit over time. The +latest version is the result of some extensive revision by Steve Campbell. A +lot of information is given by default, but there are options for suppressing +various parts of it. Following any options, the arguments to the script are a +list of files, which should be main log files. For example: + + eximstats -nr /var/spool/exim/log/mainlog.01 + +By default, 'eximstats' extracts information about the number and volume of +messages received from or delivered to various hosts. The information is sorted +both by message count and by volume, and the top fifty hosts in each category +are listed on the standard output. Similar information, based on email +addresses or domains instead of hosts can be requested by means of various +options. For messages delivered and received locally, similar statistics are +also produced per user. + +The output also includes total counts and statistics about delivery errors, and +histograms showing the number of messages received and deliveries made in each +hour of the day. A delivery with more than one address in its envelope (for +example, an SMTP transaction with more than one RCPT command) is counted +as a single delivery by 'eximstats'. + +Though normally more deliveries than receipts are reported (as messages may +have multiple recipients), it is possible for 'eximstats' to report more +messages received than delivered, even though the queue is empty at the start +and end of the period in question. If an incoming message contains no valid +recipients, no deliveries are recorded for it. A bounce message is handled as +an entirely separate message. + +'eximstats' always outputs a grand total summary giving the volume and number +of messages received and deliveries made, and the number of hosts involved in +each case. It also outputs the number of messages that were delayed (that is, +not completely delivered at the first attempt), and the number that had at +least one address that failed. + +The remainder of the output is in sections that can be independently disabled +or modified by various options. It consists of a summary of deliveries by +transport, histograms of messages received and delivered per time interval +(default per hour), information about the time messages spent on the queue, +a list of relayed messages, lists of the top fifty sending hosts, local +senders, destination hosts, and destination local users by count and by volume, +and a list of delivery errors that occurred. + +The relay information lists messages that were actually relayed, that is, they +came from a remote host and were directly delivered to some other remote host, +without being processed (for example, for aliasing or forwarding) locally. + +There are quite a few options for 'eximstats' to control exactly what it +outputs. These are documented in the Perl script itself, and can be extracted +by running the command ^perldoc^ on the script. For example: + + perldoc /usr/exim/bin/eximstats + + + +[[SECTcheckaccess]] +Checking access policy (exim_checkaccess) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:['exim_checkaccess'] +cindex:[policy control,checking access] +cindex:[checking access] +The %-bh% command line argument allows you to run a fake SMTP session with +debugging output, in order to check what Exim is doing when it is applying +policy controls to incoming SMTP mail. However, not everybody is sufficiently +familiar with the SMTP protocol to be able to make full use of %-bh%, and +sometimes you just want to answer the question 'Does this address have +access?' without bothering with any further details. + +The 'exim_checkaccess' utility is a ``packaged'' version of %-bh%. It takes +two arguments, an IP address and an email address: + + exim_checkaccess 10.9.8.7 A.User@a.domain.example + +The utility runs a call to Exim with the %-bh% option, to test whether the +given email address would be accepted in a RCPT command in a TCP/IP +connection from the host with the given IP address. The output of the utility +is either the word ``accepted'', or the SMTP error response, for example: + + Rejected: + 550 Relay not permitted + +When running this test, the utility uses `<>` as the envelope sender address +for the MAIL command, but you can change this by providing additional +options. These are passed directly to the Exim command. For example, to specify +that the test is to be run with the sender address 'himself@there.example' +you can use: + +.... +exim_checkaccess 10.9.8.7 A.User@a.domain.example \ + -f himself@there.example +.... + +Note that these additional Exim command line items must be given after the two +mandatory arguments. + +Because the %exim_checkaccess% uses %-bh%, it does not perform callouts while +running its checks. You can run checks that include callouts by using %-bhc%, +but this is not yet available in a ``packaged'' form. + + + +[[SECTdbmbuild]] +Making DBM files (exim_dbmbuild) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[DBM,building dbm files] +cindex:[building DBM files] +cindex:['exim_dbmbuild'] +cindex:[lower casing] +cindex:[binary zero,in lookup key] +The 'exim_dbmbuild' program reads an input file containing keys and data in +the format used by the ^lsearch^ lookup (see section <<SECTsinglekeylookups>>). +It writes a DBM file using the lower-cased alias names as keys and the +remainder of the information as data. The lower-casing can be prevented by +calling the program with the %-nolc% option. + +A terminating zero is included as part of the key string. This is expected by +the ^dbm^ lookup type. However, if the option %-nozero% is given, +'exim_dbmbuild' creates files without terminating zeroes in either the key +strings or the data strings. The ^dbmnz^ lookup type can be used with such +files. + +The program requires two arguments: the name of the input file (which can be a +single hyphen to indicate the standard input), and the name of the output file. +It creates the output under a temporary name, and then renames it if all went +well. + +cindex:[USE_DB] +If the native DB interface is in use (USE_DB is set in a compile-time +configuration file -- this is common in free versions of Unix) the two file +names must be different, because in this mode the Berkeley DB functions create +a single output file using exactly the name given. For example, + + exim_dbmbuild /etc/aliases /etc/aliases.db + +reads the system alias file and creates a DBM version of it in +_/etc/aliases.db_. + +In systems that use the 'ndbm' routines (mostly proprietary versions of Unix), +two files are used, with the suffixes _.dir_ and _.pag_. In this +environment, the suffixes are added to the second argument of +'exim_dbmbuild', so it can be the same as the first. This is also the case +when the Berkeley functions are used in compatibility mode (though this is not +recommended), because in that case it adds a _.db_ suffix to the file name. + +If a duplicate key is encountered, the program outputs a warning, and when it +finishes, its return code is 1 rather than zero, unless the %-noduperr% option +is used. By default, only the first of a set of duplicates is used -- this +makes it compatible with ^lsearch^ lookups. There is an option %-lastdup% +which causes it to use the data for the last duplicate instead. There is also +an option %-nowarn%, which stops it listing duplicate keys to %stderr%. For +other errors, where it doesn't actually make a new file, the return code is 2. + + + + +[[SECTfinindret]] +Finding individual retry times (exinext) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[retry,times] +cindex:['exinext'] +A utility called 'exinext' (mostly a Perl script) provides the ability to fish +specific information out of the retry database. Given a mail domain (or a +complete address), it looks up the hosts for that domain, and outputs any retry +information for the hosts or for the domain. At present, the retry information +is obtained by running 'exim_dumpdb' (see below) and post-processing the +output. For example: + + $ exinext piglet@milne.fict.example + kanga.milne.fict.example:192.168.8.1 error 146: Connection refused + first failed: 21-Feb-1996 14:57:34 + last tried: 21-Feb-1996 14:57:34 + next try at: 21-Feb-1996 15:02:34 + roo.milne.fict.example:192.168.8.3 error 146: Connection refused + first failed: 20-Jan-1996 13:12:08 + last tried: 21-Feb-1996 11:42:03 + next try at: 21-Feb-1996 19:42:03 + past final cutoff time + +You can also give 'exinext' a local part, without a domain, and it +will give any retry information for that local part in your default domain. +A message id can be used to obtain retry information pertaining to a specific +message. This exists only when an attempt to deliver a message to a remote host +suffers a message-specific error (see section <<SECToutSMTPerr>>). 'exinext' is +not particularly efficient, but then it isn't expected to be run very often. + +The 'exinext' utility calls Exim to find out information such as the location +of the spool directory. The utility has %-C% and %-D% options, which are +passed on to the 'exim' commands. The first specifies an alternate Exim +configuration file, and the second sets macros for use within the configuration +file. These features are mainly to help in testing, but might also be useful in +environments where more than one configuration file is in use. + + + + +[[SECThindatmai]] +Hints database maintenance (exim_dumpdb, exim_fixdb, exim_tidydb) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[hints database,maintenance] +cindex:[maintaining Exim's hints database] +Three utility programs are provided for maintaining the DBM files that Exim +uses to contain its delivery hint information. Each program requires two +arguments. The first specifies the name of Exim's spool directory, and the +second is the name of the database it is to operate on. These are as +follows: + +- 'retry': the database of retry information + +- 'wait-'<'transport name'>: databases of information about messages waiting +for remote hosts + +- 'callout': the callout cache + +- 'misc': other hints data + +The 'misc' database is used for + +- Serializing ETRN runs (when %smtp_etrn_serialize% is set) + +- Serializing delivery to a specific host (when %serialize_hosts% is set in an +^smtp^ transport) + + + +exim_dumpdb +~~~~~~~~~~~ +cindex:['exim_dumpdb'] +The entire contents of a database are written to the standard output by the +'exim_dumpdb' program, which has no options or arguments other than the +spool and database names. For example, to dump the retry database: + + exim_dumpdb /var/spool/exim retry + +Two lines of output are produced for each entry: + + T:mail.ref.example:192.168.242.242 146 77 Connection refused + 31-Oct-1995 12:00:12 02-Nov-1995 12:21:39 02-Nov-1995 20:21:39 * + +The first item on the first line is the key of the record. It starts with one +of the letters R, or T, depending on whether it refers to a routing or +transport retry. For a local delivery, the next part is the local address; for +a remote delivery it is the name of the remote host, followed by its failing IP +address (unless %no_retry_include_ip_address% is set on the ^smtp^ +transport). If the remote port is not the standard one (port 25), it is added +to the IP address. Then there follows an error code, an additional error code, +and a textual description of the error. + +The three times on the second line are the time of first failure, the time of +the last delivery attempt, and the computed time for the next attempt. The line +ends with an asterisk if the cutoff time for the last retry rule has been +exceeded. + +Each output line from 'exim_dumpdb' for the 'wait-''xxx' databases +consists of a host name followed by a list of ids for messages that are or were +waiting to be delivered to that host. If there are a very large number for any +one host, continuation records, with a sequence number added to the host name, +may be seen. The data in these records is often out of date, because a message +may be routed to several alternative hosts, and Exim makes no effort to keep +cross-references. + + + +exim_tidydb +~~~~~~~~~~~ +cindex:['exim_tidydb'] +The 'exim_tidydb' utility program is used to tidy up the contents of the +hints databases. If run with no options, it removes all records from a database +that are more than 30 days old. The cutoff date can be altered by means of the +%-t% option, which must be followed by a time. For example, to remove all +records older than a week from the retry database: + + exim_tidydb -t 7d /var/spool/exim retry + +Both the 'wait-''xxx' and 'retry' databases contain items that involve +message ids. In the former these appear as data in records keyed by host -- +they were messages that were waiting for that host -- and in the latter they +are the keys for retry information for messages that have suffered certain +types of error. When 'exim_tidydb' is run, a check is made to ensure that +message ids in database records are those of messages that are still on the +queue. Message ids for messages that no longer exist are removed from +'wait-''xxx' records, and if this leaves any records empty, they are +deleted. For the 'retry' database, records whose keys are non-existent +message ids are removed. The 'exim_tidydb' utility outputs comments on the +standard output whenever it removes information from the database. + +Certain records are automatically removed by Exim when they are no longer +needed, but others are not. For example, if all the MX hosts for a domain are +down, a retry record is created for each one. If the primary MX host comes back +first, its record is removed when Exim successfully delivers to it, but the +records for the others remain because Exim has not tried to use those hosts. + +It is important, therefore, to run 'exim_tidydb' periodically on all the +hints databases. You should do this at a quiet time of day, because it requires +a database to be locked (and therefore inaccessible to Exim) while it does its +work. Removing records from a DBM file does not normally make the file smaller, +but all the common DBM libraries are able to re-use the space that is released. +After an initial phase of increasing in size, the databases normally reach a +point at which they no longer get any bigger, as long as they are regularly +tidied. + +*Warning*: If you never run 'exim_tidydb', the space used by the hints +databases is likely to keep on increasing. + + + + +exim_fixdb +~~~~~~~~~~ +cindex:['exim_fixdb'] +The 'exim_fixdb' program is a utility for interactively modifying databases. +Its main use is for testing Exim, but it might also be occasionally useful for +getting round problems in a live system. It has no options, and its interface +is somewhat crude. On entry, it prompts for input with a right angle-bracket. A +key of a database record can then be entered, and the data for that record is +displayed. + +If ``d'' is typed at the next prompt, the entire record is deleted. For all +except the 'retry' database, that is the only operation that can be carried +out. For the 'retry' database, each field is output preceded by a number, and +data for individual fields can be changed by typing the field number followed +by new data, for example: + + > 4 951102:1000 + +resets the time of the next delivery attempt. Time values are given as a +sequence of digit pairs for year, month, day, hour, and minute. Colons can be +used as optional separators. + + + + +[[SECTmailboxmaint]] +Mailbox maintenance (exim_lock) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[mailbox,maintenance] +cindex:['exim_lock'] +cindex:[locking mailboxes] +The 'exim_lock' utility locks a mailbox file using the same algorithm as +Exim. For a discussion of locking issues, see section <<SECTopappend>>. +'Exim_lock' can be used to prevent any modification of a mailbox by Exim or +a user agent while investigating a problem. The utility requires the name of +the file as its first argument. If the locking is successful, the second +argument is run as a command (using C's 'system()' function); if there is no +second argument, the value of the SHELL environment variable is used; if this +is unset or empty, _/bin/sh_ is run. When the command finishes, the mailbox +is unlocked and the utility ends. The following options are available: + +*-fcntl*:: Use 'fcntl()' locking on the open mailbox. + +*-flock*:: Use 'flock()' locking on the open mailbox, provided the operating +system supports it. + +*-interval*:: This must be followed by a number, which is a number of seconds; +it sets the interval to sleep between retries (default 3). + +*-lockfile*:: Create a lock file before opening the mailbox. + +*-mbx*:: Lock the mailbox using MBX rules. + +*-q*:: Suppress verification output. + +*-retries*:: This must be followed by a number; it sets the number of times to +try to get the lock (default 10). + +*-restore_time*:: This option causes %exim_lock% to restore the modified and +read times to the locked file before exiting. This allows you to access a +locked mailbox (for example, to take a backup copy) without disturbing the +times that the user subsequently sees. + +*-timeout*:: This must be followed by a number, which is a number of seconds; +it sets a timeout to be used with a blocking 'fcntl()' lock. If it is not set +(the default), a non-blocking call is used. + +*-v*:: Generate verbose output. + +If none of %-fcntl%, %-flock%, %-lockfile% or %-mbx% are given, the default is +to create a lock file and also to use 'fcntl()' locking on the mailbox, which +is the same as Exim's default. The use of %-flock% or %-fcntl% requires that +the file be writeable; the use of %-lockfile% requires that the directory +containing the file be writeable. Locking by lock file does not last for ever; +Exim assumes that a lock file is expired if it is more than 30 minutes old. + +The %-mbx% option can be used with either or both of %-fcntl% or %-flock%. +It assumes %-fcntl% by default. +MBX locking causes a shared lock to be taken out on the open mailbox, and an +exclusive lock on the file _/tmp/._'n'.'m' where 'n' and 'm' are +the device number and inode number of the mailbox file. When the locking is +released, if an exclusive lock can be obtained for the mailbox, the file in +_/tmp_ is deleted. + +The default output contains verification of the locking that takes place. The +%-v% option causes some additional information to be given. The %-q% option +suppresses all output except error messages. + +A command such as + + exim_lock /var/spool/mail/spqr + +runs an interactive shell while the file is locked, whereas + + exim_lock -q /var/spool/mail/spqr <<End + <some commands> + End + +runs a specific non-interactive sequence of commands while the file is locked, +suppressing all verification output. A single command can be run by a command +such as + +.... +exim_lock -q /var/spool/mail/spqr \ + "cp /var/spool/mail/spqr /some/where" +.... + +Note that if a command is supplied, it must be entirely contained within the +second argument -- hence the quotes. + + + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// + +[[CHAPeximon]] +The Exim monitor +---------------- +cindex:[monitor] +cindex:[Exim monitor] +cindex:[X-windows] +cindex:['eximon'] +cindex:[Local/eximon.conf] +cindex:[_exim_monitor/EDITME_] +The Exim monitor is an application which displays in an X window information +about the state of Exim's queue and what Exim is doing. An admin user can +perform certain operations on messages from this GUI interface; however all +such facilities are also available from the command line, and indeed, the +monitor itself makes use of the command line to perform any actions requested. + + + +Running the monitor +~~~~~~~~~~~~~~~~~~~ +The monitor is started by running the script called 'eximon'. This is a shell +script that sets up a number of environment variables, and then runs the +binary called _eximon.bin_. The default appearance of the monitor window can +be changed by editing the _Local/eximon.conf_ file created by editing +_exim_monitor/EDITME_. Comments in that file describe what the various +parameters are for. + +The parameters that get built into the 'eximon' script can be overridden for a +particular invocation by setting up environment variables of the same names, +preceded by `EXIMON_`. For example, a shell command such as + + EXIMON_LOG_DEPTH=400 eximon + +(in a Bourne-compatible shell) runs 'eximon' with an overriding setting of the +LOG_DEPTH parameter. If EXIMON_LOG_FILE_PATH is set in the +environment, it overrides the Exim log file configuration. This makes it +possible to have 'eximon' tailing log data that is written to syslog, provided +that MAIL.INFO syslog messages are routed to a file on the local host. + +X resources can be used to change the appearance of the window in the normal +way. For example, a resource setting of the form + + Eximon*background: gray94 + +changes the colour of the background to light grey rather than white. The +stripcharts are drawn with both the data lines and the reference lines in +black. This means that the reference lines are not visible when on top of the +data. However, their colour can be changed by setting a resource called +``highlight'' (an odd name, but that's what the Athena stripchart widget uses). +For example, if your X server is running Unix, you could set up lighter +reference lines in the stripcharts by obeying + + xrdb -merge <<End + Eximon*highlight: gray + End + + +cindex:[admin user] +In order to see the contents of messages on the queue, and to operate on them, +'eximon' must either be run as root or by an admin user. + +The monitor's window is divided into three parts. The first contains one or +more stripcharts and two action buttons, the second contains a ``tail'' of the +main log file, and the third is a display of the queue of messages awaiting +delivery, with two more action buttons. The following sections describe these +different parts of the display. + + + + +The stripcharts +~~~~~~~~~~~~~~~ +cindex:[stripchart] +The first stripchart is always a count of messages on the queue. Its name can +be configured by setting QUEUE_STRIPCHART_NAME in the +_Local/eximon.conf_ file. The remaining stripcharts are defined in the +configuration script by regular expression matches on log file entries, making +it possible to display, for example, counts of messages delivered to certain +hosts or using certain transports. The supplied defaults display counts of +received and delivered messages, and of local and SMTP deliveries. The default +period between stripchart updates is one minute; this can be adjusted by a +parameter in the _Local/eximon.conf_ file. + +The stripchart displays rescale themselves automatically as the value they are +displaying changes. There are always 10 horizontal lines in each chart; the +title string indicates the value of each division when it is greater than one. +For example, ``x2'' means that each division represents a value of 2. + +It is also possible to have a stripchart which shows the percentage fullness of +a particular disk partition, which is useful when local deliveries are confined +to a single partition. + +cindex:[%statvfs% function] +This relies on the availability of the 'statvfs()' function or equivalent in +the operating system. Most, but not all versions of Unix that support Exim have +this. For this particular stripchart, the top of the chart always represents +100%, and the scale is given as ``x10%''. This chart is configured by setting +SIZE_STRIPCHART and (optionally) SIZE_STRIPCHART_NAME in the +_Local/eximon.conf_ file. + + + + +Main action buttons +~~~~~~~~~~~~~~~~~~~ +cindex:[size,of monitor window] +cindex:[monitor window size] +cindex:[window size] +Below the stripcharts there is an action button for quitting the monitor. Next +to this is another button marked ``Size''. They are placed here so that shrinking +the window to its default minimum size leaves just the queue count stripchart +and these two buttons visible. Pressing the ``Size'' button causes the window to +expand to its maximum size, unless it is already at the maximum, in which case +it is reduced to its minimum. + +When expanding to the maximum, if the window cannot be fully seen where it +currently is, it is moved back to where it was the last time it was at full +size. When it is expanding from its minimum size, the old position is +remembered, and next time it is reduced to the minimum it is moved back there. + +The idea is that you can keep a reduced window just showing one or two +stripcharts at a convenient place on your screen, easily expand it to show +the full window when required, and just as easily put it back to what it was. +The idea is copied from what the 'twm' window manager does for its +'f.fullzoom' action. The minimum size of the window can be changed by setting +the MIN_HEIGHT and MIN_WIDTH values in _Local/eximon.conf_. + +Normally, the monitor starts up with the window at its full size, but it can be +built so that it starts up with the window at its smallest size, by setting +START_SMALL=yes in _Local/eximon.conf_. + + + +The log display +~~~~~~~~~~~~~~~ +cindex:[log,tail of; in monitor] +The second section of the window is an area in which a display of the tail of +the main log is maintained. +To save space on the screen, the timestamp on each log line is shortened by +removing the date and, if %log_timezone% is set, the timezone. +The log tail is not available when the only destination for logging data is +syslog, unless the syslog lines are routed to a local file whose name is passed +to 'eximon' via the EXIMON_LOG_FILE_PATH environment variable. + +The log sub-window has a scroll bar at its lefthand side which can be used to +move back to look at earlier text, and the up and down arrow keys also have a +scrolling effect. The amount of log that is kept depends on the setting of +LOG_BUFFER in _Local/eximon.conf_, which specifies the amount of memory +to use. When this is full, the earlier 50% of data is discarded -- this is much +more efficient than throwing it away line by line. The sub-window also has a +horizontal scroll bar for accessing the ends of long log lines. This is the +only means of horizontal scrolling; the right and left arrow keys are not +available. Text can be cut from this part of the window using the mouse in the +normal way. The size of this subwindow is controlled by parameters in the +configuration file _Local/eximon.conf_. + +Searches of the text in the log window can be carried out by means of the ^R +and ^S keystrokes, which default to a reverse and a forward search, +respectively. The search covers only the text that is displayed in the window. +It cannot go further back up the log. + +The point from which the search starts is indicated by a caret marker. This is +normally at the end of the text in the window, but can be positioned explicitly +by pointing and clicking with the left mouse button, and is moved automatically +by a successful search. If new text arrives in the window when it is scrolled +back, the caret remains where it is, but if the window is not scrolled back, +the caret is moved to the end of the new text. + +Pressing ^R or ^S pops up a window into which the search text can be typed. +There are buttons for selecting forward or reverse searching, for carrying out +the search, and for cancelling. If the ``Search'' button is pressed, the search +happens and the window remains so that further searches can be done. If the +``Return'' key is pressed, a single search is done and the window is closed. If +^C is typed the search is cancelled. + +The searching facility is implemented using the facilities of the Athena text +widget. By default this pops up a window containing both ``search'' and ``replace'' +options. In order to suppress the unwanted ``replace'' portion for eximon, a +modified version of the %TextPop% widget is distributed with Exim. However, the +linkers in BSDI and HP-UX seem unable to handle an externally provided version +of %TextPop% when the remaining parts of the text widget come from the standard +libraries. The compile-time option EXIMON_TEXTPOP can be unset to cut out +the modified %TextPop%, making it possible to build Eximon on these systems, at +the expense of having unwanted items in the search popup window. + + + +The queue display +~~~~~~~~~~~~~~~~~ +cindex:[queue,display in monitor] +The bottom section of the monitor window contains a list of all messages that +are on the queue, which includes those currently being received or delivered, +as well as those awaiting delivery. The size of this subwindow is controlled by +parameters in the configuration file _Local/eximon.conf_, and the frequency +at which it is updated is controlled by another parameter in the same file -- +the default is 5 minutes, since queue scans can be quite expensive. However, +there is an ``Update'' action button just above the display which can be used to +force an update of the queue display at any time. + +When a host is down for some time, a lot of pending mail can build up for it, +and this can make it hard to deal with other messages on the queue. To help +with this situation there is a button next to ``Update'' called ``Hide''. If +pressed, a dialogue box called ``Hide addresses ending with'' is put up. If you +type anything in here and press ``Return'', the text is added to a chain of such +texts, and if every undelivered address in a message matches at least one +of the texts, the message is not displayed. + +If there is an address that does not match any of the texts, all the addresses +are displayed as normal. The matching happens on the ends of addresses so, for +example, 'cam.ac.uk' specifies all addresses in Cambridge, while +'xxx@foo.com.example' specifies just one specific address. When any hiding +has been set up, a button called ``Unhide'' is displayed. If pressed, it cancels +all hiding. Also, to ensure that hidden messages do not get forgotten, a hide +request is automatically cancelled after one hour. + +While the dialogue box is displayed, you can't press any buttons or do anything +else to the monitor window. For this reason, if you want to cut text from the +queue display to use in the dialogue box, you have to do the cutting before +pressing the ``Hide'' button. + +The queue display contains, for each unhidden queued message, the length of +time it has been on the queue, the size of the message, the message id, the +message sender, and the first undelivered recipient, all on one line. If it is +a bounce message, the sender is shown as ``<>''. If there is more than one +recipient to which the message has not yet been delivered, subsequent ones are +listed on additional lines, up to a maximum configured number, following which +an ellipsis is displayed. Recipients that have already received the message are +not shown. + +cindex:[frozen messages,display] +If a message is frozen, an asterisk is displayed at the left-hand side. + +The queue display has a vertical scroll bar, and can also be scrolled by means +of the arrow keys. Text can be cut from it using the mouse in the normal way. +The text searching facilities, as described above for the log window, are also +available, but the caret is always moved to the end of the text when the queue +display is updated. + + + +The queue menu +~~~~~~~~~~~~~~ +cindex:[queue,menu in monitor] +If the %shift% key is held down and the left button is clicked when the mouse +pointer is over the text for any message, an action menu pops up, and the first +line of the queue display for the message is highlighted. This does not affect +any selected text. + +If you want to use some other event for popping up the menu, you can set the +MENU_EVENT parameter in _Local/eximon.conf_ to change the default, or +set EXIMON_MENU_EVENT in the environment before starting the monitor. The +value set in this parameter is a standard X event description. For example, to +run eximon using %ctrl% rather than %shift% you could use + + EXIMON_MENU_EVENT='Ctrl<Btn1Down>' eximon + +The title of the menu is the message id, and it contains entries which act as +follows: + +- 'message log': The contents of the message log for the message are displayed in +a new text window. + +- 'headers': Information from the spool file that contains the envelope +information and headers is displayed in a new text window. See chapter +<<CHAPspool>> for a description of the format of spool files. + +- 'body': The contents of the spool file containing the body of the message are +displayed in a new text window. There is a default limit of 20,000 bytes to the +amount of data displayed. This can be changed by setting the BODY_MAX +option at compile time, or the EXIMON_BODY_MAX option at run time. + +- 'deliver message': A call to Exim is made using the %-M% option to request +delivery of the message. This causes an automatic thaw if the message is +frozen. The %-v% option is also set, and the output from Exim is displayed in +a new text window. The delivery is run in a separate process, to avoid holding +up the monitor while the delivery proceeds. + +- 'freeze message': A call to Exim is made using the %-Mf% option to request +that the message be frozen. + +- cindex:[thawing messages] +cindex:[unfreezing messages] +cindex:[frozen messages,thawing] +'thaw message': A call to Exim is made using the %-Mt% option to request that +the message be thawed. + +- cindex:[delivery,forcing failure] +'give up on msg': A call to Exim is made using the %-Mg% option to request +that Exim gives up trying to deliver the message. A bounce message is generated +for any remaining undelivered addresses. + +- 'remove message': A call to Exim is made using the %-Mrm% option to request +that the message be deleted from the system without generating a bounce +message. + +- 'add recipient': A dialog box is displayed into which a recipient address can +be typed. If the address is not qualified and the QUALIFY_DOMAIN parameter +is set in _Local/eximon.conf_, the address is qualified with that domain. +Otherwise it must be entered as a fully qualified address. Pressing RETURN +causes a call to Exim to be made using the %-Mar% option to request that an +additional recipient be added to the message, unless the entry box is empty, in +which case no action is taken. + +- 'mark delivered': A dialog box is displayed into which a recipient address can +be typed. If the address is not qualified and the QUALIFY_DOMAIN parameter +is set in _Local/eximon.conf_, the address is qualified with that domain. +Otherwise it must be entered as a fully qualified address. Pressing RETURN +causes a call to Exim to be made using the %-Mmd% option to mark the given +recipient address as already delivered, unless the entry box is empty, in which +case no action is taken. + +- 'mark all delivered': A call to Exim is made using the %-Mmad% option to mark +all recipient addresses as already delivered. + +- 'edit sender': A dialog box is displayed initialized with the current sender's +address. Pressing RETURN causes a call to Exim to be made using the %-Mes% +option to replace the sender address, unless the entry box is empty, in which +case no action is taken. If you want to set an empty sender (as in bounce +messages), you must specify it as ``<>''. Otherwise, if the address is not +qualified and the QUALIFY_DOMAIN parameter is set in +_Local/eximon.conf_, the address is qualified with that domain. + +When a delivery is forced, a window showing the %-v% output is displayed. In +other cases when a call to Exim is made, if there is any output from Exim (in +particular, if the command fails) a window containing the command and the +output is displayed. Otherwise, the results of the action are normally apparent +from the log and queue displays. However, if you set ACTION_OUTPUT=yes in +_Local/eximon.conf_, a window showing the Exim command is always opened, even +if no output is generated. + +The queue display is automatically updated for actions such as freezing and +thawing, unless ACTION_QUEUE_UPDATE=no has been set in +_Local/eximon.conf_. In this case the ``Update'' button has to be used to force +an update of the display after one of these actions. + +In any text window that is displayed as result of a menu action, the normal +cut-and-paste facility is available, and searching can be carried out using ^R +and ^S, as described above for the log tail window. + + + + + + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// + +[[CHAPsecurity]] +Security considerations +----------------------- +cindex:[security] +This chapter discusses a number of issues concerned with security, some of +which are also covered in other parts of this manual. + +For reasons that this author does not understand, some people have promoted +Exim as a ``particularly secure'' mailer. Perhaps it is because of the existence +of this chapter in the documentation. However, the intent of the chapter is +simply to describe the way Exim works in relation to certain security concerns, +not to make any specific claims about the effectiveness of its security as +compared with other MTAs. + +What follows is a description of the way Exim is supposed to be. Best efforts +have been made to try to ensure that the code agrees with the theory, but an +absence of bugs can never be guaranteed. Any that are reported will get fixed +as soon as possible. + + +Building a more ``hardened'' Exim +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[security,build-time features] +There are a number of build-time options that can be set in _Local/Makefile_ +to create Exim binaries that are ``harder'' to attack, in particular by a rogue +Exim administrator who does not have the root password, or by someone who has +penetrated the Exim (but not the root) account. These options are as follows: + +- ALT_CONFIG_PREFIX can be set to a string that is required to match the +start of any file names used with the %-C% option. When it is set, these file +names are also not allowed to contain the sequence ``/../''. (However, if the +value of the %-C% option is identical to the value of CONFIGURE_FILE in +_Local/Makefile_, Exim ignores %-C% and proceeds as usual.) There is no +default setting for %ALT_CONFIG_PREFIX%. ++ +If the permitted configuration files are confined to a directory to +which only root has access, this guards against someone who has broken +into the Exim account from running a privileged Exim with an arbitrary +configuration file, and using it to break into other accounts. + +- If ALT_CONFIG_ROOT_ONLY is defined, root privilege is retained for %-C% +and %-D% only if the caller of Exim is root. Without it, the Exim user may +also use %-C% and %-D% and retain privilege. Setting this option locks out +the possibility of testing a configuration using %-C% right through message +reception and delivery, even if the caller is root. The reception works, but by +that time, Exim is running as the Exim user, so when it re-execs to regain +privilege for the delivery, the use of %-C% causes privilege to be lost. +However, root can test reception and delivery using two separate commands. +ALT_CONFIG_ROOT_ONLY is not set by default. + +- If DISABLE_D_OPTION is defined, the use of the %-D% command line option +is disabled. + +- FIXED_NEVER_USERS can be set to a colon-separated list of users that are +never to be used for any deliveries. This is like the %never_users% runtime +option, but it cannot be overridden; the runtime option adds additional users +to the list. The default setting is ``root''; this prevents a non-root user who +is permitted to modify the runtime file from using Exim as a way to get root. + + + + +Root privilege +~~~~~~~~~~~~~~ +cindex:[setuid] +cindex:[root privilege] +The Exim binary is normally setuid to root, which means that it gains root +privilege (runs as root) when it starts execution. In some special cases (for +example, when the daemon is not in use and there are no local deliveries), it +may be possible to run Exim setuid to some user other than root. This is +discussed in the next section. However, in most installations, root privilege +is required for two things: + +- To set up a socket connected to the standard SMTP port (25) when initialising +the listening daemon. If Exim is run from 'inetd', this privileged action is +not required. + +- To be able to change uid and gid in order to read users' _.forward_ files and +perform local deliveries as the receiving user or as specified in the +configuration. + +It is not necessary to be root to do any of the other things Exim does, such as +receiving messages and delivering them externally over SMTP, and it is +obviously more secure if Exim does not run as root except when necessary. +For this reason, a user and group for Exim to use must be defined in +_Local/Makefile_. These are known as ``the Exim user'' and ``the Exim group''. +Their values can be changed by the run time configuration, though this is not +recommended. Often a user called 'exim' is used, but some sites use 'mail' +or another user name altogether. + +Exim uses 'setuid()' whenever it gives up root privilege. This is a permanent +abdication; the process cannot regain root afterwards. Prior to release 4.00, +'seteuid()' was used in some circumstances, but this is no longer the case. + +After a new Exim process has interpreted its command line options, it changes +uid and gid in the following cases: + +- cindex:[%-C% option] +cindex:[%-D% option] +If the %-C% option is used to specify an alternate configuration file, or if +the %-D% option is used to define macro values for the configuration, and the +calling process is not running as root or the Exim user, the uid and gid are +changed to those of the calling process. +However, if ALT_CONFIG_ROOT_ONLY is defined in _Local/Makefile_, only +root callers may use %-C% and %-D% without losing privilege, and if +DISABLE_D_OPTION is set, the %-D% option may not be used at all. + +- cindex:[%-be% option] +cindex:[%-bf% option] +cindex:[%-bF% option] +If the expansion test option (%-be%) or one of the filter testing options +(%-bf% or %-bF%) are used, the uid and gid are changed to those of the +calling process. + +- If the process is not a daemon process or a queue runner process or a delivery +process or a process for testing address routing (started with %-bt%), the uid +and gid are changed to the Exim user and group. This means that Exim always +runs under its own uid and gid when receiving messages. This also applies when +testing address verification +cindex:[%-bv% option] +cindex:[%-bh% option] +(the %-bv% option) and testing incoming message policy controls (the %-bh% +option). + +- For a daemon, queue runner, delivery, or address testing process, the uid +remains as root at this stage, but the gid is changed to the Exim group. + +/// +End of list +/// + +The processes that initially retain root privilege behave as follows: + +- A daemon process changes the gid to the Exim group and the uid to the Exim +user after setting up one or more listening sockets. The 'initgroups()' +function is called, so that if the Exim user is in any additional groups, they +will be used during message reception. + +- A queue runner process retains root privilege throughout its execution. Its +job is to fork a controlled sequence of delivery processes. + +- A delivery process retains root privilege throughout most of its execution, +but any actual deliveries (that is, the transports themselves) are run in +subprocesses which always change to a non-root uid and gid. For local +deliveries this is typically the uid and gid of the owner of the mailbox; for +remote deliveries, the Exim uid and gid are used. Once all the delivery +subprocesses have been run, a delivery process changes to the Exim uid and gid +while doing post-delivery tidying up such as updating the retry database and +generating bounce and warning messages. ++ +While the recipient addresses in a message are being routed, the delivery +process runs as root. However, if a user's filter file has to be processed, +this is done in a subprocess that runs under the individual user's uid and +gid. A system filter is run as root unless %system_filter_user% is set. + +- A process that is testing addresses (the %-bt% option) runs as root so that +the routing is done in the same environment as a message delivery. + + + + +[[SECTrunexiwitpri]] +Running Exim without privilege +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +cindex:[privilege, running without] +cindex:[unprivileged running] +cindex:[root privilege,running without] +Some installations like to run Exim in an unprivileged state for more of its +operation, for added security. Support for this mode of operation is provided +by the global option %deliver_drop_privilege%. When this is set, the uid and +gid are changed to the Exim user and group at the start of a delivery process +(and also queue runner and address testing processes). This means that address +routing is no longer run as root, and the deliveries themselves cannot change +to any other uid. + +Leaving the binary setuid to root, but setting %deliver_drop_privilege% means +that the daemon can still be started in the usual way, and it can respond +correctly to SIGHUP because the re-invocation regains root privilege. + +An alternative approach is to make Exim setuid to the Exim user and also setgid +to the Exim group. +If you do this, the daemon must be started from a root process. (Calling +Exim from a root process makes it behave in the way it does when it is setuid +root.) However, the daemon cannot restart itself after a SIGHUP signal because +it cannot regain privilege. + +It is still useful to set %deliver_drop_privilege% in this case, because it +stops Exim from trying to re-invoke itself to do a delivery after a message has +been received. Such a re-invocation is a waste of resources because it has no +effect. + +If restarting the daemon is not an issue (for example, if %mua_wrapper% is set, +or 'inetd' is being used instead of a daemon), having the binary setuid to the +Exim user seems a clean approach, but there is one complication: + +In this style of operation, Exim is running with the real uid and gid set to +those of the calling process, and the effective uid/gid set to Exim's values. +Ideally, any association with the calling process' uid/gid should be dropped, +that is, the real uid/gid should be reset to the effective values so as to +discard any privileges that the caller may have. While some operating systems +have a function that permits this action for a non-root effective uid, quite a +number of them do not. Because of this lack of standardization, Exim does not +address this problem at this time. + +For this reason, the recommended approach for ``mostly unprivileged'' running is +to keep the Exim binary setuid to root, and to set %deliver_drop_privilege%. +This also has the advantage of allowing a daemon to be used in the most +straightforward way. + +If you configure Exim not to run delivery processes as root, there are a +number of restrictions on what you can do: + +- You can deliver only as the Exim user/group. You should explicitly use the +%user% and %group% options to override routers or local transports that +normally deliver as the recipient. This makes sure that configurations that +work in this mode function the same way in normal mode. Any implicit or +explicit specification of another user causes an error. + +- Use of _.forward_ files is severely restricted, such that it is usually +not worthwhile to include them in the configuration. + +- Users who wish to use _.forward_ would have to make their home directory and +the file itself accessible to the Exim user. Pipe and append-to-file entries, +and their equivalents in Exim filters, cannot be used. While they could be +enabled in the Exim user's name, that would be insecure and not very useful. + +- Unless the local user mailboxes are all owned by the Exim user (possible in +some POP3 or IMAP-only environments): + +* They must be owned by the Exim group and be writable by that group. This +implies you must set %mode% in the appendfile configuration, as well as the +mode of the mailbox files themselves. + +* You must set %no_check_owner%, since most or all of the files will not be +owned by the Exim user. + +* You must set %file_must_exist%, because Exim cannot set the owner correctly +on a newly created mailbox when unprivileged. This also implies that new +mailboxes need to be created manually. + +These restrictions severely restrict what can be done in local deliveries. +However, there are no restrictions on remote deliveries. If you are running a +gateway host that does no local deliveries, setting %deliver_drop_privilege% +gives more security at essentially no cost. + +If you are using the %mua_wrapper% facility (see chapter <<CHAPnonqueueing>>), +%deliver_drop_privilege% is forced to be true. + + + + +Delivering to local files +~~~~~~~~~~~~~~~~~~~~~~~~~ +Full details of the checks applied by ^appendfile^ before it writes to a file +are given in chapter <<CHAPappendfile>>. + + + +IPv4 source routing +~~~~~~~~~~~~~~~~~~~ +cindex:[source routing,in IP packets] +cindex:[IP source routing] +Many operating systems suppress IP source-routed packets in the kernel, but +some cannot be made to do this, so Exim does its own check. It logs incoming +IPv4 source-routed TCP calls, and then drops them. Things are all different in +IPv6. No special checking is currently done. + + + +The VRFY, EXPN, and ETRN commands in SMTP +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Support for these SMTP commands is disabled by default. If required, they can +be enabled by defining suitable ACLs. + + + + +Privileged users +~~~~~~~~~~~~~~~~ +cindex:[trusted user] +cindex:[admin user] +cindex:[privileged user] +cindex:[user,trusted] +cindex:[user,admin] +Exim recognises two sets of users with special privileges. Trusted users are +able to submit new messages to Exim locally, but supply their own sender +addresses and information about a sending host. For other users submitting +local messages, Exim sets up the sender address from the uid, and doesn't +permit a remote host to be specified. + +cindex:[%-f% option] +However, an untrusted user is permitted to use the %-f% command line option in +the special form %-f <>% to indicate that a delivery failure for the message +should not cause an error report. This affects the message's envelope, but it +does not affect the 'Sender:' header. Untrusted users may also be permitted to +use specific forms of address with the %-f% option by setting the +%untrusted_set_sender% option. + +Trusted users are used to run processes that receive mail messages from some +other mail domain and pass them on to Exim for delivery either locally, or over +the Internet. Exim trusts a caller that is running as root, as the Exim user, +as any user listed in the %trusted_users% configuration option, or under any +group listed in the %trusted_groups% option. + +Admin users are permitted to do things to the messages on Exim's queue. They +can freeze or thaw messages, cause them to be returned to their senders, remove +them entirely, or modify them in various ways. In addition, admin users can run +the Exim monitor and see all the information it is capable of providing, which +includes the contents of files on the spool. + +cindex:[%-M% option] +cindex:[%-q% option] +By default, the use of the %-M% and %-q% options to cause Exim to attempt +delivery of messages on its queue is restricted to admin users. This +restriction can be relaxed by setting the %no_prod_requires_admin% option. +Similarly, the use of %-bp% (and its variants) to list the contents of the +queue is also restricted to admin users. This restriction can be relaxed by +setting %no_queue_list_requires_admin%. + +Exim recognises an admin user if the calling process is running as root or as +the Exim user or if any of the groups associated with the calling process is +the Exim group. It is not necessary actually to be running under the Exim +group. However, if admin users who are not root or the Exim user are to access +the contents of files on the spool via the Exim monitor (which runs +unprivileged), Exim must be built to allow group read access to its spool +files. + + + +Spool files +~~~~~~~~~~~ +cindex:[spool directory,files] +Exim's spool directory and everything it contains is owned by the Exim user and +set to the Exim group. The mode for spool files is defined in the +_Local/Makefile_ configuration file, and defaults to 0640. This means that +any user who is a member of the Exim group can access these files. + + + +Use of argv[0] +~~~~~~~~~~~~~~ +Exim examines the last component of %argv[0]%, and if it matches one of a set +of specific strings, Exim assumes certain options. For example, calling Exim +with the last component of %argv[0]% set to ``rsmtp'' is exactly equivalent to +calling it with the option %-bS%. There are no security implications in this. + + + +Use of %f formatting +~~~~~~~~~~~~~~~~~~~~ +The only use made of ``%f'' by Exim is in formatting load average values. These +are actually stored in integer variables as 1000 times the load average. +Consequently, their range is limited and so therefore is the length of the +converted output. + + + +Embedded Exim path +~~~~~~~~~~~~~~~~~~ +Exim uses its own path name, which is embedded in the code, only when it needs +to re-exec in order to regain root privilege. Therefore, it is not root when it +does so. If some bug allowed the path to get overwritten, it would lead to an +arbitrary program's being run as exim, not as root. + + + +Use of sprintf() +~~~~~~~~~~~~~~~~ +cindex:['sprintf()'] +A large number of occurrences of ``sprintf'' in the code are actually calls to +'string_sprintf()', a function that returns the result in malloc'd store. +The intermediate formatting is done into a large fixed buffer by a function +that runs through the format string itself, and checks the length of each +conversion before performing it, thus preventing buffer overruns. + +The remaining uses of 'sprintf()' happen in controlled circumstances where +the output buffer is known to be sufficiently long to contain the converted +string. + + + +Use of debug_printf() and log_write() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Arbitrary strings are passed to both these functions, but they do their +formatting by calling the function 'string_vformat()', which runs through +the format string itself, and checks the length of each conversion. + + + +Use of strcat() and strcpy() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +These are used only in cases where the output buffer is known to be large +enough to hold the result. + + + + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// + +[[CHAPspool]] +Format of spool files +--------------------- +cindex:[format,spool files] +cindex:[spool directory,format of files] +cindex:[spool files, format of] +cindex:[spool files, editing] +A message on Exim's queue consists of two files, whose names are the message id +followed by -D and -H, respectively. The data portion of the message is kept in +the -D file on its own. The message's envelope, status, and headers are all +kept in the -H file, whose format is described in this chapter. Each of these +two files contains the final component of its own name as its first line. This +is insurance against disk crashes where the directory is lost but the files +themselves are recoverable. + +Some people are tempted into editing -D files in order to modify messages. You +need to be extremely careful if you do this; it is not recommended and you are +on your own if you do it. Here are some of the pitfalls: + +- You must use the 'exim_lock' utility to ensure that Exim does not try to +deliver the message while you are fiddling with it. The lock is implemented +by opening the -D file and taking out a write lock on it. If you update the +file in place, the lock will be retained. If you write a new file and rename +it, the lock will be lost at the instant of rename. + +- If you change the number of lines in the file, the value of +$body_linecount$, which is stored in the -H file, will be incorrect. + +- If the message is in MIME format, you must take care not to break it. + +- If the message is cryptographically signed, any change will invalidate the +signature. + + +Files whose names end with -J may also be seen in the _input_ directory (or +its subdirectories when %split_spool_directory% is set). These are journal +files, used to record addresses to which the message has been delivered during +the course of a delivery run. At the end of the run, the -H file is updated, +and the -J file is deleted. + + +Format of the -H file +~~~~~~~~~~~~~~~~~~~~~ +cindex:[uid (user id),in spool file] +cindex:[gid (group id),in spool file] +The second line of the -H file contains the login name for the uid of the +process that called Exim to read the message, followed by the numerical uid and +gid. For a locally generated message, this is normally the user who sent the +message. For a message received over TCP/IP, it is normally the Exim user. + +The third line of the file contains the address of the message's sender as +transmitted in the envelope, contained in angle brackets. The sender address is +empty for bounce messages. For incoming SMTP mail, the sender address is given +in the MAIL command. For locally generated mail, the sender address is +created by Exim from the login name of the current user and the configured +%qualify_domain%. However, this can be overridden by the %-f% option or a +leading ``From'' line if the caller is trusted, or if the supplied address is +``<>'' or an address that matches %untrusted_set_senders%. + +The fourth line contains two numbers. The first is the time that the message +was received, in the conventional Unix form -- the number of seconds since the +start of the epoch. The second number is a count of the number of messages +warning of delayed delivery that have been sent to the sender. + +There follow a number of lines starting with a hyphen. These can appear in any +order, and are omitted when not relevant: + +%-acl% <'number'> <'length'>:: +A line of this form is present for every ACL variable that is not empty. The +number identifies the variable; the %acl_c%*x* variables are numbered 0--9 and +the %acl_m%*x* variables are numbered 10--19. The length is the length of the +data string for the variable. The string itself starts at the beginning of the +next line, and is followed by a newline character. It may contain internal +newlines. + +%-active_hostname% <'hostname'>:: +This is present if, when the message was received over SMTP, the value of +$smtp_active_hostname$ was different to the value of $primary_hostname$. + +%-allow_unqualified_recipient%:: +This is present if unqualified recipient addresses are permitted in header +lines (to stop such addresses from being qualified if rewriting occurs at +transport time). Local messages that were input using %-bnq% and remote +messages from hosts that match %recipient_unqualified_hosts% set this flag. + +%-allow_unqualified_sender%:: +This is present if unqualified sender addresses are permitted in header lines +(to stop such addresses from being qualified if rewriting occurs at transport +time). Local messages that were input using %-bnq% and remote messages from +hosts that match %sender_unqualified_hosts% set this flag. + +%-auth_id% <'text'>:: +The id information for a message received on an authenticated SMTP connection +-- the value of the $authenticated_id$ variable. + +%-auth_sender% <'address'>:: +The address of an authenticated sender -- the value of the +$authenticated_sender$ variable. + +%-body_linecount% <'number'>:: +This records the number of lines in the body of the message, and is always +present. + +%-body_zerocount% <'number'>:: +This records the number of binary zero bytes in the body of the message, and is +present if the number is greater than zero. + +%-deliver_firsttime%:: +This is written when a new message is first added to the spool. When the spool +file is updated after a deferral, it is omitted. + +%-frozen% <'time'>:: +cindex:[frozen messages,spool data] +The message is frozen, and the freezing happened at <'time'>. + +%-helo_name% <'text'>:: +This records the host name as specified by a remote host in a HELO or EHLO +command. + +%-host_address% <'address'>.<'port'>:: +This records the IP address of the host from which the message was received and +the remote port number that was used. It is omitted for locally generated +messages. + +%-host_auth% <'text'>:: +If the message was received on an authenticated SMTP connection, this records +the name of the authenticator -- the value of the $sender_host_authenticated$ +variable. + +%-host_lookup_failed%:: +This is present if an attempt to look up the sending host's name from its IP +address failed. It corresponds to the $host_lookup_failed$ variable. + +%-host_name% <'text'>:: +cindex:[reverse DNS lookup] +cindex:[DNS,reverse lookup] +This records the name of the remote host from which the message was received, +if the host name was looked up from the IP address when the message was being +received. It is not present if no reverse lookup was done. + +%-ident% <'text'>:: +For locally submitted messages, this records the login of the originating user, +unless it was a trusted user and the %-oMt% option was used to specify an ident +value. For messages received over TCP/IP, this records the ident string +supplied by the remote host, if any. + +%-interface_address% <'address'>.<'port'>:: +This records the IP address of the local interface and the port number through +which a message was received from a remote host. It is omitted for locally +generated messages. + +%-local%:: +The message is from a local sender. + +%-localerror%:: +The message is a locally-generated bounce message. + +%-local_scan% <'string'>:: +This records the data string that was returned by the 'local_scan()' function +when the message was received -- the value of the $local_scan_data$ variable. +It is omitted if no data was returned. + +%-manual_thaw%:: +The message was frozen but has been thawed manually, that is, by an explicit +Exim command rather than via the auto-thaw process. + +%-N%:: +A testing delivery process was started using the %-N% option to suppress any +actual deliveries, but delivery was deferred. At any further delivery attempts, +%-N% is assumed. + +%-received_protocol%:: +This records the value of the $received_protocol$ variable, which contains the +name of the protocol by which the message was received. + +%-sender_set_untrusted%:: +The envelope sender of this message was set by an untrusted local caller (used +to ensure that the caller is displayed in queue listings). + +%-spam_score_int% <'number'>:: +If a message was scanned by SpamAssassin, this is present. It records the value +of $spam_score_int$. + +%-tls_certificate_verified%:: +A TLS certificate was received from the client that sent this message, and the +certificate was verified by the server. + +%-tls_cipher% <'cipher name'>:: +When the message was received over an encrypted connection, this records the +name of the cipher suite that was used. + +%-tls_peerdn% <'peer DN'>:: +When the message was received over an encrypted connection, and a certificate +was received from the client, this records the Distinguished Name from that +certificate. + +/// +End of list +/// + +Following the options there is a list of those addresses to which the message +is not to be delivered. This set of addresses is initialized from the command +line when the %-t% option is used and %extract_addresses_remove_arguments% +is set; otherwise it starts out empty. Whenever a successful delivery is made, +the address is added to this set. The addresses are kept internally as a +balanced binary tree, and it is a representation of that tree which is written +to the spool file. If an address is expanded via an alias or forward file, the +original address is added to the tree when deliveries to all its child +addresses are complete. + +If the tree is empty, there is a single line in the spool file containing just +the text ``XX''. Otherwise, each line consists of two letters, which are either +Y or N, followed by an address. The address is the value for the node of the +tree, and the letters indicate whether the node has a left branch and/or a +right branch attached to it, respectively. If branches exist, they immediately +follow. Here is an example of a three-node tree: + + YY darcy@austen.fict.example + NN alice@wonderland.fict.example + NN editor@thesaurus.ref.example + +After the non-recipients tree, there is a list of the message's recipients. +This is a simple list, preceded by a count. It includes all the original +recipients of the message, including those to whom the message has already been +delivered. In the simplest case, the list contains one address per line. For +example: + + 4 + editor@thesaurus.ref.example + darcy@austen.fict.example + rdo@foundation + alice@wonderland.fict.example + +However, when a child address has been added to the top-level addresses as a +result of the use of the %one_time% option on a ^redirect^ router, each line +is of the following form: + +&&& +<'top-level address'> <'errors_to address'> <'length'>,<'parent number'>#<'flag bits'> +&&& + +The 01 flag bit indicates the presence of the three other fields that follow +the top-level address. Other bits may be used in future to support additional +fields. The <'parent number'> is the offset in the recipients list of the +original parent of the ``one time'' address. The first two fields are the +envelope sender that is associated with this address and its length. If the +length is zero, there is no special envelope sender (there are then two space +characters in the line). A non-empty field can arise from a ^redirect^ router +that has an %errors_to% setting. + + +A blank line separates the envelope and status information from the headers +which follow. A header may occupy several lines of the file, and to save effort +when reading it in, each header is preceded by a number and an identifying +character. The number is the number of characters in the header, including any +embedded newlines and the terminating newline. The character is one of the +following: + +[frame="none"] +`-`--------`---------------------------------------------- + <'blank'>header in which Exim has no special interest + `B` 'Bcc:' header + `C` 'Cc:' header + `F` 'From:' header + `I` 'Message-id:' header + `P` 'Received:' header -- P for ``postmark'' + `R` 'Reply-To:' header + `S` 'Sender:' header + `T` 'To:' header + `*` replaced or deleted header +---------------------------------------------------------- + +Deleted or replaced (rewritten) headers remain in the spool file for debugging +purposes. They are not transmitted when the message is delivered. Here is a +typical set of headers: + + 111P Received: by hobbit.fict.example with local (Exim 4.00) + id 14y9EI-00026G-00; Fri, 11 May 2001 10:28:59 +0100 + 049 Message-Id: <E14y9EI-00026G-00@hobbit.fict.example> + 038* X-rewrote-sender: bb@hobbit.fict.example + 042* From: Bilbo Baggins <bb@hobbit.fict.example> + 049F From: Bilbo Baggins <B.Baggins@hobbit.fict.example> + 099* To: alice@wonderland.fict.example, rdo@foundation, + darcy@austen.fict.example, editor@thesaurus.ref.example + 109T To: alice@wonderland.fict.example, rdo@foundation.fict.example, + darcy@austen.fict.example, editor@thesaurus.ref.example + 038 Date: Fri, 11 May 2001 10:28:59 +0100 + +The asterisked headers indicate that the envelope sender, 'From:' header, and +'To:' header have been rewritten, the last one because routing expanded the +unqualified domain 'foundation'. + + + + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// + +[titleabbrev="Adding drivers or lookups"] +Adding new drivers or lookup types +---------------------------------- +cindex:[adding drivers] +cindex:[new drivers, adding] +cindex:[drivers,adding new] +The following actions have to be taken in order to add a new router, transport, +authenticator, or lookup type to Exim: + +. Choose a name for the driver or lookup type that does not conflict with any +existing name; I will use ``newdriver'' in what follows. + +. Add to _src/EDITME_ the line ++ + <type>_NEWDRIVER=yes ++ +where <'type'> is ROUTER, TRANSPORT, AUTH, or LOOKUP. If the +code is not to be included in the binary by default, comment this line out. You +should also add any relevant comments about the driver or lookup type. + +. Add to _src/config.h.defaults_ the line ++ + #define <type>_NEWDRIVER + +. Edit _src/drtables.c_, adding conditional code to pull in the private header +and create a table entry as is done for all the other drivers and lookup types. + +. Edit _Makefile_ in the appropriate sub-directory (_src/routers_, +_src/transports_, _src/auths_, or _src/lookups_); add a line for the new +driver or lookup type and add it to the definition of OBJ. + +. Create _newdriver.h_ and _newdriver.c_ in the appropriate sub-directory of +_src_. + +. Edit _scripts/MakeLinks_ and add commands to link the _.h_ and _.c_ files +as for other drivers and lookups. + +Then all you need to do is write the code! A good way to start is to make a +proforma by copying an existing module of the same type, globally changing all +occurrences of the name, and cutting out most of the code. Note that any +options you create must be listed in alphabetical order, because the tables are +searched using a binary chop procedure. + +There is a _README_ file in each of the sub-directories of _src_ describing +the interface that is expected. + + + + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// + +[title="Option index",role="option"] +Index +----- + +[title="Concept index",role="concept"] +Index +----- + +/////////////////////////////////////////////////////////////////////////////// +Nothing needs to be included here except "Index" as pseudo chapter headings. +/////////////////////////////////////////////////////////////////////////////// diff --git a/doc/doc-docbook/x2man b/doc/doc-docbook/x2man new file mode 100755 index 000000000..a9812239e --- /dev/null +++ b/doc/doc-docbook/x2man @@ -0,0 +1,212 @@ +#! /usr/bin/perl -w + +# $Cambridge: exim/doc/doc-docbook/x2man,v 1.1 2005/06/16 10:32:31 ph10 Exp $ + +# Script to find the command line options in the DocBook source of the Exim +# spec, and turn them into a man page, because people like that. + + + + +################################################## +# Main Program # +################################################## + +open(IN, "spec.xml") || die "Can't open spec.xml\n"; +open(OUT, ">exim.8" ) || die "Can't open exim.8\n"; + +print OUT <<End; +.TH EXIM 8 +.SH NAME +exim \\- a Mail Transfer Agent +.SH SYNOPSIS +.B exim [options] arguments ... +.br +.B mailq [options] arguments ... +.br +.B rsmtp [options] arguments ... +.br +.B rmail [options] arguments ... +.br +.B runq [options] arguments ... +.br +.B newaliases [options] arguments ... + +.SH DESCRIPTION +.rs +.sp +Exim is a mail transfer agent (MTA) developed at the University of Cambridge. +It is a large program with very many facilities. For a full specification, see +the reference manual. This man page contains only a description of the command +line options. It has been automatically generated from the reference manual +source, hopefully without too much mangling. + +.SH SETTING OPTIONS BY PROGRAM NAME +.rs +.TP 10 +\\fBmailq\\fR +Behave as if the option \\fB\\-bp\\fP were present before any other options. +The \\fB\\-bp\\fP option requests a listing of the contents of the mail queue +on the standard output. +.TP +\\fBrsmtp\\fR +Behaves as if the option \\fB\\-bS\\fP were present before any other options, +for compatibility with Smail. The \\fB\\-bS\\fP option is used for reading in a +number of messages in batched SMTP format. +.TP +\\fBrmail\\fR +Behave as if the \\fB\\-i\\fP and \\fB\\-oee\\fP options were present before +any other options, for compatibility with Smail. The name \\fBrmail\\fR is used +as an interface by some UUCP systems. The \\fB\\-i\\fP option specifies that a +dot on a line by itself does not terminate a non\\-SMTP message; \\fB\\-oee\\fP +requests that errors detected in non\\-SMTP messages be reported by emailing +the sender. +.TP +\\fBrunq\\fR +Behave as if the option \\fB\\-q\\fP were present before any other options, for +compatibility with Smail. The \\fB\\-q\\fP option causes a single queue runner +process to be started. It processes the queue once, then exits. +.TP +\\fBnewaliases\\fR +Behave as if the option \\fB\\-bi\\fP were present before any other options, +for compatibility with Sendmail. This option is used for rebuilding Sendmail's +alias file. Exim does not have the concept of a single alias file, but can be +configured to run a specified command if called with the \\fB\\-bi\\fP option. + +.SH OPTIONS +.rs +End + +while (<IN>) { last if /^<!-- === Start of command line options === -->\s*$/; } +die "Can't find start of options\n" if ! defined $_; + +$optstart = 0; +$indent = ""; + +# Loop for each individual option + +$next = <IN>; + +while ($next) + { + $_ = $next; + $next = <IN>; + + last if /^<!-- === End of command line options === -->\s*$/; + + # Start of new option + + if (/^<term>$/) + { + print OUT ".TP 10\n"; + $optstart = 1; + next; + } + + # If a line contains text that is not in <>, read subsequent lines of the + # same form, so that we get whole sentences for matching on references. + + if (/^ (?> (<[^>]+>)* ) \s*\S/x) + { + while ($next =~ /^ (?> (<[^>]+>)* ) \s*\S/x) + { + $_ .= $next; + $next = <IN>; + } + } + + # Remove sentences or parenthetical comments that refer to chapters or + # sections. The order of these changes is very important: + # + # (1) Remove any parenthetical comments first. + # (2) Then remove any sentences that start after a full stop. + # (3) Then remove any sentences that start at the beginning or a newline. + + s/\s?\( [^()]+ <xref \s linkend="[^"]+" \/ > \)//xg; + s/\s?\. [^.]+ <xref \s linkend="[^"]+" \/ > [^.]*? \././xg; + s/(^|\n) [^.]+ <xref \s linkend="[^"]+" \/ > [^.]*? \./$1/xg; + + # Handle paragraph starts; skip the first one encountered for an option + + if ($optstart && /<(sim)?para>/) + { + s/<(sim)?para>//; + $optstart = 0; + } + + # Literal layout needs to be treated as a paragraph, and indented + + if (/<literallayout/) + { + s/<literallayout[^>]*>/.P/; + $indent = " "; + } + + $indent = "" if (/<\/literallayout>/); + + # Others get marked + + s/<para>/.P/; + s/<simpara>/.P/; + + # Skip index entries + + s/<primary>.*?<\/primary>//g; + s/<secondary>.*?<\/secondary>//g; + + # Convert all occurrences of backslash into \e + + s/\\/\\e/g; + + # Handle bold and italic + + s/<emphasis>/\\fI/g; + s/<emphasis role="bold">/\\fB/g; + s/<\/emphasis>/\\fP/g; + + s/<option>/\\fB/g; + s/<\/option>/\\fP/g; + + s/<varname>/\\fI/g; + s/<\/varname>/\\fP/g; + + # Handle quotes + + s/<\/?quote>/"/g; + + # Remove any remaining XML markup + + s/<[^>]*>//g; + + # If nothing left in the line, ignore. + + next if /^\s*$/; + + # It turns out that we don't actually want .P; a blank line is needed. + # But we can't set that above, because it will be discarded. + + s/^\.P\s*$/\n/; + + # We are going to output some data; sort out special characters + + s/</</g; + s/>/>/g; + + s/-/-/g; + s/ / /g; + s/–/-/g; + s/’/'/g; + s/…/.../g; # Sic - no x + + # Escape hyphens to prevent unwanted hyphenation + + s/-/\\-/g; + + # Put in the indent, and write the line + + s/^/$indent/mg; + + print OUT; + } + +# End of g2man diff --git a/doc/doc-scripts/ABOUT b/doc/doc-scripts/ABOUT index 623e88c2e..7731de2e1 100644 --- a/doc/doc-scripts/ABOUT +++ b/doc/doc-scripts/ABOUT @@ -1,9 +1,12 @@ -$Cambridge: exim/doc/doc-scripts/ABOUT,v 1.1 2004/10/08 10:38:48 ph10 Exp $ +$Cambridge: exim/doc/doc-scripts/ABOUT,v 1.2 2005/06/16 10:32:31 ph10 Exp $ CVS directory exim/exim-doc/doc-scripts --------------------------------------- -This directory contains various scripts that are used to build the distributed -documentation from its source files. +This directory contains various scripts that are used to build the distributed +documentation from its SGCAL source files. This method of maintaining the +documentation was used up to and including release 4.50 of Exim. There is also +a script for building the FAQ from its source. This is still (June 2005) +current, but may be superseded in due course. End diff --git a/doc/doc-src/ABOUT b/doc/doc-src/ABOUT index 9e281e996..990790101 100644 --- a/doc/doc-src/ABOUT +++ b/doc/doc-src/ABOUT @@ -1,11 +1,14 @@ -$Cambridge: exim/doc/doc-src/ABOUT,v 1.1 2004/10/08 10:38:48 ph10 Exp $ +$Cambridge: exim/doc/doc-src/ABOUT,v 1.2 2005/06/16 10:32:31 ph10 Exp $ CVS directory exim/exim-doc/doc-src ----------------------------------- -This directory contains documentation files that are processed in some way in -order to make the documentation files that form part of Exim distributions. A -non-standard document processor is currently in use (October 2004), but in the -long term something more standard will have to take over. +This directory contains documentation files that are processed in some way in +order to make the documentation files that form part of Exim distributions. A +non-standard document processor (SGCAL) was used up to and including release +4.50 of Exim to process the sources for the manual and filter docuement. +Subsequent documentation releases operate using DocBook input, so these files +are now historical relics. The FAQ source is still (June 2005) current, but may +be superseded in due course. End |