the djb way

mess822


control/rewrite

Both ofmipd and new-inject recognize a new qmail control file named rewrite. As with other control files in a standard qmail installation, rewrite should be placed in /var/qmail/control/rewrite by default. However, any alternative file path may be specified in the environmental variable $QMAILREWRITEFILE; this is useful for testing, as we will see below.

rewrite may be used to specify rewriting instructions for hostnames appearing in addresses found within message headers. The general purpose of rewrite is to specify fix-ups for addresses and return paths associated with the local network. This is to allow server-level correction of locally injected messages from improperly configured MUAs. But it is important to know that the transformation instructions in rewrite will be applied to all addresses found within the message header.

The facilities of rewrite expand on the basic transformations already provided by the defaulthost, defaultdomain, and plusdomain control files. In the absence of rewrite, the transformations of ofmipd and new-inject fall back to these basic qmail control files. (Also recall that, in the absence of these control files, qmail will use control/me.)

The basic instruction syntax of control/rewrite is:

pattern:replace

That is, when ofmipd finds a hostname or part of a hostname in a header address that matches the instruction pattern, it will replace it according to that instruction with replace. The pattern and replace descriptions are separated by a colon; one instruction per line.

Instructions are applied in the order they appear in rewrite. Instructions may have a cascading effect.

An instruction pattern may take one of four forms, indicated by its first character:

instruction hostname before hostname rewritten
=what:this what this
-what:this anywhat this
*what:this anywhat anythis
?what:this somewhat somethis
?what:this any.somewhat any.somewhat

The "=" form specifies an exact match, with full replacement. The "-" form specifies a partial match, with full replacement.

The "*" form specifies a partial match, with replacement of the matched part. The "?" form is the same, except the prefix to the matched part may not contain dots (".") or brackets ("[", "]"). The last "?" item in the table above is intended to show this constraint; since the prefix to the matched part does contain a dot, the hostname is not rewritten.

The specification of rewrite does not explicitly permit comments. However, the implementation simply skips any line not beginning with one of "=", "-", "*", or "?".

A typical rewrite file might include:

*.:
-localhost:
=:example.org
*+:.example.org
?:.example.org

This rewrite file would make the following transformations:

  1. if hostname ends in ".", remove the dot
  2. if hostname ends in "localhost", remove the hostname
  3. if hostname is empty, change it to "example.org"
  4. if hostname ends in "+", remove the "+" and add ".example.org"
  5. if hostname doesn't contain dots or brackets, append ".example.org"

Imagine your organization changes domain names, we'll say from "arc.co.ug" to "arc-nile.org". You have over 80 users on the network, using a variety of MUAs, and it will take awhile and a lot of bother to go around and reconfigure all of them, just to change each user's return address.

Instead you decide to take it easy and buy some time. Using rewrite, you include a couple of simple instructions on the mail server:

-arc.co.ug:
=:arc-nile.org

These will: 1) strip any hostnames ending in "arc.co.ug"; and 2) replace any empty hostname with "arc-nile.org". Now all messages will be going out with the new domain name immediately, no matter how the clients are (mis-) configured.

Ah, ha!...

The best way to understand the use of rewrite is to develop a methodology for testing the rewrite rules for your own site. First, set up a testing directory, then use your favorite text editor to create a file named testmail.txt:


To: clove@example
To: janice@bigbro
From: madonna
Cc: jjackson@localhost
Cc: ccrow@santa.monica.ave
Subject: rewriting

Dis be test.


Use any number/type of the usual address fields, i.e., "To:", "From:, "Cc:", etc. It doesn't matter, all will be processed by the rewrite rules. Then, in the same test directory, create another file with your text editor named rewrite:


*.:
-localhost:
=:example.org
*+:.example.org
?:.example.org
*.ave:.blvd

This rewrite file is the similar to the first example described above. The last instruction changes any hostname ending in ".ave" to ".blvd", for no good reason.

Then test the rewrite rules against the test message with new-inject, using the -n option to print the message to stdout:

$ QMAILREWRITEFILE=./rewrite new-inject -n < testmail.txt
Envelope-Sender: madonna@example.org
Envelope-Recipients:
  clove@example.example.org,
  janice@bigbro.example.org,
  jjackson@example.org,
  ccrow@santa.monica.blvd,
Date: 26 Feb 2004 14:05:16 -0000
Message-ID: <20040226140516.12547.qmail@virgin.example.org>
From: madonna@example.org
To: clove@example.example.org, janice@bigbro.example.org
Cc: jjackson@example.org, ccrow@santa.monica.blvd
Subject: rewriting

Dis be test.

Compare the output to the original test message, and notice the changes.

The point is to develop the rewrite file while testing the output, until the results are exactly as you intend. Once you are satisfied, copy rewrite into position:

# cp ./rewrite /var/qmail/control/rewrite

No need to restart any services; your new rewrite rules for qmail-ofmipd and new-inject will take immediate effect.


Copyright © 2004, Wayne Marshall.
All rights reserved.

Last edit 2004.02.27, wcm.