Архив метки: imap

Python 3: Сохранение вложения из письма по протоколу IMAP

Задача: посмотреть в почтовом ящике письмо. Если в нем есть вложение — сохранить его в папку. Письмо удалить.

Решение 1 (листаем по одному письму):

#!/usr/bin/env python3
#encoding: UTF-8
import sys
import imaplib
import email
import os

server = "mail.esrgsergser.ru"
port = "143"
login = "strgsere@sgergsergse.ru"
password = "werferfe"
putdir="/home/pavel/";

ver="1.0";
copyleft="(c) 2018 by Pavel Gribov http://грибовы.рф";
comment="Сей чудный скрипт смотрит почту по imap протоколу, сохраняет вложения в заданную папку, удаляет письмо с сервера";

# История изменений

##

print (ver);
print (copyleft);
print (comment);

if len(sys.argv)==1:
    print ("Возможные параметры:")
    print ("--run выполнение скрипта. Без этого параметра не выполняется.")
    exit(0)
arg=sys.argv[1]
if arg=="--run":
    print ("- подключаемся к ",server);
    mail = imaplib.IMAP4_SSL(server)
    print ("-- логинимся");
    mail.login(login, password)
    mail.list()
    print ("-- подключаемся к inbox");
    mail.select("inbox")
    print ("-- получаем UID последнего письма");
    result, data = mail.uid('search', None, "ALL")       
    try:
     latest_email_uid = data[0].split()[-1]     
    except IndexError:
     print("-- писем нет!");
     exit(0)
    result, data = mail.uid('fetch', latest_email_uid, '(RFC822)')
    raw_email = data[0][1]
    try:
     email_message = email.message_from_string(raw_email)	
    except TypeError:
     email_message = email.message_from_bytes(raw_email)
    print ("--- нашли письмо от: ",email.header.make_header(email.header.decode_header(email_message['From'])));
    for part in email_message.walk():
        print(part.get_content_type())
        if "application" in part.get_content_type() :	    
            filename = part.get_filename()
            filename=str(email.header.make_header(email.header.decode_header(filename)))
            if not(filename): filename = "test.txt"          
            print ("---- нашли вложение ",filename);	    
            fp = open(os.path.join(putdir, filename), 'wb')
            fp.write(part.get_payload(decode=1))
            fp.close
    print ("-- удаляем письмо");
    mail.uid('STORE', latest_email_uid , '+FLAGS', '(\Deleted)')  
    mail.expunge()

Решение 2 (пролистываем весь ящик):

#!/usr/bin/env python3
#encoding: UTF-8
import sys
import imaplib
import email
import os

server = "mail.sgergser.ru"
port = "143"
login = "sergfsertg@ergser.ru"
password = "esrgser"
putdir="/home/esrgser/";

ver="1.0";
copyleft="(c) 2018 by Pavel Gribov http://грибовы.рф";
comment="Сей чудный скрипт смотрит почту по imap протоколу, сохраняет вложения в заданную папку, удаляет писмо с сервера";

# История изменений

##

print (ver);
print (copyleft);
print (comment);

if len(sys.argv)==1:
    print ("Возможные параметры:")
    print ("--run выполнение скрипта. Без этого параметра не выполняется.")
    exit(0)
arg=sys.argv[1]
if arg=="--run":
    print ("- подключаемся к ",server);
    mail = imaplib.IMAP4_SSL(server)
    print ("-- логинимся");
    mail.login(login, password)
    mail.list()
    print ("-- подключаемся к inbox");
    mail.select("inbox")
    print ("-- получаем UID последнего письма");
    result, data = mail.uid('search', None, "ALL")       
    
    for num in data[0].split() :
     result, data = mail.fetch(num, '(RFC822)')
     raw_email = data[0][1]    
     try:
      email_message = email.message_from_string(raw_email)	
     except TypeError:
      email_message = email.message_from_bytes(raw_email)
     print ("--- нашли письмо от: ",email.header.make_header(email.header.decode_header(email_message['From'])));
     for part in email_message.walk():
        print(part.get_content_type())
        if "application" in part.get_content_type() :	    
            filename = part.get_filename()
            filename=str(email.header.make_header(email.header.decode_header(filename)))
            if not(filename): filename = "test.txt"          
            print ("---- нашли вложение ",filename);	    
            fp = open(os.path.join(putdir, filename), 'wb')
            fp.write(part.get_payload(decode=1))
            fp.close
     print ("-- удаляем письмо");
     mail.store(num , '+FLAGS', '(\Deleted)')  
     mail.expunge()    
    mail.close()
    mail.logout();

Вложенный в письмо файл winmail.dat

Иногда попадаются письма, которые не удается распарсить средствами модуля imap на php — вложения он упорно видит одним файлом winmail.dat . Это «подарок» от Microsoft Outlook, который когда пользователь выбирает тип письма RTF, не заморачиваясь завертывает в файл winmail.dat и письмо, и вложения и с письмом помимо заголовков отправляет только это вложение. А люди — которые не пользуются Outlook — по мнению Microsoft — это ваши проблемы 😉

Решение — использование консольной утилиты tnef. Например:

tnef -f /usr/local/www/apache24/ssl/data/pays/1/rpost/winmail.dat -C /usr/local/www/apache24/ssl/data/pays/1/rpost