Bad Daemons

Soporte de múltiples cuentas en Neomutt + encfs

En el anterior articulo expliqué como configurar neomutt con programas accesorios. Hoy toca hacerlo multicuenta y más privado.

Esto se gestionará con un simple script y moviendo todos los archivos configuración a un contenedor cifrado. Poco habrá que cambiar en la configuración ya hecha. Partiremos de la base de que los archivos de configuración están en las localizaciones que se establecieron en el anterior articulo.

Primero de todo, instalaremos y configuraremos encfs:

aptitude install encfs
# o
sbopkg -i encfs

Ahora crearemos dos directorios y luego el contenedor cifrado:

mkdir ~/.correo_{dec,enc}
encfs ~/.correo_enc ~/.correo_dec
# Presionamos p para ponerlo en modo paranoico
# Introducimos la contraseña

Ahora ya tenemos el contenedor cifrado en ~/.correo_enc/ y montado en ~/.correo_dec/. Antes de nada, recordar que si seguisteis el otro tutorial, hay que desactivar la linea de crontab que actualiza el correo. Podéis hacerlo ejecutando crontab -e. Una vez hecho, vamos a mover los archivos de configuración relevantes al contenedor. Del directorio mail, tener en cuenta que vamos a mover el directorio oculto que tiene, .notmuch, a la carpeta ~/.correo_dec/mail/, que es el directorio madre de todos los correos sea cual sea la cuenta:

mkdir -p ~/.correo_dec/{dotfiles,mail}
mv ~/.mutt ~/.correo_dec/dotfiles/mutt
mv ~/.muttrc ~/.correo_dec/dotfiles/muttrc
mv ~/.offlineimaprc ~/.correo_dec/dotfiles/offlineimaprc
mv ~/mail/ ~/.correo_dec/mail/cuenta1/
mv ~/.correo_dec/mail/cuenta1/.notmuch/ ~/.correo_dec/mail/cuenta1/
mv ~/.abook ~/.correo_dec/abook

El archivo de configuración de notmuch se queda fuera del contenedor, no importa. La base de datos que usa está en el directorio mail, que es la parte importante. Aún así, hay que editar el archivo y cambiar la ruta de la DB:

# nano ~/.notmuch-config
[database]
path=/home/$username/.correo_dec/mail/

Ahora crearemos un archivo offlineimaprc por cada cuenta que queramos tener. Yo mostraré cómo funcionar con dos (cuenta1 y cuenta2), pero si se entiende deberíais ser capaces de usar las que queráis. Crearemos los ficheros en el directorio ~/.correo_dec/dotfiles/:

cd ~/.correo_dec/dotfiles
cp offlineimaprc offlineimaprc.cuenta2
mv offlineimaprc offlineimaprc.cuenta1

Ahora hay que modificar el archivo offlineimaprc.cuenta1. No debería hacer falta modificar más que la variable localfolders, que tiene que apuntar a la nueva localización del correo de la cuenta, que será ~/.correo_dec/mail/cuenta1/. Del archivo offlineimaprc.cuenta2 habrá que cambiar todo, ya que será una cuenta de correo que aún no está configurada. Ahora ya debería funcionar offlineimap. Se puede comprobar del siguiente modo:

offlineimap -c ~/.correo_dec/dotfiles/offlineimaprc.cuenta1
offlineimap -c ~/.correo_dec/dotfiles/offlineimaprc.cuenta2

Sigamos. Ahora iremos a por mutt. Primero de todo, crear los dos archivos account igual que con offlineimap:

cd ~/.correo_dec/dotfiles/mutt/
cp account.example account.cuenta1
mv account.example account.cuenta2

Una vez más, modificamos todas las variables que sean necesarias, haciendo especial hincapié en las variables de los directorios de account.cuenta1. Una vez hecho esto, añadiremos la linea que permite el soporte multicuenta real de mutt, editando la primera linea del archivo ~/.correo_dec/dotfiles/mutt/muttrc:

# cambiamos la siguiente linea:
source "~/.mutt/account.example"
# por
source "~/.correo_dec/dotfiles/mutt/`echo $CUENTA`"

Cambiamos el resto de las rutas una vez más, haciendo que apunten de del directorio ~/.mutt/ al ~/.correo_dec/dotfiles/mutt/. Ahora sólo queda modificar dos scripts y crear uno.

Crearemos el siguiente script en /usr/local/bin/correo:

#!/bin/bash

# comprueba si encfs está montado
activo="$(mount | grep correo)"
# rutas de los contenedores cifrados
enc="/home/`whoami`/.correo_enc"
dec="/home/`whoami`/.correo_dec"
# una variable que se usará para decidir si mutt se abre en la propia terminal o si se llama a una ventana nueva
term="linux"

# Necesita que se le pase una variable, cuenta1 o cuenta2
if [[ -z $1 ]]
then
    echo "Tienes que decir que cuenta, idiota. 1 es la de cuenta1, 2 la de cuenta2."
    sleep 10
    exit
fi

if [[ $1 -eq 1 ]]
then
    cuenta="cuenta1"
    # la cuenta1 tendrá soporte de tor
    tor="torify"
fi

if [[ $1 -eq 2 ]]
then
    cuenta="cuenta2"
    # la cuenta2 no tendrá soporte de tor
fi

# creamos un archivo conteniendo el nombre de la cuenta que se usará para saber cual actualizar con el script mailsync
echo $cuenta > /tmp/mutt

if [[ $TERM = $term ]]
then
    if [[ -n $activo ]]
    then
        urxvtc -title mutt -e bash -c "CUENTA=`echo $cuenta` $tor mutt -F $dec/dotfiles/mutt/muttrc && fusermount -u $dec"
    else
        urxvtc -title mutt -e bash -c "encfs $enc $dec && CUENTA=`echo $cuenta` $tor mutt -F ~/.correo_dec/dotfiles/mutt/muttrc && fusermount -u $dec"
    fi
else
    if [[ -n $activo ]]
    then
        CUENTA=`echo $cuenta` $tor mutt -F $dec/dotfiles/mutt/muttrc && fusermount -u $dec
    else
        encfs $enc $dec && CUENTA=`echo $cuenta` $tor mutt -F ~/.correo_dec/dotfiles/mutt/muttrc && fusermount -u $dec
    fi
fi

rm /tmp/mutt

He comentado el archivo para que quede medio claro, pero añadiré un par de cosas. La variable $term, cómo dice el comentario del script, sirve para decidir si se abre una nueva terminal o se usará mutt desde la propia. Esto tiene un sentido, y es el siguiente. Yo puedo usar mutt de dos formas, llamándolo directamente desde una terminal o ejecutando dmenu, que es algo típico en i3-wm. Entonces lo que se hace es comparar $term con la variable $TERM, que todas las terminales declaran. En función a esto se decidirá si lanzar una terminal nueva o usar la actual. Si no me he explicado, podéis preguntar en los comentarios.

Otro tema a comentar es la declaración de la variable $CUENTA. Esta es la magia de mutt, permite que se le pasen variables de entorno. Por eso, si recordáis, en el archivo muttrc la primera linea era:

source "~/.correo_dec/dotfiles/mutt/`echo $CUENTA`"

Aquí es dónde se define esa variable y mutt la coge sin más. Por eso, siempre que se ejecute mutt sin pasarle la variable $CUENTA fallará. Le añadimos permisos de ejecución con chmod +x /usr/local/bin/correo. A partir de ahora, cuando queramos usar neomutt no usaremos mutt desde la terminal sin más, usaremos el script correo.

El script siempre pedirá al ejecutarse que se introduzca la contraseña del contenedor cifrado y lo desmontará al terminar. Aún así, alguna vez puede cerrarse mal y no desmontarlo, por ello se comprueba si está montado.

Ahora modificaremos ~/.correo_dec/dotfiles/mutt/scripts/auto-process.sh y /usr/local/bin/mailsync. Del primero sólo debemos cambiar la ruta de la agenda, que pasaría de --datafile ~/.abook a --datafile ~/.correo_dec/dotfiles/abook. El segundo es más complejo, por lo que yo simplemente borraría el existente y copiaría el siguiente:

#!/bin/bash

username=`whoami`

# commands
abook="/home/$username/.correo_dec/dotfiles/mutt/scripts/auto-process.sh"
autotag="/home/$username/.correo_dec/dotfiles/mutt/scripts/filtros.sh"

# accounts
cuenta1_localfolder="/home/$username/.correo_dec/mail/cuenta1/"
cuenta2_localfolder="/home/$username/.correo_dec/mail/cuenta2/"

# comprueba si el contenedor encfs está desbloqueado, entra solo si lo está
blocked="$(ls $abook 2> /dev/null)"

if [[ -n $blocked ]]
then
    # comprueba si offlineimap se ha quedado colgado
    imapactive=`ps -ef | grep offlineimap | grep -v grep | wc -l`
    # comprueba si hay conexión a internet
    online=`curl --silent http://gnu.org | wc -l`

    case $imapactive in
        '1')
            killall offlineimap && sleep 5
            ;;
    esac

    case $online in
        '9')
            # que cuenta hay que actualizar
            cuenta="$(cat /tmp/mutt)"
            if [[ $cuenta = "cuenta1" ]]
            then
                # se usa tor con cuenta1
                tor="torify"
            else
                # se usa tor con cuenta2
                tor=""
            fi

            offlineimaprc="/home/$username/.correo_dec/dotfiles/offlineimaprc.$cuenta"
            mailsync="offlineimap -c $offlineimaprc -u quiet -q"
            echo "Ejecutando offlineimap..."
            $tor $mailsync
            echo "Indexando emails..."
            notmuch new > /dev/null
            echo "Autoguardando contacts..."
            $abook
            echo "Autotaggeando..."
            $autotag
            ;;
    esac
fi

Una vez hecho todo esto, que no es poco, ya tendremos una configuración multicuenta y segura del gestor de correo liviano Neomutt.