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

avatar

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

Так що якщо у вас назбиралось декілька тисяч листів за минулі 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.



0
0
0.000
8 comments
avatar

Wow, love this post It’s been handpicked and curated by the awesome Bilpcoin team—we’re so happy to support amazing content like this! If you’d like to join us in spreading the positivity, feel free to delegate some Hive Power to this account. Every bit helps us curate and uplift even more creators in the community By adding #bilpcoin or #bpc to original posts, you can earn BPC tokens
https://hive.blog/hive-167922/@bpcvoter2/calling-all-music-artists-on-hive-elevate-your-sound-with-ai-infused-beats

By adding #bilpcoin or #bpc to original posts, you can earn BPC tokens

https://peakd.com/hive-140084/@bpcvoter1/my-way-keni-bpc-ai-music

https://peakd.com/hive-126152/@bpcvoter2/dear-themarkymark-buildawhale-gogreenbuddy-usainvote-ipromote-and-whoever-else-is-involved-in-this-scheme-you-call-us-nutty-as

https://peakd.com/hive-167922/@bilpcoinbpc/exploring-the-possibilities-of-ai-art-with-bilpcoin-nfts-episode-102-buildawhale-scam-farm-on-hive-and-dear-steevc

https://peakd.com/hive-133987/@bilpcoinbpc/comprehensive-analysis-of-punkteam-s-wallet-transactions

https://hive.blog/hive-163521/@bpcvoter1/deep-dive-into-meritocracy-s-activity-history-and-blockchain-audit

https://www.publish0x.com/the-dark-side-of-hive/to-downvoters-scammers-and-farmers-on-hive-the-time-to-chang-xmjzrmp

https://peakd.com/hive-163521/@bpcvoter3/themarkymark-we-ve-exposed-your-actions-repeatedly-how-you-and-your-army-of-bots-manipulate-rewards-to-benefit-yourselves-it-s

https://peakd.com/hive-168088/@bpcvoter3/the-shadow-matrix-a-tale-of-deceit-and-reckoning

Our move?
🔹 Unite voices: Use #bilpcoin or #bpc to highlight censorship & demand accountability.
🔹 Document abuse: Share evidence of unfair downvotes, self-voting scams, and double standards.
🔹 Push for reform: Advocate for transparent governance, vote caps, and community-driven rules.

Decentralization isn’t just a feature—it’s a fight. Let’s model fairness, rally allies, and pressure Hive to live up to its ideals.
https://peakd.com/hive-167922/@bpcvoter3/5m1kft-themarkymark-you-can-keep-pretending-to-be-oblivious-but-the-truth-is-out-you-ve-been-exposed-it-s-time-to-own-up-to-your

#StandForDecentralization #HiveTransparency

0
0
0.000
avatar

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

0
0
0.000
avatar

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

0
0
0.000
avatar

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

0
0
0.000
avatar

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

0
0
0.000