{"id":4904,"date":"2026-02-21T14:52:56","date_gmt":"2026-02-21T14:52:56","guid":{"rendered":"https:\/\/geekmungus.co.uk\/?p=4904"},"modified":"2026-02-21T14:52:56","modified_gmt":"2026-02-21T14:52:56","slug":"exim-address-re-write-flattening-sub-domain","status":"publish","type":"post","link":"https:\/\/geekmungus.co.uk\/?p=4904","title":{"rendered":"Exim &#8211; Address Re-Write (Flattening Sub-Domain)"},"content":{"rendered":"\n<p>We had an interesting issue where our EXIM configuration was flattening a subdomain&#8217;s &#8220;From&#8221; address, i.e. it was re-writing an email&#8217;s&nbsp;<strong>From (HFrom)<\/strong>&nbsp;and&nbsp;<strong>MailFrom (return-path\/envelope-from)<\/strong>&nbsp;headers to @domain.com&nbsp;addresses, i.e. to catch emails such as root@mymachine.domain.comand re-write the&nbsp;<strong>From (HFrom)<\/strong>&nbsp;and&nbsp;<strong>MailFrom (return-path\/envelope-from)<\/strong>&nbsp;to&nbsp;root@domain.com&nbsp;instead.<\/p>\n\n\n\n<p>Problem was, this configuration wasn&#8217;t documented, so needed a bit of investigation; but is also a good learning point for email, how it works, and how it can be manipulated.<\/p>\n\n\n\n<p>Remember that within an email message the From address you see in your email client isn&#8217;t the same as the MailFrom (return-path\/envelope-from) &#8211; although it could be!<\/p>\n\n\n\n<p><strong>RFC5322 From (HFrom)&nbsp;<\/strong>&#8211; This is the header field in the email message that specifies the sender&#8217;s address and name as displayed in the email client. It&#8217;s used for display purposes and is often the address the recipient sees when they reply to the email.<br><strong>RFC5321 MailFrom (return-path\/envelope-from)<\/strong>&nbsp;&#8211; This is the address used in the SMTP envelope, which is not directly visible to the recipient. It&#8217;s used for the initial handshake and delivery of the email, and it&#8217;s related to the bounce address.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\" id=\"EximAddressReWrite(FlatteningSubDomain)-RewriteExampleRules\">Rewrite Example Rules<\/h1>\n\n\n\n<p>Here is an example re-write configuration, if we explore some of the lines.<\/p>\n\n\n\n<p>You can specify that an address (or pattern of an address) never to be rewritten, which means once the address is picked up by a rule it is never passed on to the next rule. Or you can specify an address (or pattern of an address) is to be rewritten, which means once the address is picked up by a rule it is acted upon, and never passed to the next rule.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>####### Begin Address Re-Write ############\n\nbegin rewrite\n\n# Excluded Subdomains\n*@*.subdomain.domain.com * Ff\n\n# Subdomains\n*@*\\.domain.com  $1@domain.com Ff<\/code><\/pre>\n\n\n\n<p>We&#8217;ll explore a couple of the lines, to explain what is going on, for a more well rounded set of documentation see the &#8220;Additional Information&#8221; section below for some more in-depth links.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"EximAddressReWrite(FlatteningSubDomain)-ExcludedSubdomain\">Excluded Subdomain<\/h3>\n\n\n\n<p>If you want to exclude a subdomain from being processed, then 1. you need to ensure it is not matched by any rule above it, 2. then add a rule in the format:&nbsp;<strong><em>&lt;match&gt; &lt;action&gt; &lt;flags&gt;<\/em><\/strong><\/p>\n\n\n\n<p>So for example to exclude any emails which have the the From (HFrom) and MailFrom (return-path\/envelope-from) from any further processing (and possible re-write) you would use the following:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>*@*.subdomain.domain.com * Ff<\/code><\/pre>\n\n\n\n<p>Matches any email address from&nbsp;<strong>@subdomain.domain.com<\/strong>&nbsp;(or a sub-domain thereof), then &#8220;*&#8221; means do nothing, and the Ff means only evaluate the From (HFrom) and MailFrom (return-path\/envelope-from).<\/p>\n\n\n\n<p>It also means go no further and stop evaluating any more rules and move the email to delivery.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"EximAddressReWrite(FlatteningSubDomain)-Included(RewrittenSubdomain)\">Included (Rewritten Subdomain)<\/h3>\n\n\n\n<p>If you want to re-write a subdomain of domain.com for example you would use something like:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>*@*\\.domain.com  $1@domain.com Ff<\/code><\/pre>\n\n\n\n<p>Which means match anything&nbsp;<strong>@domain.com<\/strong>&nbsp;(which might include say&nbsp;<strong>root@mymachine.domain.com)<\/strong>&nbsp;and then &#8220;flatten&#8221; it with $1@domain.com&nbsp;to become&nbsp;root@domain.com&nbsp;acting only on the From (HFrom) and MailFrom (return-path\/envelope-from) attributes.&nbsp;<\/p>\n\n\n\n<p>In plain terms match any email which has a From (HFrom) and\/or MailFrom (return-path\/envelope-from) sub-domain of sanger.ac.uk and then re-write the From (HFrom) and\/or MailFrom (return-path\/envelope-from) to <strong>$1@domain.com<\/strong>&nbsp;instead, so&nbsp;<strong>root@mymachine.domain.com<\/strong>&nbsp;would become <strong>root@domain.com<\/strong>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"EximAddressReWrite(FlatteningSubDomain)-Flags\">Flags<\/h3>\n\n\n\n<p>The flags can be set to act upon different parts of the email attributes, for example:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>E       rewrite all envelope fields\nF       rewrite the envelope From field\nT       rewrite the envelope To field\nb       rewrite the Bcc: header\nc       rewrite the Cc: header\nf       rewrite the From: header\nh       rewrite all headers\nr       rewrite the Reply-To: header\ns       rewrite the Sender: header\nt       rewrite the To: header<\/code><\/pre>\n\n\n\n<h1 class=\"wp-block-heading\" id=\"EximAddressReWrite(FlatteningSubDomain)-CheckConfigurationFileSyntax\">Check Configuration File Syntax<\/h1>\n\n\n\n<p>You can check the syntax of the configuration file with the following to check for any errors:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>exim -C exim.conf -bV<\/code><\/pre>\n\n\n\n<h1 class=\"wp-block-heading\" id=\"EximAddressReWrite(FlatteningSubDomain)-Testing\">Testing<\/h1>\n\n\n\n<p>To verify your change has been successful, or to see what the current configuration is doing in terms of re-writing, you can use the following command.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"EximAddressReWrite(FlatteningSubDomain)-Before\">Before<\/h2>\n\n\n\n<p>As you can see the address\u00a0support@dev.domain.com\u00a0is being rewritten to:\u00a0support@domain.com.\u00a0<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># exim -brw support@dev.domain.com\n  sender: support@dev.domain.com\n    <strong>from: support@domain.com<\/strong>\n      to: support@dev.domain.com\n      cc: support@dev.domain.com\n     bcc: support@dev.domain.com\nreply-to: support@dev.domain.com\n<strong>env-from: support@domain.com<\/strong>\n  env-to: support@dev.domain.com<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"EximAddressReWrite(FlatteningSubDomain)-After\">After<\/h2>\n\n\n\n<p>After a change was made to the configuration to explicitly exclude this sub-domain from being re-written, we can see that the address is not being re-written.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&#91;root@mail-relay-01 ~]# exim -brw support@dev.domain.com\n  sender: support@dev.domain.com\n    from: support@dev.domain.com\n      to: support@dev.domain.com\n      cc: support@dev.domain.com\n     bcc: support@dev.domain.com\nreply-to: support@dev.domain.com\nenv-from: support@dev.domain.com\n  env-to: support@dev.domain.com<\/code><\/pre>\n\n\n\n<p>Obviously you should also check the addresses you do want to be re-written are still indeed being rewritten!<\/p>\n\n\n\n<h1 class=\"wp-block-heading\" id=\"EximAddressReWrite(FlatteningSubDomain)-TestSubmission\">Test Submission<\/h1>\n\n\n\n<p>If you want to test a real submission, you can create an email file and drop it into the submission with the following procedure.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># cat > exim-rewrite-test.eml &lt;&lt;'EOF'\n> From: support@dev.domain.com\n> To: adminuser@domain.com\n> Subject: Rewrite Test\n>\n> test\n> EOF\n&#91;root@mail-relay-01 ~]# cat exim-rewrite-test.eml\nFrom: support@dev.domain.com\nTo: adminuser@domain.com\nSubject: Rewrite Test\n\ntest\n\n# exim -odq -i -f support@dev.domain.com adminuser@domain.com &lt; exim-rewrite-test.eml\n\n# exim -bp\n 0m   379 1vrz0d-000000003gC-3jth &lt;support@domain.com>\n          adminuser@domain.com\n\n# exim -Mvh 1vrz0d-000000003gC-3jth\n1vrz0d-000000003gC-3jth-H\nroot 0 0\n&lt;support@domain.com>\n1771249891 0\n-received_time_usec .891414\n-received_time_complete 1771249891.892573\n-ident root\n-received_protocol local\n-body_linecount 1\n-max_received_linelength 46\n-allow_unqualified_recipient\n-allow_unqualified_sender\n-deliver_firsttime\n-tls_resumption A\nXX\n1\nadminuser@domain.com\n\n199P Received: from root by mail-relay-01.domain.com with local (Exim 4.97.1)\n\t(envelope-from &lt;support@domain.com>)\n\tid 1vrz0d-000000003gC-3jth\n\tfor adminuser@domain.com;\n\tMon, 16 Feb 2026 13:51:31 +0000\n047* From: support@dev.domain.com\n027F From: support@domain.com\n021T To: adminuser@domain.com\n022  Subject: Rewrite Test\n066I Message-Id: &lt;E1vrz0d-000000003gC-3jth@mail-relay-01.domain.com>\n059* X-rewrote-sender: support@dev.domain.com\n038  Date: Mon, 16 Feb 2026 13:51:31 +0000\n\n# exim -Mrm 1vrz0d-000000003gC-3jth\nMessage 1vrz0d-000000003gC-3jth has been removed\n\n# rm exim-rewrite-test.eml\nrm: remove regular file 'exim-rewrite-test.eml'? y\n<\/code><\/pre>\n\n\n\n<h1 class=\"wp-block-heading\" id=\"EximAddressReWrite(FlatteningSubDomain)-AdditionalInformation\">Additional Information<\/h1>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/www.exim.org\/exim-html-3.30\/doc\/html\/spec_34.html\">https:\/\/www.exim.org\/exim-html-3.30\/doc\/html\/spec_34.html<\/a>\u00a0(see section on rewriting)<\/li>\n\n\n\n<li><a href=\"http:\/\/www.datadisk.co.uk\/html_docs\/exim\/address_header.htm\">http:\/\/www.datadisk.co.uk\/html_docs\/exim\/address_header.htm<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/github.com\/Exim\/exim\/wiki\/TestingExim\">https:\/\/github.com\/Exim\/exim\/wiki\/TestingExim<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>We had an interesting issue where our EXIM configuration was flattening a subdomain&#8217;s &#8220;From&#8221; address, i.e. it was re-writing an email&#8217;s&nbsp;From (HFrom)&nbsp;and&nbsp;MailFrom (return-path\/envelope-from)&nbsp;headers to @domain.com&nbsp;addresses, i.e. to catch emails such as root@mymachine.domain.comand re-write the&nbsp;From (HFrom)&nbsp;and&nbsp;MailFrom (return-path\/envelope-from)&nbsp;to&nbsp;root@domain.com&nbsp;instead. Problem was, this configuration wasn&#8217;t documented, so needed a bit of investigation; but is also a good learning point &#8230; <a title=\"Exim &#8211; Address Re-Write (Flattening Sub-Domain)\" class=\"read-more\" href=\"https:\/\/geekmungus.co.uk\/?p=4904\" aria-label=\"Read more about Exim &#8211; Address Re-Write (Flattening Sub-Domain)\">Read more<\/a><\/p>\n","protected":false},"author":4,"featured_media":4361,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[30,11],"tags":[],"class_list":["post-4904","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-email","category-linux"],"_links":{"self":[{"href":"https:\/\/geekmungus.co.uk\/index.php?rest_route=\/wp\/v2\/posts\/4904","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/geekmungus.co.uk\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/geekmungus.co.uk\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/geekmungus.co.uk\/index.php?rest_route=\/wp\/v2\/users\/4"}],"replies":[{"embeddable":true,"href":"https:\/\/geekmungus.co.uk\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=4904"}],"version-history":[{"count":2,"href":"https:\/\/geekmungus.co.uk\/index.php?rest_route=\/wp\/v2\/posts\/4904\/revisions"}],"predecessor-version":[{"id":4906,"href":"https:\/\/geekmungus.co.uk\/index.php?rest_route=\/wp\/v2\/posts\/4904\/revisions\/4906"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/geekmungus.co.uk\/index.php?rest_route=\/wp\/v2\/media\/4361"}],"wp:attachment":[{"href":"https:\/\/geekmungus.co.uk\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=4904"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/geekmungus.co.uk\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=4904"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/geekmungus.co.uk\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=4904"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}