Recipe 4.12 Rewriting Sender Addresses for an Entire DomainProblemYou have been asked to configure sendmail to rewrite the sender address into your organization's standard header sender address format on all mail originating from the local domain. SolutionBuild a genericstable database to map the input address to the format desired for the header sender address. Each entry in the genericstable contains two fields. The first field matches the input address and the second field rewrites the address. To create the genericstable , first create a text file that contains the database entries, then run that text file through the makemap command to build the genericstable database. Add the genericstable feature, the GENERICS_DOMAIN macro, and the generics_entire_domain feature to the sendmail configuration. The added commands would look something like the following: dnl Process login names through the genericstable FEATURE(`genericstable') dnl Load wrotethebook.com into G GENERICS_DOMAIN(`wrotethebook.com') dnl Interpret the value in G as a domain name FEATURE(`generics_entire_domain') Build sendmail.cf , copy it to /etc/mail , and then restart sendmail. See Recipe Recipe 1.8 if you need an example of this step. DiscussionThe input sender address is rewritten as specified by the genericstable . All or part of the input address is used as a key to search the genericstable . When a value is returned by the search, that value is used to rewrite the address. For this example, we create the following genericstable : # cd /etc/mail # cat > genericstable kathy kathy.mccafferty@wrotethebook.com craig craig.hunt@wrotethebook.com sara sara.henson@wrotethebook.com dave david.craig@wrotethebook.com becky rebecca.fro@wrotethebook.com jay jay.james@wrotethebook.com alana@blur.wrotethebook.com alana.darling@wrotethebook.com alana@giant.wrotethebook.com alana.henson@wrotethebook.com alana alana.smiley@wrotethebook.com Ctrl-D # makemap hash genericstable < genericstable The genericstable feature adds the code sendmail needs to make use of the genericstable . The GENERICS_DOMAIN macro adds the value specified on the macro command line to sendmail class $=G . Normally, the values listed in class $=G are interpreted as hostnames, and only exact matches enable genericstable processing. The generics_entire_domain feature causes sendmail to interpret the values in class $=G as domain names, and any host within one of those domains is processed through the genericstable . Here is a test of a system running this recipe: # sendmail -bt ADDRESS TEST MODE (ruleset 3 NOT automatically invoked) Enter <ruleset> <address> > $=G wrotethebook.com > /tryflags HS > /try esmtp dave@tassajara.wrotethebook.com Trying header sender address dave@tassajara.wrotethebook.com for mailer esmtp canonify input: dave @ tassajara . wrotethebook . com Canonify2 input: dave < @ tassajara . wrotethebook . com > Canonify2 returns: dave < @ tassajara . wrotethebook . com . > canonify returns: dave < @ tassajara . wrotethebook . com . > 1 input: dave < @ tassajara . wrotethebook . com . > 1 returns: dave < @ tassajara . wrotethebook . com . > HdrFromSMTP input: dave < @ tassajara . wrotethebook . com . > PseudoToReal input: dave < @ tassajara . wrotethebook . com . > PseudoToReal returns: dave < @ tassajara . wrotethebook . com . > MasqSMTP input: dave < @ tassajara . wrotethebook . com . > MasqSMTP returns: dave < @ tassajara . wrotethebook . com . > MasqHdr input: dave < @ tassajara . wrotethebook . com . > canonify input: david . craig @ wrotethebook . com Canonify2 input: david . craig < @ wrotethebook . com > Canonify2 returns: david . craig < @ wrotethebook . com . > canonify returns: david . craig < @ wrotethebook . com . > MasqHdr returns: david . craig < @ wrotethebook . com . > HdrFromSMTP returns: david . craig < @ wrotethebook . com . > final input: david . craig < @ wrotethebook . com . > final returns: david . craig @ wrotethebook . com Rcode = 0, addr = david.craig@wrotethebook.com > /map generics dave map_lookup: generics (dave) returns david.craig@wrotethebook.com (0) > /quit The test shows that the hostname tassajara.wrotethebook.com is not in class $=G ; in fact, class $=G only contains the domain name wrotethebook.com . Yet the header sender address dave@tassajara.wrotethebook.com is rewritten to david.craig@wrotethebook.com , which is the value returned by the genericstable for the key dave . In this example, every dave account in the entire wrotethebook.com domain belongs to David Craig. No matter what host in that domain he sends mail from, when the mail passes through this system, it is rewritten to david.craig@wrotethebook.com . For replies to the rewritten address to work correctly, the rewritten hostname must resolve to a host that will accept the mail, and that host must have an alias for david.craig that delivers the mail to the real dave account. A more interesting case is the mapping of the username alana . Three people in the wrotethebook.com domain have this username: Alana Darling, Alana Henson, and Alana Smiley. The following test shows how each of these names are mapped: # sendmail -bt ADDRESS TEST MODE (ruleset 3 NOT automatically invoked) Enter <ruleset> <address> > /tryflags HS > /try esmtp alana@blur.wrotethebook.com Trying header sender address alana@blur.wrotethebook.com for mailer esmtp canonify input: alana @ blur . wrotethebook . com Canonify2 input: alana < @ blur . wrotethebook . com > Canonify2 returns: alana < @ blur . wrotethebook . com . > canonify returns: alana < @ blur . wrotethebook . com . > 1 input: alana < @ blur . wrotethebook . com . > 1 returns: alana < @ blur . wrotethebook . com . > HdrFromSMTP input: alana < @ blur . wrotethebook . com . > PseudoToReal input: alana < @ blur . wrotethebook . com . > PseudoToReal returns: alana < @ blur . wrotethebook . com . > MasqSMTP input: alana < @ blur . wrotethebook . com . > MasqSMTP returns: alana < @ blur . wrotethebook . com . > MasqHdr input: alana < @ blur . wrotethebook . com . > canonify input: alana . darling @ wrotethebook . com Canonify2 input: alana . darling < @ wrotethebook . com > Canonify2 returns: alana . darling < @ wrotethebook . com . > canonify returns: alana . darling < @ wrotethebook . com . > MasqHdr returns: alana . darling < @ wrotethebook . com . > HdrFromSMTP returns: alana . darling < @ wrotethebook . com . > final input: alana . darling < @ wrotethebook . com . > final returns: alana . darling @ wrotethebook . com Rcode = 0, addr = alana.darling@wrotethebook.com > /try esmtp alana@giant.wrotethebook.com Trying header sender address alana@giant.wrotethebook.com for mailer esmtp canonify input: alana @ giant . wrotethebook . com Canonify2 input: alana < @ giant . wrotethebook . com > Canonify2 returns: alana < @ giant . wrotethebook . com . > canonify returns: alana < @ giant . wrotethebook . com . > 1 input: alana < @ giant . wrotethebook . com . > 1 returns: alana < @ giant . wrotethebook . com . > HdrFromSMTP input: alana < @ giant . wrotethebook . com . > PseudoToReal input: alana < @ giant . wrotethebook . com . > PseudoToReal returns: alana < @ giant . wrotethebook . com . > MasqSMTP input: alana < @ giant . wrotethebook . com . > MasqSMTP returns: alana < @ giant . wrotethebook . com . > MasqHdr input: alana < @ giant . wrotethebook . com . > canonify input: alana . henson @ wrotethebook . com Canonify2 input: alana . henson < @ wrotethebook . com > Canonify2 returns: alana . henson < @ wrotethebook . com . > canonify returns: alana . henson < @ wrotethebook . com . > MasqHdr returns: alana . henson < @ wrotethebook . com . > HdrFromSMTP returns: alana . henson < @ wrotethebook . com . > final input: alana . henson < @ wrotethebook . com . > final returns: alana . henson @ wrotethebook . com Rcode = 0, addr = alana.henson@wrotethebook.com > /try esmtp alana@anywhere.wrotethebook.com Trying header sender address alana@anywhere.wrotethebook.com for mailer esmtp canonify input: alana @ anywhere . wrotethebook . com Canonify2 input: alana < @ anywhere . wrotethebook . com > Canonify2 returns: alana < @ anywhere . wrotethebook . com . > canonify returns: alana < @ anywhere . wrotethebook . com . > 1 input: alana < @ anywhere . wrotethebook . com . > 1 returns: alana < @ anywhere . wrotethebook . com . > HdrFromSMTP input: alana < @ anywhere . wrotethebook . com . > PseudoToReal input: alana < @ anywhere . wrotethebook . com . > PseudoToReal returns: alana < @ anywhere . wrotethebook . com . > MasqSMTP input: alana < @ anywhere . wrotethebook . com . > MasqSMTP returns: alana < @ anywhere . wrotethebook . com . > MasqHdr input: alana < @ anywhere . wrotethebook . com . > canonify input: alana . smiley @ wrotethebook . com Canonify2 input: alana . smiley < @ wrotethebook . com > Canonify2 returns: alana . smiley < @ wrotethebook . com . > canonify returns: alana . smiley < @ wrotethebook . com . > MasqHdr returns: alana . smiley < @ wrotethebook . com . > HdrFromSMTP returns: alana . smiley < @ wrotethebook . com . > final input: alana . smiley < @ wrotethebook . com . > final returns: alana . smiley @ wrotethebook . com Rcode = 0, addr = alana.smiley@wrotethebook.com > /quit The complete addresses used in the genericstable keys for Alana Darling and Alana Henson make it possible for sendmail to do one-to-one mappings for those addresses. The key used for Alana Smiley's entry, however, is just a username. That key matches any input address that contains the username alana , except for the input addresses alana@blur.wrotethebook.com and alana@giant.wrotethebook.com . When a system handles mail that originates from several hosts , it is possible to have duplicate login names. The fact that the key in the genericstable can contain a full email address allows you to map these overlapping usernames. See AlsoRecipe 4.11 provides another genericstable example, and Recipe 4.14 shows how the genericstable can be read from an LDAP server. The sendmail book covers the genericstable in 4.8.16, the GENERICS_DOMAIN macro in 4.8.16.1, and the generics_entire_domain feature in 4.8.15. Chapter 9 of Linux Sendmail Administration , by Craig Hunt (Sybex), contains the tutorial section "Masquerading Usernames" that provides additional information. |