Sendmail (I): Fundamentos del Correo Electrónico

Autor: Juan Antonio Martínez Castaño
E-Mail: jantonio@drake.dit.upm.es

Copyright

Este artículo es Copyright 1998 de Juan Antonio Martínez Castaño y se distribuye bajo las siguientes condiciones:

Indice:

  1. Introducción
  2. Filosofía
  3. El Protocolo SMTP
  4. Las Cabeceras de un mensaje
  5. Extensiones MIME
  6. Resumen. Conclusiones
  7. Referencias

Entradilla

Iniciamos aquí una serie de artículos sobre uno de los componentes más conocidos, antiguos y potentes subsistemas de nuestro servidor: El gestor de correo electrónico Sendmail. En este primer artículo desarrollaremos los conceptos básicos del correo electrónico, dejando para posteriores entregas la configuración y detalles de SendMail

Introducción

Podríamos decir que el correo electrónico ha sido el padre de InterNet: antes incluso de existir el concepto de Red Local, existían en el mundo UNIX una serie de utilidades para transferencia de datos entre máquinas a través de modem. Es el venerable -y todavía ampliamente usado- UUCP. Básicamente no era sino una serie de utilidades que permitían transferir ficheros entre dos máquinas ( UUCP es acrónimo de Unix-to-Unix-CoPy ) y ordenar la ejecución remota de diversas aplicaciones. En paralelo con estos programas, todos los sistemas incluían una utilidad para intercambiar mensajes entre los diversos usuarios de un sistema. Esta utilidad se denominaba -cómo no- "mail"

No tardó mucho en surgir la idea de que los intercambios de mensajes pudieran producirse entre diversas maquinas, aprovechando los programas existentes "mail" y "uucp". En este momento surgió la necesidad de establecer un mecanismo para saber de dónde venían los mensajes, a dónde iban, y cómo y por dónde debían encaminarse ( recordad que no tenemos aún red local, sino un montón de sistemas ocasionalmente conectados vía módem ). La solución a este problema fue un nuevo programa delivermail que todavía aparece en algunas distribuciones de UNIX'es basados en 4.1 BSD ( año 1979 )

Con la aparición de ARPANet y las primeras redes locales, la complejidad del sistema de correo, del encaminamiento y los problemas añadidos de gestión de listas, modos de conexión entre máquinas, diferentes sistemas "UNIX", etc hacen que delivermail crezca y crezca en complejidad. Finalmente en 1980 se publican los primeros Drafts sobre lo que será la futura InterNet ( lo que ahora tenemos ) y aparece el primer RFC sobre un protocolo específico para transferencia de correo electrónico: el Simple Mail Transfer Protocol ( SMTP )

Por entonces un estudiante de la Universidad de Berkeley, Eric Allman modifica delivermail y lo transforma en sendmail. La primera versión pública de sendmail apareció en la distribución 4.1c de BSD UNIX, que fue también la primera versión de UNIX que soportó de base TCP-IP

Desde entonces SendMail ha evolucionado rápidamente, creciendo en potencia y en complejidad. En el momento de escribirse este artículo, la última versión oficial es la 8.9.1. La potencia de este programa ha hecho que siendo el "corazón" de la conectividad UNIX, sendmail sea también el programa más difícil de configurar -que no de mantener- Por ello han aparecido diversas variantes de sendmail, que hacen hincapié en los métodos de configuración, asi como diversos agentes de correo mucho más simples -y mucho menos potentes- como puedan ser smail o qmail

Filosofía de funcionamiento del correo electrónico

Ya está bien de historia. Veamos el ejemplo del listado 1:

[jantonio@cochito jantonio]$ telnet cochito.micasa.es smtp
Trying 192.1.1.1...
Connected to cochito.micasa.es.
Escape character is '^]'.
220 cochito.micasa.es ESMTP Sendmail 8.8.7/8.8.7; Thu, 6 Aug 1998 23:14:05 +0200
HELO cochito
250 cochito.micasa.es Hello jantonio@cochito.micasa.es [192.1.1.1], pleased to meet you
MAIL FROM: jantonio
250 jantonio... Sender ok
RCPT TO: jamc@eurielec.etsit.upm.es
250 jamc@eurielec.etsit.upm.es... Recipient ok (will queue)
DATA
354 Enter mail, end with "." on a line by itself
Hola mundillo
.
250 XAA00868 Message accepted for delivery
QUIT
221 cochito.micasa.es closing connection
Connection closed by foreign host.
Listado 1: Ejemplo de diálogo SMTP

Podríamos llamar a este listado como el "hello world" del correo electrónico. La primera línea es una invocación mediante "telnet" al puerto smtp ( definido en el /etc/services como "25/tcp" ) lo siguiente es un diálogo con el servidor en "lenguaje SMTP"

Antes de explicar en detalle el protocolo SMTP, vamos a ver qué es lo que sendmail debe ser capaz de hacer, y las razones de su complejidad. Para ello establecemos una primera distinción: Agentes de "entrega" de correo y Agentes de "distribución" de correo ( en inglés MUA -Mail User Agent y MTA -Mail Transfer Agent-, respectivamente ). La figura 1 ilustra las diferentes relaciones entre los diversos elementos del sistema de correo

diagrama de flujo
Figura 1: Diagrama de flujo del subsistema de correo

Un MUA se encarga de la distribución local de correo. Básicamente es un interfaz de usuario, que permite editar, componer y enviar mail local. Ejemplos tipicos son "mail" "pine" "mailx" Algunos MUA's más elaborados permiten "tunelizar" correo a través de pasarelas ppp, o gestionar listas ( p. ej "fetchmail" o "procmail" ). Todos los MUA's saben hablar SMTP para enviar correo no local

Un MTA se encarga del encaminamiento del correo entre los diversos sistemas. Entre sus funciones se cuentan:

El encaminamiento del correo debe ser rápido, fiable y consumir pocos recursos. El sistema debe garantizar que el correo llegue a su destino o sea rechazado como "no válido". pero NUNCA debe perderse por el camino

Por todo ello, Sendmail, y en general todos los MTA's hacen hincapié en la rapidez, la posibilidad de configuración y el bajo consumo de recursos.
¿Cómo conjuntar estos tres puntos, aparentemente irreconciliables? piénsese, por ejemplo, que sólo el "parser" para leer la configuración del sistema de correo consume más de la mitad del tiempo de CPU que necesita sendmail para saber qué hacer con nuestro inocente "hola mundillo". Una alternativa es tener permanentemente en memoria una database con la configuración, pero entonces nos encontramos con el problema de gasto de recursos...

El truco consiste en hacer un fichero de configuración cuyo análisis sea inmediato para sendmail, aun a costa de hacerlo incomprensible para los humanos. Un ejemplo típico, extraído de un /etc/sendmail.cf:

....
R$* < @ > $*            $@ $>Parse0 $>3 $1              user@ => user
R< @ $=w . > : $*       $@ $>Parse0 $>3 $2              @here:... -> ...
R$- < @ $=w . >         $: $(dequote $1 $) < @ $2 . >   dequote "foo"@here
R< @ $+ >               $#error $@ 5.1.1 $: "user address required"
R$* $=O $* < @ $=w . >  $@ $>Parse0 $>3 $1 $2 $3        ...@here -> ...
....

Incomprensible, ¿verdad?. Bueno, con un poco de entrenamiento... No debemos olvidar que se trata de un código escrito para que lo entienda el programa, no el usuario

Hasta hace unos años, configurar sendmail era una tarea para auténticos gurús. La frase "No puede llamarse gurú de UNIX quien nunca ha editado a mano un sendmail.cf" afortunadamente ha pasado a la historia. Ahora, mediante el uso de macros y de directivas "prefabricadas" de configuración, la configuración de sendmail está convirtiéndose en una tarea rutinaria, y sólo es necesario editar el fichero en casos desesperados.

Hoy en día, mediante el uso de macros y de directivas "predefinidas" de configuración, el manejo de sendmail se ha convertido en una tarea rutinaria

Como conclusión podemos decir que todas las reglas que van a definir el comportamiento de nuestro sendmail están definidas en /etc/sendmail.cf. SendMail no es sino el operario de la oficina de correos que coge cada carta e intenta buscarse la vida para hacer que llegue a su destino, en función de lo que el administrador del sistema le ha dicho que puede y debe hacer

El protocolo SMTP

Antes de introducirnos en la instalación y configuración de sendmail - que será desarrollada en mayor amplitud en próximos números de LINUX ACTUAL - echaremos un vistazo al protocolo SMTP. para ello miremos los siguientes RFC's

O mejor, una vez superado el susto volvemos a nuestro telnet y tecleamos:

[jantonio@cochito jantonio]$ telnet cochito.micasa.es smtp
Trying 192.1.1.1...
Connected to cochito.micasa.es.
Escape character is '^]'.
220 cochito.micasa.es ESMTP Sendmail 8.8.7/8.8.7; Fri, 7 Aug 1998 00:22:12 +0200
help
214-This is Sendmail version 8.8.7
214-Topics:
214-    HELO    EHLO    MAIL    RCPT    DATA
214-    RSET    NOOP    QUIT    HELP    VRFY
214-    EXPN    VERB    ETRN    DSN
214-For more info use "HELP ".
214-To report bugs in the implementation send email to
214-    sendmail-bugs@sendmail.org.
214-For local information send email to Postmaster at your site.
214 End of HELP info

Todos los comandos ( realmente DSN no es un comando, sino una serie de flags que indican que hacer con el destinatario y el remitente ) constan de cuatro letras ( idealmente mayúsculas; los nuevos MTA's reconocen indistintamente mayúsculas y minúsculas )

Con estos pocos comandos se construye toda la historia....

Las cabeceras del mensaje

Ahora que sabemos como se envía el mensaje, vamos a ver cómo se identifica cada mensaje, y como extraer e introducir información sobre la fecha, el origen y destino, la ruta, las extensiones, el status, etc... para ello cogemos el RFC-822 y empezamos a estudiar las cabeceras de un mensaje de correo electrónico. Veamos un ejemplo en el listado 2:

From mdw21@hermes.cam.ac.uk  Thu May  7 00:34:41 1998
Return-Path: 
Received: from sanson.dit.upm.es (sanson-cdc.dit.upm.es [138.4.1.130])
        by drake.dit.upm.es (8.8.7/8.8.7) with ESMTP id AAA01509
        for ; Thu, 7 May 1998 00:34:41 +0200
Received: from violet.csi.cam.ac.uk (violet.csi.cam.ac.uk [131.111.8.58]) 
	by sanson.dit.upm.es (8.8.4/3.14) with ESMTP 
	id BAA14729
	for ; Thu, 7 May 1998 01:34:16 +0200 (MET DST)
Received: from mdw21.clare.cam.ac.uk ([131.111.214.145] helo=mdw21)
        by violet.csi.cam.ac.uk with smtp (Exim 1.92 #1)
        for jantonio@dit.upm.es
        id 0yXDhZ-00075a-00; Thu, 7 May 1998 00:34:17 +0100
Message-ID: <001501bd7947$a68f73e0$91d66f83@mdw21.clare.cam.ac.uk>
From: "Mark Wever" 
To: "Juan Antonio Martinez" 
Subject: Re: Puzzle bobble source code for Linux 
Date: Thu, 7 May 1998 00:35:27 +0100
MIME-Version: 1.0
Content-Type: text/plain;
        charset="iso-8859-1"
Content-Transfer-Encoding: 7bit
X-Priority: 3
X-MSMail-Priority: Normal
X-Mailer: Microsoft Outlook Express 4.72.3110.1
X-MimeOLE: Produced By Microsoft MimeOLE V4.72.3110.3
Status: RO
X-Status: 

Hello, you may remember you wrote to me ages ago about PB.
....
Listado 2: Ejemplo de cabecera de mensaje de correo

Todo mensaje de correo trae una cabecera y un cuerpo. Las cabeceras empiezan siempre con un "From " al comienzo de la línea y acaban con una línea en blanco. El cuerpo empieza y acaba siempre con una linea en blanco. Aunque Microsoft se empeñe en decir lo contrario, el RFC-822 prohíbe expresamente utilizar en las cabeceras caracteres no-ASCII ( códigos mayores que 0x7f ). Esto implica que ninguna dirección de correo puede tener tildes, eñes, etc

Echemos un vistazo a los datos que son relevantes a Sendmail.

No podemos incluír aquí todas las posibles cabeceras por motivos más que evidentes de espacio. Remitimos al lector a la lectura del RFC-822 y a sus diversas revisiones.

¿Cómo se incluye la información de cabecera en el protocolo SMTP?. Muy sencillo: Despues de la instrucción DATA, y hasta encontrar la primera línea vacia, sendmail reconoce e inserta los diversos "tags" correspondientes a las cabeceras del mensaje. una vez encontrada una linea vacia o una que no corresponda a una cabecera válida, sendmail interpreta como "body" o cuerpo del mensaje todo lo que siga a continuación

Multi-Purpose Internet Mail Extensions.

Hasta ahora hemos asumido que todos los mensajes estaban basados en caracteres ASCII de 7 bits. Pero ¿Qué hacer cuando lo que se desea es enviar un mensaje que incluye caracteres internacionales, o código binario?.

Una primera aproximación es utilizar un MTA que hable ESMTP ( extended SMTP ). Este protocolo permite la transmision de caracteres de 8 bits. El problema fundamental consiste en que nosotros ( el usuario que envía el mensaje ) no tenemos control sobre el camino que dicho mensaje va a recorrer, específicamente: no sabemos si todos los MTA's que nuestro mensaje se va a encontrar saben hablar ESMTP

Una segunda aproximación consiste en convertir nuestro mensaje a un código 7bits puro. Las utilidades "uudecode" y "uuencode" se encargan de dicha tarea. El problema añadido es que estos paquetes sólo son estándard en el mundo UNIX, y aunque parezca mentira, no todo el mundo tiene la suerte de tener un UNIX encima de la mesa...

La solución más viable consiste en dejarle al MUA la tarea de codificar y descodificar el mensaje de forma transparente al usuario: mediante los famosos "Attachments" le indicamos a nuestro mailer que vamos a insertar un fichero con un formato X y que dicho fichero debe ser incluído en el cuerpo del mensaje a enviar.

Para ello el MUA "clasifica" el fichero en una "categoría", y lo codifica en la forma que considere más conveniente, incluyendo en las cabeceras y en el cuerpo del mensaje que envia información sobre los datos que incluye y su forma de decodificación. Estas categorías están definidas - cómo no - en un RFC y constituyen las denominadas MIME's ( Multipurpose Internet Mail Extensions ). El objetivo de MIME es el de permitir que cualquier tipo de mensaje ( texto, imagenes, voz, datos, binarios, etc ) pueda ser enviado a través de SMTP, de una forma sencilla y reversible

El objetivo de MIME es el de permitir que cualquier tipo de mensaje ( texto, imagenes, voz, datos, binarios, etc ) pueda ser enviado a través de SMTP, de una forma sencilla, reversible y transparente al usuario

Volviendo a nuestra cabecera ejemplo, nos encontramos con las entradas

MIME-Version: 1.0
Content-Type: text/plain;
        charset="iso-8859-1"
Content-Transfer-Encoding: 7bit

Se pueden incluír múltiples attachments en un mensaje, cada uno con su propio content-type y Content-transfer-encoding. Sendmail es transparente a dichos datos, pues están insertados en el cuerpo del mensaje, y lo único que requiere es que sean datos de 7bits ( 8, si soporta ESMTP ). Los Mimetypes serán usados a la recepción del mensaje por el MUA para reconstruír el fichero original

Resumen. Conclusión

A modo de resumen se puede indicar:

En este artículo hemos introducido al lector en los fundamentos del correo electrónico. En futuros números de LINUX ACTUAL nos centraremos especificamente en el caso de SendMail, introduciendo al lector en la instalación y configuración de dicho software, presentando ejemplos de configuraciones e introduciendo las diversas opciones y posibilidades. Posteriormente se describirá sendmail y los ficheros de configuración en profundidad, explicando detalladamente la "magia" de la configuración de sendmail

En el CD-Rom que acompaña a esta revista encontrará el lector los RFC's que se refieren de una u otra forma al correo electrónico, asi como la última distribución disponible de sendmail en formatos .rpm y .tgz

Referencias

Puesto que el correo electrónico es incluso más antiguo que InterNet, está profundamente documentado, existiendo una ampila bibliografía y referencias sobre el tema. Indicamos aquí alguna de las más relevantes:

Referencias sobre TCP-IP y SMTP

Douglas E. Comer
"Internetworking con TCP-IP" Tercera Edición ( tres volúmenes )
Prentice Hall international
ISBN 0-13-474321-0
http://www.phall.com
( una colección que todo administrador de sistemas debe tener en su biblioteca informática )

Referencias sobre Sendmail

Eric Allman,Bryan Costales, Neil Rickert
"Sendmail" Segunda edición
O'Reilly Associates, Inc
ISBN 1-56592-056-2
http://www.ora.com
( considerado como "la biblia de sendmail" es el manual oficial -reconocido como tal por el creador de sendmail- )

RFC's

Consultar el fichero indice incluído en el CD-Rom

Sendmail Home Page && ftp site

http://www.sendmail.org
ftp://ftp.sendmail.org/pub/sendmail
Grupos de News y listas de correo
news:comp.mail.sendmail
mailto:majordomo@lists.sendmail.org
FAQ && Tutorials de sendmail
http://www.informatik.uni-kiel.de/~Eca/faqs/sendmailv8.html
http://www.wcmh.com/uworld/archives/95/tutorial/008/008.txt.html