[IT] Bash: come interfacciarsi con Apple Mail via script (Mac OS X Leopard) – Parte 1/4

Introduzione:
Sulla mia macchina Mac OS X Leopard uso Apple Mail come client di posta, perchè ha una serie di funzioni (come le smart folders) e chicche di usabilità che altri client si sognano. Ma quando avete esigenze che esulano da quelle standard, come nel mio caso (ma va? quando mai!), bisogna ricorrere ad altri strumenti per portare a compimento il lavoro. Nel mio caso, lo strumento da me scelto è la mia amata (e immensamente potente) shell Bash.

La Apple per il suo client Mail ha scelto un approccio diverso da tutti gli altri client sulla piazza: la posta scaricata, infatti, non viene tutta compressa in un unica, elefantiaca mailbox e salvata nel comunissimo formato .mbox, bensì ogni e-mail viene salvata in un file .emlx a sè stante. Se questa scelta da un lato ha lo svantaggio di rallentare parecchio il software nella gestione di caselle di 20000+ email, di contro rende semplicissimo usare strumenti di terze parti per interfacciarsi con la posta scaricata da Mail.

Un file .emlx, infati, non è altro che un comune file di testo contenente tutte le informazioni relative ad una e-mail, nè più nè meno. Provate ad aprirne uno con TextEdit (o altro editor a scelta) e vi renderete conto da soli che non vi sto imbarcando di cazzate 🙂

I quattro scripts che vi illustrerò in questa serie di tutorial servono tutti a trasformare le mail ricevute in una serie di dati utilizzabili ai fini statistici e/o per levarsi qualche curiosità 🙂 Per non “sporcare” i risultati è quindi consigliabile ripulire la propria casella con Mail (a mano o usando apposite smart folders) da e-mail inutili, come possono essere spam, pubblicità varie, newsletter etc. Se non si vogliono eliminare, si possono spostare temporaneamente da Posta In Arrivo in un altra cartella, per poi ripristinare il tutto quando lo script ha terminato il suo lavoro.

Lo script mail2topwordslist.sh:
Vi siete mai chiesti quali sono le parole più ricorrenti nei vostri scambi epistolari? Se la risposta è affermativa, il primo dei quattro esempi di interazione Apple Mail / Bash che voglio mostrarvi vi verrà molto comodo.

Questo script estrae tutte le parole dal corpo delle vostre email e genera tre files:
– un elenco grezzo di parole;
– una lista in formato testo nella quale suddette parole sono ordinate per numero di ricorrenze; esempio:

492 Ospedale
254 sedia
120 ghb
118 cannabis

– quest’ultima lista in formato CSV, utile per essere importato in un foglio di calcolo per ricavarne un grafico; esempio:

Ospedale,492
sedia,254
ghb,120
cannabis,118

Questi tre files vengono salvati nella sottocartella “output” presente nella cartella da cui viene lanciato lo script, e possono presentare della “sporcizia” (simboli come “>>” intesi come parole..) che, una volta terminata l’esecuzione dello script, dovrete ripulire a mano.

Prima di eseguire lo script, cambiate il contenuto della variabile “mail_folder”, sostituendola col il path della vostra inbox. Infine, da Terminale entrate nella cartella dello script e date i comandi:


chmod +x mail2topwordlist.sh #per dargli i permessi di esecuzione
sh mail2topwordlist.sh #per lanciarlo

Il codice sorgente
Ecco il codice dello script. Commenti, variabili e messaggi a schermo sono in inglese per renderlo comprensibile anche all’estero qualora servisse a qualche straniero.


#!/bin/sh

# eldino's mail2topwordslist v1.0
# take as input a folder full of e-mails in .emlx format (Apple Mail)
# and create a sorted list with all the most frequent words.

# CUSTOMIZE THE VARIABLE(S) BELOW BEFORE EXECUTING THE SCRIPT:
mail_folder="/Users/ruben/Library/Mail/POP-numbworks@pop.gmail.com/INBOX.mbox/Messages"

# --------You don't need to modify anything below!--------

# get the folder from which the script is running
# source: http://www.mydatabasesupport.com/forums/shell/176524-currently-executing-script-path.html
prog_path=$(cd -P -- "$(dirname -- "$0")" && pwd -P) && prog_path=$prog_path/$(basename -- "$0")
scriptFolder=$(echo $(dirname $prog_path)/)

# function: clear some garbage that you could find in the e-mail
# instead of accented letters etc.. you can improve
# this function yourself, basing on your language needs

MailSubjectCleanUp() {

 echo $* | sed 's/=?windows-1252?Q?//g' | sed 's/=?ISO-8859-1?Q?//g' | sed 's/=5B/[/g' | sed 's/=5D/]/g' | sed 's/=3A/:/g' | sed 's/=E8/è/g' | sed 's/_/ /g' | sed 's/=E0/ì/g' | sed "s/=27/'/g"

}

# function: extract the body of the e-mail

MailBodyExtract() {

 nTotalLines=`cat -n $* | tail -1 | cut -f1`
 BlockStartLineNumber=`cat -n $* | grep "\-\-00" | cut -f1 | head -1`
 BlockEndLineNumber=`cat -n $* | grep "\-\-00" | cut -f1 | head -2 | tail -1`
 shift_up=`expr $nTotalLines - $BlockStartLineNumber - 3`
 shift_down=`expr $BlockEndLineNumber - $BlockStartLineNumber - 4`

 cat $* | tail -$shift_up | head -$shift_down
}

# header
clear
echo "eldino's mail2topwordslist v1.0"
echo "---------------------------------------------------"
echo

# show intro advice
echo "The chosen mail_folder is:\n " $mail_folder "\nDo you wish to continue? [y/n]"
echo "WARNING: THE SCRIPT WILL DELETE THE CONTENT OF 'OUTPUT' SUBFOLDER, SO IF YOU NEED IT BACKUP IT NOW BEFORE PROCEED!"

read answer
if test "$answer" != "y"
then
 echo "You typed 'n' or something else, so I assume it's No."
 echo "Customize the mail_folder variable in the script and try again."
 exit
fi

# test: if folder doesn't exist..
echo
echo "Checking if the mail_folder exists..."
if test -d $mail_folder
then
 echo "Ok: The mail_folder exists!"
else
 echo "Error: The given mail_folder doesn't exists."
 echo "Fix the mail_folder variable in the script and try again."
 exit
fi

# test: if folder is empty, display error and stop script
echo
echo "Counting emails in mail_folder..."
mail_count=`ls $mail_folder | grep -c .emlx`
if test $mail_count == 0
then
 echo "Error: Folder is empty!"
 exit
else
 echo "Ok: You have" $mail_count "e-mails in the given folder."
fi

# test: if the output subfolder doesnt' exist, create it
echo
echo "Checking output subfolder..."
if test -d $scriptFolder/output/
then
 echo "Ok: The output subfolder exists!"
else
 echo "Error: The output subfolder doesn't exists. Creating it.."
 mkdir $scriptFolder/output/
 echo "Ok: Done!"
fi

# routine: remove and create fresh support files
# from 'output' subfolder inside 'mail_folder'
echo
echo "Removing support files from 'output' subfolder..."
echo $scriptFolder/output/
rm -f $scriptFolder/output/_words-list.txt
rm -f $scriptFolder/output/_words-list.csv
rm -f $scriptFolder/output/_words_tmp.txt
touch $scriptFolder/output/_words-list.txt
touch $scriptFolder/output/_words-list.csv
touch $scriptFolder/output/_words_tmp.txt
echo "Ok: Done!"

# routine: browse all the files in the folder
echo
echo "Generating words list..."
actual_count=0
for file in $mail_folder/*
do
 # if the file contains subject, it's an e-mail
 if test `cat $file | grep -c "Subject:"` == 1
 then

 # create word lists
 tmp_body=`MailBodyExtract $file`
 tmp_body=`MailSubjectCleanUp $tmp_body`
 echo $tmp_body | tr " " "\n" >> $scriptFolder/output/_words_tmp.txt

 fi

 # display the % of progress
 actual_count=`expr $actual_count + 1`
 echo "["`date "+20%y-%m-%d %H:%M"`"]" "Processed: " $actual_count "/" $mail_count "(" `echo "scale=4; ($actual_count / $mail_count) * 100" | bc` "%)"
done
echo "Ok: Done!"

# sort the list by number of occurences and create the final list
echo
echo "Sorting words list..."
sort $scriptFolder/output/_words_tmp.txt | uniq -c | sort -nr  > $scriptFolder/output/_words-list.txt
echo "Ok: Done!"

# convert result text files to csv
# (from scheme "<number> <word>" to scheme "<word>,<number>"
echo
echo "Creating the CSV file..."
exec < $scriptFolder/output/_words-list.txt
while read line
do
 line_array=($line)
 formatted_line="${line_array[1]}${line_array[2]}${line_array[3]},${line_array[0]}"

 echo $formatted_line >> $scriptFolder/output/_words-list.csv
done
echo "Ok: Done!"

# footer
echo
echo "Finish! Check the result files inside the following folder:"
echo $scriptFolder/output/
echo
echo "Thank you for using a script by eldino!"

Screenshots:
Di seguito posto qualche screenshot dello script in funzione, tanto per darvene un’idea 🙂

Advertisements

4 risposte a [IT] Bash: come interfacciarsi con Apple Mail via script (Mac OS X Leopard) – Parte 1/4

  1. […] [IT] Bash: come interfacciarsi con Apple Mail via script (Mac OS X Leopard) – Parte 2/4 Parte 1/4 […]

  2. […] con Apple Mail via script (Mac OS X Leopard) (Mac OS X Leopard) – Parte 3/4 Parte 1/4, Parte […]

  3. […] Bash: come interfacciarsi con Apple Mail via script (Mac OS X Leopard) – Parte 4/4 Parte 1/4, Parte 2/4, Parte […]

  4. […] Post & sourcecode here mail2subjectslist.sh […]

Rispondi

Inserisci i tuoi dati qui sotto o clicca su un'icona per effettuare l'accesso:

Logo WordPress.com

Stai commentando usando il tuo account WordPress.com. Chiudi sessione / Modifica )

Foto Twitter

Stai commentando usando il tuo account Twitter. Chiudi sessione / Modifica )

Foto di Facebook

Stai commentando usando il tuo account Facebook. Chiudi sessione / Modifica )

Google+ photo

Stai commentando usando il tuo account Google+. Chiudi sessione / Modifica )

Connessione a %s...

%d blogger hanno fatto clic su Mi Piace per questo: