13. Reglas y Rulesets

En una primera lectura de este tutorial sugiero evitar todo este material puesto que no es esencial para la gran mayoría de administradores de Sendmail.

Las reglas son especificaciones de configuración que sirven para modificar las direcciones electrónicas y detectar errores en las mismas. Hay diversos motivos por los que una direccion electrónica debe ser modificada; por ejemplo, si se desea que todos los mensajes luzcan como si hubieran sido enviados desde cierto computador aunque en realidad se han enviados desde diversos computadores de distinto nombre.

Los conjuntos de reglas se agrupan en los llamados "Rulesets" que funcionan a modo de "subrutina" de cualquier lenguaje de programación. Los "Rulesets" se identifican con un número, aunque en las últimas versiones de Sendmail es posible identificarlos con una palabra (que internamente es traducida a un número por Sendmail.)

Algunos rulesets son definidos internamente (como los rulesets 0, 1, 2, 3, 4, y 5) mientras que otros se definen manualente en el archivo "cf".

Los rulesets se definen mediante el comando "S" y las reglas mediante el comando "R". A continuación un extracto del archivo "cf" que viene con RedHat 8.0 en el que se ilustra el ruleset "0" o también denominado "parse". Obsérvese que el ruleset termina donde empieza uno nuevo:

######################################
###   Ruleset 0 -- Parse Address   ###
######################################

Sparse=0

R$*                     $: $>Parse0 $1          initial parsing
R<@>                    $#local $: <@>          special case error msgs
R$*                     $: $>ParseLocal $1      handle local hacks
R$*                     $: $>Parse1 $1          final parsing

Esta salida puede ser muy distinta en otros sistemas Unix/Linux, pero por el momento eso no importa.

El ruleset 0 se pudo definir mediante "S0" en lugar de "Sparse", pero como "parse" es más "comprensible" que "0", entonces se prefiere esta última forma (Sparse=0.)

Para verificar cómo ha cargado Sendmail las reglas, se puede usar el modo de test de Sendmail con el comando "=S" y el número del ruleset:

# sendmail -bt
ADDRESS TEST MODE (ruleset 3 NOT automatically invoked)
Enter <ruleset> <address>
> =S 0
R$*             $: $> Parse0 $1
R< @ >          $# local $: < @ >
R$*             $: $> ParseLocal $1
R$*             $: $> Parse1 $1
Nótese que esto coincide con la definición del archivo de configuración. De igual modo puede consultarse con el nombre del ruleset:
# sendmail -bt
ADDRESS TEST MODE (ruleset 3 NOT automatically invoked)
Enter <ruleset> <address>
> =S parse
R$*             $: $> Parse0 $1
R< @ >          $# local $: < @ >
R$*             $: $> ParseLocal $1
R$*             $: $> Parse1 $1

Como es fácil de apreciar, cada ruleset consiste de varias "reglas" definidas con el comando "R".

Cada regla consiste de dos partes separadas por un tabulador, posiblemente seguidas de un comentario (separado también por un tabulador.)

13.1. Ejemplo de ruleset con una regla

Para esta sección haremos algunas modificaciones al archivo de configuración "cf". Sin embargo, a fin de evitar alterar la configuración actual, trabajaremos sobre un archivo "cf" alternativo. Empecemos haciendo una copia del archivo "cf":

# cp /etc/mail/sendmail.cf prueba.cf
Ahora podremos hacer nuestros cambios en "prueba.cf". Añadiremos a éste último las siguientes líneas en la parte final:

D{MAILHUB}mail.peru.com.pe
Sprueba
R$+@$+		$1*${MAILHUB}       convierte user@host
Como se ve, hemos definido la macro "MAILHUB", el ruleset "prueba" y una única regla. Para que la regla esté adecuadamente definida, es imprescindible que sus tres partes estén separadas por al menos un tabulador (no espacios):
R$+@$+ <TAB> $1*${MAILHUB} <TAB> convierte user@host
Para probar nuestra regla, ejecutaremos Sendmail en modo de prueba pero especificando el nuevo archivo "cf":
# sendmail -Cprueba.cf -bt
ADDRESS TEST MODE (ruleset 3 NOT automatically invoked)
Enter <ruleset> <address>
> prueba diego@hotmail.com
prueba             input: diego @ hotmail . com
prueba           returns: diego *mail . peru . com . pe
#
Como se aprecia, el modo de prueba permite especificar el nombre de cualquier ruleset seguido por una dirección electrónica a procesar.

13.1.1. Partes de una regla

Cada regla tiene hasta tres partes (el comentario es opcional) separadas por tabuladores (puede haber espacios dentro de cada parte.)

Recuérdese que las reglas alteran las direcciones de correo electrónico.

La primera parte (que sigue inmediatamente al comando "R") es la "left hand side" (lado izquierdo o LHS) mientras que la segunda es la "right hand side" (lado derecho o RHS.) La LHS especifica un patrón de búsqueda. De haber coincidencia con el patrón de búsqueda, la dirección de correo electrónico que se está procesando es convertida en el RHS.

13.1.2. Tokens

A fin de comprender las reglas, es necesario conocer el concepto de "token".

Las direcciones electrónicas procesadas en los rulesets por las reglas son internamente fraccionadas en varias unidades independientes denominadas "token". Así, la dirección proporcionada en el ejemplo de arriba: "diego@hotmail.com" es internamente dividida en los siguientes cinco tokens:

diego
@
hotmail
.
com
Los siguientes caracteres normalmente delimitan los tokens (y actúan ellos mismos como tokens adicionales):
.:@[]
()<>,;\"\r\n

13.1.3. Expresiones de búsqueda

En el ejemplo de arriba, la LHS está conformada por dos "expresión de búsqueda" (comodines o wildcards) de tipo "$+". Estos sirven para buscar coincidencias de uno o más "tokens". Más adelante veremos más de estos comodines.

En nuestro ejemplo, la dirección proporcionada hizo coincidir el primer "$+" con el token "diego" y el segundo "$+" con los tokens "hotmail", ".", "com".

Por el lado de la RHS, el contenido de cada "expresión de búsqueda" es accesible mediante los operadores $1, $2, ... respectivamente. Para nuestro caso, tendremos:

$1 = diego
$2 = hotmail . com
En nuestro ejemplo, el RHS es "$1*${MAILHUB}", lo que equivale a "diego*mail.peru.com.pe", cosa que se aprecia en la respuesta.

El modificador de debug 21.12 permite obtener más información acerca del procesamiento de cada regla.

# sendmail -d21.12 -bt -Cprueba.cf
ADDRESS TEST MODE (ruleset 3 NOT automatically invoked)
Enter <ruleset> <address>
> prueba diego@hotmail.com
prueba             input: diego @ hotmail . com
-----trying rule: $+ @ $+
-----rule matches: $1 *mail . peru . com . pe
rewritten as: diego *mail . peru . com . pe
-----trying rule: $+ @ $+
----- rule fails
prueba           returns: diego *mail . peru . com . pe

13.2. Rulesets Internos

Los rulesets 0, 1, 2, 3, 4, 5 están reservados para usos específicos de Sendmail. A futuro Sendmail puede definir los rulesets 6, 7, 8, 9. En general, es conveniente que el usuario defina - si lo requiere - rulesets con textos identificatorios (para que Sendmail automáticamente los numere) con lo que se evitan conflictos innecesarios.

Es conveniente conocer el uso que da Sendmail a los rulesets internos. La siguiente figura intenta ilustrar este punto.

Figura 1. reglitas.jpg

En general, todas las direcciones electrónicas pasan por el ruleset 3 apenas se inicia el procesamiento de las mismas. Entre otras cosas, el ruleset 3 extrae la dirección electrónica "apta para procesamiento" a partir de la dirección electrónica entregada por los clientes.

Por ejemplo, es usual que las direcciones electrónicas luzcan así (tal como las genera el programa cliente):

Pedro Escobedo <pescobedo@noskhon.com.pe>
Obviamente, para efectos de la transferencia del mensaje, el nombre real no es importante. Probemos esto:
# sendmail -bt
ADDRESS TEST MODE (ruleset 3 NOT automatically invoked)
Enter <ruleset> <address>
> 3 Pedro Escobedo <pescobedo@noskhon.com.pe>
canonify           input: Pedro Escobedo < pescobedo @ noskhon . com . pe >
Canonify2          input: pescobedo < @ noskhon . com . pe >
Canonify2        returns: pescobedo < @ noskhon . com . pe . >
canonify         returns: pescobedo < @ noskhon . com . pe . >
Lo que hemos hecho es transformar la dirección electrónica mediante el ruleset 3, el cual se encarga de "preprocesar" todas las direcciones electrónicas. Nótese que la respuesta consiste de la dirección electrónica en un formato especial usado internamente.

Es sencillo imprimir el ruleset 3 (o cualquier otro) desde Sendmail. Para esto, simplemente entrar en modo debug (con -bt) y tipear el comando "=S":

> =S 3
R$@             $@ < @ >
R$*             $: $1 < @ >
R$* < $* > $* < @ >             $: $1 < $2 > $3
...

Finalmente, todavía en modo test, pruébese el comando "/parse" que permite simular el procesamiento de una dirección de correo electrónico (por ejemplo, pruebe "/parse user@localhost".)

13.3. Macros en el archivo "cf"

Para explicar esto, copiaré una parte del archivo "cf" que se vió anteriormente (en la sección del delivery local.)

Mlocal,		P=/usr/bin/procmail, F=lsDFMAw5:/|@qSPfhn9,
		S=EnvFromL/HdrFromL,
		R=EnvToL/HdrToL,
		T=DNS/RFC822/X-Unix,
		A=procmail -t -Y -a $h -d $u
Como se aprecia, aquí se emplearon las construcciones "$h" y "$n". Como ya sospechará el lector, esto corresponde a la expansión de dos "macros".

En particular, la macro "h" (cuyo valor se obtiene con "$h") corresponde al host destinatario del mensaje, mientras que la macro "n" corresponde al usuario destinatario del mensaje. En este caso el valor de la macro es ajustado por Sendmail automáticamente para cada mensaje.

Las macros se pueden definir con el comando "D" en cualquier parte del archivo "cf". Por ejemplo, esto redefine la macro "w" al valor "jibaros":

Dwjibaros
Las macros cuyos nombres tienen más de un caracter deben usar llaves en su definición y su expansión:
D{PRUEBA}amazonas.com.pe
... ${PRUEBA} ...
La opción de debug -d35.9 permite obtener un extenso listado de macros definidas por Sendmail y vía el archivo "cf".

Ciertas macros son asignadas internamente por el programa Sendmail (como la macro "w" que es inicializada al nombre del host "sin dominio") y otras son creadas explícitamente en el archivo "cf" con diversos propósitos.

13.4. Clases

Las "clases" son una suerte de variables tipo "array", es decir, que pueden contener un conjunto de valores.

Las clases no se solapan con las macros. Por ejemplo, existe la clase "w" que no tiene relación alguna con la macro "w". Los elementos de la clase se añaden con el comando "C". Por ejemplo, los siguientes dos comandos añaden los elementos "localhost" y "localhost.localdomain" a la clase "w" del archivo "cf":

[root@edithpiaf tmp]# grep '^Cw' /etc/mail/sendmail.cf
Cwlocalhost.localdomain
Cwlocalhost
Tal como se mencionó anteriormente, la clase "w" corresponde a los "nombres de host" que Sendmail considera "locales" y que permiten que un mensaje sea dirigido al mailbox en lugar de ser redirigido hacia otro destino.

Como se recordará, esa configuración la hacíamos mediante el archivo /etc/mail/local-host-names. En otras palabras, las líneas de este archivo pasan a conformar la clase "w". Esto se define en el archivo "cf" mediante el comando "F":

[root@edithpiaf tmp]# grep '/etc/mail/local-host-names' /etc/mail/sendmail.cf
Fw/etc/mail/local-host-names
Evidentemente, esto también se pudo configurar añadiendo directamente directivas "Cw..." al archivo "cf", pero es un método menos flexible.

13.4.1. La clase w desde M4

Como se ve, esta clase es especial. A tal efecto si usamos el método M4 y se desea generar un archivo "cf" que incluya la configuración via el archivo local-host-names deberá usarse:

FEATURE(use_cw_file)dnl