Очищення електронної пошти за допомогою Python

in Team Ukraine4 months ago

Привіт! Продовжуючи тему корисних для особистого застосування скриптів, сьогодні хочу поділитись з вами кодом, що чистить електронну пошту.

Так що якщо у вас назбиралось декілька тисяч листів за минулі 5 років, серед яких може бути щось важливе, а часу перебирати вручну хронічно не вистачає (чи просто немає бажання), то ця тема саме для вас.

Отже, до вашої уваги наступний скрипт на Python:

import imaplib import email from email.header import decode_header from datetime import datetime, timedelta #Email credentials EMAIL_USER = "your_email" EMAIL_PASSWORD = "your_app_password" IMAP_SERVER = "your_imap_server" #for google - imap.gmail.com #Adjustable settings DELETE_UNREAD_OLDER_THAN_DAYS = 30 # Age limit for unread emails DELETE_READ_UNFLAGGED_OLDER_THAN_DAYS = 90 # Age limit for read & unflagged emails DRY_RUN = False # If True, only lists emails without deleting #Custom spam keywords (Always filter spam) SPAM_KEYWORDS = ["win", "free", "prize", "click here", "lottery", "urgent", "claim now", "exclusive offer", "discount", "get rich"] #Function to reconnect IMAP session def reconnect_mail(): global mail try: mail.close() mail.logout() except: pass # Avoid crashes if already disconnected mail = imaplib.IMAP4_SSL(IMAP_SERVER, timeout=60) mail.login(EMAIL_USER, EMAIL_PASSWORD) mail.select("inbox") #Connect initially reconnect_mail() deleted_count = 0 # Counter for deleted emails def search_and_process(search_query): """Search emails based on query & filter spam if enabled.""" global deleted_count try: status, messages = mail.search(None, search_query) except imaplib.IMAP4.abort: print("Connection lost, reconnecting...") reconnect_mail() status, messages = mail.search(None, search_query) if status == "OK": message_nums = messages[0].split() print(f"Found {len(message_nums)} emails matching criteria: {search_query}") if message_nums: batch_size = 50 # Process emails in smaller chunks for start in range(0, len(message_nums), batch_size): batch = message_nums[start:start + batch_size] try: _, data = mail.fetch(",".join(num.decode() for num in batch), "(RFC822)") except imaplib.IMAP4.abort: print("Connection lost during fetch, reconnecting...") reconnect_mail() _, data = mail.fetch(" ".join(num.decode() for num in batch), "(RFC822)") for i in range(0, len(data), 2): # Every email fetch returns two tuples if isinstance(data[i], tuple): msg = email.message_from_bytes(data[i][1]) # Extract email date email_date = msg["Date"] if email_date: try: email_date = email.utils.parsedate_to_datetime(email_date).strftime("%Y-%m-%d") except: email_date = "Unknown Date" # Decode subject subject, encoding = decode_header(msg["Subject"])[0] if isinstance(subject, bytes): subject = subject.decode(encoding or "utf-8", errors="ignore") # Check if spam is_spam = any(keyword in subject.lower() for keyword in SPAM_KEYWORDS) if is_spam: action_message = "[DRY RUN] Would delete spam: " if DRY_RUN else "Deleting spam: " else: action_message = "[DRY RUN] Would delete: " if DRY_RUN else "Deleting: " print(f"{action_message} ({email_date}) {subject}") if not DRY_RUN: try: mail.store(batch[i//2].decode(), "+FLAGS", "\\Deleted") deleted_count += 1 except imaplib.IMAP4.abort: print("Connection lost during deletion, reconnecting...") reconnect_mail() mail.store(batch[i//2].decode(), "+FLAGS", "\\Deleted") #Delete unread emails older than 1 month search_and_process(f'UNSEEN BEFORE {(datetime.today() - timedelta(days=DELETE_UNREAD_OLDER_THAN_DAYS)).strftime("%d-%b-%Y")}') #Delete read but unflagged emails older than 3 months search_and_process(f'SEEN BEFORE {(datetime.today() - timedelta(days=DELETE_READ_UNFLAGGED_OLDER_THAN_DAYS)).strftime("%d-%b-%Y")} NOT FLAGGED') if not DRY_RUN: # Permanently delete flagged emails mail.expunge() #Close the connection mail.close() mail.logout() print(f"Total deleted emails: {deleted_count}") Коментар до коду

Підключення до IMAP-сервера (Gmail):

  • Використовується модуль imaplib, щоб підключитися до пошти через протокол IMAP.

  • Логін виконується за допомогою EMAIL_USER та EMAIL_PASSWORD. Для gmail потрібно ставити пароль застосунку (https://myaccount.google.com/apppasswords)

Налаштування фільтрації пошти:

  • DELETE_UNREAD_OLDER_THAN_DAYS = 30 → Видаляє непрочитані листи, якщо їм більше 30 днів.

  • DELETE_READ_UNFLAGGED_OLDER_THAN_DAYS = 90 → Видаляє прочитані та не позначені прапорцем листи, якщо їм більше 90 днів.

  • DRY_RUN = False → Якщо True, скрипт лише показує, які листи будуть видалені, але не видаляє їх.

Фільтрація спаму:

  • Листи, що містять ключові слова (SPAM_KEYWORDS), видаляються незалежно від віку (наприклад, "win", "free", "prize").

  • Використовується decode_header(), щоб правильно розшифрувати заголовок теми.

Обробка розриву з’єднання:

  • Якщо IMAP-сервер обриває з'єднання (imaplib.IMAP4.abort), скрипт автоматично перепідключається.

  • Використовується reconnect_mail() для повторного з'єднання з сервером.

Пошук та видалення листів:

search_and_process() виконує:

  • Пошук електронних листів, що відповідають критеріям (наприклад, старі, непрочитані, спам).

  • Групове отримання листів у пакетах по 50, щоб уникнути перевантаження серверу.

  • Перевірку на спам, використовуючи ключові слова.

  • Видалення листів, якщо вони відповідають критеріям.

Остаточне очищення пошти:

  • Якщо DRY_RUN = False, викликається mail.expunge(), що остаточно видаляє помічені листи. Для тестування змініть на DRY_RUN = True

  • Закривається з'єднання mail.close() та mail.logout().

Рекомендація: якщо вам сподобався скрипт та у вас є сервер, можна автоматизувати очищення через додання задачі до crontab.

Sort:  
 4 months ago  

Цей скрипт підходить лише для Gmail чи його можна також застосовувати і для інших поштових сервісів?

Теоретично підходить до всіх поштових сервісів що використовують imap. У gmail просто фішка: замість паролю на пошту треба ставити пароль на застосунок, який треба згенерувати. Особисто я використовую для свого акаунту в gmail, просто для інших провайдерів не перевіряв

Thank you for your witness vote!
Have a !BEER on me!
To Opt-Out of my witness beer program just comment STOP below


Hey @stranger27, here is a little bit of BEER from @isnochys for you. Enjoy it!

Learn how to earn FREE BEER each day by staking your BEER.


Hey @stranger27, here is a little bit of BEER from @isnochys for you. Enjoy it!

We love your support by voting @detlev.witness on HIVE .

Thank you for your witness vote!
Have a !BEER on me!
To Opt-Out of my witness beer program just comment STOP below


Hey @stranger27, here is a little bit of BEER from @isnochys for you. Enjoy it!

Learn how to earn FREE BEER each day by staking your BEER.

Loading...