procmailex - ejemplos de ficheros de recursos Para un descripción del formato del fichero de recursos véase La técnica de puntuación de peso se describe en detalle en la página de manual de Esta página de manual muestra varios ejemplos de recetas. Por ejemplo ficheros de recursos completos que puede comprobar en la sección NOTAS en o mirar a la parte de ejemplos de ficheros de recursos de la distribución fuente de procmail (procmail*/examples/?procmailrc). Ordena todo el correo procedente de la lista de correo scuba-dive en la carpeta de correo ficheroscuba (usa el fichero de bloqueo local scubafile.lock). 3 :0: * ^TOscuba ficheroscuba Reenvía todo el correo de pedro sobre compiladores a guillermo (y mantiene una copia aquí en petcompil). 10 :0 * ^From.*pedro * ^Subject:.*compiladores { :0 c ! guillermo@algunsitio.edu :0 petcompil } Una solución equivalente que realiza lo mismo: 7 :0 c * ^From.*pedro * ^Subject:.*compiladores ! guillermo@algunsitio.edu :0 A petcompil Una solución equivalente, pero ligeramente más lenta que realiza lo mismo: 9 :0 c * ^From.*pedro * ^Subject:.*compiladores !guillermo@somewhere.edu :0 * ^From.*pedro * ^Subject:.*compiladores petcompil Si vd. es completamente nuevo en procmail y quiere experimentar un poquito, con frecuencia ayuda tener una de algún tipo. Inserte las dos siguientes recetas sobre todas las otras recetas para estar seguro de que todo el correo que llega siempre conserva los últimos 32 mensajes. Para que funcione como se prentende, tiene que crear un directorio llamado `backup' en $MAILDIR antes de insertar estas dos recetas. 5 :0 c backup :0 ic | cd backup && rm -f dummy `ls -t msg.* | sed -e 1,32d` Si su sistema no genera o genera líneas `From' iniciales incorrectas en cada mensaje, puede corregir esto llamando a procmail con la opción -f- . Para corregir el mismo problema por medios distintos, podría haber insertado las dos siguientes recetas sobre todas las otras del fichero de recursos. Estas filtrarán la cabecera de cualquier mensaje mediante formail que elimina cualquier `From' inicial y lo regenera automáticamente a continuación. 2 :0 fhw | formail -I "From " -a "From " Añade las cabeceras de todos los mensajes que no vienen del postmaster a su colección de cabeceras privadas (para uso estadístico o depuración de correo); y usa el fichero de bloqueo `headc.lock'. Para estar seguro de que el fichero de bloqueo no se elimina hasta que la tubería ha finalizado, tendrá que especificar la opción `w'; en otro caso el fichero de bloqueo sería eliminado tan pronto como la tubería ha aceptado el correo. 3 :0 hwc: * !^FROM_MAILER | uncompress headc.Z; cat >>headc; compress headc O, si usara gzip, más eficiente que compress: 3 :0 hwc: * !^FROM_MAILER | gzip >>headc.gz Reenvía todos los mensajes de menos de 1000 bytes a mi dirección personal (no se necesita fichero de bloqueo en esta receta). 3 :0 * < 1000 ! myname@home Divide las recopilaciones de la lista de correo surfing en mensajes individuales y los almacena en surfing, usando como fichero de bloqueo local surfing.lock. 3 :0: * ^Subject:.*surfing.*Digest | formail +1 -ds >>surfing Almacena todo lo que llega del postmaster o mailer-daemon (como correo rebotado) en el fichero postm, usando como fichero de bloqueo local postm.lock. 3 :0: * ^FROM_MAILER postm Una simple receta de respuesta automática. Se toma la seguridad que ni el correo de cualquier demonio (como correo rebotado o correo de una lista), ni las respuestas automáticas procedentes de usted mismo serán respondidas automáticamente. Si no se toma esta precaución, podrían suceder desastres (correo en anillo). Para que esta receta responda a todo el correo entrante, desde luego, debería insertarla antes que cualquier otra receta en su fichero de recursos. Sin embargo es aconsejable ponerla cualquier receta que procese los correos de una lista de correo a la que estemos suscritos; generalmente no es buena idea generar autorespuestas a las lista de correo(sí, la expresión regular !^FROM_DAEMON debería coger esos, pero si la lista de correo no sigue las convenciones aceptadas, esto podría ser 6 :0 h c * !^FROM_DAEMON * !^X-Loop: your@own.mail.address | (formail -r -I"Precedence: junk" \ -A"X-Loop: su_propia@dirección.de.correo" ; \ echo "Mail recibido.") | $SENDMAIL -t Una receta de autorespuesta más complicada que lleva a cabo funciones equivalentes al bien conocido programa Esta receta está basada en los mismos principios que la última (previniendo el correo en `anillo'). Además de eso, sin embargo, mantiene una base de datos vacation extrayendo el nombre del remitente e insertandolo en el fichero vacation.cache si el nombre es nuevo (el fichero vacation.cache lo mantiene formail que estará seguro que siempre contiene los nombres más recientes, el tamaño del fichero está limitado a un máximo de aproximadamente 8192 bytes). Si el nombre es nuevo, se envía una respuesta automática. Como puede ver, la siguiente receta tiene comentarios las condiciones. Esto está permitido. Sin embargo ponga comentarios en la misma línea que una condición. 18 SHELL=/bin/sh # para otras shells, esto podría necesitar ajustes :0 Whc: vacation.lock # Realiza un chequeo rápido para ver si el correo va dirigido a nosotros * $^To:.*\<$\LOGNAME\> # No responde a demonios ni a listas de correo * !^FROM_DAEMON # Los bucles de correo son un desastre * !^X-Loop: your@own.mail.address | formail -rD 8192 vacation.cache :0 ehc # si el nombre no está en el caché | (formail -rI"Precedence: junk" \ -A"X-Loop: your@own.mail.address" ; \ echo "He recibido tu correo,"; \ echo "pero no regresaré hasta el lunes."; \ echo "-- "; cat $HOME/.signature \ ) | $SENDMAIL -oi -t Almacena todos los mensajes referentes a TeX en un fichero único separado, en un directorio llamado texmail (este directorio tiene que existir); no hay necesidad de usar ficheros locales de bloqueo en este caso, por tanto no lo haremos. 3 :0 * (^TO|^Subject:.*)TeX[^t] texmail Lo mismo que arriba, salvo que ahora almacenamos los mensajes en ficheros numerados (carpeta de correo MH). 3 :0 * (^TO|^Subject:.*)TeX[^t] texmail/. O podría archivar el correo en varios carpetas directorios a la misma vez. La siguiente receta entregará el correo a carpetas MH y una carpeta directorio. Actualmente es sólo un fichero con dos enlaces duros extras. 3 :0 * (^TO|^Subject:.*)TeX[^t] texmail/. wordprocessing dtp/. Almacena todos los mensajes sobre encuentros en una carpeta que está en un directorio que cambia cada mes. V. g. si fuera Enero de 1994, la carpeta tendría el nombre `94-01/encuentros' y le fichero de bloqueo local sería `94-01/encuentros.lock'. 3 :0: * meeting `date +%y-%m`/encuentros Lo mismo que arriba, pero si el directorio `94-01' no existiera, se crearía automáticamente 9 CARPETAMESUAL=`date +%y-%m` :0 Wic * ? test ! -d $CARPETAMESUAL | mkdir $CARPETAMESUAL :0: * encuentro ${CARPETAMESUAL}/encuentro Lo mismo que arriba, pero con medios ligeramente diferentes: 6 CARPETAMESUAL=`date +%y-%m` DUMMY=`test -d $CARPETAMESUAL || mkdir $CARPETAMESUAL` :0: * encuentros ${CARPETAMESUAL}/meeting Si está suscrito a varias listas de correo y la gente envía mesajes cruzados a varias de ellas, normalmente recibe varios correos duplicados (uno de cada lista). La siguiente receta simple elimina mensajes duplicados. Le dice a formail que mantenga un fichero cache de 8Kb en el cual se almacenan los identificadores de mensaje de los correos más reciente que ha recibido. Como se garantiza que los identificadores de mensaje son únicos para cada mensaje, son ideales para descartar los mensajes duplicados. Simplemente ponga la siguiente receta al comienzo de su fichero de recursos y ningún mensaje duplicado logratá pasarla. 2 :0 Wh: msgid.lock | formail -D 8192 msgid.cache si tiene problemas de entrega en las recetas debajo de esto y procmail intenta reencolar el correo, entonces en la próxima ejecución de la cola, este mensaje se considerará duplicado y seráeliminado. Para quienes quieren seguridad pueden usar la siguiente receta en su lugar. Esta pone los duplicados en una carpeta separada en lugar de eliminarlos. Esto le obliga a vaciar periódicamente la carpeta, por supuesto. 5 :0 Whc: msgid.lock | formail -D 8192 msgid.cache :0 a: duplicates Procmail puede entregar a carpetas MH directamente, pero no actualiza las secuencias no vistas que el MH real gestiona. Si quiere que procmail actualice estas también , use una receta como la siguiente que almacena todo lo que tenga la palabra spam en el cuerpo del mensaje en una carpeta MH llamada spamfold. Observe que el fichero de bloqueo local, que es necesario porque los progamas MH no bloquean el ficher de secuencias. Las llamadas asíncronas de los progamas MH que cambian el fichero de secuencias pueden corromper el fichero o simplemente perder los cambios. Por desgracia, el fichero de bloqueo no resuelve el problema completamente ya que rcvstore se podría llamar mientras `show' o `mark' u otro programa MH está en ejecución. El problema se epera corregir en alguna versión futura de MH, pero hasta entonces tendrá que valorar el riesgo de perder o corromper las secuencias contra lo beneficios de las secuencias no vistas. 3 :0 :spamfold/$LOCKEXT * B ?? spam | rcvstore +spamfold Cuando entregue a carpetas emacs (i.e. carpetas de correo gestionadas por cualquier paquete de correo de emacs, v.g. RMAIL o VM) directamente, debería usar ficheros de bloqueo compatibles con emacs. Los programas de correo de emacs son un poco descerebrados en ese respecto, se molestan mucho si alguien entrega a carpetas de correo que ellos ya tienen en sus bufferes internos. La siguiente receta supone que $HOME es igual a /home/john. 5 MAILDIR=Mail :0:/usr/local/lib/emacs/lock/!home!john!Mail!mailbox * ^Subject:.*loquesea mailbox De forma alternativa, puede hacer que procmail entrega en su propio conjunto de carpetas, las cuales se pueden vaciar periódicamente yu copiarlas sobre sus porpios ficheros emacs usando Movemail usa ficheros de bloqueo locales buzón.lock por buzón. Actualmente este es el modo de operación preferido en conjunción con procmail. Para extraer ciertas cabeceras de un correo y pponerlas en variables de entorno puede usar cualquiera de las siguientes construcciones: 5 SUBJECT=`formail -xSubject:` # campo regular FROM=`formail -rt -xTo:` # caso especial :0 h # método alternativo KEYWORDS=| formail -xKeywords: Si usa ficheros temporales en un fichero procmailrc, y quieres estar seguro de que se eliminan antes de que procmail termine, podría usar algo como las líneas de: 2 TEMPORARY=$HOME/tmp/pmail.$$ TRAP="/bin/rm -f $TEMPORARY" TRAP se puede usar para modificar el código de salida de procmail. I.e. si quiere que procmail devuelva un código de salida de `1' en lugar de sus códigos de salida regulares, podría usar: 3 EXITCODE="" TRAP="exit 1;" # El punto y coma final es importante. # ya que exit no es un programa standalone O, si el código de salida no necesita depender de la ejecución de programas de TRAP, puede usar un simple: 1 EXITCODE=1 La siguiente receta imprime cada correo de entrada que se parezca a un fichero postscript. 3 :0 Bb * ^^%! | lpr La siguiente receta hace lo mismo, pero un poco más selectiva. Sólo imprime el fichero postscript si viene del servidor de impresión. La primera condición concuerda sólo si se encuentra en la cabecera. La segunda condición sólo concuerda al comienzo del cuerpo. 4 :0 b * ^From[ :].*print-server * B ?? ^^%! | lpr Lo mismo que arriba, pero por unos medios ligeramente diferentes: 7 :0 * ^From[ :].*print-server { :0 B b * ^^%! | lpr } Igualmente: 4 :0 HB b * ^^(.+$)*From[ :].*print-server * ^^(.+$)*^%! | lpr Supongamos que tiene dos cuentas y usa esas dos cuentas regularmente, pero están en lugares distintos (i.e. sólo podría leer el correo que llega a una de las cuentas). Le gustaría reenviar el correo que llega a la cuenta uno a la cuenta dos y al contrario. Lo primero que se viene a la mente es usar ficheros .forward en ambos sitios; esto no funcionará, desde luego, ya que estará creando un bucle de correo. Este bucle se puede evitar insertando la siguiente receta frente a todas las otras recetas en los ficheros$HOME/.procmailrc de ambos sitios. Si está seguro que añade el mismo campo X-Loop: en ambos sitios, el correo se puede reenviar de una cuenta a otra con garantías. 4 :0 c * !^X-Loop: yourname@your.main.mail.address | formail -A "X-Loop: yourname@your.main.mail.address" | \ $SENDMAIL -oi yourname@the.other.account Si alguien le envía un correo con la palabra `retrieve' en el campo `subject', lo siguiente devolverá automáticamente el contenido del fichero info_file al remitente. Como en todas las recetas donde enviamos correo, tenemos que vigilar los bucles de correo. 6 :0 * !^From +YOUR_USERNAME * !^Subject:.*Re: * !^FROM_DAEMON * ^Subject:.*retrieve | (formail -r ; cat info_file) | $SENDMAIL -oi -t A continuación un ejemplo para un simple servidor de ficheros accesible por correo. Para aplicaciones con mayores exigencias, le sugiero que le eche un vistazo a (disponible en el mismo lugar que la distribución de procmail). Como se indica, este servidor de ficheros devuelve sólamente un fichero por petición, ignora el cuerpo del mensaje recibido, la línea Subject: tiene que parecerse a "Subject: envia fichero el_fichero_que_quiere" (los espacios en blanco son significativos), no devuelve ficheros que empiezan por punto ni permite recuperar ficheros que estén fuera del árbol de directorios del servidor de ficheros (si decide usar este ejemplo, esté seguro de perder esta última restricción por descuido). 18 :0 * ^Subject: send file [0-9a-z] * !^X-Loop: yourname@your.main.mail.address * !^Subject:.*Re: * !^FROM_DAEMON * !^Subject: send file .*[/.]\. { MAILDIR=$HOME/fileserver # cambiar al directorio del servidor de ficheros :0 fhw # invierte las cabeceras y extrae el nombre * ^Subject: send file \/[^ ]* | formail -rA "X-Loop: yourname@your.main.mail.address" FILE="$MATCH" # el fichero soliciatado :0 ah | cat - ./$FILE 2>&1 | $SENDMAIL -oi -t } El siguiente ejemplo pre-convierte todos los correos que llegan en texto simple en cierto formato codificado MIME en otro formato de 8 bits más compacto que se puede usar y mostrar con más facilidad por la mayoría de los programas. El programa es parte del paquete metamail de Nathaniel Borenstein. 17 :0 * ^Content-Type: *text/plain { :0 fbw * ^Content-Transfer-Encoding: *quoted-printable | mimencode -u -q :0 Afhw | formail -I "Content-Transfer-Encoding: 8bit" :0 fbw * ^Content-Transfer-Encoding: *base64 | mimencode -u -b :0 Afhw | formail -I "Content-Transfer-Encoding: 8bit" } El siguiente es más bien exótico, pero sólo sirve para demostrar una característica. Suponga que tiene un fichero en su directorio HOME llamado ".urgent", y la única persona incluida en ese fichero es el remitente de un correo entrante, y le gustaría que el correo se almacenara en $MAILDIR/urgent en lugar de cualesquiera de las otras carpetas de correo normales en las que lo habría puesto. Esto es lo que podría hacer (tenga cuidado con la longitud del fichero de $HOME/.urgent que debería estar por debajo de $LINEBUF, incremente LINEBUF si es necesario): 5 URGMATCH=`cat $HOME/.urgent` :0: * $^From.*${URGMATCH} urgent Una aplicación completamente diferente a procmail aplicaría condicionalmente filtros a ciertos textos o mensajes (salientes). Un ejemplo típico sería un filtreo a través del cual encauza todo su correo saliente, para estar seguro que se codificará con MIME sólo si se necesita. 1 cat newtext | procmail ./mimeconvert | mail chris@where.ever El fichero de recursos podría contener algo como ( =0x80= y =0xff= se deberían sustituir por caracteres reales de 8 bits): 10 DEFAULT=| # tubería a la salida estándar # de entrega de correo como es normal :0 Bfbw * [=0x80=-=0xff=] | mimencode -q :0 Afhw | formail -I 'MIME-Version: 1.0' \ -I 'Content-Type: text/plain; charset=ISO-8859-1' \ -I 'Content-Transfer-Encoding: quoted-printable' Stephen R. van den Berg <srb@cuci.nl>