Parches actualizados para "getmail"

En Migración de mi servidor de correo a IMAP4 y parches en "getmail" publico un parche para getmail que, entre otras cosas, detiene la descarga de correo cuando la partición IMAP4 se queda sin espacio, dejando algo de margen para poder procesar los buzones y hacer sitio.

Ese parche es incorrecto. Resulta que si se llena la partición la descarga se corta, pero los mensajes que se hayan recibido hasta ese momento no se borran en el servidor ni se deja constancia de su descarga. Es decir, cuando tengamos espacio libre... se volverán a descargar creando duplicados.

Esta fragilidad de getmail (hay muchas razones para que un programa falle en mitad de su ejecución) es fastidiosa, pero es lo que hay hasta que escriba un reemplazo. Estudiando el código y mirando cómo gestiona getmail los mensajes configurados como demasiado grandes, etc., veo que hay una forma "oficial" de hacer lo que quiero.

El parche actualizado, en formado diff, es el siguiente:

 --- /tmp/getmail-4.47.0/getmail 2015-02-26 02:10:44.000000000 +0100
 +++ getmail 2016-06-15 23:04:16.006254137 +0200
 @@ -1,3 +1,7 @@
 +#!/usr/local/bin/python
 +
 +# No uso lo siguiente porque entonces usa
 +# la version de Python del sistema, con OpenSSL antiguo y vulnerable.
  #!/usr/bin/env python

  import sys
 @@ -122,6 +126,20 @@
          log.info('more than one config file given with --idle, ignoring\n')
          idle = False

 +
 +    # JCEA - 08/mar/16
 +    import fcntl
 +    lock_jcea = open('/home/jcea/.getmail/getmail.lock', 'a')
 +    try :
 +        fcntl.flock(lock_jcea, fcntl.LOCK_EX | fcntl.LOCK_NB)
 +    except IOError :
 +        log.info('Proceso ya en curso. Muriendo')
 +        raise
 +
 +
 +
 +
 +
      for (configfile, retriever, _filters, destination, options) in configs:
          if options['read_all'] and not options['delete']:
              if idle:
 @@ -192,6 +210,23 @@
                                  > options['max_bytes_per_session']):
                          retrieve = False
                          reason = 'would surpass max_bytes_per_session'
 +
 +
 +           # JCEA - 17/mar/16
 +           import os
 +           vfs = os.statvfs('/home/jcea/.thunderbird/vtcvfnl8.default/Mail')
 +           free = vfs.f_bsize * vfs.f_bavail
 +           if free < 100*1024*1024 :
 +           msg = 'Solo quedan %dKbytes libres en la particion de correo. Abortando' %(free/1024)
 +           log.critical(msg)
 +           if configs[0][-1]['logfile']:
 +               configs[0][-1]['logfile'].write(msg)
 +           retrieve = False
 +           reason = msg
 +
 +           raise StopIteration(msg)
 +
 +
         try:
             if retrieve:
                 try:

El funcionamiento del parche ya está descrito con detalle en Migración de mi servidor de correo a IMAP4 y parches en "getmail". Los cambios respecto a esa versión son:

  1. El último fragmento de código se mueve más arriba en el código original, a la sección donde se decide si un mensaje concreto debe descargarse o no.

    La clave aquí son las líneas 47 y 48, donde se marca un mensaje como "no descargar" y se da un motivo.

    Este cambio sería suficiente para nuestros propósitos. El problema es que yo recibo miles de mensajes al día y, si se me llena la partición IMAP4, voy a imprimir miles de líneas de logs, uno por mensaje cada vez que getmail revisa mi buzón.

  2. Añado la línea 50 para solucionar el problema anterior. Ahora solo se imprime una línea de log por iteración de getmail, no por cada mensaje pendiente. Con este cambio las líneas 47 y 48 son innecesarias, pero no estorban y permiten que haga cambios en el futuro sin prestar mucha atención a los detalles.

Además de funcionar correctamente, una consecuencia de esta versión de mi parche es que getmail sigue utilizando IDLE correctamente para enterarse de que ha recibido correo nuevo. Eso es bueno, pero implica que no volverá a intentar descargar correo hasta que entre un mensaje nuevo en el buzón. Esto no es problema en mi caso concreto, porque raro es el minuto en el que no me entra algún mensaje nuevo. Pero si no fuera así, habría que desactivar el uso de IDLE y limitarse al CRON periódico. O parchear más, claro.