Как правильно подойти к вопросу: получение на сервер вложений яндекс почты по IMAP?

Ссылка скопирована
1 ответ

Нужно понять: подскажите, как можно получать вложения из писем с яндекса к себе на сервер? И письма из папки спам и удаленные?

По вводным: вот в таком виде код находит только во входящих и рассылках письма

def get_folder_names(mail): folders = [] status, data = mail.list() if status != 'OK': return [] folder_map = { 'INBOX': 'Входящие', 'Sent': 'Отправленные', 'Sent Items': 'Отправленные', 'Отправленные': 'Отправленные', 'Спам': 'Спам', 'Junk': 'Спам', 'Trash': 'Удаленные', 'Удалённые': 'Удаленные', 'Корзина': 'Удаленные', '[Gmail]/Trash': 'Удаленные', 'DELETED': 'Удалённые', 'SPAM': 'Спам' } logger.info(" Ищем папки...") for line in data: line = line.decode('utf-8') logger.info(f"Папка найдена: {line}") for imap_name, label in folder_map.items(): if imap_name.lower() in line.lower(): folders.append((f'"{imap_name}"', label)) logger.info(f"✅ [{label}] IMAP: {imap_name}") break if not folders: folders = [('"INBOX"', 'Входящие')] return folders

По вводным: а так я получаю только название вложения

def extract_attachments(msg) -> List[Dict]: attachments = [] try: for part in msg.walk(): if part.get_content_maintype() == 'multipart': continue filename = part.get_filename() if not filename: continue decoded_filename = decode_mime_words(filename) if decoded_filename: attachments.append({ 'name': decoded_filename[:100], 'url': f"https://mail.yandex.ru/message_part/{decoded_filename}", 'size': len(part.get_payload(decode=True) or b''), 'content_type': part.get_content_type() or 'application/octet-stream' }) except: pass return attachments def extract_message_data(msg) -> Dict[str, Any]: data = {} try: from_header = msg.get('From', '') decoded_from = decode_mime_words(from_header) name_match = re.match(r'(.+?)\s*[<(]([^<>@()]+@[^<>@()]+)[>)]', decoded_from) if name_match: data['from_name'] = name_match.group(1).strip()[:50] data['from_email'] = name_match.group(2).strip() else: data['from_email'] = decoded_from.strip() data['from_name'] = data['from_email'].split('@')[0][:50] if '@' in data['from_email'] else 'Неизвестный' data['from_full'] = f"{data['from_name']} <{data['from_email']}>" data['avatar'] = get_gravatar(data['from_email']) text_plain = text_html = None for part in msg.walk(): if part.get_content_maintype() == 'multipart': continue payload = part.get_payload(decode=True) if payload is None: continue charset = part.get_content_charset() or 'utf-8' try: content = payload.decode(charset, errors='ignore') except: content = payload.decode('utf-8', errors='ignore') ctype = part.get_content_type() if ctype == 'text/plain' and not text_plain: text_plain = content elif ctype == 'text/html' and not text_html: text_html = content data['message'] = clean_text(text_plain or text_html or '(Пустое сообщение)') data['subject'] = clean_text(decode_mime_words(msg.get('Subject', ''))) data['date'] = msg.get('Date', '') data['attachments'] = extract_attachments(msg) except Exception as e: logger.error(f"Парсинг ошибка: {e}") return data

Вот лог к вложениям:

[ { "message": "", "flag": true, "from": "TEST <test@site.com>", "shown": false, "avatar": "/5d27610776efc9ef0b1f7a79598e187f.jpg", "subject": "sd", "from_email": "gartung1996@gmail.com", "from_name": "TEST", "folder": " Входящие", "attachments": [ { "name": "file.wav", "url": "https://mail.yandex.ru/message_part/file.wav", "size": 24362748, "content_type": "audio/wav" } ], "timestamp": "2026-01-04T13:45:08.839121" } ]
Нужно решить такую задачу?

Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.

Заказать помощь
Лучший ответ
1
Роман IT Ответ

Получение вложений с Яндекс Почты по IMAP на Python делается в несколько этапов: подключение по SSL, авторизация паролем приложения, выбор папки, поиск нужных писем, разбор MIME-структуры и сохранение частей с disposition attachment. Обычный пароль от аккаунта может не подойти, если включена двухфакторная защита — нужен пароль приложения.

Минимальный пример:

import imaplib
import email
from email.header import decode_header
from pathlib import Path
 
imap = imaplib.IMAP4_SSL("imap.yandex.ru", 993)
imap.login("user@yandex.ru", "APP_PASSWORD")
imap.select("INBOX")
 
status, data = imap.search(None, "ALL")
for msg_id in data[0].split():
    status, msg_data = imap.fetch(msg_id, "(RFC822)")
    msg = email.message_from_bytes(msg_data[0][1])
    for part in msg.walk():
        filename = part.get_filename()
        if not filename:
            continue
        decoded = decode_header(filename)[0]
        name = decoded[0]
        enc = decoded[1]
        if isinstance(name, bytes):
            name = name.decode(enc or "utf-8", errors="replace")
        payload = part.get_payload(decode=True)
        Path("attachments").mkdir(exist_ok=True)
        Path("attachments", name).write_bytes(payload)
 
imap.logout()

import imaplib import email from email.header import decode_header from pathlib import Path imap = imaplib.IMAP4_SSL("imap.yandex.ru", 993) imap.login("user@yandex.ru", "APP_PASSWORD") imap.select("INBOX") status, data = imap.search(None, "ALL") for msg_id in data[0].split(): status, msg_data = imap.fetch(msg_id, "(RFC822)") msg = email.message_from_bytes(msg_data[0][1]) for part in msg.walk(): filename = part.get_filename() if not filename: continue decoded = decode_header(filename)[0] name = decoded[0] enc = decoded[1] if isinstance(name, bytes): name = name.decode(enc or "utf-8", errors="replace") payload = part.get_payload(decode=True) Path("attachments").mkdir(exist_ok=True) Path("attachments", name).write_bytes(payload) imap.logout()

В реальном коде добавьте фильтр, чтобы не скачивать всю почту каждый раз. Например, искать только непрочитанные письма, письма от конкретного отправителя или письма за период:

imap.search(None, 'UNSEEN')
imap.search(None, 'FROM "sender@example.com"')
imap.search(None, 'SINCE "01-May-2026"')

imap.search(None, 'UNSEEN') imap.search(None, 'FROM "sender@example.com"') imap.search(None, 'SINCE "01-May-2026"')

Проверьте названия папок: в IMAP они могут быть закодированы, а “Входящие” обычно выбираются как INBOX. Для пользовательских папок сначала выполните imap.list().

Частые ошибки: неверный пароль приложения, отключён IMAP в настройках Яндекс Почты, попытка сохранить файл с недопустимым именем, вложение лежит не как attachment, а как inline part, или письмо имеет сложную MIME-структуру. Поэтому разбор через msg.walk() надёжнее, чем ожидание одной конкретной части.

Итог: используйте imaplib.IMAP4_SSL, пароль приложения и MIME-разбор через стандартный модуль email. После теста на нескольких письмах добавьте фильтры и хранение обработанных UID, чтобы не скачивать одни и те же вложения повторно.

Другие ответы (0)

Пока нет других ответов. Будьте первым, кто поможет автору.

Ответить на вопрос

комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Вам также может быть интересно