Configurar Gmail en Emacs

2023-03-07

Índice

  1. Programas necesarios
    1. mbsync
    2. mu
    3. mu4e
  2. Configuración de mbsync
  3. Preparando Gmail
    1. Habilitar IMAP
    2. 2FA
  4. Inicializar el almacenamiento
  5. Indexación mensajes
  6. Configuración de Emacs
  7. Envío de correo
  8. Securizando los ficheros de configuración
  9. Referencias:

Poco a poco sigo integrando mi flujo de trabajo dentro de Emacs, agenda, calendario, lector de noticias, mastodon, telegram pero me faltaba integrar el correo electrónico.

A parte de gmail, manejo otras dos cuentas más de correo, protonmail y la de mi propio servidor de correo, las cuales manejaba a través de sus interfaces web, ello supone el tener que cambiar desde Emacs al navegador web cada vez que quiero comprobar si tengo correos nuevos, por no hablar de que al no tener una copia local de mis correos, si esos servicios caen o cierran, mis correos también.

Unas de las cosas que más me abruma de Emacs, es la cantidad de paquetes que hay para realizar una misma cosa, como por ejemplo, manejar el correo electrónico.

Otro de los problemas que suelo encontrar es que aunque todo esta documentado, dan por sentado ciertos conocimientos, que en mi caso, carezco de ellos, y es casi imposible encontrar guías para torpes que me lleven paso a paso a mi objetivo.

Programas necesarios

Para configurar Emacs como cliente de correo, voy a utilizar los siguientes programas

mbsync

Se utiliza para descargar correos electrónicos desde diferentes servidores IMAP y sincronizar los cambios realizados con nuestro buzon local. En algunas distribuciones GNU/Linux el paquete para su instalación se conoce como Isync

mbsync --version

isync 1.4.4

img

mu

Se utiliza para indexar nuestros correos electrónicos en una base de datos local, para poder buscar, eliminar, etc.

mu -V

mu (mail indexer/searcher) version 1.8.13
Copyright (C) 2008-2022 Dirk-Jan C. Binnema
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

img

mu4e

Interfaz para Emacs de mu

Al instalar mu, también se instala mu4e ya que es parte de mu. Por ejemplo en Arch Linux esta disponible en el repositorio AUR

img

Configuración de mbsync

Necesitamos crear un fichero de configuración para mbsync, crea un fichero llamado .mbsyncrc en tu $HOME con el siguiente código:

IMAPAccount gmail
Host imap.gmail.com
User [email protected]
Pass password_gmail
AuthMechs LOGIN
SSLType IMAPS
CertificateFile /etc/ssl/certs/ca-certificates.crt

IMAPStore gmail-remote
Account gmail

MaildirStore gmail-local
Subfolders Verbatim
Path ~/.mail/gmail/
Inbox ~/.mail/gmail/Inbox

Channel gmail
Far :gmail-remote:
Near :gmail-local:
Patterns * ![Gmail]* "[Gmail]/Sent Mail" "[Gmail]/Starred" "[Gmail]/All Mail"
Create Both
SyncState *

IMAPStore synology-remote
Account synology

IMAPAccount synology
Host synology.es
User [email protected]
Pass xxxxxxx
AuthMechs LOGIN
SSLType IMAPS
CertificateFile /etc/ssl/certs/ca-certificates.crt

IMAPStore synology-remote
Account synology

MaildirStore synology-local
Subfolders Verbatim
Path ~/.mail/synology/
Inbox ~/.mail/synology/Inbox

Channel synology
Far :synology-remote:
Near :synology-local:
Patterns *
Create Both
SyncState *

Sustituye las x por tu usuario

Crea la carpeta ~/.mail para alojar el buzón de correo local

  • Path carpeta local de nuestro ordenador donde mbsync almacena los correos, en mi caso gmail
  • Inbox carpeta local para la bandeja de entrada de nuestro buzón
  • Patterns filtra las carpetas que queremos sincronizar, en mi ejemplo solo las carpetas Sent Mail, Starred y All Mail, si quieres sincronizar todas las carpetas utiliza Patterns *
  • Pass contraseña de gmail, si utilizas 2FA salta lee la siguientte seccion

Aneas de ejecutar mu debes de haber creada la carpeta ~/.mail/gmail

En caso de necesitar trabajar con más de una cuenta de correo IMAP, puedes ir añadiendo las que necesites como en el ejemplo (cuenta synology)

Preparando Gmail

Habilitar IMAP

Tienes que habilitar IMAP en tu cuenta Gmail, dirigirte a la configuración de tu cuenta, pestaña Reenvio y correo POP/IMAP

img

2FA

Si utilizas autentificación de dos factores en tu cuenta de Gmail necesitas generar una Contraseña de aplicaciones, lo puedes hacer desde la configuración de Gmail en Cuentas e importación -> Seguridad -> Otra configuración de la cuenta de Google

img

Contraseña de aplicaciones

img

Abre el desplegable Seleccionar dispositivo y elige un nombre

img

Cuando pulses en el botón Generar te aparecera la contrassña que utilizaremos en el fichero .mbsyncrc

img

img

Inicializar el almacenamiento

La primera vez que ejecutamos mu, debemos inicializar la base de datos, agregamos la dirección de correo electrónico para que mu la reconozca como suya

Ejecutamos el siguiente comando:

mu init --maildir=~/.mail [email protected] [email protected]

+-------------------+-------------------------------+
| maildir           | /home/carlos/.mail            |
+-------------------+-------------------------------+
| database-path     | /home/carlos/.cache/mu/xapian |
+-------------------+-------------------------------+
| schema-version    | 465                           |
+-------------------+-------------------------------+
| max-message-size  | 100000000                     |
+-------------------+-------------------------------+
| batch-size        | 250000                        |
+-------------------+-------------------------------+
| created           | vie 20 ene 2023 23:56:45      |
+-------------------+-------------------------------+
| personal-address  | [email protected]             |
+-------------------+-------------------------------+
| personal-address  | [email protected]            |
+-------------------+-------------------------------+
| messages in store | 0                             |
+-------------------+-------------------------------+
| last-change       | never                         |
+-------------------+-------------------------------+
| last-index        | never                         |
+-------------------+-------------------------------+

store created; use the 'index' command to fill/update it.

Indexación mensajes

Una vez descargado todo el correo el correo e inicializado la base de datos, debemos indexar los mensajes para almacenar la información sobre ellos

mu index

indexing maildir /home/carlos/.mail -> store /home/carlos/.cache/mu/xapian
\ indexing messages; checked: 0; updated/new: 0; cleaned-up: 0

| indexing messages; checked: 126; updated/new: 0; cleaned-up: 0 / indexing messages; checked: 126; updated/new: 0; cleaned-up: 0

Configuración de Emacs

Ahora que ya tenemos todo lo relativo a mu funcionando, pasamos a configurar mu4e (mu for Emacs), para su instalación utilizo Use Package

Lo mas importante de esta configuración, es que al utilizar dos buzones de correo (gmail y synology) utilizo dos “contexts”

También hay una función que pregunta si vas a firmar o cifrar el mensaje antes de enviarlo. mml-secure-message-sign-pgpmime y mml-secure-message-encrypt-pgpmime, que recuperan automáticamente las claves gpg y las agrega al mensaje antes de enviarlo.

(use-package mu4e
  :ensure nil
  :bind ("C-c m" . mu4e)
:config
(setq mail-user-agent 'mu4e-user-agent          ; mu4e e-mail default program
      message-kill-buffer-on-exit t
      message-send-mail-function 'smtpmail-send-it
      mu4e-attachment-dir "~/Descargas"
      mu4e-change-filenames-when-moving t
      mu4e-completing-read-function 'completing-read
      mu4e-compose-complete-addresses t
      mu4e-compose-context-policy nil
      mu4e-compose-dont-reply-to-self t
      mu4e-compose-keep-self-cc nil
      mu4e-context-policy 'pick-first
      mu4e-get-mail-command "mbsync -a"
      mu4e-headers-date-format "%d-%m-%Y %H:%M"
      mu4e-headers-fields '((:human-date . 20)
                            (:flags . 6)
                            (:mailing-list . 10)
                            (:from . 22)
                            (:subject))
      mu4e-headers-include-related t
      mu4e-sent-messages-behavior 'delete       ; don't save messages to Sent Messages
      mu4e-view-show-addresses t
      smtpmail-debug-info t
      smtpmail-stream-type 'starttls
      mm-sign-option 'guided
      mu4e-html2text-command "w3m -T text/html" ; how to hanfle html-formatted emails
      mu4e-update-interval 300                  ; seconds between each mail retrieval
      mu4e-headers-auto-update t                ; avoid to type `g' to update
      mu4e-view-show-images t                   ; show images in the view buffer
      mu4e-compose-signature-auto-include nil   ; I don't want a message signature
      mu4e-use-fancy-chars t)                   ; allow fancy icons for mail threads


(when (fboundp 'imagemagick-register-types)
  (imagemagick-register-types))

(defun sign-or-encrypt-message ()
  (let ((answer (read-from-minibuffer "Firmar o cifrar?\nEn blanco no hace nada.\n[f/c]: ")))
    (cond
     ((string-equal answer "f") (progn
                                  (message "Firmando mensaje.")
                                  (mml-secure-message-sign-pgpmime)))
     ((string-equal answer "c") (progn
                                  (message "Cifrando y formando mensaje.")
                                  (mml-secure-message-encrypt-pgpmime)))
     (t (progn
          (message "No firmar o cifrar mensaje.")
          nil)))))

(add-hook 'message-send-hook 'sign-or-encrypt-message)

(setq mu4e-contexts
      `( ,(make-mu4e-context
           :name "gmail"
           :enter-func (lambda ()
                         (mu4e-message "Entering gmail context")
                         (when (string-match-p (buffer-name (current-buffer)) "mu4e-main")
                           (revert-buffer)))
           :leave-func (lambda ()
                         (mu4e-message "Leaving gmail context")
                         (when (string-match-p (buffer-name (current-buffer)) "mu4e-main")
                           (revert-buffer)))
           :match-func (lambda (msg)
                         (when msg
                           (or (mu4e-message-contact-field-matches msg :to "[email protected]")
                               (mu4e-message-contact-field-matches msg :from "[email protected]")
                               (mu4e-message-contact-field-matches msg :cc "[email protected]")
                               (mu4e-message-contact-field-matches msg :bcc "[email protected]")
                               (string-match-p "^/gmail/Inbox" (mu4e-message-field msg :maildir)))))
           :vars '( ( user-mail-address            . "[email protected]" )
                    ( smtpmail-smtp-user           . "[email protected]" )
                    ( mu4e-compose-signature       . "Carlos M." )
                    ( smtpmail-smtp-server         . "smtp.gmail.com" )
                    ( smtpmail-smtp-service        . 587 )
                    ( mu4e-maildir-shortcuts       . ((:maildir "/gmail/Inbox" :key ?i)))
                    ( mu4e-bookmarks
                      .
                      (( :name  "Unread messages"
                         :query "maildir:/gmail/Inbox AND flag:unread AND NOT flag:trashed AND NOT outdoorexperten"
                         :key ?u)
                       ( :name "Today's messages"
                         :query "maildir:/gmail/Inbox AND date:today..now"
                         :key ?t)
                       ( :name "Last 7 days"
                         :query "maildir:/gmail/Inbox AND date:7d..now"
                         :hide-unread t
                         :key ?w)
                       ( :name "Deleted"
                         :query "flag:trashed"
                         :key ?d)))))

         ,(make-mu4e-context
           :name "synology"
           :enter-func (lambda ()
                         (mu4e-message "Entering synology context")
                         (when (string-match-p (buffer-name (current-buffer)) "mu4e-main")
                           (revert-buffer)))
           :leave-func (lambda ()
                         (mu4e-message "Leaving synology context")
                         (when (string-match-p (buffer-name (current-buffer)) "mu4e-main")
                           (revert-buffer)))
           :match-func (lambda (msg)
                         (when msg
                           (or (mu4e-message-contact-field-matches msg :to "[email protected]")
                               (mu4e-message-contact-field-matches msg :from "[email protected]")
                               (mu4e-message-contact-field-matches msg :cc "[email protected]")
                               (mu4e-message-contact-field-matches msg :bcc "[email protected]"))))

           :vars '( ( user-mail-address       . "[email protected]" )
                    ( smtpmail-smtp-user      . "[email protected]" )
                    ( smtpmail-smtp-server    . "smtp.synology.es" )
                    ( smtpmail-smtp-service   . 587 )
                    ( mu4e-compose-signature  . "Carlos M." )
                    ( mu4e-maildir-shortcuts  . ((:maildir "/synology/Inbox" :key ?i)))
                    ( mu4e-bookmarks
                      .
                      (
                       ( :name  "Unread messages"
                         :query "maildir:/synology/Inbox AND flag:unread AND NOT flag:trashed"
                         :key ?u)
                       ( :name  "Draft mails"
                         :query "maildir:/synology/Draft"
                         :key ?b)
                       ( :name  "Sent mails"
                         :query "maildir:/synology/Sent"
                         :key ?s)
                       ( :name  "Junk"
                         :query "maildir:/synology/Junk"
                         :key ?j)
                       ( :name  "Trash"
                         :query "maildir:/synology/Trash"
                         :key ?t)
                       ( :name "Deleted"
                       :query "flag:trashed"
                       :key ?d))))))))

Tan solo nos queda ejecutar mu4e, la primera vez que lo ejecutamos nos preguntara si queremos crear ciertas carpetas que no existen en nuestro buzón local y responde que si.

img

Al final tendremos una pantalla parecid a esto

img

Envío de correo

Para el envío de correo hacemos uso de smtpmail-smtp-server y smtpmail-smtp-user, Emacs busca los datos de conexión en el fichero ~/.authinfo o en la ruta que especifiquemos en auth-sources de la configuración. Por ejemplo

(setq auth-sources '("~/.gnupg/shared/authinfo"))

El fichero ha de tener el siguiente formato

machine servidor login usuario port numero_puerto password xxxxxxxxxxx

Ejemplo:

machine smtp.gmail.com login [email protected] port 587 password xxxxxxxxxxx
machine smtp.dominio.es login [email protected] port 587 password xxxxxxxxxx

Securizando los ficheros de configuración

Durante el proceso de configuración de los ficheros .mbsync y autinfo hemos introducido las contraseñas de nuestro usuario de modo que cualquiera con acceso a nuestro ordenador puede verlas sin problemas.

Podemos arreglar esto fácilmente haciendo uso de gpg y aprovechar la integración de Emacs con gpg.

Debemos de crear un fichero por cada clave de correo, en el ejemplo un fichero cifrado con gpg qwe contendrá la clave de gmail y otro para la clave de la cuenta synology

Además también cifraremos el fichero authinfo

ls -lh ~/.gnupg/shared

total 12K
-rw-r--r-- 1 carlos carlos 540 dic 16 21:33 authinfo.gpg
-rw-r--r-- 1 carlos carlos 476 dic 16 21:42 gmail.gpg
-rw-r--r-- 1 carlos carlos 480 dic 17 15:09 synology.gpg

Después de cifrar los ficheros modificamos .mbsync borrando la linea que hace refecnaia a PASS por PassCmd "gpg2 --quiet --for-your-eyes-only --no-tty --decrypt ~/.gnupg/shared/gmail.gpg" y PassCmd "gpg2 --quiet --for-your-eyes-only --no-tty --decrypt ~/.gnupg/shared/synology.gpg"

IMAPAccount gmail
Host imap.gmail.com
User [email protected]
PassCmd "gpg2 --quiet --for-your-eyes-only --no-tty --decrypt ~/.gnupg/shared/gmail.gpg"
AuthMechs LOGIN
................

Espero que te haya gustado, pasa un gran día 🐧

Referencias:


Ingrese la dirección de su instancia