sdgathman / pysrs

Other
4 stars 3 forks source link

Multiple .forward aliases sometimes give pysrs the wrong destination domain. #7

Open asciipip opened 5 years ago

asciipip commented 5 years ago

If a person has a .forward file in their home directory and that .forward file contains multiple email addresses with different domains, pysrs will sometimes get the domains mixed up.

e.g. if the .forward file contains this:

person@example.com, person@example.edu

Sometimes the SRS address for the email sent to person@example.edu will use the hash for person@example.com.

This is particularly problematic when one of the addresses is local, e.g.

\person, person@example.com

In that case, sometimes the email to person@example.com doesn't have a destination domain, so pysrs simply doesn't do SRS on the address. (And that, of course, causes problem if the destination domain does SPF checking.)

Sometimes things do work, but sometimes they don't. If I understand the process correctly (and this is the first time I've delved past sendmail.mc into sendmail.cf rules), I suspect that the order in which sendmail is running the EnvFromSMTP ruleset and ruleset zero is non-deterministic. I'm hoping you have a deeper understanding of this level of communication, though.

I'm running pysrs on Scientific Linux 6 (a RHEL 6 clone). /wtc/mail/sendmail.cf contains (excerpted):

MAILER(smtp)dnl
define(`NO_SRS_FILE',`/etc/mail/no-srs-mailers')dnl
HACK(`pysrs',`/var/run/milter/pysrs')dnl

Here's an excerpt from pysrs.log, with domains sanitized:

2018Nov19 11:32:28 make_srs example.com.�phil<@sender.com.>
2018Nov19 11:32:28 h = example.com.
2018Nov19 11:32:28 OK SRS0=dWVaj=N6=sender.com=phil<@forwarder.com.>
2018Nov19 11:32:30 make_srs example.com.�phil<@sender.com.>
2018Nov19 11:32:30 h = example.com.
2018Nov19 11:32:30 OK SRS0=dWVaj=N6=sender.com=phil<@forwarder.com.>

Although the .forward file for the account on "forwarder.com" contained two email addresses with different domains, only one domain was used for both message forwards.

sdgathman commented 5 years ago

pysrs operates on MAIL FROM. RCPT TO doesn't come into the picture, and hasn't even been seen yet when your logs are output. The default pysrs.cfg has comments that hopefully describe how to control MAIL FROM rewriting.

In trying to guess what you were thinking, I considered that perhaps you were hoping there was a way to configure MAIL FROM rewriting based on RCPT TO. srsmilter knows the recipients, but has a different problem, as noted in the comments:

# The logical problem is that a milter gets to change MFROM only once for
# multiple recipients.  When there is a conflict between recipients, we
# either have to punt (all SRS or all no-SRS) or resubmit some of the
# recipients to "split" the message.
sdgathman commented 5 years ago

I suggest you describe what you are trying to do on the pymilter@gathman.org mailing list, and we can give some suggestions.

asciipip commented 5 years ago

I think I have some more time to work on this now. I think I abstracted my problem description too much here initially. My main problem is what happens when my mail server receives a message with both local and remote recipients. In that case, sometimes PySRS does not rewrite the envelope-from address, which causes problems when sendmail forwards the message.

More concretely, let's say a message comes in to my server. Let's say it's MAIL FROM:<sender@origin.com> with two recipients: RCPT TO:<person1@dest.com> and RCPT TO:<person2@dest.com>. Person 2 has a .forward file which sends all of their email to person2@gmail.com.

I'm using HACK(`pysrs',`/var/run/pilter/pysrs') in my sendmail.mc file. The pysrs.m4 file attaches a call to the MakeSrs ruleset to the EnvFromSMTP ruleset. I'm allowing SRS from local addresses and my NO_SRS_FILE is empty, so the MakeSrs ruleset is:

R$*     $: $&h $| $1
R$*     $: $(make_srs $1 $)

If I understand that correctly, it first takes the envelope-from address and prepends the $h macro and a separator character ($|) to it. $h is "The recipient host. This is set in ruleset 0 from the $@ field of a parsed address." Then it passes that modified address through the socket to PySRS and waits for a response.

I can see in the PySRS log the requests that are made of it. With the above example, sometimes I see this:

2019Feb18 16:22:06 make_srs gmail.com.�sender<@origin.com.>
2019Feb18 16:22:06 h = gmail.com.
2019Feb18 16:22:06 OK SRS0=dWVaj=N6=dest.com=sender<@dest.com.>

and sometimes I see this:

2019Feb18 16:22:06 make_srs �sender<@origin.com.>
2019Feb18 16:22:06 h = 
2019Feb18 16:22:06 OK sender<@origin.com.>

I believe what's happening is that the $h macro is being set to whichever recipient sendmail processed last, even when it doesn't line up with the recipient that sendmail is delivering to at the moment. This is most damaging when the last recipient was a local delivery, because it means that the address is not rewritten at all even when the message is being forwarded.

Does that make my problem any clearer?

asciipip commented 5 years ago

I worked around the problem by just removing the or not h test on line 47 of pysrs.py. I guess that test was an attempt to avoid unnecessary rewriting for messages that were being delivered locally, but as far as I can tell the EnvFromSMTP ruleset (and, thus, the MakeSrs ruleset) is only called when a message is forwarded, so local deliveries are already filtered out. In any case, even if it were rewriting addresses unnecessarily, I'd prefer that over sometimes not rewriting addresses when forwarding.

sdgathman commented 5 years ago

I will try your tweak to see if anything breaks. So you have local mailboxes on the same mailserver that forwards outgoing mail? That would explain why I haven't seen the problem. I always have a separate "mail gateway" VM that doesn't deliver anything locally (except root notifications).

sdgathman commented 5 years ago

I think that with your tweak, you will still have the problem if one of the alias recipient domains is in nosrsdomain. Sendmail is kind enough to run the ruleset for every RCPT TO, but apparently not for every recipient generated by aliasing.