SendMail (I): Fundamentos del Correo Electrónico Autor: Juan Antonio Martínez Castaño E-Mail: jantonio@dit.upm.es Indice: 1- Introducción 2- Filosofía 3- El RFC 822 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 tardo 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 monton 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 tambien 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. Vamos con un ejemplo: [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. 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 ) 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: - Detectar si el mail es local, y en caso afirmativo, ceder el control a un MUA local - En el caso de mail remoto, debe ser capaz de reescribir las direcciones de correo del destinatario y remitentes del correo de manera que sean compatibles con el sistema remoto y el agente de transporte - Debe ser capaz de reconocer aliases, manejar ficheros de forwarding - Se deben poder discriminar diversos agentes de distribución de correo: faxes, uucp, bitnet, arpanet, etc. - Puesto que cada sistema tiene sus propios usuarios, configuraciones, requerimientos, condicionantes, etc, el MTA debe ser altamente configurable de manera que ningun potencial usuario se vea limitado - Especial hincapié debe hacerse en cuanto a la seguridad: no debemos olvidar que estamos conectando con una maquina remota, cuya configuración desconocemos, y que debemos hacer lo posible por autentificar tanto el origen como el destinatario del mensaje - El encaminamiento del correo debe ser rapído, fiable y que consuma pocos recursos. El sistema debe garantizar que el correo llegue a su destino o sea rechazado como "no valido". pero NUNCA debe perderse por el camino Vamos, que igualito que en la vida real.... 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 dos 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 tipico, extraido 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 codigo 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 guru 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á convirtiendose en una tarea rutinaria, y sólo es necesario editar el fichero en casos desesperados. 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 - Standard for the format of ARPA Internet text messages: RFC-822 - Simple Mail Transfer Protocol: RFC-821 - Extensions for SMTP and Internet text message format: RFC-1123 - Domain Name Convention for Internet User Aplications (DNS): RFC-819 - UUCP Mail Interchange Format Standards: RFC-976 - Multi-purpose Internet Mail Extensions (MIME) RFC-1341 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 ) - HELO ( de "hello" ) inicia el dialogo e identifica la maquina desde la que se establece la conexión. Los nuevos sendmails autentifican el saludo, de manera que no le podemos "mentir" a sendmail - EHLO ( de "Extended hello" ) es equivalente, solo que le indica al sistema remoto que "sabemos" hablar extended SMTP - MAIL FROM: indica que vamos a enviar un mensaje, y que el origen ( sender ) es el indicado - RCPT TO: indica la direccion de destino del correo. Pueden ser especificados diversos destinos, pero solo un remitente - DATA indica el comienzo del mensaje. Para finalizar la introducción de datos, se introduce una línea que comience por punto "." En el caso de querer introducir una línea que comienze por "." dentro del texto, lo haremos duplicando dicho punto ".." - NOOP ( "No Operation" ) pues eso... - QUIT para finalizar la sesion - EXPN ( "Expand" ) sirve para indicar como se va a resolver la dirección de correo del RCPT que le indiquemos. - VRFY ( "Verify" ) sirve para saber si el sendmail remoto va a aceptar o no una dirección de correo. Puesto que un antiguo truco de hacker consistía en buscar usuarios "standard" en un sistema preguntando con VRFY y EXPN al sendmail de dicho sistema, estos son inhabilitados en los sendmails modernos - VERB ( "Verbose" ) presenta mensajes en modo verboso. SMTP especifica que las respuestas a las peticiones del protocolo son salidas numericas. Poniendo verbose a ON se le añaden diversos textos que sirven de ayuda a interpretes humanos. - RSET ( "Reset" ) resetea la introduccion de datos, partiendo de cero - TURN indica al sendmail remoto, que el cliente pasa a modo "escucha" pudiendo actuar el antiguo servidor como cliente. Utilizado antiguamente en conexiones telefónicas, casi ningun MTA lo utiliza hoy en día - ETRN fuerza el envio de correo dirigido a un determinado host o dominio en el servidor. su implementación y uso es opcional 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: 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 san son.dit.upm.es (8.8.4/3.14) with ESMTP id BAA14729 for ; Th u, 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. .... 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 linea 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 prohibe expresamente utilizar en las cabeceras caracteres no-ASCII ( códigos mayores que 0x7f ). Esto implica que ninguna direccion de correo puede tener tildes, eñes, etc Echemos un vistazo a los datos que son relevantes a Sendmail. - Tenemos en primer lugar el campo From. Indica quién envia el mensaje. Puesto que el SMTP no impone ninguna restricción al mensaje MAIL FROM: es mision de sendmail autentificar dicho sender. Por ello intenta hacer una petición de identd con la máquina remota, y en el caso de que la conexión no la establezca un "trusted user" ( otro sendmail, por ejemplo ) genera en la cabecera un mensaje de X-Autentication-Warnig indicando que es posible que el sender no corresponda a quien dice ser - Return-path: indica a sendmail, por donde debe ser rutado el mensaje en caso de devolución. No todos los mailers hacen caso de dicho mensaje, salvo que sendmail sea expresamente instruído para hacerlo. Otro truco antiguo de hacker consistía en engañar al correo para que el que recibía el mensaje, al responder respondiera a la máquina "ladrona" en lugar de a la persona suplantada. Existen diversas variantes al uso "truculento" de esta cabecera, cuyo estudio se deja a los fanáticos del "hackering" - Received: indica todas y cada una de las máquinas por donde ha ido pasando el mensaje. Cada MTA inserta un "Received", de manera que estudiando detenidamente la cabecera es posible hacer el seguimiento de un mensaje ( a menos que la cabecera este "trampeada", lo que exige un cierto nivel de conocimiento... ) Asimismo, Contando el número de "Received" que contiene una cabecera podemos especificar un "time-to-live" de un mensaje, definiendolo como el numero de saltos que puede dar un mensaje entre máquina y máquina antes de considerar que dicho mensaje no puede ser entregado. De nuevo, un parámetro del fichero de configuración de sendmail, define el TTL de un mensaje - Message-ID: es una etiqueta que identifica el mensaje y garantiza que sea unico en toda la Internet. El método habitual consiste en formar dicho ID con el nombre de la maquina origen, la fecha del mensaje y el nombre asignado en la cola de envio - X-Priority: Indica al MTA la prioridad con que debe ser tratado un mensaje El fichero de configuración de sendmail define diversos niveles de prioridad, asignando diversos valores a diversas etiquetas ( "normal", "urgent", etc ) Cuando sendmail procesa la cola de mensajes en espera de ser enviados, intenta enviar primero los de mayor prioridad 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 ¿Que 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 icluí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 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 - La primera indica la version de MIME que utiliza el mensaje - Content-Type indica la clasificacion del "attachment" que se incluye en el mensaje - Content-Transfer-Encoding: indica el tipo de codificación utilizada a la hora de incluir el attachment en el cuerpo del mensaje 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 unico 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 la gestión de correo electrónico intervienen dos tipos de agentes: MUA's ( interfaz de usuario ) y MTA's ( encaminamiento y distribución ) SendMail es un MTA, aunque tiene un mínimo MUA para su uso directo desde línea de comandos - El MTA ideal es rápido, eficiente, altamente configurable, y garantiza que ningún mensaje es perdido. El mayor problema de cara al usuario es casi siempre la configuración - Sendmail posee un fichero de configuración /etc/sendmail.cf, de sintaxis casi criptica, pensado para un rápido procesamiento por el programa, no por el usuario. Diversas utilidades de configuración mediante macros facilitan al administrador del sistema la tarea de configurar sendmail - La transferencia de mensajes a través de InterNet está regulada mendiante una serie de RFC's, que regulan: El protocolo de transferencia El formato de los mensajes Las extensiones al protocolo 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 en profundidad 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 único manual reconocido como oficial por el creador de sendmail ) RFC's Consultar el fichero indice incluído en el CD-Rom Sendmail Home Page http://www.sendmail.org