GENERIC(5)

πŸŽ€ NAME πŸŽ€

okay so bestie, welcome to generic β€” it's the Postfix generic table format page, and yes it came out of the File Formats Manual section, we love a format legend πŸ’–


✨ SYNOPSIS ✨

the whole vibe in three little commands, no notes:

postmap /etc/postfix/generic
postmap -q "string" /etc/postfix/generic
postmap -q - /etc/postfix/generic <inputfile

periodt πŸ’…


🌸 DESCRIPTION 🌸

okay so the generic(5) table is optional, and what it does is specify an address mapping that kicks in when mail is delivered. it's literally the mirror image of canonical(5) mapping, which does its thing when mail is received. two sisters, opposite directions, both iconic πŸ¦‹

typically you'd pull out the generic(5) table on a system that does not have a valid Internet domain name and that uses something like localdomain.local instead. so then the smtp(8) client uses the generic(5) table to turn local mail addresses into valid Internet mail addresses whenever mail has to be sent across the Internet. there's a whole EXAMPLE section at the end of this doc, go look, it eats πŸ”₯

so the generic(5) mapping hits both:

  • message header addresses (aka the addresses that appear inside messages), and
  • message envelope addresses (aka for example the addresses used in SMTP protocol commands)

both. every time. main character behavior tbh πŸ‘‘

normally the generic(5) table is given as a text file, and that file serves as input to postmap(1) so it can create an indexed file for fast lookup. speed queen ⚑

run this to rebuild a default-type indexed file after you change the text file:

postmap /etc/postfix/generic

or run this if you want to specify an explicit type:

postmap type:/etc/postfix/generic

the default indexed file type gets configured with the default_database_type parameter. depending on the platform, that could be one of lmdb:, cdb:, hash:, or dbm: β€” note: without the trailing : πŸ’€

when the table comes from other means like NIS, LDAP or SQL, the same lookups happen as for ordinary indexed files. managing those databases is outside the scope of Postfix, so that's a you problem bestie, no cap πŸ™ˆ

OR, alternatively β€” and this is the fun part β€” the table can be provided as a regular-expression map, where patterns are given as regular expressions. OR lookups can be directed to a TCP-based server. in those cases the lookups happen in a slightly different way, described below under "REGULAR EXPRESSION TABLES" or "TCP-BASED TABLES". keep scrolling ✨


πŸ’… CASE FOLDING πŸ’…

the search string gets folded to lowercase before the database lookup. simple as that.

BUT β€” as of Postfix 2.3, the search string is not case folded when you're using database types such as regexp: or pcre:, because those lookup fields can match both upper and lower case. so those ones are just built different πŸ’…


πŸ“‹ TABLE FORMAT πŸ“‹

here's the input format for the postmap(1) command, bestie:

  • pattern result β€” when the pattern matches a mail address, replace it with the corresponding result. match made in heaven fr fr πŸ’–
  • blank lines and comments β€” empty lines and whitespace-only lines get ignored, and so do lines whose first non-whitespace character is a #. silent. unbothered. irrelevant πŸ’€
  • multi-line text β€” a logical line starts with non-whitespace text. a line that starts with whitespace continues a logical line. it's giving paragraph energy πŸ¦‹

πŸ” TABLE SEARCH ORDER πŸ”

when the lookups come from indexed files like DB or DBM, or from networked tables like NIS, LDAP or SQL, every user@domain query produces a whole sequence of query patterns, listed below.

each query pattern gets sent to each specified lookup table before the next query pattern is even tried, and this goes on until a match is found. patient, thorough, organized β€” the way a real one operates ✨

  • user@domain address β€” replace user@domain by address. this form has the highest precedence, she's first in line πŸ‘‘
  • user address β€” replace user@site by address when site is equal to $myorigin, when site is listed in $mydestination, or when it's listed in $inet_interfaces or $proxy_interfaces. so many conditions, so much range πŸ’œ
  • @domain address β€” replace other addresses in domain by address. this form has the lowest precedence. someone has to be last, bestie 😭

πŸͺ„ RESULT ADDRESS REWRITING πŸͺ„

the lookup result is subject to address rewriting, and here's the tea:

  • when the result has the form @otherdomain, the result becomes the same user in otherdomain. glow-up preserved, identity intact 🫢
  • when append_at_myorigin=yes, append "@$myorigin" to addresses without "@domain"
  • when append_dot_mydomain=yes, append ".$mydomain" to addresses without ".domain"

🌈 ADDRESS EXTENSION 🌈

when a mail address localpart contains the optional recipient delimiter β€” like user+foo@domain β€” the lookup order becomes this exact sequence:

user+foo@domain, user@domain, user+foo, user, and @domain

and the propagate_unmatched_extensions parameter controls whether an unmatched address extension (+foo) gets propagated to the result of the table lookup. iykyk 🌸


🧚 REGULAR EXPRESSION TABLES 🧚

this section explains how the table lookups change when the table is given in the form of regular expressions. want the full regular expression lookup table syntax? check regexp_table(5) or pcre_table(5), they've got you πŸ’–

each pattern is a regular expression that gets applied to the entire address being looked up. so that means user@domain mail addresses are not broken up into their user and @domain constituent parts, and user+foo is not broken up into user and foo. they stay whole. integral. unbothered πŸ¦‹

patterns are applied in the order specified in the table, until a pattern is found that matches the search string. first match wins, no tiebreakers needed πŸ’…

results are the same as with indexed file lookups, plus one extra feature that's genuinely so good: parenthesized substrings from the pattern can be interpolated as $1, $2 and so on. iconic ✨


πŸ–₯️ TCP-BASED TABLES πŸ–₯️

this section explains how the table lookups change when lookups get directed to a TCP-based server. for the whole description of the TCP client/server lookup protocol, go read tcp_table(5). this feature is available in Postfix 2.5 and later πŸ“…

every lookup operation uses the entire address once. so again, user@domain mail addresses are not broken up into their user and @domain constituent parts, and user+foo is not broken up into user and foo. same rule, same energy 🌟

results are the same as with indexed file lookups. periodt πŸ’œ


πŸ“ EXAMPLE πŸ“

here's a generic mapping with an indexed file in the wild. when mail gets sent to a remote host via SMTP, this replaces his@localdomain.local by his ISP mail address, replaces her@localdomain.local by her ISP mail address, and replaces other local addresses by his ISP account with an address extension of +local. (this example assumes the ISP supports "+" style address extensions β€” no cap, check first 🫢)

/etc/postfix/main.cf:

smtp_generic_maps = hash:/etc/postfix/generic

/etc/postfix/generic:

his@localdomain.local   hisaccount@hisisp.example
her@localdomain.local   heraccount@herisp.example
@localdomain.local      hisaccount+local@hisisp.example

run this command every single time the table changes, bestie, don't skip it:

postmap /etc/postfix/generic

and instead of hash, some systems use dbm database files. want to find out what tables your system supports? run:

postconf -m

πŸ”βœ¨


πŸ’€ BUGS πŸ’€

okay so this is the one sad part: the table format does not understand quoting conventions. that's it. that's the whole bug. no quotes for you 😭


βš™οΈ CONFIGURATION PARAMETERS βš™οΈ

these main.cf parameters are especially relevant, bestie. the text below is only a parameter summary β€” go read postconf(5) for more details, examples included πŸ’–

  • smtp_generic_maps (empty) β€” optional lookup tables that perform address rewriting in the Postfix SMTP client, typically to transform a locally valid address into a globally valid address when sending mail across the Internet. literally the star of the show πŸ‘‘
  • propagate_unmatched_extensions (canonical, virtual) β€” what address lookup tables copy an address extension from the lookup key to the lookup result 🫢

other parameters of interest β€” yes there's more, we're not done:

  • inet_interfaces (all) β€” the local network interface addresses that this mail system receives mail on 🌐
  • proxy_interfaces (empty) β€” the remote network interface addresses that this mail system receives mail on by way of a proxy or network address translation unit πŸ›°οΈ
  • mydestination ($myhostname, localhost.$mydomain, localhost) β€” the list of domains that are delivered via the $local_transport mail delivery transport πŸ“¬
  • myorigin ($myhostname) β€” the domain name that locally-posted mail appears to come from, and that locally posted mail is delivered to πŸ’Œ
  • owner_request_special (yes) β€” enable special treatment for owner-listname entries in the aliases(5) file, and don't split owner-listname and listname-request address localparts when the recipient_delimiter is set to "-" πŸŽ€

πŸ‘€ SEE ALSO πŸ‘€

the holy trinity honestly πŸ™


πŸ“š README FILES πŸ“š

use "postconf readme_directory" or "postconf html_directory" to locate this information βœ…

  • ADDRESS_REWRITING_README, address rewriting guide
  • DATABASE_README, Postfix lookup table overview
  • STANDARD_CONFIGURATION_README, configuration examples

required reading, bestie, do your homework πŸ“–βœ¨


πŸ“œ LICENSE πŸ“œ

the Secure Mailer license must be distributed with this software. legal girlies stay winning πŸ’…


πŸ•°οΈ HISTORY πŸ•°οΈ

a genericstable feature appears in the Sendmail MTA. so yes, this concept has lore πŸ“–

and this feature is available in Postfix 2.2 and later. old but gold πŸ‘‘


πŸ’Œ AUTHOR(S) πŸ’Œ

  • Wietse Venema IBM T.J. Watson Research P.O. Box 704 Yorktown Heights, NY 10598, USA
  • Wietse Venema Google, Inc. 111 8th Avenue New York, NY 10011, USA

two addresses, one legend 🫢


and that's the whole page bestie!! this was generic(5) from the File Formats Manual β€” thank you for coming to my ted talk, see u in the next lookup, mwah πŸ’–πŸŽ€βœ¨

πŸ“¦ where this page comes from