Genues / opensmtpd-filter-replace-from_reply

This is a simple OpenSMTPD filter for overwriting the email address in the MAIL FROM command, in the header in all sent messages, as well as for substituting the original MAIL FROM address in the Reply-To field. Designed to send all relayed messages from a given email address (for example no-reply@example.com).
MIT License
0 stars 1 forks source link

Filter goes into recursive loop if transaction fails #1

Closed iambesi closed 2 months ago

iambesi commented 2 years ago

Hello @Genues,

First and foremost, I thank for taking the time to create this OpenSMTPD filter. From what I have seen, it seems to have the potential to do what I need. Generally speaking, said filter seems to be working and modifying the MAIL-FROM and From headers; however, I am running into an issue. To give you a bit of background, what I am looking to do is send e-mails locally between a few users, but also, allow relaying of e-mails via an authenticated Yahoo! (or similarly Google) account. These two services are very picky when it comes to authentication and headers, which is where your script comes into the picture as I am trying to use it to fix that issue.

The problem, however, is that when the sent e-mail fails to be delivered and a Mailer Daemon response is sent, the filter seems to go into a recursive email-sending loop. Whilst I am not a proper developer or an expert in SMTP, my theory is that either the Mailer Daemon is falsely triggering the filter to generate a new e-mail (that is, trying to answer the failed e-mail reply) or the fact that the Mailer Daemon contains the original message, it is trying to resend itself again and again. As I said, I am not a proper developer, but looking at your Go script, I see that it scans the buffer IO in an infinite loop (as per the definition of filters), but it simply seems to look for mail-from and data-line requests.

Nevertheless, it feels like there should be some sort of logic there to read I suppose a tx-rollback event (I believe that is triggered when an e-mail transaction fails) or similar so that it can a) stop processing data, b) instruct OpenSMTPD to proceed, and then, c) go into an idle (or better said, wait state) until it receives a mail-from request from a new message. I was trying to think how to write this on my own, but the problem is that 1) I am not a proper developer, 2) I cannot seem to find a proper example on basic filter writing to see how to read an event or a basic filter for that matter, and 3) the documentation for OpenSMTPD seems to be a bit lacking to me.

Whilst Gilles Chehade seems really good at writing articles and explaining the theory behind his work, he never seems to provide a few here-is-how-you-get-started sort of examples. In short, when I came across OpenSMTPD I thought that I had hit the jackpot in terms of an alternative to postfix; but sadly, I cannot seem to get off the ground. That being said, I hope that you can offer some insight or help.

Thanks and regards, iambesi

Genues commented 2 years ago

@iambesi hi! I use this filter in my production on five different servers and not have problem, when send email to bad address for example. Need more information about this problem to understand what happened. May be problem with local address? Check without this. Run OpenSMTPD in debug mode. I am not a proper developer too :) Exactly for OpenSMTPD on Go language it my first experience. Thank you.

iambesi commented 2 years ago

Hello @Genues,

Thanks for your response. So you say that you are using this in production on five different servers? Hmm … now I am nervous that I am doing something dumb in my setup. :-( Let me give you more information on it in hopes that you spot something wrong.

I am running Oracle Enterprise Linux (OEL) 8.3 with kernel 5.4.17-2102.201.3.el8uek.x86_64 in a test environment with OpenSMTPD 6.8.0p2 installed. My current /etc/opensmptd/smtpd.conf file looks like this:

#   $OpenBSD: smtpd.conf,v 1.10 2018/05/24 11:40:17 gilles Exp $

# This is the smtpd server system-wide configuration file.
# See smtpd.conf(5) for more information.

filter "replace-from_reply" proc-exec "/etc/opensmtpd/opensmtpd-filter-replace-from_reply-dbg --mailFrom={user}@yahoo.com"
listen on socket filter "replace-from_reply"

table aliases file:/etc/aliases

# Tables

table creds   "/etc/opensmtpd/creds"
table vdoms   "/etc/opensmtpd/vdoms"
table vusers  "/etc/opensmtpd/vusers"
table secrets "/etc/opensmtpd/secrets"

# To accept external mail, replace with: listen on all

listen on localhost

action "local_mail" mbox alias <aliases>
action "outbound" relay host smtp+tls://relay@smtp.mail.yahoo.com:587 \
       auth <secrets> 

# Uncomment the following to accept external mail for domain "example.org"

match for local action "local_mail"
match from local for local action "local_mail"
match from local for any action "outbound"

--

As for the specific issue, when I run smtpd -dv > dbg.log 2>&1 (in order to capture the debug information to a file), everything works perfectly fine if the test e-mail is sent successfully. However, if the e-mail delivery fails, the log file just keeps growing and growing until I press Ctrl + C to kill the smtpd process.

Since I could not figure out what was going on, I decided to use my limited developer skills and add some logging to your filter script, which logs the information to a file called filter.log . For your reference, I have included a modified copy, opensmtpd-filter-replace-from_reply-dbg.go, of your Go script. Looking at the logged information, I see where my initial e-mail delivery attempt is made, and then, when it fails my test domain receives the Mailer Daemon’s delivery status notification as expected.

After that, however, it almost seems as if the filter is trying re-process and send the e-mail received from the mailer daemon. And then, it tries to do it again and again in an endless loop – until I break it by pressing Ctrl + C or I pause the MTA and remove the envelope / message. To try to give you a better idea, I have included a copy of my dbg.log and filter.log files for review. I replaced the e-mail user with {user} and added ‘---’ for better readability (I hope). With that said, do you have any thoughts? That is, am I doing something dumb here?

Thanks, iambesi

dbg.zip

Genues commented 2 months ago

hi If it's still relevant, then I've added a change that I think should solve the problem.