Быстрый в изучении - мощный в программировании
Скрипт ИНВЕСТОР на Python

Попробуйте себя в качестве инвестора имея в помощники мощный алгоритм советника на Python...

Все уроки по PyQt5

PyQt5 реализован как комплект Python-модулей. Он включает в себя около 620 классов и 6000 функций и методов...

Скрипт отправки SMS через Python

Была задача отправить SMS-ки большому списку номеров телефона с уточнением цены за всю рассылку "До" ее отправки...

Читаем почту через IMAP в Python

30 марта 2017 г. Archy Просмотров: 1062 RSS 1
Примеры Python , , ,

IMAP Python

У меня не вышло найти всю необходимую информацию об 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, все письма, находящиеся выше этой отметки указывают на неправильный адрес.

Это неприемлемо!

К счастью, мы можем отправить запрос на сервер 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.

Комментариев: 1
  1. Эдуард | 2017-05-10 в 08:02:48

    А ссылку на оригинал?

    (https://yuji.wordpress.com/2011/06/22/python-imaplib-imap-example-with-gmail/)

Оставьте комментарий!

Используйте нормальные имена.

Имя и сайт используются только при регистрации

Если вы уже зарегистрированы как комментатор или хотите зарегистрироваться, укажите пароль и свой действующий email. При регистрации на указанный адрес придет письмо с кодом активации и ссылкой на ваш персональный аккаунт, где вы сможете изменить свои данные, включая адрес сайта, ник, описание, контакты и т.д., а также подписку на новые комментарии.

(обязательно)