Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Detecting if an email is a "Delivery Status Notification" and extract information - Python

Tags:

python

email

I'm using the Python email module to parse emails.

I need to be able to tell if an email is a "Delivery Status Notification", find out what the status is, and extract information on the email that failed, eg. the Subject.

The object I get after parsing with .parsestr(email) is like this:

{'Content-Transfer-Encoding': 'quoted-printable',
 'Content-Type': 'text/plain; charset=ISO-8859-1',
 'Date': 'Mon, 14 Mar 2011 11:26:24 +0000',
 'Delivered-To': '[email protected]',
 'From': 'Mail Delivery Subsystem <[email protected]>',
 'MIME-Version': '1.0',
 'Message-ID': '<[email protected]>',
 'Received': 'by 10.142.13.8 with SMTP id 8cs63078wfm;\r\n        Mon, 14 Mar 2011 04:26:24 -0700 (PDT)',
 'Return-Path': '<>',
 'Subject': 'Delivery Status Notification (Failure)',
 'To': '[email protected]',
 'X-Failed-Recipients': '[email protected]'}

Firstly, how do I tell that this is a DSN without using a regexp on the subject?

Secondly, how do I access the body of the email, and information such as the error that was returned by the mail server?

edit: worked out I need to use .get_payload() to get the contents of the message.

The email docs say:

The Parser class has no differences in its public interface. It does have some additional smarts to recognize message/delivery-status type messages, which it represents as a Message instance containing separate Message subparts for each header block in the delivery status notification


Update:

Basically, I need to be able to reliable detect that an email is a DSN, and then also to extract the original message so I can parse that with email.Parser() and get information about it.

like image 764
Acorn Avatar asked Mar 14 '11 12:03

Acorn


1 Answers

The docs you cited says that the message is multi-part if it is DSN:

import email

msg = email.message_from_string(emailstr)

if (msg.is_multipart() and len(msg.get_payload()) > 1 and 
    msg.get_payload(1).get_content_type() == 'message/delivery-status'):
    # email is DSN
    print(msg.get_payload(0).get_payload()) # human-readable section
    
    for dsn in msg.get_payload(1).get_payload():
        print('action: %s' % dsn['action']) # e.g., "failed", "delivered"
        
    if len(msg.get_payload()) > 2:
        print(msg.get_payload(2)) # original message

Format of a Delivery Status Notification (from rfc 3464):

A DSN is a MIME message with a top-level content-type of
multipart/report (defined in [REPORT]).  When a multipart/report
content is used to transmit a DSN:

(a) The report-type parameter of the multipart/report content is
    "delivery-status".

(b) The first component of the multipart/report contains a human-
    readable explanation of the DSN, as described in [REPORT].

(c) The second component of the multipart/report is of content-type
    message/delivery-status, described in section 2.1 of this
    document.

(d) If the original message or a portion of the message is to be
    returned to the sender, it appears as the third component of the
    multipart/report.
like image 152
jfs Avatar answered Nov 15 '22 20:11

jfs