No more Spam in Webmail

News: dopo aver faticato, ho scoperto questo fantastico script: 
https://github.com/isbg/isbg/blob/master/isbg.py
ora vedo se riesco a installare SpamAssassin 
sul mio server, ed è fatta.

Dopo vari anni di utilizzo del WebMail di Unisalento, ho perso la pazienza contro lo SPAM. Tutti i colleghi e forse anche gli studenti si saranno accorti che il livello di SPAM ricevuto è davvero impressionante.

Di solito il problema dello spam può essere risolto in vari modi, il primo molto semplicemente consiste nel NON USARE il Webmail, ma uno dei client di posta tipo Mail su MacOS o se si possiede la suite Office, Outlook. Oppure scaricare dei client liberi come Thunderbird. Questi programmi consentono di creare un filtro che ad esempio prende tutti i messaggi che contengono SPAM nel subject e li butta nel cestino o in un apposito folder, con una serie di filtri ben studiati si riesce quantomeno a limitare l'impatto dello spam.

A volte però questo non è possibile, ad esempio perché state leggendo l'email da altri computer, e quindi dovete usare il Webmail, oppure avete configurato un client email sul vostro cellulare, e su questi programmi non vi sono sistemi di filtro sofisticati come sui client per desktop. Uno dei limiti maggiori del Webmail attuale è che segnala con la presenza di un antispam se alcune email sono appunto SPAM (e aggiunge la parola SPAM al subject) ma non li sposta automaticamente in un folder apposito, inoltre fare una ricerca delle email con quel subject e spostarle è estremamente lento, risultato: finiamo tutti per dover selezionare una dopo l'altra a mano le email per cancellarle.

Ed eccoci quindi, a come provare a risolvere la questione con un po di Python e di pazienza. Questo script, sotto, si connette al vostro account su Unisalento, legge le prime N email (ma potete configurarlo a piacere), e se ne trova marcate dal sistema di antispam le sposta nella cartella Spam, automaticamente. Naturalmente questo non vi aiuta nel caso in cui come sopra siete in giro, ma se avete (come me) un sistema magari con Linux o MacOS sempre acceso in ufficio, potete risolvere il tutto aggiungendo questo script tra i cron job che vengono eseguiti ogni ora.

Risultato niente più SPAM. Almeno quello marcato dal sistema. Ma è solo il primo passo, con uno script simile si può ad esempio costruire in modo automatico l'elenco di coloro che vi hanno scritto, selezionare un sottoinsieme di "coautori", persone che sono abitualmente vostri collaboratori, e spostare tutte le email con mittenti diversi in un altro folder, cosi in INBOX otterrete di solito solo le email di lavoro e tutte le altre finiranno in un 'Others' a cui potete dedicare tempo solo dopo aver spulciato quelle importanti.

Ecco lo script:


import imaplib
import sys
import email
import email.header
from dateutil.parser import parse
import datetime
import re
from colorama import Fore, Back, Style

def decode_mime_words(s):
    return u''.join(
        word.decode(encoding or 'utf8') if isinstance(word, bytes) else word
        for word, encoding in email.header.decode_header(s))

def listemail(num):
    SERVER = 'in.unisalento.it' # IMAP server
    FOLDER = 'INBOX' # cartella sul server
    ACCOUNT = 'youraccount'    # nome account
    PASSWORD = 'yourpassword'  # password (mettere quella giusta).

    print("Fetch %d messages from %s, user %s\n" %(num,SERVER,ACCOUNT))
    # Connessione
 
    M = imaplib.IMAP4_SSL(SERVER)
    rv, data = M.login(ACCOUNT, PASSWORD)
    if rv == 'OK':
        print("connessione aperta")
    else:
        print("errore di connessione/autenticazione")
        sys.exit(1)
 
    # Apertura del folder
    rv, data = M.select(FOLDER)
    if rv != 'OK':
        print("Errore in apertura del folder %s",FOLDER)

    num_msgs = int(data[0])
    print('There are %d messages in INBOX' % num_msgs)

    rv, data = M.search(None, "UNSEEN")
    if rv != 'OK':
        print("No messages found!")
        sys.exit(1)
    print("There are %d unread messages" % len(data))
 
    # Ok, adesso vediamo di filtrare
    count = 1
    spam = 0
    for n in reversed(data[0].split()):
        rv, data = M.fetch(n, '(BODY.PEEK[HEADER])')
        if rv != 'OK':
            print("ERROR getting message", n)
            continue
        for response_part in data:
            if isinstance(response_part, tuple):
                msg = email.message_from_bytes(response_part[1])  
                if (msg['X-Spam-Flag'] == "YES"):
                    rv, data = M.copy(n,'INBOX.Spam')
                    if rv == 'OK':
                        spam = spam + 1
                        print("Copied %d in Spam" % int(n),end=" ")
                        rv, response = M.store(n, '+FLAGS', r'(\Deleted)')
                        rv, response = M.expunge()
                        print("Deleted %d from INBOX" % int(n))
        rv,data = M.uid('STORE', n, '-FLAGS', '(\Seen)')
        if rv != 'OK':
            print("Error in marking message",n)
            continue
        count = count + 1
        if (count > num): break;
    print("Scan %d messages Moved %d Spam" % (count,spam))
    # finito, chiudiamo la connessione
    M.close()


if __name__ == "__main__":
    if (len(sys.argv) > 1):
        num = int(sys.argv[1])
    else:
        num = 20
    listemail(num)

Come si vede lo script è molto semplice, e se si fa girare ogni ora con CRON, basta decisamente controllare i primi 20-30 messaggi per liberarsi dello SPAM. Per usare questo script da Windows dovete installare Python3, per usarlo da MacOs, installate homebrew e poi usare "brew install python3", per installare i pacchetti python che sono usati potete semplicemente usare "pip3 install nomepacchetto".

Email con Python

Possiamo usare Python per accedere al proprio account di posta elettronica e scaricare alcuni messaggi. Il modulo da usare è imaplib.

E' utile verificare i vari comandi, usando l'interprete. Se volete copiare il programma, fate doppio click (cambiate posizione del click e sperimentate fin quando non viene selezionato tutto il testo, tranne i numeri di linea)


import imaplib
import sys
import email
import email.header

SERVER = 'in.unisalento.it' # IMAP server
FOLDER = 'INBOX' # cartella sul server
ACCOUNT = 'ancaruso' # nome account
PASSWORD = '@@@@@@@' # password (mettere quella giusta, attenzione al sorgente).

# Connessione

M = imaplib.IMAP4_SSL(SERVER)
rv, data = M.login(ACCOUNT, PASSWORD)
if rv == 'OK':
    print("connessione aperta")
else:
    print("errore di connessione/autenticazione")
    sys.exit(1)

# Apertura del folder
rv, data = M.select(FOLDER)
if rv != 'OK':
    print("Errore in apertura del folder %s",FOLDER)

rv, data = M.search(None, "ALL")
if rv != 'OK':
    print("No messages found!")
    sys.exit(1)

# Ok, adesso listo e elenco

for num in data[0].split():
    rv, data = M.fetch(num, '(RFC822)')
    if rv != 'OK':
        print("ERROR getting message", num)
        continue
    msg = email.message_from_bytes(data[0][1])
    t = email.header.decode_header(msg['Subject'])
    hdr = email.header.make_header(t)
    subject = str(hdr)
    print("%s",subject)

# finito, chiudiamo la connessione
M.close()