Читаем почту через IMAP в Python
Примеры Python imap python, imaplib, почта imap, протокол imap
У меня не вышло найти всю необходимую информацию об IMAP в интернете, кроме RFC3501. Документ протокола IMAP Python – ключ к пониманию доступных пользователю команд, однако позвольте пропустить попытки объяснить все сразу, и лучше взглянем на пример, где я смогу объяснить основные принципы работы
Заходим в почтовый ящик
import imaplib
mail = imaplib.IMAP4_SSL('imap.gmail.com')
mail.login('myusername@gmail.com', 'mypassword')
mail.list()
# Выводит список папок в почтовом ящике.
mail.select("inbox") # Подключаемся к папке "входящие".
- Выбираем последние письма
- Начнем с поиска входящих среди всех писем при помощи функции поиска
- Воспользуемся встроенным ключом “ALL”, чтобы получить все результаты (документировано в RFC3501)
Далее мы извлечем необходимые нам данные из ответа, затем получим почту, через вычисленный нами ID.
result, data = mail.search(None, "ALL")
ids = data[0] # Получаем сроку номеров писем
id_list = ids.split() # Разделяем ID писем
latest_email_id = id_list[-1] # Берем последний ID
result, data = mail.fetch(latest_email_id, "(RFC822)") # Получаем тело письма (RFC822) для данного ID
raw_email = data[0][1] # Тело письма в необработанном виде
# включает в себя заголовки и альтернативные полезные нагрузки
Используем UID вместо ID
Функция поиска imap возвращает последовательный ID: если значение ID равно 5, значит это пятый электронный адрес в вашей почте. Это значит, что когда пользователь удаляет адрес под номером 10, все письма, находящиеся выше этой отметки указывают на неправильный адрес.
Это неприемлемо!
Не можете найти дешевых подписчиков в YouTube с гарантиями? Предлагаем Вам обратиться за помощью по ссылке и сделать выгодную покупку на надежном сайте SMM услуг. Здесь Вы получите качественный гарантированный ресурс по заманчивым ценам.
К счастью, мы можем отправить запрос на сервер imap и вернуть уникальный id (UID). Это работает очень просто: мы используем функцию uid и передаём её строке команды in в качестве первого аргумента. Остальная часть кода остается неизменной.
result, data = mail.uid('search', None, "ALL") # Выполняет поиск и возвращает UID писем.
latest_email_uid = data[0].split()[-1]
result, data = mail.uid('fetch', latest_email_uid, '(RFC822)')
raw_email = data[0][1]
Анализ необработанных писем
Работа с почтой очень похожа на разбор невнятной речи. К счастью, мы располагаем библиотекой python для работы с почтой, которая называется, кто бы мог подумать, email. Данная библиотека может конвертировать необработанные письма в знакомый нам объект EmailMessage.
import email
email_message = email.message_from_string(raw_email)
print email_message['To']
print email.utils.parseaddr(email_message['From']) # получаем имя отправителя "Yuji Tomita"
print email_message.items() # Выводит все заголовки.
def get_first_text_block(self, email_message_instance):
maintype = email_message_instance.get_content_maintype()
if maintype == 'multipart':
for part in email_message_instance.get_payload():
if part.get_content_maintype() == 'text':
return part.get_payload()
elif maintype == 'text':
return email_message_instance.get_payload()
Расширенный поиск
Мы только что закончили с базовым поиском для всей почты в целом. Теперь мы научимся сортировать выдачу поиска на нужную и ненужную. Все доступные параметры поиска находятся в протокольной документации IMAP, так что вам определенно захочется ознакомиться с разделом SEARCH Command поближе.
Попробуем следующие способы поиска.
Поиск любых заголовков
Для поиска заголовков, так их как «Ответы», «Входящие» и т.д., используем команду (HEADER “”)
mail.uid('search', None, '(HEADER Subject "My Search Term")')
mail.uid('search', None, '(HEADER Received "localhost")')
Поиск писем, начиная с датированных вчерашним днем
Часто количество входящих сообщений слишком велико, и в IMAP не указывается способ ограничения результатов, и это делает поиск слишком медленным. Существует способ ограничить этот объем – использовать ключевое слово SENTSINCE. Формат даты SENTSINCE будет следующими: ДД-МММ-ГГГГ. В то время как Python формат будет следующем: strftime('%d-%b-%Y')
import datetime
date = (datetime.date.today() - datetime.timedelta(1)).strftime("%d-%b-%Y")
result, data = mail.uid('search', None, '(SENTSINCE {date})'.format(date=date))
Ограничение по дате, поиск по темам и исключение отправителей
date = (datetime.date.today() - datetime.timedelta(1)).strftime("%d-%b-%Y")
result, data = mail.uid('search', None, '(SENTSINCE {date} HEADER Subject "My Subject" NOT FROM "yuji@grovemade.com")'.format(date=date))
Выборка
Получаем ID переписки Gmail
Выборка может включать в себя как все тело письма, так и любое сочетание результатов выдачи, такие как отмеченные письма (просмотренные\не просмотренные). Также это касается и определенных ID в Gmail, таких как ID переписки.
result, data = mail.uid('fetch', uid, '(X-GM-THRID X-GM-MSGID)')
Получаем только ключ заголовка
result, data = mail.uid('fetch', uid, '(BODY[HEADER.FIELDS (DATE SUBJECT)]])')
Множественная выборка
Вы можете выбрать несколько писем за раз. Опытным путем я пришел к тому, что это обязательно подразумевает ввод данных через запятую.
result, data = mail.uid('fetch', '1938,2398,2487', '(X-GM-THRID X-GM-MSGID)')
Используем регулярное выражение для анализа
Полученную выдачу достаточно трудно понять, так как результат разделен парами «ключ-значение». Так что мы используем регулярное выражение для получения необходимых данных. Это достаточно просто:
import re
result, data = mail.uid('fetch', uid, '(X-GM-THRID X-GM-MSGID)')
re.search('X-GM-THRID (?P\d+) X-GM-MSGID (?P\d+)', data[0]).groupdict()
# это ваш спасательный круг, который поможет организовать большой объем полученных данных.
Подведем итоги
Поздравляем, теперь вы свободно ориентируетесь в протоколе IMAP и можете использовать Python для работы с Gmail.
А ссылку на оригинал?
(https://yuji.wordpress.com/2011/06/22/python-imaplib-imap-example-with-gmail/)
А можно забирать файлы с эл. почты? Как скачивать файлы по ссылке через python, я уже знаю.
Купить натяжной потолок в Киеве и Киевской области:Ирпень, Буча можно купить натяжной потолок
"Функция поиска imap возвращает последовательный ID: если значение ID равно 5, значит это пятый электронный адрес в вашей почте." – бред какой-то! Это пятое по счету письмо в папке входящих, а вовсе не пятый адрес электронной почты. Адрес электронной почты, он же e-mail – это, например, fuckinshit@yandex.ru. И писем от с этого адреса может быть десять или тысяча. Похоже, автор не понимает, о чем пишет.
Под заголовком "Анализ необработанных писем" приведет кусок кода, явно относящийся к версии языка Python 2. А всё, что до этого, было для Python 3. Автор издевается?
В куске кода под заголовком "Анализ необработанных писем" грубая ошибка во второй строке. Функция email.message_from_stringтребует строку в качестве аргумента, а raw_email – это байтовый список. Вместо message_from_string нужно использовать message_from_bytes
Разве есть ошибка во второй строке? я не вижу
Если оставить этот код без изменений, то вылетает длинное сообщение об ошибке, заканчивающееся строкой
TypeError: initial_value must be str or None, not bytes
Это потому, что raw_email – вовсе не строка текста, а список байтов. У меня в последнем письме этот список выглядит так:
b'Received: from iva6-94240f0bdfbb.qloud-c.yandex.net......'
Видите символ b перед строкой? Признак байтов. Элемент raw_email[0] не равен 'R', он равен 82.
import imaplib
mail = imaplib.IMAP4_SSL('imap.gmail.com')
mail.login('my_adress', 'mypassword')
mail.list()
Это не работает. Дальнейшее не имеет смысла.