sábado, 18 de octubre de 2008

ASP.NET - Enviar correos mediante plantillas - II

Como les adelantaba en el post anterior:
Que el diseñador haga su trabajo por separado... dale una pagina.htm vacía y que te pase el html de cómo debería verse cada mensaje que se envía por correo...
para ti será muy fácil coger ese html y usarlo como plantilla para enviar mensajes de correo desde tu aplicación web.
Lo bueno?
cada vez que se quiera cambiar el formato del mensaje no tienes que recompilar la aplicación...
simplemente se reemplaza la plantilla y listo!!!

Sigamos. Ya hemos hecho la plantilla que se usará para enviar correos. Ahora necesitamos:
1.-Una funcionalidad que permita recoger los datos de un usuario y,
2.-Una funcionalidad que recupere el html de la plantilla que usaremos para enviar correos.
2.-Una funcionalidad que envíe correos de bienvenida a los usuarios.

Entonces, recogeremos los datos de los usuarios, mediante este formulario en una página default.aspx

Ahora, la pregunta es:
cómo recupero el contenido html de la plantilla?
simple... uso esta función:

    Public Shared Function GetHTMLFromAddress(ByValAddress As String) As String
        Dim 
ASCII As New System.Text.ASCIIEncoding
      
Dim netWeb As New System.Net.WebClient
      
Dim lsWeb As String
        Dim 
laWeb As Byte()

        Try
          
laWeb = netWeb.DownloadData(Address)
            lsWeb = ASCII.GetString(laWeb)
        Catch ex As Exception
          
Throw New Exception(ex.Message.ToString + ex.ToString)
        End Try
        Return 
lsWeb
    End Function

Algunos se preguntarán por qué no uso System.IO.File... para recuperar el contenido html?
porque con esa manera de recuperar el contenido de un archivo bloqueamos el archivo hasta terminar la operación de lectura... y puede ocurrir que dos personas coincidan en el mismo instante en su intento de registrarse en el sistema web y plop!! se cae tu sistema. Ese es el motivo.
En cambio, con la fución GetHTMLFromAddress no ocurre eso.

También necesitamos esta función para reemplazar en la plantilla, para mostrar la url en donde estamos:

    Public Shared Function GetApplicationPath() As String
        Dim 
strPath As String= ""
        If(Not HttpContext.Current.Request.Url Is Nothing) Then
          
strPath = HttpContext.Current.Request.Url.AbsoluteUri.Substring(0, (HttpContext.Current.Request.Url.AbsoluteUri.ToLower.IndexOf(HttpContext.Current.Request.ApplicationPath.ToLower, CType((HttpContext.Current.Request.Url.AbsoluteUri.ToLower.IndexOf(HttpContext.Current.Request.Url.Authority.ToLower) + HttpContext.Current.Request.Url.Authority.Length), Integer)) + HttpContext.Current.Request.ApplicationPath.Length))

End If
      
strPath = strPath & "/"
        Return strPath
    End Function

Luego, imagínense que alguien se registra en el sistema... luego aprieta el botón Registrarse...


Este código iría en el botón registrarse:





Protected Sub btnSend_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btnSend.Click
Dim urlTemplate As String = Server.MapPath("~/Plantillas/Bienvenida.htm"
        Dim Template As New StringBuilder
Template.Append(GetHTMLFromAddress(urlTemplate))
Template.Replace("$USER_NAME$", txtUserName.Text)
Template.Replace("$USER$", txtEmail.Text)
Template.Replace("$PASSWORD$", "abcde")
Template.Replace("$URL$", GetApplicationPath)

sendMail("unmonitored@jabs.com.pe", txtEmail.Text, "Bienvenido al mundo .NET", Template.ToString)

End Sub

Como ven, luego de recuperar el html de la plantilla, hago un simple reemplazo de algunos textos por los datos que ingresó el usuario y otros de la aplicación.
 Y, para redondear la faena... les adjunto la función que envía los mensajes de bienvenida:



Public Shared Function sendMail(ByVal strFrom As String, ByVal strTo As String, _
ByVal strSubject As String, ByVal strBody As String) As Boolean
Try
Dim Email As New System.Net.Mail.MailMessage(strFrom, strTo)
Email.Subject = strSubject
Email.IsBodyHtml = True
Email.Body = strBody

Dim mailClient As New System.Net.Mail.SmtpClient()
Dim basicAuthenticationInfo As New System.Net.NetworkCredential("ponga su correo aquí", "ponga su password aquí")
mailClient.Host = "ponga su servidor de correo aquí"
            mailClient.UseDefaultCredentials = False
mailClient.Credentials = basicAuthenticationInfo
mailClient.Send(Email)

Catch ex As Exception
Return False

End Try

Return True
End Function

Finalmente vean el mensaje simpaticón que llegaría a su correo...



pero lo más importante... es fácil cambiar el diseño de la plantilla.

Ahora sí, díganle a su jefe que haga todos los cambios que quiera en la plantilla... jeje.


Nota: Para el tema de aquellas plantillas que tienen palabras con acentos, simplemente reemplacen esas palabras con acentos por sus correspondientes en HTML (sólo en la plantilla), veamos:

á = &aacute
é = &eacute
í = &iacute
ó = &oacute
ú = &uacute

osea, si quiero escribir página, escribiré p&aacutegina.
;)

14 comentarios:

Unknown dijo...

Hola encontré tu post y me sirvió mucho. Quería hacerte una consulta, ¿ si la página template tiene que cargar contenido de un gridview, el método GetHTMLFromURL ejecuta el load de la página? o solo trae HTMl estático como si la abriera con el System.IO.File?

Saludos

Segundo Serrano dijo...

Hola Diego,
El método descrito ejecuta el Load de la página y lo que recuperas es el html generado.

No es lo que necesitas? cuéntame y juntos hallamos una solución.

Saludos.

Unknown dijo...

hola encontre tu post y me base en el para hacer una aplicacion de correo electronico que utiliza una plantilla html, pero no se que este haciendo mal ya que me muestra el codigo html es decir como si lo leyera como un archivo de texto, no le da el formato html.
ojala me puedas orientar porque soy nueva en esto del manejo de las plantillas para correo.
Saludos y gracias

Segundo Serrano dijo...

Hola Lorena,

Pueden ocurrir algunas situaciones:
+la más probable es que tu cliente de correo no esté configurado para mostrar emails con formato html... si es así, para prevenir esa situación tendrías que revisar este post http://dotnet-peru.blogspot.com/2009/02/aspnet-enviar-correos-en-formato-html-y.html

+Lo otro podría ser que tu código tenga una falla por allí... puedes poner tu código?

Saludos.

Unknown dijo...

Hola Segundo
Gracias por tu respuesta, revise el post que me dices pero aun asi sigo con el problema, intente ponerte el codigo pero me marca error el blog al publicar el comentario. Tendras algun correo a donde enviartelo.
Saludos gracias por tu ayuda

Segundo Serrano dijo...

Hola Lorena,

puedes enviarme tu código a sserrano[@]jabs[.]com[.]pe.

Elimina los corchetes del correo.

Saludos.

Unknown dijo...

el código va bien el detalle que le veo son los acentos.

no los generaría bien

Segundo Serrano dijo...

Hola Octavio,

los acentos no son problema, lo único que tienes que hacer en tu plantilla html es reemplzar los acentos por su correspondientes caracteres html... He añadido una sección al final del mismopost que indica cómo hacerlo.

Saludos.

Unknown dijo...

si la solución es lógica sólo que lleva un proceso más. habrá que cambiarlos Hard-code. m.m. haber si despúes genero una función para ahcer el reemplazo autómatico utilizando alguna función por ejemplo "HttpUtility.HtmlDecode,HttpUtility.HtmlEncode" que haga la codificación de cualquier caracter, por el momento ando algo corto de tiempo.

salu2, grax por contestar.

Anónimo dijo...

Gracias por ejemplo claro y conciso muy útil..........

Anónimo dijo...

Sere curioso, en lugar de crear toda una funcion para obtener el path real de la plantilla, no seria mas simple usar= "Server.mapPath("~/plantillas/bienvenida.htm")?

Segundo Serrano dijo...

Hola Gonzalo,

Para este caso está muy bien y es suficiente, lo he modificado según tu sugerencia.

Saludos.

esteban769 dijo...

esta muy buena la publicacion pero en el mio no fuciona me manda este error System.Web.HttpException te agradeceria k me ayudaras a corregir el error

Segundo Serrano dijo...

Hola esteban769,

asegúrate que la plantilla está en la carpeta que le indicas... si esto no soluciona tu problema...
puedes ejecutar línea a línea tu código y enviarme la línea donde te sale el error?

Saludos