miércoles, 3 de junio de 2009

ASP.NET - Enviar correos asíncronos

async_email La forma normal de enviar correos es síncrona, osea se intenta enviar el email y esperamos la respuesta de envío exitoso o de error.
Si enviamos un correo que probablemente tome su tiempo en llegar a su destino, ocurrirá que tendremos que esperar a que el correo se termine de enviar,
lo cual en ASP.NET se refleja en una pantalla congelada que de a pocos se va cargando, y como deducirías, afecta a toda la aplicación... ya que ese tiempo que se tarda en enviar el correo es tiempo perdido para el usuario.

ASP.NET permite enviar realizar tareas de manera asíncrona, esto quiere decir que podemos enviar un correo y no tenemos que esperar a ver si se envió correctamente, sino que podemos continuar con nuestra navegación por el resto de páginas.

Veamos cómo sería esto:

El primer paso es incluir el atributo Async al elemento @Page:

<%@ Page Language="C#" AutoEventWireup="true"
CodeBehind="WebForm1.aspx.cs"
Inherits="SamplesCS.WebForm1"
Async="true" %>

En el code-beside, se requiere incluir los sgtes espacios de nombres:

using System.Net.Mail;
using System.Net;
using System.ComponentModel;

Luego este método hace el trabajo sucio:

public void SendEmail(string strFrom, string strTo, string strSubject, string strBodyText)
{
MailMessage Mail = new MailMessage();
Mail.From = new MailAddress(strFrom);
Mail.To.Add(strTo);
Mail.Subject = strSubject;
Mail.Body = strBodyText;
SmtpClient SMTPClient = new SmtpClient();
NetworkCredential basicAuthenticationInfo = new NetworkCredential("algun_correo1", "algun_password1") ;
SMTPClient.Host = "algun_email_host";
SMTPClient.UseDefaultCredentials = true;
SMTPClient.Credentials = basicAuthenticationInfo;

SMTPClient.SendCompleted += new SendCompletedEventHandler(CheckIfError);
SMTPClient.SendAsync(Mail, Mail);


}

Chequeen las líneas con negrita, esas son las que hacen el trabajo ásíncrono, observen también que recibe un parámetro llamado CheckIfError, ese es el delegado para el evento SendCompleted, y se usa cuando se termina la operación... para determinar si el email se envió correctamente o hubo algún error.

private static void CheckIfError(object sender, AsyncCompletedEventArgs e)
{
if (e.Error != null || e.Cancelled)
{
//podrías escribir el error a un archivo de texto
}
else
{
//podrías grabar el éxitoso envío a un archivo de texto.
}
}

Si revisan el método… en la parte comentada se sugiere guardar en un archivo de texto si la operación fue exitosa o no… de esta manera cuando el usuario desee determinar si hubo error, simplemente accede al archivo de texto. De esta manera no tenemos que estar creando código que trate con los resultados de la operación asíncrona, dado que no sabemos cuánto puede tardar, ni si ya se realizó.

;)

3 comentarios:

DEvil dijo...

SMTPClient.SendCompleted += new SendCompletedEventHandler(CheckIfError);
SMTPClient.SendAsync(Mail, Mail);

hola man cuando paso tu codigo al que tengo en .net me sale error. Me dice que el SendCompleted no existe y estoy en el 2005 lo tienes el codigo en .net

Segundo Serrano dijo...

Hola Fernando,

te refieres a convertirlo a VB.NET?

si es así, prueba esto:
AddHandler SMTPClient.SendCompleted, AddressOf SmtpClient_OnCompleted

y luego:
Public Sub SmtpClient_OnCompleted(ByVal sender As Object, ByVal e As AsyncCompletedEventArgs)
If IsNothing(e.Error) Then
'correcto
Else
'error
End If
End Sub

Saludos,

DEvil dijo...

Si asi es en VB.Net pero especificate no entiendo lo que tratas de decir soy nuevo enviando correos de esta manera.