Por Willly Mejía [WillyXoft]
Para que una aplicación .Net
pueda realizar envío de correo electrónico
normalmente se
emplea el espacio de nombres System.Web.Mail
que contiene las clases que permiten construir y enviar mensajes
mediante el componente de mensajería CDO (Collaboration Data
Objects) formalmente "Microsoft CDO for Windows 2000 Library"
incluido en Windows 2000 y posteriores. El
mensaje de correo se entrega por medio del servicio de correo SMTP
(Simple Mail Transport Protocol) incluido en Windows con IIS o
bien mediante algún otro servidor SMTP. Las clases de este
espacio de nombres se pueden utilizar desde cualquier aplicación
administrada ya sea de consola, Windows o ASP.NET.
Un sencillo ejemplo que ilustra lo fácil que es
enviar correo electrónico desde Visual Basic .NET lo vemos
en el siguiente página: http://support.microsoft.com/default.aspx?scid=314201
Ahora bien, existe un problema en los siguientes escenarios:
- Cuando deseamos enviar un mensaje hacia Internet a través
de Exchange Server.
- Cuando deseamos enviar un mensaje hacia un servidor
SMTP externo que requiere autentificación.
En realidad en ambos escenarios el problema es el mismo: la
autenticación. Si examinamos las clases de System.Web.Mail
no vemos
ningún miembro que sirva para especificar dicha
información, entonces ¿Como podemos mandar
correo electrónico con autenticación? las posibilidades
son:
- Para el .Net Framework 1.0 (v1.0.XXXX), usar la Biblioteca COM
de CDO por medio de
Interoperabilidad.
- Para el .Net Framework 1.1 (v1.1.XXXX), emplear el nuevo miembro Fields de MailMessage.
- Emplear algún componente de terceros, o incluso crear
uno propio.
En el presente artículo analizaremos las dos primeras.
Usando CDO para el envío de mensajes con
autenticación.
Esta es, la solución mas obvia para el
envío de mensajes con autenticación y la
única (gratuita) para el .NET Framework 1.0. Para empezar
tenemos que tomar en cuenta que nuestro código tendrá que
emplear la Biblioteca de tipos de CDO a través de
Interoperabilidad COM, por ello lo primero que tenemos que hacer es
crear nuestro Ensamblado de Interoperabilidad (IA).
Desde su IDE puede hacerlo agregando la referencia COM de dicho
componente, para ello:
- En nuestro entorno hacer click derecho sobre el
arbol "Referencias" y elegimos "Agregar referencia...".
- En la ventana que emerge pasamos al tabulador COM
- En en el listado que aparece buscaremos "Microsoft CDO for
Windows 2000 Library", lo seleccionamos con doble click o a
través del botón correspondiente, por último
pulsamos el botón "Aceptar".
O bien, en la línea de comandos lo obtenemos escribiendo:
>tlbimp
cdosys.dll /out:Interop.CDO.dll
Si todo resulto bien veremos un mensaje como el siguiente:
Type library imported to Interop.CDO.dll
Una vez obtenido el Ensamblado de Interoperabilidad, ya sea desde
nuestro IDE o desde la línea de comandos, podemos examinarlo
mediante algun Inspeccionador de Ensamblados como el "Examinador de
Objetos" de Visual Studio .NET, el "ClassBrowser" de WebMatrix, o bien
el "Desensamblador
IL" (ILDasm.exe) del .NET Framework SDK.
El objeto principal de CDO utilizado para la construcción
y envío de mensajes es
Message. por lo que será el primero que analizaremos:

Este objeto entre las propiedades y métodos
necesarios para la construcción y envío de mensajes
tiene un miembro llamado Configuration, que es la
implementación de la interface IConfiguration, la cual define
las propiedades y métodos para la
configuración de CDO.

La configuración de CDO se
establece a través de Campos (Fields). pero
¿Que es un
Campo para CDO? Veamos lo que dice la documentación:
"'Microsoft CDO for Windows 2000' emplea URIs (Uniform
Resource
Identifiers) para cualificar o delimitar los nombres de
campos y sus definiciones semánticas. Cada campo accesible
a través de la colección Fields esta
comprendido de un prefijo de espacio de nombres (namespace) y un
nombre local. El prefijo del espacio de nombres es una referencia URI
utilizada para cualificar o delimitar la definición
semántica de la propiedad..."
Extraido de:
http://msdn.microsoft.com/library/en-us/cdosys/html/_cdosys_fields.asp
Podemos decir entonces que son una serie
de propiedades con nombre compuesto por un Espacio de Nombre
y un Nombre Local que se almacenan y acceden a través de una
colección de nombre Fields, a los cuales se le asigna un
valor que los califican o delimitan.
Fields("URLnamespace/localname") = valor
Los campos se establecen
mediante una implementación de la colección IConfiguration.Fields de tipo
ADODB.Fields. Esta implementación esta asociada al objeto
Configuration quien a su vez esta asociado a los distintos objetos
COM de CDO.
Es el objeto Configuration
entonces el que se emplea para
definir parámetros de configuración específicos al
objeto CDO.Message. Para ello debemos crear un
objeto Configuration
para a través de su
colección Fields establecer los valores de los
Campos necesarios para realizar
la autenticación en el servicio SMTP para
después asignar dicha configuración al objeto Message y
de ese modo lograr nuestro objetivo.
Dim oMsg As New CDO.Message()
Dim iConfig As New CDO.Configuration()
Dim Flds As ADODB.Fields = iConfig.Fields
'Modificacion de los campos...
oMsg.Configuration=iConfig
|
Todos los Campos que necesitamos establecer se encuentran bajo el
Espacio de
Nombres CDO:
"http://schemas.microsoft.com/cdo/configuration/"
Para mayor información sobre este Espacio de Nombres ver:
http://msdn.microsoft.com/library/en-us/cdosys/html/_cdosys_schema_configuration.asp
Los Campos correspondientes al Espacio de Nombres
"http://schemas.microsoft.com/cdo/configuration/" están
agrupadas en la Biblioteca de CDO bajo el Módulo (desde el .Net
Framework se ve como una clase abstracta) CdoConfiguration y
están representados por Constantes que equivalen a los "nombre
completo" del Campo, tal y como
vemos en la siguiente imagen:
Así por ejemplo, la constante
seleccionada cdoSMTPAuthenticate
equivale al Campo de Nombre Local smtpauthenticate,
esta constante equivale al "nombre completo" correspondiente al Campo
el cual
es: "http://schemas.microsoft.com/cdo/configuration/smtpauthenticate"
Es mediante el Campo smtpauthenticate que podemos
indicar el mecanismo de autenticación requerida para enviar
mensajes, los valores que se le asigna son los listados por el
Enumerado CdoProtocolsAuthentication,
el cual alberga a tres constantes: cdoAnonymous
(0), cdoBasic (1)
y cdoNTLM (2). En
otras palabras, podemos especificar 3
tipos de autentificación: Anónima (sin
autenticación), Básica (simple) o NTLM (integrada). Si
deseáramos enviar un correo electrónico por medio de un
servidor SMTP externo a la red local necesitamos usar
autenticación Básica.
La documentación de CDO menciona que, para que el Campo
smtpauthenticate sea
tomado en cuenta debe establecerse a su vez el Campo
sendusing ("http://schemas.microsoft.com/cdo/configuration/sendusing"),
igual a la constante
cdoSendUsingPort
(2) albergada por el Enumerado
CdoSendUsing;
este campo define si se debe enviar el mensaje utilizando el servicio
local SMTP (si es que el hot local tuviese el servicio SMTP
instalado) o un servicio SMTP externo directamente sobre
la red de trabajo local, que es el que debemos establecer. Así
mismo menciona que también debe establecerse el valor
del Campo
smtpserver ("http://schemas.microsoft.com/cdo/configuration/smtpserver")
la dirección IP específica o el nombre DNS del
host que alberga el servicio SMTP, y en caso de ser necesario, debe
establecerse el valor numérico del puerto del mismo en el
Campo
smtpserverport ("http://schemas.microsoft.com/cdo/configuration/smtpserverport").
Por último y mas importante, para establecer
las credenciales de
autenticación requeridas para la conexión con el
servicio SMTP, deben establecerse los valores
de los Campos sendusername
("http://schemas.microsoft.com/cdo/configuration/sendusername") y sendpassword ("http://schemas.microsoft.com/cdo/configuration/sendpassword") correspondientes
a el nombre (login) y la contraseña de usuario.
Estos dos Campos junto con el Campo smtpauthenticate
son los indispensables para llevar a cabo nuestro cometido.
Pues bien, con lo estudiado
hasta aquí podemos elaborar un ejemplo con VB.NET:
Para ello creamos un Proyecto de Consola y agregamos la referencia de
CDO, o bien, simplemente creamos un archivo de nombre Module1.vb con
Visual Notepad. Después, en cualquiera de los casos,
introducimos el código siguiente:
|
Option Explicit
On
Module Module1
Sub Main()
Const ConfigNamespace as
String = _
"http://schemas.microsoft.com/cdo/configuration/"
Dim oMsg As New CDO.Message()
Dim iConfig As New CDO.Configuration()
Dim Flds As ADODB.Fields = iConfig.Fields
With Flds
.Item(ConfigNamespace
& "smtpserver").Value = "smtp.mail.dominio"
.Item(ConfigNamespace
& "smtpserverport").Value = 25
.Item(ConfigNamespace
& "sendusing").Value = _
CDO.CdoSendUsing.cdoSendUsingPort
.Item(ConfigNamespace
& "sendusername").Value = "usuario"
.Item(ConfigNamespace
& "sendpassword").Value = "contraseña"
.Item(ConfigNamespace
& "smtpauthenticate").Value = _
CDO.CdoProtocolsAuthentication.cdoBasic
.Update()
End With
With oMsg
.Configuration = iConfig
.From = "usuario@dominio"
.To = "alguien@dominio"
.Subject =
"Test CDO con VB.NET"
.TextBody = "Hola Mundo"
.Send()
End With
oMsg = Nothing
iConfig = Nothing
End Sub
End Module
|
Compilamos desde nuestro IDE, o bien, para compilar desde la
línea de comandos:
>vbc Module1.vb
/r:Interop.CDO.dll,adodb.dll
Nota: ADODB.DLL es el PIA
de ADO
que por lo general se encuentra en:
"%programfiles%\Microsoft.NET\Primary Interop Assemblies" de lo
contrario deberá crearlo por su cuenta.
Como puede observarse, el enviar mensajes con autenticación
con
CDO
solo requiere conocer y establecer unos cuantos Campos a sus valores
adecuados. Lo anterior podemos realizarlo también con el .Net
Framework 1.1 pero esta versión
tiene la ventaja de poderlo realizar sin necesidad de incorporar la
Referencia COM a CDO.
Usando MailMessage.Fields para el envío de mensajes con
autenticación.
Las clases involucradas en el Namespace System.Web.Mail para la
construcción y envío de correo electrónico desde
.NET son::
En la documentación del
versión 1.1 del .Net Framework se observa que la clase
MailMessage de
System.Web.Mail tiene
un nuevo miembro llamado Fields,
mismo que hasta el día de hoy no está documentado:
Lo único que nos dice la documentación es
que es de tipo System.Collections.IDictionary. Mas
ahora que ya
hemos visto como funciona CDO podríamos suponer, al
menos como una aproximación, que podría tratarse
de la
colección Fields del
objeto Configuration asociado
al objeto Message de
CDO.
Con espíritu investigador realicemos una prueba en base
al código anterior cambiando los objetos CDO por sus
equivalentes en System.Web.Mail,
empleando un System.Collections.IDictionary
en lugar de
ADODB.Fields, así como
cambiando las
nombres de las constantes CDO por sus valores numéricos
correspondientes para evitar cualquier referencia a CDO. Esto nos da
como resultado el siguiente código:
Option Explicit On
Module Module1
Sub Main()
Const ConfigNamespace as
String = _
"http://schemas.microsoft.com/cdo/configuration/"
Dim oMsg As New System.Web.Mail.MailMessage
Dim Flds As System.Collections.IDictionary
Flds = oMsg.Fields
With Flds
.Add(ConfigNamespace
& "smtpserver", "smtp.mail.dominio")
.Add(ConfigNamespace
& "smtpserverport", 25)
.Add(ConfigNamespace
& "sendusing", 2)
.Add(ConfigNamespace
& "sendusername", "usuario")
.Add(ConfigNamespace
& "sendpassword", "contraseña")
.Add(ConfigNamespace
& "smtpauthenticate", 1)
End With
With oMsg
.From = "usuario@dominio"
.To = "alguien@dominio"
.Subject =
"Test MailMessage.Fields con VB.NET"
.Body = "Hola Mundo"
End With
System.Web.Mail.SmtpMail.Send(oMsg)
End Sub
End Module |
Observe que dado a que se especificó el host del
servicio
SMTP
mediante el Campo "smtpserver" ya no es necesario hacerlo mediante
la propiedad
SmtpMail.SmtpServer.
Por otro lado también, si se emplea SmtpMail.SmtpServer
se pueden omitir los Campos "smtpserver", "smtpserverport" y
"sendusing" siendo sólo necesario especificar los tres campos
restantes: "sendusername", "sendpassword" y "smtpauthenticate".
Compilamos el ejemplo sin ningun error, despues
ejecutamos unas cuantas veces enviando correos...
¡Funciona!. Luego entonces, el miembro Fields
de System.Web.Mail.MailMessage
equivale, por asi decirlo, al miembro Fields
de CDO.Configuration
asociado a CDO.Message
tal y como se
ilustró anteriormete.
Por lo visto entonces podemos enviar mensajes
con autenticación sin necesidad de emplear directamente la
Biblioteca COM de CDO gracias a System.Web.Mail.MailMessage.Fields,
pero recuerde que éste esta presente sólo a partir de la
versión 1.1 del .Net
Framework, si por alguna razón aún trabaja con la
versión 1.0 tendrá que emplear el primer método, o
bien, actualizarse a la versión 1.1.
Ahora talvez se
preguntará ¿MailMessage.Fields servirá
para los Campos de otros Espacios de Nombres de CDO? Talvez
sí, pero eso mejor lo comprobaremos en otra
ocasión.
Resumen:
Si su servidor SMTP requiere
autenticación para el envío de correo electrónico
tendrá que
establecer el valor de los siguientes Campos CDO:
|
"http://schemas.microsoft.com/cdo/configuration/sendusername" =
Usuario
"http://schemas.microsoft.com/cdo/configuration/sendpassword" = Contraseña
"http://schemas.microsoft.com/cdo/configuration/smtpauthenticate" = 1 'Basic
|
Para ello tiene que adjuntarlos a la colección Fields de un
objeto Configuration de CDO si está trabajando con el Net
Framework v.1.0, o bien agregarlos al Diccionario Fields de
System.Web.Mail.MailMessage si está trabajando con el .Net
Framework v.1.1.