Привіт! Продовжуючи тему корисних для особистого застосування скриптів, сьогодні хочу поділитись з вами кодом, що чистить електронну пошту.
Так що якщо у вас назбиралось декілька тисяч листів за минулі 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.