Piero V.

Bulk delete emails with Python

Recently, I had to check a legacy email address we used at home until a few years ago.

We almost stopped using it, but some services are still tied to it. The result is that whenever I need to check it, I find tons of spam, and the web interface is kinda bad, so it takes ages to delete all of it.

Some months ago, I learned to interact with IMAP from Python when I wrote a script to download and back up email accounts.

So, I modified it to output a CSV with all the senders and subjects of the emails in the mailbox. The scripts left a column empty to mark the emails that should be deleted with an x.

Then, I wrote another script to read the modified changes and to move the marked emails to the trash for a final review before emptying it.

Recently, I found myself in the same situation again, but I did not keep these scripts, so I had to write a new one.

It did not take much, but since it might be helpful to someone (at least the future me), I decided to share it here.

It takes the parameters to connect to the IMAP server on the command line. Then, it takes the action (write-csv to create the CSV with the list of emails, or read-csv to read it to send the changes to the server), and finally the name of the CSV file.

The script is released in the public domain, and, as always, it comes without any warranty.

IMAP downloader

Two weeks ago, I needed to mass-download a few IMAP mailboxes before migrating them to another provider.

Gist contains many scripts to do so, and I tried one of them, but it did not work as I wanted. I wanted to download all the IMAP folders, not only Inbox.

Therefore, I wrote my version of that script 😄️.

I used imapclient instead of the built-in imaplib because it is more Pythonic and handles all the tedious conversions between bytes, strings, and other types.

The center of the script is the process function. It connects to an IMAP server, queries the list of folders, and downloads all the messages from each one but trash and spam (but notice that the comparison is case-sensitive!).

client.fetch downloads all the messages you provide to it, which caused an OOM in my case. Therefore, I split the list with the message IDs into chunks. I had to write the batches function because I was running on Python 3.11. From Python 3.12, you can use itertools.batched instead. … [Leggi il resto]

Vandalismi nei commenti

Recentemente ho avuto più di una volta dei vandalismi da parte di un utente che si faceva chiamare “Repliche orologi”, chissà come mai 😊

Beh, caro “Repliche orologi”, mi rivolgo direttamente a te: mi hai fatto 264 commenti, quasi tutti molto vicini con il tempo. Sei riuscito a passare non solo il mio captcha ma anche Akismet copiando il contenuto direttamente dai post.

Ovviamente per fare tutti quei commenti penso tu sia un bot, però ti avvisa lo stesso: prova a premere un’altra volta il tasto di invio dei commenti e ti ritroverai un bel filtro che censurerà il tuo username e il tuo sito, questo solo per te!

Sono disposto ad aggiungere questa funzionalità al comment center, perché una volta e pochi post li posso accettare, ma la seconda e una cosa come più di 200 post no.

Comunque se lo vuoi sapere anche io sono in grado di scrivere degli script e non appena mi sono accorto dei tuoi commenti ci ho messo poco a eliminarli.

Per chi volesse, questo è uno script PHP che consente di fare la lista dei commenti ed eliminare file multipli con un account su un server FTP.

È solo una parte base, ovvero la lista e l’eliminazione tramite un array, ma ci si mette poco tempo, specialmente se si sa il periodo di tempo in cui un bot ha agito, a eliminare tutti i commenti in un solo click.

SQLite Quick Admin

Visto che mi ritrovo più di una volta a lavorare col database SQLite e PHP ho deciso di scrivere questa mini interfaccia grafica per questo tipo di database.

Infatti i primi software di questo genere che avevo trovato avevano due tipi di problemi: o erano talmente datati da non andare con PHP 5, oppure utilizzavano la versione 3 di SQLite, mentre PHP usa la versione 2.x.

Allora ho scritto questa peste di script. Perché è una peste? Perché non fa controlli di sicurezza di nessun tipo.

Per esempio è possibile fare attacchi di SQL Injection, oppure si può tranquillamente eliminare un database o una tabella senza che il software vi chieda la conferma.

Insomma: usate questo script solo in locale, altrimenti perfezionatelo.

Lo rilascio sotto il pubblico dominio (mi vergogno troppo di aver fatto una tale schifezza 😁 ).

Download: SQLite Quick Admin.

Cosa sono gli hook

Spesso quando parlo dello sviluppo dei plugin di Flatoress o in generale dello sviluppo di un sito web dico sempre qualcosa riguardante gli hook, che però non sono un concetto noto a tutti, perciò ho deciso di fare questo post di spiegazione.

Innanzitutto un programma o uno script possono essere divisi in blocchi (più o meno grandi), come inizializzazione, preparazione del contenuto, output del contenuto, chiusura delle risorse utilizzate (connessioni al database etc…).

Lo scopo degli hook è di poter inserire dinamicamente una porzione di codice (per esempio una funzione) in questi blocchi, infatti hook in italiano vuol dire gancio. Talvolta gli hook possono anche sostituire i comportamenti di default di un programma.

Gli hook sono praticamente ciò che rende un programma estendibile.

Per esempio grazie agli hook si può commutare da un sistema di indirizzi che si basa su variabili GET ad un sistema di indirizzi basato sul mod_rewrite più SEO-compatibile: si inserisce una funzione che all’inizializzazione dei parametri “raccoglie” gli URL riscritti e poi si usa un altro hook per creare i link.

Usano gli hook anche grandi progetti come Wordpress o Dokuwiki.

Le caratteristiche pratiche dal punto di vista della programmazione degli hook sono:

  • presenza di funzioni che permettono di aggiungerli, modificarli, rimuoverli o eseguirli
  • un sistema di priorità per eseguire delle porzioni di codice prima o dopo di altre
  • la possibilità di essere chiamati molte volte
  • la possibilità di poterne creare di nuovi dinamicamente

Un primordiale sistema di hook è abbastanza semplice da implementare: è una lista di callback da eseguire. Perciò, per esempio, basta creare un array multidimensionale: nel primo array si inserisce la priorità per chiave e il valore un array con il nome delle funzioni da chiamare (per esempio, in PHP tramite call_user_func).

Spero di essere stato il più chiaro possibile, altrimenti fatemelo sapere via commento.