The Wiert Corner – irregular stream of stuff

Jeroen W. Pluimers on .NET, C#, Delphi, databases, and personal interests

  • My badges

  • Twitter Updates

  • My Flickr Stream

  • Pages

  • All categories

  • Enter your email address to subscribe to this blog and receive notifications of new posts by email.

    Join 1,860 other subscribers

roehling/postsrsd: Postfix Sender Rewriting Scheme daemon

Posted by jpluimers on 2025/11/12

This finally made me perform the (long overdue) migration from Sendmail to Postfix:

The Sender Rewriting Scheme (SRS) is a technique to forward mails from domains which deploy the Sender Policy Framework (SPF) to prohibit other Mail Transfer Agents (MTAs) from sending mails on their behalf. With SRS, an MTA can circumvent SPF restrictions by replacing the envelope sender with a temporary email address from one of their own domains. This temporary address is bound to the original sender and only valid for a certain amount of time, which prevents abuse by spammers.

[Wayback/Archive] roehling/postsrsd: Postfix Sender Rewriting Scheme daemon

Via a long queste to figure out why Gmail every now and then bounces forwarded messages because of Sender Policy Framework (SPF). Below are a few of the links that brought me here in mostly reverse order, but first some links that should help me further on the topic of Postfix virtual aliases.

The sendmail setup had some features not covered below (like a catch-all forward for email to addresses virtual domains not covered by a virtual alias) which I hopefully can cover later.

One thing learned both over the past decades and related postfix material: use separate servers or containers for each of your functions. So do not mix web-hosting, outgoing mail, incoming mail, fail2ban and others on the same server.

Links:

Postfix and virtual aliases

  • [Wayback/Archive] Postfix Virtual Domain Hosting Howto – Postfix virtual ALIAS example: separate domains, UNIX system accounts
  • [Wayback/Archive] debian – Confused about alias_maps and virtual_alias_maps – Server Fault (thanks [Wayback/Archive] Neel, [Wayback/Archive] ]masegaloeh and [Wayback/Archive] NickW):

    Q

    I have already re-read the docs on this as well as other posts here and this is still very unclear to me. I have been testing various things to understand the difference between alias_maps and virtual_alias_maps and I don’t see the use of these 2 separate settings in postfix. This is what I found so far (Note – I am using postfix in the same server as my web server as null client to send emails only):
    1) /etc/aliases file:
    root: me@somedomain.com
    
    When I add the above to the alias_maps, I noticed that some services like fail2ban are able to pick this and it sends root emails to the alias email addresses mentioned. However, I also noticed that some other services (like mail command) does not respect this and tries to send the email directly to root@mydomain.com which does not exist (I think its the postfix myorigin setting that is adding the @mydomain.com). To fix this I then added the virtual_alias_maps
    2) /etc/postfix/virtual
    root     me@someotherdomain.com
    
    When the above is added, all services uses this virtual aliases email. I also noticed that once I add the above, even fail2ban begins to ignore my initial settings in /etc/aliases/ file and starts to follow the email address given in virtual file.
    Now this has confused me even more –
    1. Why do we need /etc/aliases/ when having the email inside virtual aliases map seems to override it?
    2. What is the purpose of having these 2 separate aliases mapping and when do we decide when to use what?
    3. Why did fail2ban (which is configured to email to root@localhost) first follow email address given in alias_maps (/etc/aliases/) and later decides to ignore that once virtual_alias_maps was added?
    4. Why doesn’t all services read email aliases mentioned in /etc/aliases and they only work when the email aliases are added in virtual alias map?

    A

    Some background

    Postfix inherited some features from older sendmail like milter and aliases. The file /etc/aliases is part of aliases inheritance and implemented by alias_maps. On the other side, postfix has virtual_maps/virtual_alias_maps for handle email aliasing. So what’s the difference between them?

    Parameter alias_maps

    • Used only for local(8) delivery
    • According to address class in postfix, email will delivery by local(8) if the recipient domain names are listed in the mydestination
    • The lookup input was only local parts from full email addres (e.g myuser from myuser@example.com). It discard domain parts of recipient.
    • The lookup result can contains one or more of the following:
      • email address: email will forwarded to email address
      • /file/name: email will be appended to /file/name
      • |command: mail piped to the command
      • :include:/file/name: include alias from /file/name

    Parameter virtual_alias_maps

    • Used by virtual(5) delivery
    • Always invoked first time before any other address classes. It doesn’t care whether the recipient domain was listed in mydestinationvirtual_mailbox_domains or other places. It will override the address/alias defined in other places.
    • The lookup input has some format
      • user@domain: it will match user@domain literally
      • user: it will match user@site when site is equal to $myorigin, when site is listed in $mydestination, or when it is listed in $inet_interfaces or $proxy_interfacesThis functionality overlaps with functionality of the local aliases(5) database.
      • @domain: it will match any email intended for domain regardless of local parts
    • The lookup result must be
      • valid email address
      • user without domain. Postfix will append $myorigin if append_at_myorigin set yes

    Why do we need /etc/aliases when having the email inside virtual aliases map seems to override it?

    As you can see above, alias_maps(/etc/aliases) has some additional features (beside forwarding) like piping to command. In contrast with virtual_alias_maps that just forwards emails.

    What is the purpose of having these 2 separate aliases mapping and when do we decide when to use what?

    The alias_maps drawback is that you cannot differentiate if the original recipient has root@example.com or root@example.net. Both will be mapped to root entry in alias_maps. In other words, you can define different forwarding address with virtual_alias_maps.

    Why did fail2ban (which is configured to email to root@localhost) first follow email address given in alias_maps (/etc/aliases/) and later decides to ignore that once virtual_alias_maps was added?

    Before virtual_alias_maps added: root@localhost was aliased by alias_maps because localhost was listed in mydestination.

    After virtual_alias_maps defined: The entry root (in virtual_alias_maps) doesn’t have domain parts and localhost was listed in mydestination, so it will match root me@example.com.

    Why doesn’t all services read email aliases mentioned in /etc/aliases and they only work when the email aliases are added in virtual alias map?

    Command mail root will send email to root. Because lacks of domain parts, postfix trivial-rewrite will append myorigin to domain parts. So, mail will be send to root@myorigin.

    Before virtual_alias_maps added: Unfortunately, myorigin isn’t listed in mydestination, so it won’t be processed by alias_maps.

    After virtual_alias_maps added: The entry root (in virtual_alias_maps) doesn’t have domain parts and myorigin (obviously) same as myorigin, so it will match root me@example.com.

    A

    You need to be more specific, which services, how and where do they submit mail?

    C

    hi @NickW yes I did rebuilt aliases using newaliases after change. The only thing I can think for why its not using aliases is maybe due to the postfix setting that adds @$domain_name after the user and hence virtual_alias_maps is needed to redirect those emails. I read this in postfix docs and maybe thats why mail command to root is not working with aliasespostfix.org/STANDARD_CONFIGURATION_README.html#some_local Anyhow, thank you so much for helping me understand this better Nick. I really appreciate it.. :)

  • [Wayback/Archive] Postfix Configuration Parameters

    alias_maps (default: see “postconf -d” output)

    The alias databases that are used for local(8) delivery. See aliases(5) for syntax details. Specify zero or more “type:name” lookup tables, separated by whitespace or comma. Tables will be searched in the specified order until a match is found. Note: these lookups are recursive.

    The default list is system dependent. On systems with NIS, the default is to search the local alias database, then the NIS alias database.

    If you change the alias database, run “postalias /etc/aliases” (or wherever your system stores the mail alias file), or simply run “newaliases” to build the necessary DBM or DB file.

    The local(8) delivery agent disallows regular expression substitution of $1 etc. in alias_maps, because that would open a security hole.

    The local(8) delivery agent will silently ignore requests to use the proxymap(8) server within alias_maps. Instead it will open the table directly. Before Postfix version 2.2, the local(8) delivery agent will terminate with a fatal error.

    Examples:

    alias_maps = hash:/etc/aliases, nis:mail.aliases
    alias_maps = hash:/etc/aliases
  • [Wayback/Archive] Postfix Address Classes
    Postfix version 2.0 introduces the concept of address classes. This is a way of grouping recipient addresses by their delivery method. The idea comes from discussions with Victor Duchovni. Although address classes introduced a few incompatibilities they also made it possible to improve the handling of hosted domains and of unknown recipients.
  • [Wayback/Archive] Postfix Address Classes

    This is how Postfix decides what mail to accept, and how to deliver it. In other words, address classes are very important for the operation of Postfix.

    An address class is defined by three items.

    • The list of domains that are a member of that address class: for example, all local domains, or all relay domains.
    • The default delivery transport for that address class. For example, the local, virtual or relay delivery transport (delivery transports are defined in master.cf). This helps to keep Postfix configurations simple, by avoiding the need for explicit routing information in transport maps.
    • The list of valid recipient addresses for that address class. The Postfix SMTP server rejects invalid recipients with “User unknown in <name of address class here> table”. This helps to keep the Postfix queue free of undeliverable MAILER-DAEMON messages.

    What address classes does Postfix implement?

    • The local domain class.
    • The virtual alias domain class.
    • The virtual mailbox domain class.
    • The relay domain class.
    • The default domain class.
  • [Wayback/Archive] Postfix manual – aliases(5)

    aliases – Postfix local alias database format

  • [Wayback/Archive] Postfix manual – virtual(5)

    virtual – Postfix virtual alias table format

  • [Wayback/Archive] Postfix Configuration Parameters

    virtual_alias_maps (default: $virtual_maps)

    Optional lookup tables that alias specific mail addresses or domains to other local or remote addresses. The table format and lookups are documented in virtual(5). For an overview of Postfix address manipulations see the ADDRESS_REWRITING_README document.

    This feature is available in Postfix 2.0 and later. The default value is backwards compatible with Postfix version 1.1.

    Specify zero or more “type:name” lookup tables, separated by whitespace or comma. Tables will be searched in the specified order until a match is found. Note: these lookups are recursive.

    If you use this feature with indexed files, run “postmap /etc/postfix/virtual” after changing the file.

    Examples:

    virtual_alias_maps = dbm:/etc/postfix/virtual
    virtual_alias_maps = hash:/etc/postfix/virtual
  • [Wayback/Archive] Postfix Address Rewriting

    Rewrite addresses to standard form

    Before the cleanup(8) daemon runs an address through any address mapping lookup table, it first rewrites the address to the standard “user@fully.qualified.domain” form, by sending the address to the trivial-rewrite(8) daemon. The purpose of rewriting to standard form is to reduce the number of entries needed in lookup tables.

  • [Wayback/Archive] ‘Re: alias_maps and virtual_alias_maps’ – MARC
    > I would like postfix to look through my /etc/postfix/aliases.db file
    > first and then look through at my MYSQL database second.  Postfix
    > seems to jump straight to the database.
    
    virtual_alias_maps will *always* be used before alias_maps. Read
    ADDRESS_CLASS_README.
    
    > The reason for this is I would like to be able to run executables for
    > some e-mail address (specifically for use with Mailman List Manager).
    > Any help with what I am doing wrong is greatly appreciated!
    
    To run commands from addresses in virtual domains, alias them to
    addresses in the local domain(s).
    
    virtual alias map:
    address@virtualdomain           address.virtualdomain@localhost
    
    alias map:
    address.virtualdomain: |mailman
    
    > #####postconf | grep alias
    
    "postconf -n" is preferred.
    
    [...]
    
    -- 
    Magnus Bäck
    magnus@dsek.lth.se
  • [Wayback/Archive] Postfix Standard Configuration Examples

    Delivering some but not all accounts locally

    A drawback of sending mail as “user@example.com” (instead of “user@hostname.example.com”) is that mail for “root” and other system accounts is also sent to the central mailhost. In order to deliver such accounts locally, you can set up virtual aliases as follows:

    1 /etc/postfix/main.cf:
    2     virtual_alias_maps = hash:/etc/postfix/virtual
    3 
    4 /etc/postfix/virtual:
    5     root     root@localhost
    6     . . .
    

    Translation:

    Execute the command “postmap /etc/postfix/virtual” after editing the file.

  • [Wayback/Archive] Postfix Lookup Table Overview

    Postfix lookup table types

    To find out what database types your Postfix system supports, use the “postconf -m” command. Here is a list of database types that are often supported:

    btree
    A sorted, balanced tree structure. This is available only on systems with support for Berkeley DB databases. Database files are created with the postmap(1) or postalias(1) command. The lookup table name as used in “btree:table” is the database file name without the “.db” suffix.
    cdb
    A read-optimized structure with no support for incremental updates. Database files are created with the postmap(1) or postalias(1) command. The lookup table name as used in “cdb:table” is the database file name without the “.cdb” suffix. This feature is available with Postfix 2.2 and later.
    cidr
    A table that associates values with Classless Inter-Domain Routing (CIDR) patterns. The table format is described in cidr_table(5).
    dbm
    An indexed file type based on hashing. This is available only on systems with support for DBM databases. Public database files are created with the postmap(1) or postalias(1) command, and private databases are maintained by Postfix daemons. The lookup table name as used in “dbm:table” is the database file name without the “.dir” or “.pag” suffix.
    environ
    The UNIX process environment array. The lookup key is the variable name. The lookup table name in “environ:table” is ignored.
    fail
    A table that reliably fails all requests. The lookup table name is used for logging only. This table exists to simplify Postfix error tests.
    hash
    An indexed file type based on hashing. This is available only on systems with support for Berkeley DB databases. Public database files are created with the postmap(1) or postalias(1) command, and private databases are maintained by Postfix daemons. The database name as used in “hash:table” is the database file name without the “.db” suffix.
    inline (read-only)
    A non-shared, in-memory lookup table. Example: “inline:{ key=value, { key = text with whitespace or comma }}”. Key-value pairs are separated by whitespace or comma; with a key-value pair inside “{}”, whitespace is ignored after the opening “{“, around the “=” between key and value, and before the closing “}”. Inline tables eliminate the need to create a database file for just a few fixed elements. See also the static: map type.
    internal
    A non-shared, in-memory hash table. Its contents are lost when a process terminates.
    lmdb
    OpenLDAP LMDB database. This is available only on systems with support for LMDB databases. Public database files are created with the postmap(1) or postalias(1) command, and private databases are maintained by Postfix daemons. The database name as used in “lmdb:table” is the database file name without the “.lmdb” suffix. See lmdb_table(5) for details.
    ldap (read-only)
    LDAP database client. Configuration details are given in the ldap_table(5).
    memcache
    Memcache database client. Configuration details are given in memcache_table(5).
    mysql (read-only)
    MySQL database client. Configuration details are given in mysql_table(5).
    netinfo (read-only)
    Netinfo database client.
    nis (read-only)
    NIS database client.
    nisplus (read-only)
    NIS+ database client. Configuration details are given in nisplus_table(5).
    pcre (read-only)
    A lookup table based on Perl Compatible Regular Expressions. The file format is described in pcre_table(5). The lookup table name as used in “pcre:table” is the name of the regular expression file.
    pipemap (read-only)
    A pipeline of lookup tables. Example: “pipemap:{type1:name1, …, typen:namen}”. Each “pipemap:” query is given to the first table. Each lookup result becomes the query for the next table in the pipeline, and the last table produces the final result. When any table lookup produces no result, the pipeline produces no result. The first and last characters of the “pipemap:” table name must be “{” and “}”. Within these, individual maps are separated with comma or whitespace.
    pgsql (read-only)
    PostgreSQL database client. Configuration details are given in pgsql_table(5).
    proxy
    Postfix proxymap(8) client for shared access to Postfix databases. The lookup table name syntax is “proxy:type:table“.
    randmap (read-only)
    An in-memory table that performs random selection. Example: “randmap:{result1. …, resultn}”. Each table query returns a random choice from the specified results. The first and last characters of the “randmap:” table name must be “{” and “}”. Within these, individual maps are separated with comma or whitespace. To give a specific result more weight, specify it multiple times.
    regexp (read-only)
    A lookup table based on regular expressions. The file format is described in regexp_table(5). The lookup table name as used in “regexp:table” is the name of the regular expression file.
    sdbm
    An indexed file type based on hashing. This is available only on systems with support for SDBM databases. Public database files are created with the postmap(1) or postalias(1) command, and private databases are maintained by Postfix daemons. The lookup table name as used in “sdbm:table” is the database file name without the “.dir” or “.pag” suffix.
    socketmap (read-only)
    Sendmail-style socketmap client. The name of the table is either inet:host:port:name for a TCP/IP server, or unix:pathname:name for a UNIX-domain server. See socketmap_table(5) for details.
    sqlite (read-only)
    SQLite database. Configuration details are given in sqlite_table(5).
    static (read-only)
    A table that always returns its name as the lookup result. For example, “static:foobar” always returns the string “foobar” as lookup result. Specify “static:{ text with whitespace }” when the result contains whitespace; this form ignores whitespace after the opening “{” and before the closing “}”. See also the inline: map type.
    tcp
    TCP/IP client. The protocol is described in tcp_table(5). The lookup table name is “tcp:host:port” where “host” specifies a symbolic hostname or a numeric IP address, and “port” specifies a symbolic service name or a numeric port number.
    texthash (read-only)
    A table that produces similar results as hash: files, except that you don’t have to run the postmap(1) command before you can use the file, and that texthash: does not detect changes after the file is read. The lookup table name is “texthash:filename”, where the file name is taken literally; no suffix is appended.
    unionmap (read-only)
    A table that sends each query to multiple lookup tables and that concatenates all found results, separated by comma. The table name syntax is the same as for pipemap tables.
    unix (read-only)
    A limited view of the UNIX authentication database. The following tables are implemented:

    unix:passwd.byname
    The table is the UNIX password database. The key is a login name. The result is a password file entry in passwd(5) format.
    unix:group.byname
    The table is the UNIX group database. The key is a group name. The result is a group file entry in group(5) format.

    Other lookup table types may be available depending on how Postfix was built. With some Postfix distributions the list is dynamically extensible as support for lookup tables is dynamically linked into Postfix.

  • [Wayback/Archive] Postfix Configuration Parameters

    virtual_mailbox_maps (default: empty)

    Optional lookup tables with all valid addresses in the domains that match $virtual_mailbox_domains.

    Specify zero or more “type:name” lookup tables, separated by whitespace or comma. Tables will be searched in the specified order until a match is found.

    In a lookup table, specify a left-hand side of “@domain.tld” to match any user in the specified domain that does not have a specific “user@domain.tld” entry.

    With the default “virtual_mailbox_domains = $virtual_mailbox_maps“, lookup tables also need entries with a left-hand side of “domain.tld” to satisfy virtual_mailbox_domain lookups (the right-hand side is required but will not be used).

    The remainder of this text is specific to the virtual(8) delivery agent. It does not apply when mail is delivered with a different mail delivery program.

    The virtual(8) delivery agent uses this table to look up the per-recipient mailbox or maildir pathname. If the lookup result ends in a slash (“/”), maildir-style delivery is carried out, otherwise the path is assumed to specify a UNIX-style mailbox file. Note that $virtual_mailbox_base is unconditionally prepended to this path.

    When a recipient address has an optional address extension (user+foo@domain.tld), the virtual(8) delivery agent looks up the full address first, and when the lookup fails, it looks up the unextended address (user@domain.tld).

    Note 1: for security reasons, the virtual(8) delivery agent disallows regular expression substitution of $1 etc. in regular expression lookup tables, because that would open a security hole.

    Note 2: for security reasons, the virtual(8) delivery agent will silently ignore requests to use the proxymap(8) server. Instead it will open the table directly. Before Postfix version 2.2, the virtual(8) delivery agent will terminate with a fatal error.

  • [Wayback/Archive] Postfix Virtual Domain Hosting Howto (the howto has a ton of other examples, but this one fits my purpose best)

    Mail forwarding domains

    Some providers host domains that have no (or only a few) local mailboxes. The main purpose of these domains is to forward mail elsewhere. The following example shows how to set up example.com as a mail forwarding domain:

     1 /etc/postfix/main.cf:
     2     virtual_alias_domains = example.com ...other hosted domains...
     3     virtual_alias_maps = hash:/etc/postfix/virtual
     4 
     5 /etc/postfix/virtual:
     6     postmaster@example.com postmaster
     7     joe@example.com        joe@somewhere
     8     jane@example.com       jane@somewhere-else
     9     # Uncomment entry below to implement a catch-all address
    10     # @example.com         jim@yet-another-site
    11     ...virtual aliases for more domains...
    

    Notes:

    • Line 2: The virtual_alias_domains setting tells Postfix that example.com is a so-called virtual alias domain. If you omit this setting then Postfix will reject mail (relay access denied) or will not be able to deliver it (mail for example.com loops back to myself).NEVER list a virtual alias domain name as a mydestination domain!
    • Lines 3-11: The /etc/postfix/virtual file contains the virtual aliases. With the example above, mail for postmaster@example.com goes to the local postmaster, while mail for joe@example.com goes to the remote address joe@somewhere, and mail for jane@example.com goes to the remote address jane@somewhere-else. Mail for all other addresses in example.com is rejected with the error message “User unknown”.
    • Line 10: The commented out entry (text after #) shows how one would implement a catch-all virtual alias that receives mail for every example.com address not listed in the virtual alias file. This is not without risk. Spammers nowadays try to send mail from (or mail to) every possible name that they can think of. A catch-all mailbox is likely to receive many spam messages, and many bounces for spam messages that were sent in the name of anything@example.com.

    Execute the command “postmap /etc/postfix/virtual” after changing the virtual file, and execute the command “postfix reload” after changing the main.cf file.

    More details about the virtual alias file are given in the virtual(5) manual page, including multiple addresses on the right-hand side.

  • [Wayback/Archive] alias – Postfix, virtual aliases and catchall for undefined addresses – Server Fault (thanks [Wayback/Archive] Konzertheld, [Wayback/Archive] hiergiltdiestfu and [Wayback/Archive] Thorsten Schöning)

    Q

    In Postfix 2.10.2, I have a setup with multiple domains and several virtual aliases to assign mail addresses to local users. It works fine as long as I do not add a catchall.

    Before I used virtual aliases, I had a catchall defined with

    local_recipient_maps =
    luser_relay = catchall
    

    but as I need to sort out mail addresses from different domains, I had to use virtual aliases.

    Now postfix.org says I should do it like this, which I did:

    /etc/postfix/main.cf:

    virtual_alias_domains = example.com
    virtual_alias_maps = hash:/etc/postfix/virtual
    

    /etc/postfix/virtual:

    postmaster@example.com account1
    info@example.com       account1
    sales@example.com      account2
    @example.com         catchall
    

    But if I do so, the catchall address grabs all my mail instead of just the mail to not explicitly defined addresses. Why is that and how do I change it?

    I did postmap virtual and also restarted Postfix. There are no errors in the log, it just logs the delivery to the catchall address. And there is a warning “do not list domain example.com in BOTH mydestination and virtual_alias_domains”, but I did not do that! I don’t even have a mydestination directive. (There is one in the config below, but I added that after NickW suggested so.)

    A

    The important part is that all real mailbox users are also put into the virtual alias lookup. This works around the fact that aliases have priority over real accounts. So it’s not about the order of the entries, or whatever your mydestination is set to, you just have to add your real mailboxes as aliases, too, and the catchall will work as intended and only collect the mail for the undefined addresses.

    So in the end, your lookup must look like that

    @example.org   catchall@example.org
    actually-exists@example.org       actually-exists@example.org
    concrete-alias1@example.org       actually-exists@example.org
    concrete-alias2@example.org       actually-exists@example.org
    

    That way, mails for “actually-exists”, “concrete-alias1” and “concrete-alias2” will all go to “actually-exists”, a user that does actually exist on the system, while mail for all other possible receipients is shoved into “catchall”.

    Shoutout to this article for the tip. Confirmed with postfix 3.4.13.

    C

    The official docs describe that use-case pretty much the same as well: @domain address, address, ... Redirect mail for other users in domain to address. This form has the lowest precedence. Note: @domain is a wild-card. With this form, the Postfix SMTP server accepts mail for any recipient in domain, regardless of whether that recipient exists. postfix.org/virtual.5.html

  • [Wayback/Archive] Postfix: Catch-All für nicht existierende Postfächer [Update] has the above solution as well as this one:
    So ein CatchAll lässt sich in deinem Setup recht einfach bauen, ohne für jeden User einen Alias auf sich selbst anlegen zu müssen.
    Für den User, der den Catchall empfängt, trägt man als Alias wie hier gezeigt

    source: "@domain.com"
    destination: "sammlung@meinkonto.de"

    ein.
    In der Datei /etc/postfix/virtual/mysql-aliases.conf ändert man dann die query-Zeile so:

    query = SELECT destination FROM aliases WHERE source='%s' UNION SELECT CONCAT(username, '@', domain) AS destination FROM users WHERE CONCAT(username, '@', domain)='%s'
    Das macht nichts anderes, als den Alias auf sich selbst virtuell einzufügen, wenn es den User gibt.

Return-Path related links (which one needs to understand SRS)

  • [Wayback/Archive] What is Return-Path? – SendGrid
    Return-path is a hidden email header that indicates where and how bounced emails will be processed. This header, also referred to as a bounce address or reverse path, is an SMTP address that is separate from your original sending address, and is used specifically for collecting and processing bounced messages.
  • [Wayback/Archive] email – What is the behavior difference between return-path, reply-to and from? – Stack Overflow (thanks [Wayback/Archive] Geo, [Wayback/Archive] User Accountant م, [Wayback/Archive] dave wanta, [Wayback/Archive] Jesse Hobart and [Wayback/Archive] cdhowie)

    Q

    On our mailing application we are sending emails with the following header:

    FROM: marketing@customer.com
    TO: subscriber1@domain1.example
    Return-PATH: bouncemgmt@ourcompany.example
    

    The problem that we are facing is that some email servers will bounce back a message immediately and use the from or reverse path (marketing@customer.example) instead to our bounce mgmt server. We want to know if we modify in the header the reply-to to be the same as the return-path if we will be able to catch all bounces.

    Any other ideas are welcome?

    We are using the following documents as references: VERP RFC Bounce Messages

    SMTP Log Parsing to get Bounces

    EDIT 1: A few more bits of information to see if we can get this resolve.

    We want to know at what point the email server relaying the message will choose to use the reply-to versus the return-path. We have notice that when the first SMTP server relaying the message gets rejected it sends it to the reply-to, but when it happens after one hop it sends it to the return-path.

    C

    postmastery.com/blog/about-the-return-path-header

    A

    Let’s start with a simple example. Let’s say you have an email list, that is going to send out the following RFC2822 content.

    From: <coolstuff@mymailinglist.example>
    To: <you@example.com>
    Subject: Super simple email
    Reply-To: <coolstuff-threadId=123@mymailinglist.example>
    
    This is a very simple body.
    

    Now, let’s say you are going to send it from a mailing list, that implements VERP (or some other bounce tracking mechanism that uses a different return-path). Lets say it will have a return-path of coolstuff-you=yourcompany.com@mymailinglist.example. The SMTP session might look like:

    {S}220 workstation1 Microsoft ESMTP MAIL Service
    {C}HELO workstation1
    {S}250 workstation1 Hello [127.0.0.1]
    {C}MAIL FROM:<coolstuff-you=yourcompany.com@mymailinglist.example>
    {S}250 2.1.0 me@mycompany.com....Sender OK
    {C}RCPT TO:<you@example.com>
    {S}250 2.1.5 you@example.com
    {C}DATA
    {S}354 Start mail input; end with <CRLF>.<CRLF>
    {C}From: <coolstuff@mymailinglist.example>
    To: <you@example.com>
    Subject: Super simple email
    Reply-To: <coolstuff-threadId=123@mymailinglist.example>
    
    This is a very simple body.
    .
    
    {S}250 Queued mail for delivery
    {C}QUIT
    {S}221 Service closing transmission channel
    

    Where {C} and {S} represent Client and Server commands, respectively.

    The recipient’s mail would look like:

    Return-Path: coolstuff-you=yourcompany.com@mymailinglist.example
    From: <coolstuff@mymailinglist.example>
    To: <you@example.com>
    Subject: Super simple email
    Reply-To: <coolstuff-threadId=123@mymailinglist.example>
    
    This is a very simple body.
    

    Now, let’s describe the different “FROM”s.

    1. The return path (sometimes called the reverse path, envelope sender, or envelope from — all of these terms can be used interchangeably) is the value used in the SMTP session in the MAIL FROM command. As you can see, this does not need to be the same value that is found in the message headers. Only the recipient’s mail server is supposed to add a Return-Path header to the top of the email. This records the actual Return-Path sender during the SMTP session. If a Return-Path header already exists in the message, then that header is removed and replaced by the recipient’s mail server.

    All bounces that occur during the SMTP session should go back to the Return-Path address. Some servers may accept all email, and then queue it locally, until it has a free thread to deliver it to the recipient’s mailbox. If the recipient doesn’t exist, it should bounce it back to the recorded Return-Path value.

    Note, not all mail servers obey this rule; Some mail servers will bounce it back to the FROM address.

    1. The FROM address is the value found in the FROM header. This is supposed to be who the message is FROM. This is what you see as the “FROM” in most mail clients. If an email does not have a Reply-To header, then all human (mail client) replies should go back to the FROM address.
    2. The Reply-To header is added by the sender (or the sender’s software). It is where all human replies should be addressed too. Basically, when the user clicks “reply”, the Reply-To value should be the value used as the recipient of the newly composed email. The Reply-To value should not be used by any server. It is meant for client-side (MUA) use only.

    However, as you can tell, not all mail servers obey the RFC standards or recommendations.

    A

    Another way to think about Return-Path vs Reply-To is to compare it to snail mail.

    When you send an envelope in the mail, you specify a return address. If the recipient does not exist or refuses your mail, the postmaster returns the envelope back to the return address. For email, the return address is the Return-Path.

    Inside of the envelope might be a letter and inside of the letter it may direct the recipient to “Send correspondence to example address“. For email, the example address is the Reply-To.

    In essence, a Postage Return Address is comparable to SMTP’s Return-Path header and SMTP’s Reply-To header is similar to the replying instructions contained in a letter.

    C

    I would point out that the primary concept not captured in this analogy is that the Return-Path header is added by the receiving mail server and not by the sender. So it’s more like this: you can write whatever address you want inside of the envelope, but to deliver it you have to take it to the post office and show them your drivers license (or other ID) and they put that address on the envelope before sending it. In other words, the Return-Path header is as trustworthy as the checks performed by the receiving SMTP server, where the others can be easily spoofed

  • [Wayback/Archive] Postmastery | About the Return-Path header most common error
    The following fragment is from RFC 5321 which specifies the SMTP protocol:
    When the delivery SMTP server makes the “final delivery” of a message, it inserts a return-path line at the beginning of the mail data. This use of return-path is required; mail systems MUST support it. The return-path line preserves the information in the from the MAIL command. Here, final delivery means the message has left the SMTP environment. Normally, this would mean it had been delivered to the destination user or an associated mail drop, but in some cases it may be further processed and transmitted by another mail system.
    So when the email leaves the SMTP environment, for example by putting it in a mailbox, the Return-Path is added to preserve the value of the SMTP MAIL FROM command. Thus it is the mailbox provider (for example Google, Hotmail, Yahoo) that adds the Return-Path header.
  • Bounce message – Wikipedia

    bounce message or just “bounce” is an automated message from an email system, informing the sender of a previous message that the message has not been delivered (or some other delivery problem occurred). The original message is said to have “bounced”.

    This feedback may be immediate (some of the causes described here) or, if the sending system can retry, may arrive days later after these retries end.

    More formal terms for bounce message include “Non-Delivery Report” or “Non-Delivery Receipt” (NDR), [Failed] “Delivery Status Notification” (DSN) message, or a “Non-Delivery Notification” (NDN)

  • Simple Mail Transfer Protocol – Wikipedia

    SMTP is a connection-orientedtext-based protocol in which a mail sender communicates with a mail receiver by issuing command strings and supplying necessary data over a reliable ordered data stream channel, typically a Transmission Control Protocol (TCP) connection. An SMTP session consists of commands originated by an SMTP client (the initiating agent, sender, or transmitter) and corresponding responses from the SMTP server (the listening agent, or receiver) so that the session is opened, and session parameters are exchanged. A session may include zero or more SMTP transactions. An SMTP transaction consists of three command/reply sequences:

    1. MAIL command, to establish the return address, also called return-path,[17] reverse-path,[18] bounce address, mfrom, or envelope sender.
    2. RCPT command, to establish a recipient of the message. This command can be issued multiple times, one for each recipient. These addresses are also part of the envelope.
    3. DATA to signal the beginning of the message text; the content of the message, as opposed to its envelope. It consists of a message header and a message body separated by an empty line. DATA is actually a group of commands, and the server replies twice: once to the DATA command itself, to acknowledge that it is ready to receive the text, and the second time after the end-of-data sequence, to either accept or reject the entire message.

    Besides the intermediate reply for DATA, each server’s reply can be either positive (2xx reply codes) or negative. Negative replies can be permanent (5xx codes) or transient (4xx codes). A reject is a permanent failure and the client should send a bounce message to the server it received it from. A drop is a positive response followed by message discard rather than delivery.

  • Variable envelope return path – Wikipedia

    Variable envelope return path (VERP) is a technique used by some electronic mailing list software to enable automatic detection and removal of undeliverable e-mail addresses. It works by using a different return path (also called “envelope sender”) for each recipient of a message.

    While bounce message formats in general vary wildly, there is one aspect of a bounce message that is highly predictable: the address to which it will be sent. VERP takes full advantage of this. In a mailing list that uses VERP, a different sender address is used for each recipient.

    With VERP, the original message would be different:

    • envelope sender: wikipedians-owner+bob=example.org@example.net
    • recipient: bob@example.org

    The bounce, then, will be more useful:

    • envelope sender: empty
    • recipient: wikipedians-owner+bob=example.org@example.net
    • contents: example.org was unable to deliver the following message to bob: …

    From this bounce message the mailing list manager can deduce that a message to bob@example.org must have failed.

    This example shows the simplest possible method of matching a VERP to a list subscriber: the entire recipient address is included within the return path, with the at sign replaced by an equals sign because a return path with two at signs would be invalid. Other encoding schemes are possible.

  • Source: Sender Rewriting Scheme – Wikipedia

    The Sender Rewriting Scheme (SRS) is a scheme for bypassing the Sender Policy Framework‘s (SPF) methods of preventing forged sender addresses. Forging a sender address is also known as email spoofing.

    SRS is a form of variable envelope return path (VERP) inasmuch as it encodes the original envelope sender in the local part of the rewritten address.[2] Consider example.com forwarding a message originally destined to bob@example.com to his new address <bob@example.net>:

       ORIGINAL
       envelope sender:     alice@example.org
       envelope recipient:  bob@example.com
    
       REWRITTEN
       envelope sender:     SRS0=HHH=TT=example.org=alice@example.com
       envelope recipient:  bob@example.net
    

  • [Wayback/Archive] The MAIL, RCPT, and DATA verbs

    The server keeps track of an envelope for the client.

    The envelope contains any number of envelope recipient addresses and at most one return path. The envelope is empty when it contains no addresses.
    When the client connects to the server, the envelope is empty.
    For example, after the following responses and requests, the envelope contains the return path djb@silverton.berkeley.edu, the recipient address God@heaven.af.mil, and the recipient address angels@heaven.af.mil:
         220 heaven.af.mil ESMTP
         MAIL FROM:<djb@silverton.berkeley.edu>
         250 ok
         RCPT TO:<God@heaven.af.mil>
         250 ok
         RCPT TO:<devils@heaven.af.mil>
         550 wrong address, buddy
         RCPT TO:<angels@heaven.af.mil>
         250 ok
    

    The MAIL verb

    The point of a MAIL request is to set the envelope return path and clear the list of envelope recipient addresses.

    A MAIL request has a parameter containing
    1. the string "FROM:" in any combination of uppercase and lowercase;
    2. an encoded return path: either the empty string, encoded as <>, or an encoded address; and
    3. extra information.

    If the server accepts the MAIL request, then the new envelope contains the return path specified in MAIL, and no recipient addresses. The server is required to use code 250 here.

  • [Wayback/Archive] Information on RFC 821 » RFC Editor (Simple Mail Transfer Protocol, AUGUST 1982)
  • [Wayback/Archive] Information on RFC 2822 » RFC Editor (Internet Message Format, APRIL 2001)
  • [Wayback/Archive] Information on RFC 5321 » RFC Editor (Simple Mail Transfer Protocol, OCTOBER 2008)
    • [Wayback/Archive] RFC 5321: Simple Mail Transfer Protocol section 4.4: Trace Information
         When the delivery SMTP server makes the "final delivery" of a
         message, it inserts a return-path line at the beginning of the mail
         data.  This use of return-path is required; mail systems MUST support
         it.  The return-path line preserves the information in the <reverse-
         path> from the MAIL command.  Here, final delivery means the message
         has left the SMTP environment.  Normally, this would mean it had been
         delivered to the destination user or an associated mail drop, but in
         some cases it may be further processed and transmitted by another
         mail system.

         The primary purpose of the Return-path is to designate the address to
         which messages indicating non-delivery or other mail system failures
         are to be sent.  For this to be unambiguous, exactly one return path
         SHOULD be present when the message is delivered.
    • [Wayback/Archive] RFC 5321: Simple Mail Transfer Protocol section 7.2: “Blind” Copies
         Addresses that do not appear in the message header section may appear
         in the RCPT commands to an SMTP server for a number of reasons.  The
         two most common involve the use of a mailing address as a "list
         exploder" (a single address that resolves into multiple addresses)
         and the appearance of "blind copies".  Especially when more than one
         RCPT command is present, and in order to avoid defeating some of the
         purpose of these mechanisms, SMTP clients and servers SHOULD NOT copy
         the full set of RCPT command arguments into the header section,
         either as part of trace header fields or as informational or private-
         extension header fields.  Since this rule is often violated in
         practice, and cannot be enforced, sending SMTP systems that are aware
         of "bcc" use MAY find it helpful to send each blind copy as a
         separate message transaction containing only a single RCPT command.
      
         There is no inherent relationship between either "reverse" (from
         MAIL, SAML, etc., commands) or "forward" (RCPT) addresses in the SMTP
         transaction ("envelope") and the addresses in the header section.
         Receiving systems SHOULD NOT attempt to deduce such relationships and
         use them to alter the header section of the message for delivery.
         The popular "Apparently-to" header field is a violation of this
         principle as well as a common source of unintended information
         disclosure and SHOULD NOT be used.
      
  • zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz

SRS with Postfix

Back to the the links in reverse order that made me find roehling/postsrsd: Postfix Sender Rewriting Scheme daemon:

  • [Wayback/Archive] How to forward with postfix, SPF and SRS – Mind IT (the domain has died fall 2021)
  • [Wayback/Archive] Postfix as email forwarder to gmail, SPF problems – Server Fault (thanks [Wayback/Archive] Laurent):

    Q

    I’m trying to configure postfix as forwarder to Gmail. I’ve successfully configured the virtual aliases for the domains I’m hosting and that I want to redirect, but the Gmail Sender Policy Framework (SPF) verification is failing due to this:

    Delivered-To: realrcpt@gmail.com
    Received: by 10.25.28.147 with SMTP id c141csp88155lfc;
        Sat, 11 Oct 2014 09:08:40 -0700 (PDT)
    X-Received: by 10.224.70.83 with SMTP id c19mr21300511qaj.66.1413043720159;
        Sat, 11 Oct 2014 09:08:40 -0700 (PDT)
    Return-Path: <realsender@gmail.com>
    Received: from mail1.mycompany.com (mail1.mycompany.com. [2604:xxxxxxx:b5c8])
        by mx.google.com with ESMTP id d63si16549011qgd.80.2014.10.11.09.08.39
        for <realrcpt@gmail.com>;
        Sat, 11 Oct 2014 09:08:40 -0700 (PDT)
    Received-SPF: softfail (google.com: domain of transitioning realsender@gmail.com does not designate 2604:xxxxxxx:b5c8 as permitted sender) client-ip=2604:180:2:2cf::b5c
    

    I think the problem lies in the return path. When doing email forwarding with another hoster (e.g. namecheap) that gets rewritten to this automatically:

    Return-Path: <SRS0+BJjl=7C=gmail.com=realsender@eforward3e.registrar-servers.com>
    

    Is there any way to perform such a rewrite in postfix? Thanks

    A

    I fixed this with postsrsd by following this guide: https://www.mind-it.info/forward-postfix-spf-srs/

    In short:

    Download and compile the software

    cd ~
    wget https://github.com/roehling/postsrsd/archive/master.zip
    unzip master
    cd postsrsd-master/
    make
    sudo make install
    

    Add postfix configuration parameters for postsrsd

    sudo postconf -e "sender_canonical_maps = tcp:127.0.0.1:10001"
    sudo postconf -e "sender_canonical_classes = envelope_sender"
    sudo postconf -e "recipient_canonical_maps = tcp:127.0.0.1:10002"
    sudo postconf -e "recipient_canonical_classes = envelope_recipient"
    

    Add SRS daemon to startup

    sudo chkconfig postsrsd on
    # Start SRS daemon
    sudo service postsrsd restart
    #Reload postfix
    sudo service postfix reload
    

    https://github.com/roehling/postsrsd was still maintained in 2023 which mentions in the README.rst

    If your Linux distribution has a sufficiently recent PostSRSd package, install it! Unless you need a specific new feature or bugfix from a newer version, it will be much less of a maintenance burden.

  • [Wayback/Archive] linux – Postfix forwarding – SPF issues – Sender rewrite – Server Fault (thanks [Wayback/Archive] Nick Nelson and [Wayback/Archive] Rodolfo Saccani)

    Q

    When using Postfix virtual alias maps to forward email to another domain, is it possible to have Postfix re-write the sender address exclusively for forwards to avoid SPF rejection at the final destination.

    i.e. If user1@ourdomain.com has a forward configured to anotheruser@externaldomain.com, we want Postfix (running at ourdomain.com) to rewrite the sender address to user1@ourdomain.com.

    Currently email sent from source@randomdomain.com to user1@ourdomain.com will be forwarded to anotheruser@externaldomain.com with the sender address staying as source@randomdomain.com, which causes an SPF rejection.

    I’ve found in other answers such as this one that this is possible with postsrsd, however installing new software on these hosts is likely not possible.

    I was initially looking into sender canonical maps, however the Postfix documentation suggests that canonical maps are not used with virtual alias maps:

    Postfix address rewriting documentation:

    Addresses found in virtual alias maps … are not subjected to canonical mapping, in order to avoid loops.

    Is there another way to re-write the sender address which will work with virtual alias maps without installing something like postsrsd?

    A

    postsrsd is not difficult to set-up and it is the correct way to handle the issue because it makes clear to the receiving system that the message is a forward. By plainly rewriting the envelope sender you are taking on yourself the reputation burden of the email you are forwarding. Should you forward spam, the receiving system will blame your domain for it and lower your reputation.

    This may happen anyway, even with SRS, because it depends on the receiving domain to be capable of discriminating a forwarded message from a direct message. Gmail, for example, prefers a plain forward that fails spf to an SRS forward. Go figure.

    The perfect solution would be not to forward at all.

  • [Wayback/Archive] Best practices for forwarding email to Gmail – Google Workspace Admin Help

    This article is for email administrators who forward email to Gmail from other servers or services. Follow these best practices to help ensure Gmail’s spam filter correctly classifies forwarded messages.

    Forwarding and spam

    Avoid changing the envelope sender when forwarding email to Gmail.

    Some email software or services change the envelope sender to your domain when forwarding messages. If the envelope sender is changed to your domain for forwarded spam, Gmail might learn that your domain sends spam. Gmail might treat future messages from your domain as spam.

    You can use third-party software to identify spam message and prevent them from being forwarded. If you never forward spam to Gmail, you can change the envelope sender to your domain.

    Procmail forwarding

    Procmail typically changes the envelope sender for forwarded messages. To fix this issue, add the following to your Procmail configuration file:

    SENDER=`formail -c -x Return-Path`

    SENDMAILFLAGS="-oi -f $SENDER"

    Forwarding and authentication

    We recommend email administrators always set up email authentication for their domain. However, authentication can affect message forwarding.

    Don’t modify message headers or message body for forwarded messages. If the body of the message is changed, messages won’t pass DKIM authentication and might be sent to spam.

    Other reasons that forwarded messages fail DKIM include: Modifying the mime boundaries, third-party software modifying the body of the message, expanding the message recipient using LDAP, and re-encoding the message.

    Gmail has strict authentication for frequently spoofed domains, such as eBay, PayPal, and Google. If your mail server modifies forwarded messages from these domains, Gmail might mark them as phishing. Forwarded messages from these domains have an Authentication-Results header that shows DKIM failed. Messages sent directly to Gmail from these domains pass DKIM.

    Forwarding with a mail provider

    To prevent spam from being forwarded to Gmail, update your mail provider’s forwarding settings. If you can’t modify the forwarding settings, contact the mail provider for help.

    Your users can update their Gmail Accounts settings to prevent Gmail from displaying a phishing warning for forwarded messages. In the Accounts tab, enter the email address being forwarded to the Send mail as setting. For detailed instructions, go to Send emails from a different address or alias.

  • [Wayback/Archive] Prevent spam, spoofing & phishing with Gmail authentication – Google Workspace Admin Help

    Set up SPF, DKIM & DMARC for your organization

    Important: Starting November 2022, new senders who send email to personal Gmail accounts must set up either SPF or DKIM. Google performs random checks on new sender messages to personal Gmail accounts to verify they’re authenticated. Messages without at least one of these authentication methods will be rejected or marked as spam. This requirement doesn’t apply to you if you’re an existing sender. However, we recommend you always set up SPF and DKIM to protect your organization’s email and to support future authentication requirements.

  • [Wayback/Archive] Send emails from a different address or alias – Gmail Help
    If you own another email address, you can send mail as that address. For example:
    • •Yahoo, Outlook, or other non-Gmail address
    • •Your work, school, or business domain or alias, like @yourschool.edu or youralias@gmail.com
    • •Another Gmail address
    Tip: You can send emails from up to 99 different email addresses.
  • [Wayback/Archive] Working around SPF problems delivering to Gmail | End Point Dev
    We recently discovered that Gmail has been misusing email header information in its SPF checks.
    When one of our outgoing emails originated from server dashboard.endpointdev.com and was then forwarded to maildrop.endpointdev.com which then delivered it to Gmail, Gmail looked at the earliest sender server it could find in the Received headers of the email message, found dashboard.endpointdev.com, and flagged it as an SPF failure because our SPF policy didn’t include dashboard.endpointdev.com [206.191.128.233].
    This can be seen in this excerpt of relevant email headers. (Some specific details here were changed to protect the innocent.) Note that email headers appear in reverse chronological order, so the most recent events are at the top:
    Received: from maildrop14.epinfra.net (maildrop14.epinfra.net. [69.25.178.35])
            by mx.google.com with ESMTPS id l20si5561179oos.78.2022.01.25.10.52.05
            for <notifications@endpointdev.com>
            (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);
            Tue, 25 Jan 2022 10:52:05 -0800 (PST)
    Received-SPF: fail (google.com: domain of notifier@endpointdev.com does not designate 206.191.128.233 as permitted
        sender) client-ip=206.191.128.233;
    Authentication-Results: mx.google.com;
           dkim=pass header.i=@endpointdev.com header.s=maildrop header.b=hR445V77;
           spf=fail (google.com: domain of notifier@endpointdev.com does not designate 206.191.128.233 as permitted
        sender) smtp.mailfrom=notifier@endpointdev.com
    Received: from dashboard.endpointdev.com (dashboard.endpointdev.com [206.191.128.233])
        by maildrop14.epinfra.net (Postfix) with ESMTP id A2AA03E8A7
        for <notifications@endpointdev.com>; Tue, 25 Jan 2022 18:52:05 +0000 (UTC)
    To: <notifications@endpointdev.com>
    
    That is wrong! The SPF check should have been done against maildrop14.epinfra.net [69.25.178.35] because that is the IP address that actually connected to Gmail to send the email. That server is one of our infrastructure hostnames allowed to send email as part of the maildrop.endpointdev.com DNS record, so checking it would have led Gmail to give a passing SPF result.
    Why did Gmail do this? I don’t know, and at the time didn’t find any public discussion that would explain it. I suspect it has something to do with Gmail’s internal systems being comprised of many, many servers, and the SPF check being done long after the email was passed on from the initial receiving point through various other servers. Then Gmail parses the headers to find out who the sender was, and gets confused.
  • [Wayback/Archive] SPF, SRS rewriting and how it affects forwarding email – Pobox

    SPF stands for Sender Policy Framework.  It is an authentication check on the envelope sender.  That is: it asks, “Is this computer allowed to send mail from this address/domain?”  It is not a reputation check; it is just supposed to prevent or reduce the likelihood that a message is forged.

    What does this mean for email forwarding?  Well, a lot, actually!  When Pobox forwards mail to your forwarding address, your ISP may do an SPF lookup.  If the domain that the message came from published an SPF record, our servers definitely wouldn’t be in it!  So, if we forwarded the message using the original envelope sender, the mail we are forwarding to you could get rejected.

    Instead, we SRS rewrite the envelope sender, so that it will come from @pobox.com.  Basically, that means that we take the original sender address, and (with some modifications) make that the username portion of an email address @pobox.com.  That way, the SPF lookup your ISP will do is on @pobox.com, instead of the domain of the sender.   But, if your ISP rejects the message for another reason, like your account being over quota, we can still reverse the address, and send the bounce message back to the original message sender.

    You can maintain either a cache or a temporal list of SRS return addresses in order not to store an ever increasing mapping of rewritten and original return addresses, or encode the original return address in the rewritten return-path.

  • [Wayback/Archive] Can I stop a SPF SOFTFAIL in Gmail when sending to and from addresses that have a mail alias? – Server Fault (thanks [Wayback/Archive] Richard and [Wayback/Archive] Appleoddity)

    Q

    I have a vanity domain (mydomain.com) hosted by Gandi and configured with mail aliases for my family that point to our respective Gmail addresses:

    Alias Real address
    me@mydomain.com me5678@gmail.com
    mybrother@mydomain.com brother1234@gmail.com

    and so on.

    Gmail is configured to send email as the vanity address and I also have a SPF record set up:

    v=spf1 include:_spf.google.com include:_spf.gpaas.net include:_mailcust.gandi.net ?all
    

    Although mail-tester.com reports that the SPF is set up correctly, it’s possible to get a SOFTFAIL when sending an email from [anyone]@mydomain.com to [anyone else]@mydomain.com:

    Sent from Sent to SPF result of email
    me5678@gmail.com brother1234@gmail.com PASS
    me5678@gmail.com mybrother@mydomain.com PASS
    me@mydomain.com brother1234@gmail.com PASS
    me@mydomain.com mybrother@mydomain.com SOFTFAIL

    Is there any way I can stop emails sent from mydomain.com to another address at mydomain.com failing SPF?

    A

    You can see that the mail was received from a Gandi server:

    Received: from relay10.mail.gandi.net (relay10.mail.gandi.net. [2001:4b98:dc4:8::230])
    

    You can see that the Gandi servers are not authorized in the SPF record:

    Received-SPF: softfail (google.com: domain of transitioning me5678@gmail.com does not designate 2001:4b98:dc4:8::230 as permitted sender)
    

    SPF checks against the return-path header. Not the mailfrom header. The return-path is me5678@gmail.com. Therefore, gmail.com SPF records do not permit Gandi servers to send email using a return-path with gmail.com email addresses.

    SPF is functioning normally. What you are seeing is an inherent weakness in the SPF protocol regarding mail forwarding. When mail is forwarded at the MTA (mail server) level, the mailfrom and return-path headers are not rewritten (nor should they be), but when the forwarded mail reaches the recipient’s email server it is coming from the forwarding server, and not from the sender’s original e-mail server. Therefore, the recipient’s email server checks SPF and sees that the return-path domain does not authorize the forwarding email server to send mail.

    Forwarding breaks SPF. Because you do not control the SPF records for the gmail.com domain, you can not authorize Gandi servers to forward mail on gmail’s behalf. This is why SPF cannot be used, alone, to determine if mail is authorized or not.

    C

    An update: Due to other issues, I recently moved my mail forwarding away from Gandi to forwardemail.net. The emails that were previously getting a SPF SOFTFAIL now all get PASS, suggesting that Gandi wasn’t doing something right.

    Note that the last comment is wrong: header Return-Path rewriting fixes the SPF problem. But I didn’t known that back then. Now I know it is called Sender Rewriting Scheme, but note:

    Please note : Using SRS protocol fails the SPF Alignment check for your DMARC record, and it’s by design. Your DMARC record can still pass with a DKIM check.

  • [Wayback/Archive] Email forwarding to Gmail and SPF – Web Applications Stack Exchange (thanks [Wayback/Archive] daunpunk and [Wayback/Archive] K7AAY) suggest lowering security which I don’t like

    Q

    I have a domain with webmail on Gandi. I use that address for work. I set up mail forwarding to a personal Gmail address. Sometimes emails sent to my work address get bounced.

    A

    I solved it by lowering security in Gmail, following instructions (IIRC) I found at Google. which I am having trouble finding now. There is an active case https://support.google.com/accounts/thread/16039385?hl=en you could follow, or step through their eleven-item list at https://support.google.com/accounts/thread/6071257?hl=en then post a support request of your own, titled something like email forwarded from my domain hosted elsewhere bounces when it reaches gMail.

  • [Wayback/Archive] Automatically forward Gmail messages to another account – Gmail Help (which was my alternative plan in case none of the above worked: ensure everything ends up in one Gmail box then handle it from there)

Queries

--jeroen

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.