ValiMail / authentication-headers

library for the generation of email authentication headers
Other
16 stars 4 forks source link

The check_dmarc method can fail to find a From: domain #32

Closed msapiro closed 9 months ago

msapiro commented 9 months ago

A message with a From: header like

From: "Txxxxxx Mxxxxxxx de Vxxxxxx, Fxxxxxxxx" <fxxxxxxxx.txxxxxx@subd.example.net>

when flattened as_bytes and passed to check_dmark will have the header folded as

From:  "Txxxxxx Mxxxxxxx de Vxxxxxx,
  Fxxxxxxxx" <fxxxxxxxx.txxxxxx@subd.example.net>

While this is reported as a bug at https://github.com/python/cpython/issues/114362, it is compliant with RFC 5322 which allows FWS within a quoted string. In any case the code acting on this does the following:

headers, _ = rfc822_parse(msg)

which returns one of the elements in the headers list as

[b'From', b' "Txxxxxx Mxxxxxxx de Vxxxxxx,\r\n Fxxxxxxxx" <fxxxxxxxx.txxxxxx@subd.example.net>\r\n']

and then

from_headers = [a[1] for a in getaddresses(x[1].decode(errors='ignore').strip() for x in headers if x[0].lower() == b"from")]

yields

['Txxxxxx Mxxxxxxx de Vxxxxxx,']

as from_headers.

One way to fix this is to change

from_headers = [a[1] for a in getaddresses(x[1].decode(errors='ignore').strip() for x in headers if x[0].lower() == b"from")]

to

from_headers = [a[1] for a in getaddresses(x[1].replace(b'\r\n', b'')
    .decode(errors='ignore').strip() for x in headers
    if x[0].lower() == b"from")]

to unfold the header value before passing it to getaddresses. Normally getaddresses handles folded headers, but I think folding with \r\n is an issue.

kitterma commented 9 months ago

Thanks. Applied your suggested fix in git.

kitterma commented 9 months ago

Fixed in 0.16.2.