Обнаружение, является ли электронная почта «Уведомлением о статусе доставки» и извлечение информации - Python - PullRequest
11 голосов
/ 14 марта 2011

Я использую модуль Python email для разбора электронных писем.

Мне нужно иметь возможность определить, является ли электронная почта «Уведомлением о статусе доставки», выяснить, каков статус, и извлечь информацию по электронной почте, которая не удалась, например. Тема.

Объект, который я получаю после анализа с помощью .parsestr (email), выглядит так:

{'Content-Transfer-Encoding': 'quoted-printable',
 'Content-Type': 'text/plain; charset=ISO-8859-1',
 'Date': 'Mon, 14 Mar 2011 11:26:24 +0000',
 'Delivered-To': 'sender@gmail.com',
 'From': 'Mail Delivery Subsystem <mailer-daemon@googlemail.com>',
 'MIME-Version': '1.0',
 'Message-ID': '<000e08jf90sd9f00e6f943f@google.com>',
 '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': 'sender@gmail.com',
 'X-Failed-Recipients': 'recipient@gmail.com'}

Во-первых , как мне сказать, что это DSN без использования регулярного выражения для предмета?

Во-вторых , как мне получить доступ к телу электронной почты и такой информации, как ошибка, возвращенная почтовым сервером?

edit: сработало Мне нужно использовать .get_payload() для получения содержимого сообщения.

Документы электронной почты говорят:

Класс Parser не имеет различий в своем открытом интерфейсе. Это делает иметь некоторые дополнительные умения распознать тип сообщения / состояния доставки сообщения , которые он представляет в виде Экземпляр сообщения, содержащий отдельный Подчасти сообщения для каждого блока заголовка в уведомлении о состоянии доставки


Обновление:

По сути, мне нужно иметь возможность надежно определять, что электронная почта является DSN, а также извлекать исходное сообщение, чтобы я мог проанализировать его с помощью email.Parser () и получить информацию о нем.

Ответы [ 3 ]

17 голосов
/ 14 марта 2011

В цитируемых вами документах говорится , что сообщение состоит из нескольких частей, если оно 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

Формат уведомления о статусе доставки (от 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.
2 голосов
/ 27 сентября 2012

Заголовок X-Failed-Recipients, кажется, является самым быстрым способом определения DSN Gmail.После этого кажется, что вы должны проанализировать текстовое / простое содержимое.

2 голосов
/ 04 мая 2012

Я не использую Python, но полагаю, что Gmail улучшил свою поддержку DSN, потому что мои тесты прошли успешно:

В приведенном ниже примере вы видите многокомпонентное сообщение с "Content-Type: multipart /report; type-type = delivery-status ".

Способ надежного определения, что это DSN:

  • Первая строка -" Return-path: <> "
  • Content-Type - «multipart / report» с «report-type = delivery-status»

Тогда я знаю, что:

  • Отчетсодержимое находится в части с Content-Type = "message / delivery-status"
  • Поля Status и Action всегда присутствуют в содержимом отчета.
  • Обратите внимание, что поле Status может быть менее точным, чемдругое состояние в конечном итоге присутствует в поле «Диагностический код» (не обязательно).Тем не менее, приведенный ниже пример хорош (одинаковый статус во всех полях)
  • Исходное сообщение находится в части с Content-Type = "message / rfc822".Иногда MTA возвращает только оригинальные заголовки сообщений без содержимого.В этом случае Content-Type - это «text / rfc822-headers».

Образец уведомления о доставке, полученного после отправки электронного письма на адрес test-dsn-failure@gmail.com:

Return-path: <>
Received: from xxx ([xxx])
    by xxx with ESMTP; Fri, 04 May 2012 16:18:13 +0200
From: <Mailer-Daemon@xxx> (Mail Delivery System)
To: xxx
Subject: Undelivered Mail Returned to Sender
Date: Fri, 04 May 2012 15:25:09 +0200
MIME-Version: 1.0
Content-Type: multipart/report; report-type=delivery-status;
 boundary="HTB3nt3RR7vw/QMPR4kDPbKg+XWjXIKdC/rfHQ=="

This is a MIME-encapsulated message.

--HTB3nt3RR7vw/QMPR4kDPbKg+XWjXIKdC/rfHQ==
Content-Description: Notification
Content-Type: text/plain

I'm sorry to have to inform you that your message could not
be delivered to one or more recipients. It's attached below.

For further assistance, please send mail to <postmaster@xxx>

If you do so, please include this problem report. You can
delete your own text from the attached returned message.

<test-dsn-failure@gmail.com>: 550-5.1.1 The email account that you tried to reach does not exist. Please try
550-5.1.1 double-checking the recipient's email address for typos or
550-5.1.1 unnecessary spaces. Learn more at
550 5.1.1 http://support.google.com/mail/bin/answer.py?answer=6596 t12si10077186weq.36


--HTB3nt3RR7vw/QMPR4kDPbKg+XWjXIKdC/rfHQ==
Content-Description: Delivery report
Content-Type: message/delivery-status

Reporting-MTA: dns; xxx
Arrival-Date: Fri, 04 May 2012 15:25:09 +0200

Final-Recipient: rfc822; test-dsn-failure@gmail.com
Status: 5.1.1
Action: failed
Last-Attempt-Date: Fri, 04 May 2012 15:25:09 +0200
Diagnostic-Code: smtp; 550-5.1.1 The email account that you tried to reach does not exist. Please try
550-5.1.1 double-checking the recipient's email address for typos or
550-5.1.1 unnecessary spaces. Learn more at
550 5.1.1 http://support.google.com/mail/bin/answer.py?answer=6596 t12si10077186weq.36

--HTB3nt3RR7vw/QMPR4kDPbKg+XWjXIKdC/rfHQ==
Content-Description: Undelivered Message
Content-Type: message/rfc822

[original message...]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...