Обнаружение, если электронное письмо является "уведомлением о статусе доставки" и извлекает информацию - Python
Я использую модуль 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': '[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]'}
Во-первых,, как я могу сказать, что это DSN без использования регулярного выражения по этому вопросу?
Во-вторых, как мне получить доступ к телу электронной почты, а также к такой информации, как ошибка, которая была возвращена почтовым сервером?
изменить:. Мне нужно использовать .get_payload()
для получения содержимого сообщения.
сообщения электронной почты говорят:
Класс Parser не имеет отличий в публичном интерфейсе. Он делает иметь некоторые дополнительные умения для распознавать тип сообщения/статус доставки сообщений, которые он представляет как Экземпляр сообщения, содержащий отдельные Подчасти для каждого блока заголовка в уведомлении о статусе доставки
Обновление:
В принципе, мне нужно иметь возможность надежно обнаруживать, что электронное письмо является DSN, а затем также извлекать исходное сообщение, чтобы я мог разобрать его с помощью email.Parser() и получить информацию об этом.
Ответы
Ответ 1
В документах, которые вы указали, говорится, что сообщение является многочастным, если оно 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
Заголовок X-Failed-Recipients
кажется самым быстрым способом идентификации gmail DSN. После этого кажется, что вы должны разобрать текст/обычный контент.
Ответ 3
Я не использую Python, но я полагаю, что Gmail улучшил поддержку DSN, потому что мои тесты успешны:
В приведенном ниже примере вы можете увидеть многостраничное сообщение с типом "Content-Type: multipart/report; report-type = delivery-status".
Как я уверен, что это DSN:
- Первая строка: "Return-path: < > "
- Content-Type - это "multipart/report" с "report-type = delivery-status"
Тогда я знаю, что:
- Содержимое отчета находится в составе Content-Type = "message/delivery-status"
- Поля статуса и действия всегда присутствуют в содержимом отчета.
- Примечание. Поле "Состояние" может быть менее точным, чем другое состояние, которое в конечном итоге присутствует в поле "Диагностический код" (не обязательно). Однако пример ниже хорош (тот же статус во всех полях)
- Исходное сообщение находится в части с Content-Type = "message/rfc822". Иногда MTA возвращает только исходные заголовки сообщений без содержимого. В этом случае Content-Type является "text/rfc822-headers".
Пример DSN, полученный после отправки по электронной почте [email protected]:
Return-path: <>
Received: from xxx ([xxx])
by xxx with ESMTP; Fri, 04 May 2012 16:18:13 +0200
From: <[email protected]> (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 attached below.
For further assistance, please send mail to <[email protected]>
If you do so, please include this problem report. You can
delete your own text from the attached returned message.
<[email protected]>: 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 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; [email protected]
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 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...]