ValiMail / authentication-headers

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

DNS exceptions cause errors to throw (since they are not DKIMException) #18

Closed niftylettuce closed 3 years ago

niftylettuce commented 4 years ago

For example, this code does not catch the following errors:

def check_dkim(msg, dnsfunc=None):
    try:
        d = DKIM(msg)
        if(dnsfunc):
            res = d.verify(dnsfunc=dnsfunc) and 'pass' or 'fail'
        else:
            res = d.verify() and 'pass' or 'fail'
    except DKIMException as e:
        res = 'fail'
niftylettuce commented 4 years ago

I think that instead of catching them as failures, the best approach is tempfail.

niftylettuce commented 4 years ago

I propose the following fix:

def check_dkim(msg, dnsfunc=None):
    try:
        d = DKIM(msg)
        if(dnsfunc):
            res = d.verify(dnsfunc=dnsfunc) and 'pass' or 'fail'
        else:
            res = d.verify() and 'pass' or 'fail'
    except DKIMException as e:
        res = 'fail'
+    except DNSException as e:
+        res = 'tempfail'
+    except Exception as e:
+        res = 'fail'

    header_i = d.signature_fields.get(b'i', b'').decode('ascii')
    header_d = d.signature_fields.get(b'd', b'').decode('ascii')

    return DKIMAuthenticationResult(result=res, header_d=header_d, header_i=header_i)
niftylettuce commented 4 years ago

See https://github.com/forwardemail/authentication-headers/commit/b123501bd8e5998a52b52978dc39e0f263311607.

niftylettuce commented 4 years ago

I have also similarly added a fix here:

def check_arc(msg, logger=None, dnsfunc=None):
    """ Compute the chain validation status of an inbound message.
    @param msg: an RFC822 formatted message (with either \\n or \\r\\n line endings)
    @param logger: An optional logger
    @param dnsfunc: An optional dns lookup function (intended for testing)
    """

    a = ARC(msg)
    try:
        if(dnsfunc):
            cv, results, comment = a.verify(dnsfunc=dnsfunc)
        else:
            cv, results, comment = a.verify()
    except DKIMException as e:
        cv, results, comment = CV_Fail, [], "%s" % e
+    except DNSException as e:
+        cv, results, comment = CV_Fail, [], "%s" % e
+    except Exception as e:
+        cv, results, comment = CV_Fail, [], "%s" % e

    return ARCAuthenticationResult(result=cv.decode('ascii'))
niftylettuce commented 4 years ago

See <https://github.com/forwardemail/authentication-headers/commit/54d1bc2d312baa1c8ea9159d7801417749ab746a.

niftylettuce commented 4 years ago

Correction to my earlier comment here https://github.com/ValiMail/authentication-headers/issues/18#issuecomment-670843354:

def check_dkim(msg, dnsfunc=None): try: d = DKIM(msg) if(dnsfunc): res = d.verify(dnsfunc=dnsfunc) and 'pass' or 'fail' else: res = d.verify() and 'pass' or 'fail' except DKIMException as e: res = 'fail'

  • except DNSException as e:
  • res = 'tempfail'
  • except Exception as e:
  • res = 'fail'

    header_i = d.signature_fields.get(b'i', b'').decode('ascii') header_d = d.signature_fields.get(b'd', b'').decode('ascii')

    return DKIMAuthenticationResult(result=res, header_d=header_d, header_i=header_i)

Instead of tempfail it should just be fail. Also, we might just want to consolidate it into one line except Exception as e to catch-all exceptions for dummy-proofing.

kitterma commented 3 years ago

I think you've got it right here. According to https://www.iana.org/assignments/email-auth/email-auth.xhtml#email-auth-result-names there is no temporary error result fro ARC.

kitterma commented 3 years ago

For DKIM, it does have a temperror, so I think that's fine the way you have it.

kitterma commented 3 years ago

Fixed in https://github.com/ValiMail/authentication-headers/commit/b36571421cbadc00eebb3b27dd62f6f2d7e51ee9 .