ProblemYou have been asked to configure sendmail to replace the login name used as the sender address for mail originating from the local host with an address that meets the organization's desired address format. SolutionBuild a genericstable database to map the input sender address to the format you desire in the header sender address. Each entry in the genericstable contains two fields: the key and the value returned for that key. The key field of a genericstable entry can be either a full email address or a username. The value returned is the value that will be used as the rewritten sender address, which is normally a full address containing both a username and a hostname. To create the genericstable , first create a text file that contains the database entries and then run that text file through the makemap script to build the genericstable database. To use the newly created genericstable database, create a sendmail configuration containing the genericstable feature and the GENERICS_DOMAIN macro. The domain name argument of the GENERICS_DOMAIN macro tells sendmail when to use the genericstable . Here are sample lines that could be added to the sendmail configuration: dnl Process login names through the genericstable FEATURE(`genericstable') dnl Identify the host that the genericstable applies to GENERICS_DOMAIN(`chef.wrotethebook.com') Rebuild, reinstall, and restart sendmail as described in Recipe 1.8. DiscussionBy default, mail originating on the local host uses the user 's login name as the username part, so, in this example, the key field of the genericstable is a login name and the value returned is a full email address. The mapping can be anything you wish, but, for this example, we map login names to the user's real name and the local domain name formatted as firstname . lastname @ domain . [5] To do this, a text file is created and then run through makemap :
# 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 alana alana.smiley@wrotethebook.com jay jay.james@wrotethebook.com Ctrl-D # makemap hash genericstable < genericstable Of course, if mail arrives at the local host addressed to firstname . lastname @ domain , aliases are needed to deliver the mail to the users' real address. Aliases based on the genericstable entries shown above could be added to the aliases database in the following manner: # cd /etc/mail # cat > aliases kathy.mccafferty: kathy craig.hunt: craig sara.henson: sara david.craig: dave rebecca.fro: becky alana.smiley: alana jay.james: jay Ctrl-D # newaliases After building the genericstable database and adding the genericstable feature to the configuration, the genericstable data is available to sendmail, as this sendmail -bt test shows: # sendmail -bt ADDRESS TEST MODE (ruleset 3 NOT automatically invoked) Enter <ruleset> <address> > /map generics sara map_lookup: generics (sara) returns sara.henson@wrotethebook.com (0) > /quit Here sendmail is run with the -bt option and the /map command is used to lookup the entry for the login name sara . The value returned is sara.henson@wrotethebook.com . Thus, one would expect that any mail originating on this host from sara would have the sender address rewritten to sara.henson@wrotethebook.com . That would be the case here, but only because this recipe includes the GENERICS_DOMAIN macro. Without the GENERICS_DOMAIN macro, the genericstable feature does not act as one might expect. Here is an example using the genericstable feature without the GENERICS_DOMAIN macro: # sendmail -bt -Cspecial4-11-test.cf ADDRESS TEST MODE (ruleset 3 NOT automatically invoked) Enter <ruleset> <address> > $j chef.wrotethebook.com > /tryflags HS > /try esmtp sara Trying header sender address sara for mailer esmtp canonify input: sara Canonify2 input: sara Canonify2 returns: sara canonify returns: sara 1 input: sara 1 returns: sara HdrFromSMTP input: sara PseudoToReal input: sara PseudoToReal returns: sara MasqSMTP input: sara MasqSMTP returns: sara < @ *LOCAL* > MasqHdr input: sara < @ *LOCAL* > canonify input: sara . henson @ wrotethebook . com Canonify2 input: sara . henson < @ wrotethebook . com > Canonify2 returns: sara . henson < @ wrotethebook . com . > canonify returns: sara . henson < @ wrotethebook . com . > MasqHdr returns: sara . henson < @ wrotethebook . com . > HdrFromSMTP returns: sara . henson < @ wrotethebook . com . > final input: sara . henson < @ wrotethebook . com . > final returns: sara . henson @ wrotethebook . com Rcode = 0, addr = sara.henson@wrotethebook.com > /try esmtp sara@chef Trying header sender address sara@chef for mailer esmtp canonify input: sara @ chef Canonify2 input: sara < @ chef > Canonify2 returns: sara < @ chef . wrotethebook . com . > canonify returns: sara < @ chef . wrotethebook . com . > 1 input: sara < @ chef . wrotethebook . com . > 1 returns: sara < @ chef . wrotethebook . com . > HdrFromSMTP input: sara < @ chef . wrotethebook . com . > PseudoToReal input: sara < @ chef . wrotethebook . com . > PseudoToReal returns: sara < @ chef . wrotethebook . com . > MasqSMTP input: sara < @ chef . wrotethebook . com . > MasqSMTP returns: sara < @ chef . wrotethebook . com . > MasqHdr input: sara < @ chef . wrotethebook . com . > MasqHdr returns: sara < @ chef . wrotethebook . com . > HdrFromSMTP returns: sara < @ chef . wrotethebook . com . > final input: sara < @ chef . wrotethebook . com . > final returns: sara @ chef . wrotethebook . com Rcode = 0, addr = sara@chef.wrotethebook.com > /quit The test just shown is run on a host named chef.wrotethebook.com , as the $j command shows. This host is using the genericstable feature without the GENERICS_DOMAIN macro. Because Unix login names must be unique on a given host, we know that sara , sara@chef, and sara@chef.wrotethebook.com are all the same person. Yet the test shows that sendmail does not treat these input addresses the same with regard to the genericstable . When the input address has no host part, it is rewritten; otherwise , it is not rewritten. The reason is simple: the genericstable we created only maps login names; none of the database keys contains a hostname part. However, we want to create a consistent header sender address ”not an address that varies depending on the address input by the user. For this to be accomplished, this recipe uses the GENERICS_DOMAIN macro and sets that macro to the fully qualified name used in the $j macro. This causes sendmail to consistently apply the genericstable to rewriting the header sender address for all mail that originates on this host. Here is a test run with this recipe's configuration: # sendmail -bt ADDRESS TEST MODE (ruleset 3 NOT automatically invoked) Enter <ruleset> <address> > $=G chef.wrotethebook.com > /tryflags HS > /try esmtp sara@[127.0.0.1] Trying header sender address sara@[127.0.0.1] for mailer esmtp canonify input: sara @ [ 127 . 0 . 0 . 1 ] Canonify2 input: sara < @ [ 127 . 0 . 0 . 1 ] > Canonify2 returns: sara < @ chef . wrotethebook . com . > canonify returns: sara < @ chef . wrotethebook . com . > 1 input: sara < @ chef . wrotethebook . com . > 1 returns: sara < @ chef . wrotethebook . com . > HdrFromSMTP input: sara < @ chef . wrotethebook . com . > PseudoToReal input: sara < @ chef . wrotethebook . com . > PseudoToReal returns: sara < @ chef . wrotethebook . com . > MasqSMTP input: sara < @ chef . wrotethebook . com . > MasqSMTP returns: sara < @ chef . wrotethebook . com . > MasqHdr input: sara < @ chef . wrotethebook . com . > canonify input: sara . henson @ wrotethebook . com Canonify2 input: sara . henson < @ wrotethebook . com > Canonify2 returns: sara . henson < @ wrotethebook . com . > canonify returns: sara . henson < @ wrotethebook . com . > MasqHdr returns: sara . henson < @ wrotethebook . com . > HdrFromSMTP returns: sara . henson < @ wrotethebook . com . > final input: sara . henson < @ wrotethebook . com . > final returns: sara . henson @ wrotethebook . com Rcode = 0, addr = sara.henson@wrotethebook.com > /quit The GENERICS_DOMAIN macro loads the value specified on its command line into sendmail.cf class $=G . sendmail applies the genericstable to any sender address that has a name listed in class $=G as its hostname part. In this test, the $=G command shows that class $=G contains only chef.wrotethebook.com , which is the fully qualified name of this host ”the same value found in $j . Therefore, any hostname that sendmail rewrites to $j will match the value in $=G and will also be processed through the genericstable . In this test, we show an extreme case using the loopback address [127.0.0.1] as the hostname, which sendmail rewrites to the value returned by $j and then rewrites through the genericstable . We could just as easily have used chef , localhost , [192.168.0.8] , or chef.wrotethebook.com as the hostname ”all valid variations of the local host's name work. [6]
In this recipe, the email processed through the genericstable all originates on the local host. Thus, the input sender address either has no hostname part, or the hostname in the sender address is a hostname of the local host. Many systems (mail relay hosts are an example) handle mail from a variety of hosts . The sender address in that case can contain the hostname of any host granted relaying privileges. Because mail is only processed through the genericstable when the sender's hostname is found in class $=G , the hostnames of all of the hosts allowed to send mail through the relay should be loaded into class $=G . If this is a small number of hostnames, it can be done by placing multiple GENERICS_DOMAIN macros in the configuration. If there are more than a few hostnames, it is simpler to create a file that lists all of the hosts and then to reference that file inside the configuration with a GENERICS_DOMAIN_FILE macro. For example, the following macro used in this recipe, in place of the GENERICS_DOMAIN macro, would load $=G with all of the hostnames listed in a file called /etc/mail/generics-domains : GENERICS_DOMAIN_FILE(`/etc/mail/generics-domains') The GENERICS_DOMAIN_FILE macro makes it possible to coordinate genericstable processing with other sendmail functions simply by extracting hostnames from the files that control those other functions and storing those names in the file loaded by the GENERICS_DOMAIN_FILE macro. For example, copying the hostnames from /etc/mail/local-host-names to the file loaded by the GENERICS_DOMAIN_FILE macro enables genericstable processing for all systems that use a mail exchanger . See AlsoRecipe 4.12 shows another genericstable example. 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_DOMAIN_FILE macro in 4.8.16.2. Chapter 9 of Linux Sendmail Administration , by Craig Hunt (Sybex), contains the tutorial section "Masquerading Usernames" that provides additional information. |