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