3

I'm trying to find a way to have my Postfix server appear to reject emails from particular envelope senders while still delivering those same emails to their intended recipients.

Microsoft's email servers keep repeatedly blacklisting my mailserver's IP address, rejecting emails from my server with a message advising to

Please contact your Internet service provider since part of their network is on our block list (S3150).

Three times now over the past few months both I and my hosting provider have verified that no suspicious activity is originating from my very low volume mailserver and that it is properly configured with reverse DNS, SPF, and DKIM records, does not appear on any public blacklists, and has no issues sending mail to other large email provider domains such as gmail and yahoo.

My provider has been very helpful in jumping through Microsoft's hoops to successfully attain "mitigation" 3 times thus far, briefly allowing me to again correspond with the one person I regular email on one of their domains, but each time this mitigation has proved temporary and the situation soon recurs.

As I've gotten tired of playing this pointless game, I've given this one regular correspondent an account on my mail server that we now use to exchange emails, cutting MS out of the picture.

Since my email history shows this to be the only MS "customer" I've corresponded with over the last few years, rather than continuing to jump through MS's hoops repeatedly I'd like instead to appear to reject messages from MS's mailservers with an appropriate reject message that lets the senders know that I will not be able to respond to them because MS keeps censoring my mailserver for no apparent reason.

Since I cannot reply to any such emails, this seems to only way to get that information to them. At the same time, however, I would like to be able to see what any such senders wrote in case it is someone I know who has changed email providers or been out of touch for awhile.

So, can anyone tell me if such a thing is possible using Postfix and if so the best way to configure it?

Rich
  • 51
  • The way your wrote this is silly. When calling out Microsoft, call out Microsoft. Don't find cute alternative names or abbreviations. Microsoft isn't Voldemort. You can say its name. – Marcus Müller Apr 15 '23 at 18:14
  • Sorry, was just trying to lighten it up a bit. – Rich Apr 15 '23 at 19:05
  • 1
    I might just be co-frustrated by the same issue with live.com/hotmail.com rejecting basically any email account I have but for the GMail account that I need to use my android phone and basically never use for email these days. – Marcus Müller Apr 15 '23 at 19:08
  • Not surprised. My hosting provider said Microsoft was notorious for this. Maybe no coincidence I had only one regularly active correspondent still using them. – Rich Apr 15 '23 at 19:49
  • Interestingly I no longer have the issue with Microsoft, but I do with Gmail – Chris Davies Apr 15 '23 at 21:40

2 Answers2

2

After more research and experimentation, I've arrived at one solution that appears to be working so far.

I followed the approach described at http://www.postfix.org/SMTPD_PROXY_README.html, editing master.cf as the link shows and using socat via:

socat tcp-l:10025,fork,bind=127.0.0.1 system:/path/to/filterscript.sh

to listen on 127.0.0.1:10025 and upon each connection launch an instance of a bash filter script that I wrote and which is posted below

Per the last section of the SMTPD_PROXY_README, my script simply relays the smtp commands and data coming to it from the before-filter Postfix smtp server back to Postix's after-filter smtp server at 127.0.0.1:10026, then returns (most of) the command responses it receives from the after-filter server back to the before-filter server.

However, if during this process the script saw a "MAIL FROM:" address ending with "@hotmail.com", then instead of fowarding the after-filter server's 250 success response back to the pre-filter server when the message is completed, it instead sends the pre-filter server a 550 reject code with a custom message. This causes Postfix's pre-filter server to report to hotmail that the message was rejected even though the post-filter server has actually delivered it.

Here's the script I used:

#!/usr/bin/bash

exec 4<>/dev/tcp/127.0.0.1/10026 # output back to postfix

export IFS='$\n'

function relay_smtp_responses { while read -r -t 1 -u 4 rline; do if [[ $rline == "221 "* ]]; then Finished=true else echo "$rline" fi done }

InDataMode=false Finished=false Reject=false

relay_smtp_responses # relay initial smtp greeting from after filter server back to before filter server

until "$Finished"; do if ! read -r -t 5 line; then # fetch line from before filter smtp server relay_smtp_responses echo -e "QUIT\r" >&4 exit fi echo "$line" >&4 # relay line to after filter smtp server if "$InDataMode"; then if [[ ${line%$'\r'} == "." ]]; then InDataMode=false if "$Reject"; then echo "550 5.7.1 Replies to you are blocked, see <insert link to customized error explanation here>" else relay_smtp_responses # relay post-filter's eom response back to pre-filter server fi fi else relay_smtp_responses # relay command response from after filter server back to pre filter server if [[ ${line%$'\r'} == "MAIL FROM:"*"@hotmail.com>" ]]; then Reject=true elif [[ ${line%$'\r'} == "DATA" ]]; then InDataMode=true fi fi done

Since bash's read command doesn't play well with binary data, I also had to disable the BDAT command by adding

smtpd_discard_ehlo_keywords = chunking

to the Postfix main.cf file. Using another language could likely avoid this.

I'm not yet sure how well my script will handle 8 bit data, but for now have not disabled 8BITMIME or SMTPUTF8 and encountered no problems.

Though it so far is doing what I wanted, this script is still mainly for proof of concept and I expect to enhance or replace it after more testing.

Any thoughts or suggestions would be welcome, and hopefully this information will help somebody.

Rich
  • 51
  • 1
    Been running an enhanced version of the above script for awhile without problems and it's doing what I wanted: telling the sender that their email was rejected (so they don't expect a reply Microsoft would block) while still delivering the email to me. I did change the check for a MAIL FROM: sender ending with "hotmail.com" to instead extract the originating mailserver's IP from the XFORWARD command and set the Reject flag if that IP is a valid SPF sender for hotmail.com. That way I likely catch other MS email domains that would also block any reply. So I'm accepting this solution. – Rich Apr 29 '23 at 16:04
  • Thanks! I was looking for exactly this, but built into Google Workspace (catch-all email to certain people in the workspace, but return rejection / undeliverable / 550 response)

    Seems to me like there would be some use cases for this: email addresses which are "deprecated" or have been updated. Instead of dropping the message, still forward it along.

    If anyone figures out how to do this in Google Workspace, please let me know

    – Karl Horky Feb 07 '24 at 16:13
0

Been where you are. Gave up. Advising you to do the same.

I'd like instead to appear to reject messages from MS's mailservers with an appropriate reject message that lets the senders know that I will not be able to respond to them because MS keeps censoring my mailserver for no apparent reason.

Chances are this won't work out the way you want.

If your email server could respond with a reply email, you could also directly deliver email.

So, all you can do is really modify the failure-to-deliver reason; one line that mustn't be too long.

That will just lead to Microsoft autogenerating an information that their customer's email could not be delivered to display to them. If I remember correctly, that email will contain that reject reason – but nobody, including me, reads these emails. "Email could not be delivered": fine. I need to consider whether I have the energy to dig up a different way of contacting the other side. Usually, things are not that important, and the person I was writing to will simply not get the info I was about to give them. I will certainly not be scrolling down to figure out whether their email server is misconfigured, disk full, doesn't work on full moons, or rejects people whose names are alliterations.

You cannot win armwrestling against Microsoft. That's not how this power dynamic is.

Regarding technical feasibility: Depends. Typically you'd configure postfix to reject as early as possible, i.e. as soon as that From: gets passed to your server, making it impossible to deliver the email, as it hasn't even been sent to your server at that point.

You can add a filter further down the line that internally makes a copy, rejects the original, and talks to local delivery agent to still put the email in the right inbox. As far as I'm aware, Postfix doesn't let you do the "deliver although rejected" – you need to write that postfix plugin yourself.

  • 1
    Thanks for the quick response. I do realize that the SMTP reject reason must be short. I was thinking to include a link to a more detailed explanation as MS does in their reject message. Perhaps you're right that nobody (aside from me anyway) reads the reject reasons, but at least the sender would not be left thinking that I was ignoring their email. And I'm not trying to beat Microsoft, just to let those who may write that I won't be able to reply while still seeing what they wrote in case it's important or interesting enough to seek out some alternative means of communication. – Rich Apr 15 '23 at 19:17
  • Re: the technical feasibility, I do understand that such a rejection would have to occur much later in the SMTP exchange than may be optimal. But given that Postfix does allow for filtering further down the line (I use one now based on the "From:" header), I'm hoping somebody might be able to point me to some examples of such a filter that demonstrates how to make the internal copy and arrange for its delivery. – Rich Apr 15 '23 at 19:25
  • If you had very technically inclined people emailing you, that link might help (but even less than trying to read the reject reason would I click on a link in one, which I partially ascribe to be technically proficient enough to be not expecting much useful info there; so… there's a really small chance that especially a hotmail or live.com user would read that link. – Marcus Müller Apr 15 '23 at 19:26
  • Re filter: as said, I think if your filter says "reject", you're not going to be able to convice postfix to still deliver things. If you wrote your own filtering plugin, then you could of course do whatever you please with that email, but it's not just "writing a filter"; the contract, as far as I understood postfix (it's been awhile) is that a filter is "drop" or "OK". – Marcus Müller Apr 15 '23 at 19:27
  • Thanks, sounds like I may have to start researching Postscript plugins. Used to do a fair amount of such custom stuff when I used Qmail but am fairly new to Postscript. – Rich Apr 15 '23 at 19:52