От автора: Я продолжаю писать заметки о насущных проблемах и я очень надеюсь, что буду не одинок в этом деле и
Вы тоже поделитесь какими-то небольшими решениями, которые помогли вам в автоматизации.
Предыдущая заметка была о RobotFramework, а в этот раз я хотел бы поделиться небольшим разъяснением, как же все таки работать с mail.ru.
Если Вы хоть когда-то читали сообщения по imap протоколу, но наверное знаете, что ничего сложного в этом нет. Вот например python код, который читает subject непросмотренных емейлов:
from imaplib import IMAP4, IMAP4_SSL
server = IMAP4_SSL('imap.gmail.com')
server.login(
'email.productivity.conf@gmail.com',
'happy@conf')
server.select()
result, ids = server.search(
None, '(UNSEEN')
print "New emails with your email in TO is %d" % len(ids[0].split())
for id in ids[0].split():
print "\t" + server.fetch(id,
'(BODY.PEEK[HEADER.FIELDS (SUBJECT)])')[1][0][1].strip()
в результате получаем
New emails with your email in TO is 5
Subject: [Lesson24] Your username and password
Subject: Your Lesson24 order receipt from May 6, 2013
Subject: Your Lesson24 order from May 6, 2013 is complete
Subject: [Lesson24] Order Received
Subject: Suspicious sign-in prevented
Проблема
Как бы все хорошо работает, но предположим у вас емейл не на gmail.com, а на yandex или mail.ru. И если мы применим этот же код, только к mail.ru:
from imaplib import IMAP4, IMAP4_SSL
server = IMAP4_SSL('imap.mail.ru')
server.login('your_loging@mail.ru', 'your_password_here')
server.select()
result, ids = server.search(None, '(UNSEEN)')
print "New emails with your email in TO is %d" % len(ids[0].split())
for id in ids[0].split():
print "\t" + server.fetch(id,
'(BODY.PEEK[HEADER.FIELDS (SUBJECT)])')[1][0][1].strip()
то получим совсем не то, что ожидаем:
New emails with your email in TO is 2
Subject: =?utf-8?Q?=D0=9B=D1=83=D1=87=D1=88=D0=B8=D0=B5=20=D0=BF=D1=80=D0=B5=D0=B4=D0=BB=D0=BE=D0=B6=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=BC=D0=B5=D1=81=D1=8F=D1=86=D0=B0=20=D0=BE=D1=82=20Group=20Travel=21?=
Subject: =?utf-8?Q?=D0=92=D1=81=D0=B5=20=D0=BF=D1=83=D1=82=D0=B5=D1=88=D0=B5=D1=81=D1=82=D0=B2=D0=B8=D1=8F=20=D0=9C=D0=B0=D0=BD=D0=B4=D1=80=D1=83=D0=B9=20=D0=94=D0=B5=D1=88=D0=B5=D0=B2=D1=88=D0=B5=20=D0=BD=D0=B0=2005=2F10=2F2013?=
Решение
Почему такая странная кодировка? Потому что там есть русские символы. Но это ведь не unicode и не ascii, что же это? Это специальная quoted printable encoding, которая используется в MIME для передачи не ascii содержимого в емейле. Более подробно можно почитать на википедии Quoted-printable - Wikipedia
Ну и как теперь решать такую проблему? Просто, потому что в python есть встроенный модуль, который называется quopri. Все что нам нужно сделать - это декодировать полученную строку в нормальный божеский вид. Смотрим код:
import quopri
from imaplib import IMAP4, IMAP4_SSL
server = IMAP4_SSL('imap.mail.ru')
server.login('your_loging@mail.ru', 'your_password_here')
server.select()
result, ids = server.search(None, '(UNSEEN)')
print "New emails with your email in TO is %d" % len(ids[0].split())
for id in ids[0].split():
subject = server.fetch(id,
'(BODY.PEEK[HEADER.FIELDS (SUBJECT)])')[1][0][1].strip()
print "\t" + quopri.decodestring(subject.encode('utf-8')).decode('utf-8')
получаем:
New emails with your email in TO is 2
Subject: =?utf-8?Q?DOU-активность за 5 октября 2013?
Subject: =?utf-8?Q?Все путешествия Мандруй Дешевше на 07/10/2013?
Дальше можно еще строки обрабатывать, но суть в том, чтобы превратить непонятные символы в понятные. Чего мы с вами и добились.
Дополнение
Забыл еще сказать, что кроме quoted printable encoding может быть и base64. Как это распознать?
Вот строка в quoted printable encoding:
=?utf-8?Q?=D0=92=D1=81=D0=B5=20=D0=BF=D1=83=D1=82=D0=B5=D1=88=D0=B5=D1=81=D1=82=D0=B2=D0=B8=D1=8F=20=D0=9C=D0=B0=D0=BD=D0=B4=D1=80=D1=83=D0=B9=20=D0=94=D0=B5=D1=88=D0=B5=D0=B2=D1=88=D0=B5=20=D0=BD=D0=B0=2005=2F10=2F2013?=
и в base64:
Subject: =?UTF-8?B?0J/QvtC30LTRgNCw0LLQu9C10L3QuNGPINGBINC/0YDQsNC30LTQvdC40LrQsNC80Lgg0L3QtdC00LXQu9C4INGBIDcg0L/QviAxMyDQvtC60YLRj9Cx0YDRjywg0L3QvtCy0YvQtSDQv9GA0LjQutC+0LvRjNC90YvQtSDQvtGC0LrRgNGL0YLQutC4INC90LAg0LzQvtCx0LjQu9GM0L3Ri9C5IQ=?
Если хорошо присмотреться, то сразу заметите зарницу между ?utf-8?Q?
и ?UTF-8?B?
. Т.е. Q = quoted, B = base.
И как теперь декодировать base64? Правильно, с помощью специального модуля, смотрим код:
import base64
base64.b64decode('aHR0cDovLzR1ZnJlZS50ay9tZWRpYTcyMzY0Ni9mdWVuZi8wMzYubXAz')
на выходе получаем:
'http://4ufree.tk/media723646/fuenf/036.mp3'
От автора: Пишите свои заметки и комментируйте код. Хорошей вам автоматизации!