forwardemail.net icon indicating copy to clipboard operation
forwardemail.net copied to clipboard

[feat] relay server support

Open rhansen opened this issue 9 months ago • 4 comments

Describe the feature

Currently, forwardemail.net only supports forwarding to an email address in a different domain (the original envelope recipient is transformed to a different address). When forwarding, forwardemail.net does the usual MX lookup for the transformed destination domain and uses SMTP to send it to an appropriate server.

I want forwardemail.net to support a new operating mode: relaying. This is almost identical to forwarding, with the following differences:

  • The envelope recipient is unchanged.
  • Instead of performing an MX lookup on the recipient domain to find the next hop (which would cause a routing loop to itself because the envelope recipient is unchanged), forwardemail.net would use an explicitly configured server as the next hop.
  • As a configurable option, forwardemail.net would use RFC 6409 message submission to port 587 or 465 instead of the usual SMTP to port 25.
  • Ideally, forwardemail.net would use the Postfix XFORWARD command when relaying a message (assuming the destination server advertises support).

I believe this feature request is a duplicate of https://github.com/forwardemail/free-email-forwarding/issues/284 which has been archived.

Example

  1. outgoingsmtp.sender.examplemx1.forwardemail.net:
    1. MAIL FROM:<[email protected]>
    2. RCPT TO:<[email protected]>
  2. mx1.forwardemail.netreceivingsmtp.recipient.example:587
    1. STARTTLS
    2. AUTH PLAIN <base64>
    3. XFORWARD (optional, but preferred)
    4. MAIL FROM:<[email protected]>
    5. RCPT TO:<[email protected]>

The above can be achieved in Postfix with a configuration that includes something like the following in main.cf:

relay_domains = recipient.example
transport_maps = inline:{
    recipient.example=relay:[receivingsmtp.recipient.example]:submission
  }
smtp_tls_policy_maps = inline:{
    [receivingsmtp.recipient.example]:submission=verify
  }
smtp_sasl_password_maps = inline:{
    [receivingsmtp.recipient.example]:submission=username:password
  }
smtp_send_xforward_command = yes

Motivation

This feature would make it possible to adopt forwardemail.net as a drop-in frontend for an existing MX setup. All a new customer would need to do is:

  1. Sign up for forwardemail.net
  2. Tell forwardemail.net to relay recipient.example emails to the existing receivingsmtp.recipient.example:25 server
  3. Optionally tell forwardemail.net to relay via submission as an authenticated user:
    1. Create a submission-only account called forwardemail on receivingsmtp.recipient.example
    2. Configure receivingsmtp.recipient.example to listen on port 587 (submission)
    3. Update the forwardemail.net configuration to relay to receivingsmtp.recipient.example:587 with username forwardemail and the appropriate password
  4. Configure receivingsmtp.recipient.example to accept emails from forwardemail.net's mail servers (SRS should make this a no-op)
  5. Optionally set up outgoing email from *@recipient.example to relay through forwardemail.net
  6. Change MX records for recipient.example to return forwardemail.net's MX servers
  7. Update SPF records if necessary

Checklist

  • [x] I have searched through GitHub issues for similar issues.
  • [x] I have completely read through the README and documentation.

rhansen avatar Apr 05 '25 01:04 rhansen

How is this different from existing setup where you just put the domain as the forwarding recipient?

e.g. forward-email=yourotherdomain.com (or similarly in the UI setting the Forwarding Recipient to "yourotherdomain.com")

titanism avatar Apr 09 '25 17:04 titanism

@titanism I updated the original post to clarify.

rhansen avatar Apr 12 '25 23:04 rhansen

Just to re-iterate and confirm, is this about what you're looking for:

  • Don't rewrite the RCPT TO envelope address
  • Don't do MX lookup → use preconfigured "next-hop" server
  • Optionally connect to ports 587 or 465 (secure submission ports), not only port 25
  • Use SMTP AUTH if credentials are supplied (still need to think through this one)
  • Try using the XFORWARD extension if supported by destination

I guess the biggest risk is this becoming an open relay and that would make reputation management even harder.

Some other items to think about 🤔

  • Force all relayed domains to be verified (we already do this for normal forwarding, but need to double-check)
  • Only allow relaying if next hop server is configured explicitly
  • Possibly rate-limit relay deliveries per domain/user
  • Protect against mail loops (e.g., with Received: header counting or hop limit)

shaunwarman avatar Apr 26 '25 16:04 shaunwarman

Just to re-iterate and confirm, is this about what you're looking for:

Yes, exactly.

I guess the biggest risk is this becoming an open relay and that would make reputation management even harder.

The recipient address is guaranteed to be *@recipient.example (otherwise forwardemail.net would not match the customer record) so I don't think an open relay is possible. I guess if the spammer figures out the next hop's SRS secret (or similar address rewriting scheme) then it could become an open relay, but that's not a new problem—forwardemail.net already has that risk right now.

Some other items to think about 🤔

  • Only allow relaying if next hop server is configured explicitly

Do you mean the forwardemail.net account is configured explicitly? Or do you mean the next hop mail server is configured explicitly? The next hop server shouldn't need any special configuration except maybe:

  • Create a username+password if secure submission is desired
  • Disable SPF checks on messages coming via forwardemail.net unless forwardemail.net does SRS for this case. (Typically secure submission already disables SPF and other spam checks.)
  • Enable XFORWARD if desired

Some other things to think about:

  • Allow both specific address relaying ([email protected]) and default/wildcard relaying (*@recipient.example). I personally only need default relaying.

  • Reject messages if forwardemail.net's MX servers aren't included in the MX records for the recipient domain. (Is this what you mean by verifying the domain?) This prevents a spammer from attempting to set up gmail.com to relay to gmail-smtp-in.l.google.com and leveraging forwardemail.net's reputation to spam Gmail users, for example.

  • Support mixing forwarding and relaying modes for the same domain. E.g., [email protected] forwards to [email protected], and everything else relays to the SMTP server receivingsmtp.recipient.example. I personally don't need this.

  • Another configurable option: do an MX lookup for a different domain and relay to that instead of a specific preconfigured server. For example, for recipient [email protected], the UI could allow the customer to choose one of the following:

    • Forward to this address: ________________________
    • Relay to this SMTP or secure submission server: ________________________ (to avoid a routing loop, this must not be one of forwardemail.net's MX servers)
    • Relay to an MX server for this domain: ________________________ (to avoid a routing loop, this must not be recipient.example)

    I imagine most users won't use that third option (I wouldn't) so it might be best to omit that option to reduce user confusion until a customer requests it.

rhansen avatar Apr 26 '25 20:04 rhansen