Проблема с кодировкой цитируемой и печатной почты в Python - PullRequest
4 голосов
/ 28 октября 2010

Я извлекаю письма из Gmail, используя следующее:

def getMsgs():
 try:
    conn = imaplib.IMAP4_SSL("imap.gmail.com", 993)
  except:
    print 'Failed to connect'
    print 'Is your internet connection working?'
    sys.exit()
  try:
    conn.login(username, password)
  except:
    print 'Failed to login'
    print 'Is the username and password correct?'
    sys.exit()

  conn.select('Inbox')
  # typ, data = conn.search(None, '(UNSEEN SUBJECT "%s")' % subject)
  typ, data = conn.search(None, '(SUBJECT "%s")' % subject)
  for num in data[0].split():
    typ, data = conn.fetch(num, '(RFC822)')
    msg = email.message_from_string(data[0][1])
    yield walkMsg(msg)

def walkMsg(msg):
  for part in msg.walk():
    if part.get_content_type() != "text/plain":
      continue
    return part.get_payload()

Однако, некоторые электронные письма, которые я получаю, почти невозможно для меня извлечь даты (используя регулярные выражения) из символов, связанных с кодировкой, таких как '=', случайно попадающих в середину различных текстовых полей. Вот пример, где это происходит в диапазоне дат, который я хочу извлечь:

Имя: KIRSTI E-mail: kirsti@blah.blah Номер телефона: + 999 99995192 Всего в партии: 4 всего, 0 дети Прибытие / Отъезд: 9 октября = , 2010 г. - 13 октября 2010 г. - 13 октября 2010 г.

Есть ли способ удалить эти символы кодирования?

Ответы [ 3 ]

5 голосов
/ 28 октября 2010

Вы можете / должны использовать модуль email.parser для декодирования почтовых сообщений, например (быстрый и грязный пример!):

from email.parser import FeedParser
f = FeedParser()
f.feed("<insert mail message here, including all headers>")
rootMessage = f.close()

# Now you can access the message and its submessages (if it's multipart)
print rootMessage.is_multipart()

# Or check for errors
print rootMessage.defects

# If it's a multipart message, you can get the first submessage and then its payload
# (i.e. content) like so:
rootMessage.get_payload(0).get_payload(decode=True)

Используя параметр "decode"Message.get_payload, модуль автоматически декодирует контент, в зависимости от его кодировки (например, цитируемые печатные формы, как в вашем вопросе).

2 голосов
/ 28 октября 2010

Это известно как кодировка для печати в кавычках.Вы, вероятно, хотите использовать что-то вроде quopri.decodestring - http://docs.python.org/library/quopri.html

0 голосов
/ 22 декабря 2018

Если вы используете Python3.6 или новее, вы можете использовать метод email.message.Message.get_content() для автоматического декодирования текста.Этот метод заменяет get_payload(), хотя get_payload() все еще доступен.

Скажем, у вас есть строка s, содержащая это сообщение электронной почты (на основе примеров в документах):

Subject: Ayons asperges pour le =?utf-8?q?d=C3=A9jeuner?=
From: =?utf-8?q?Pep=C3=A9?= Le Pew <pepe@example.com>
To: Penelope Pussycat <penelope@example.com>,
 Fabrette Pussycat <fabrette@example.com>
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: quoted-printable
MIME-Version: 1.0

    Salut!

    Cela ressemble =C3=A0 un excellent recipie[1] d=C3=A9jeuner.

    [1] http://www.yummly.com/recipe/Roasted-Asparagus-Epicurious-203718

    --Pep=C3=A9
   =20

Не-ascii символы в строке были закодированы с кодировкой quoted-printable, как указано в заголовке Content-Transfer-Encoding.

Создать объект электронной почты:

import email
from email import policy

msg = email.message_from_string(s, policy=policy.default)

Здесь требуется настройка политики;в противном случае используется policy.compat32, который возвращает устаревший экземпляр сообщения, у которого нет метода get_content.policy.default в конечном итоге станет политикой по умолчанию, но на Python3.7 он все еще policy.compat32.

Метод get_content() автоматически обрабатывает декодирование:

print(msg.get_content())

Salut!

Cela ressemble à un excellent recipie[1] déjeuner.

[1] http://www.yummly.com/recipe/Roasted-Asparagus-Epicurious-203718

--Pepé

Если у вас есть составное сообщение, необходимо вызвать get_content() для отдельных частей, например:

for part in message.iter_parts():
    print(part.get_content())
...