Ir al contenido
  1. Publicaciones/

Configurar Gmail en Emacs

··1766 palabras·9 mins

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
Figura 1: Repositorio oficial en Arch Linux

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.
Figura 2: mu en Arch Linux

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

Figura 3: Repositorio AUR en Arch Linux

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

Figura 4: Habilitar IMAP

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

Figura 5: Otra configuración de la cuenta de Google

Contraseña de aplicaciones

Figura 6: Contraseña de aplicaciones

Abre el desplegable Seleccionar dispositivo y elige un nombre

Figura 7: Elige un nombre

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

Figura 8: Contraseña de la aplicación
Figura 9: Aplicaciones que permiten su acceso mediante contraseña

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 --my-address=[email protected] --my-address=[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.

Figura 10: Solo lo pregunta la primera vez

Al final tendremos una pantalla parecid a esto

Figura 11: Tablero inicial de mu4e, para el buzon Gmail

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: #