Forwarding mail to gmail (how SPF broke forwarding)

As a mail server admin, I have a few users where their accounts don’t do anything but forward their email on to other addresses. It can be because they prefer the convenience of gmail/have an Android device or because they are still receiving email on a domain they own and don’t want to check multiple accounts.

The old fashioned way to do this was very simple, you created a file called .forward in their home directory, containing the email address you’d like their email forwarded to.

Enter SPF. SPF allows you to designate in your DNS records which SMTP servers are allowed to send email for a domain. If the owner of the domain you’re forwarding to decides to bounce or limit email based on SPF pass/fails, then you’re screwed because your forwarding server won’t be a permitted sender for all the domains you receive email from. gmail of course now does this.

One proposed fix is to use a rather convoluted tool called SRS to rewrite the email before it’s forwarded. I checked this out on my Debian Wheezy mailserver (using Postfix) and found it rather fragile in its complexity, I did not like that creating additional aliases is required, not to mention that people seem to advocate it as an MTA plugin when I’d consider rewriting and forwarding mail to be the job of the delivery agent.

Simple Solution

The simplest solution to this problem is to rewrite the envelope sender prior to forwarding (that’s the first From line of the email). By rewriting the sender to the account you are forwarding for and having SPF records for your domain, you will get an SPF pass from gmail for your forwarded email.

I use procmail as my delivery agent, here’s a procmail script to rewrite the envelope sender:

| /root/bin/overridefrom.py test@example.com

! bobtoast@gmail.com

This has procmail call out to a python script called overridefrom.py, telling it to replace the envelope sender with test@example.com. Once the sender has been rewritten, the mail is forwarded on to a gmail account. Note that changing the envelope sender does not affect the From: header that mail user agents display.

The code for the python script is here:

#!/usr/bin/env python
import sys
mail = sys.stdin.readlines()
REWRITE_ADDRESS = "default@ifnotsupplied.org"
if len(sys.argv) > 1:
    REWRITE_ADDRESS = sys.argv[1]
if mail[0].startswith("From "):
    bits = mail[0].split(" ", 2)
    mail[0] = "From %s%s" % (REWRITE_ADDRESS, bits[2])
print "".join(mail)