Diferencias entre System.Web.Mail y System.Net.Mail para el envío de correos electrónicos

Diferencias entre System.Web.Mail y System.Net.Mail

Ambos System.Web.Mail y System.Net.Mail pueden implementar el envío básico de correos electrónicos, pero existen varias diferencias importantes que deben considrearse según el caso de uso.

  1. System.Web.Mail no es una implementación nativa completa del protocolo SMTP en .NET. Utiliza las funcionalidades preeixstentes de COM en CDONTS, lo que requiere procesamiento adicional para enviar mensajes HTML con recursos incrustados (como imágenes), utilizando rutas de archivo para construir adjuntos.
  2. System.Net.Mail es un espacio de nombres añadido en la versión 2.0 del .NET Framework. Contiene clases para enviar correos electrónicos a servidores SMTP para su transmisión. Admite correctamente MIME, lo que permite generar mensajes HTML con recursos incrustados (como imágenes), implementando la funcionalidad completa de un cliente SMTP. Con System.Net.Mail se encuentran muchos menos problemas, ya que evita los porblemas relacionados con COM.
  3. System.Web.Mail ha sido marcado como obsoleto por Microsoft, lo que puede requerir suprimir advertencias de obsolescencia al usarlo.
  4. System.Net.Mail no admite el envío de correos mediante SSL implícito, lo que puede causar que muchos programas de envío de correos electrónicos que cambian de System.Web.Mail a System.Net.Mail no funcionen correctamente. Por ejemplo, muchos proveedores de servicios de correo en el país utilizan el puerto 465 para servicios SMTP, que utiliza protocolos de cifrado implícito.

A continuación se presentan implementaciones más completas que soportan la adición de adjuntos, envío asíncrono, múltiples destinatarios en copia, etc., con una entrada unificada para el código de envío. Por supuesto, se recomienda usar excelentes dependencias para el envío de correos como MimeKit.

Clase de cliente de correo electrónico System.Web.Mail

Clase de utilidad para enviar correos electrónicos usando System.Web.Mail

/// <summary>
/// Cliente de correo electrónico System.Web
/// Generalmente utilizado para servicios de correo con SSL implícito, puerto 465
/// </summary>
public class CorreoElectronicoWeb
{
    #region Miembros privados
    private readonly System.Web.Mail.MailMessage _mensajeCorreo;   //Procesa el contenido del correo (destinatarios, asunto, cuerpo, imágenes, adjuntos)
    private EventHandler<AsyncCompletedEventArgs> _manejadorCompletadoEnvio = null;
    #endregion

    #region Constructor
    /// <summary>
    /// Constructor
    /// </summary>
    /// <param name="usuario">Correo del remitente</param>
    /// <param name="contrasena">Contraseña del correo del remitente</param>
    /// <param name="servidor">Dirección del servidor de correo del remitente</param>
    /// <param name="puerto">Número de puerto para enviar correos (predeterminado 25 para SMTP)</param>
    /// <param name="sslHabilitado">true indica cifrado SSL para el contenido del correo, false sin cifrado</param>
    public CorreoElectronicoWeb(string usuario, string contrasena, string servidor, int puerto, bool sslHabilitado)
    {
        _mensajeCorreo = new System.Web.Mail.MailMessage();
        _mensajeCorreo.BodyFormat = System.Web.Mail.MailFormat.Text;
        _mensajeCorreo.BodyEncoding = Encoding.UTF8;
        _mensajeCorreo.Priority = System.Web.Mail.MailPriority.Alta; //Prioridad

        _mensajeCorreo.Fields.Add("server", servidor);
        _mensajeCorreo.Fields.Add("http://schemas.microsoft.com/cdo/configuration/smtpauthenticate", "1");
        _mensajeCorreo.Fields.Add("http://schemas.microsoft.com/cdo/configuration/sendusername", usuario); //Nombre de usuario
        _mensajeCorreo.Fields.Add("http://schemas.microsoft.com/cdo/configuration/sendpassword", contrasena); //Contraseña
        _mensajeCorreo.Fields.Add("http://schemas.microsoft.com/cdo/configuration/smtpserverport", puerto); //Puerto
        _mensajeCorreo.Fields.Add("http://schemas.microsoft.com/cdo/configuration/smtpusessl", sslHabilitado.ToString().ToLower());
    }

    /// <summary>
    /// Constructor
    /// </summary>
    /// <param name="usuario">Correo del remitente</param>
    /// <param name="contrasena">Contraseña del correo del remitente</param>
    /// <param name="servidor">Dirección del servidor de correo del remitente</param>
    /// <param name="puerto">Número de puerto para enviar correos (predeterminado 25 para SMTP)</param>
    /// <param name="sslHabilitado">true indica cifrado SSL para el contenido del correo, false sin cifrado</param>
    /// <param name="direccionRemitente">Dirección del correo del remitente</param>
    /// <param name="nombreRemitente">Nombre del remitente</param>
    public CorreoElectronicoWeb(string usuario, string contrasena, string servidor, int puerto, bool sslHabilitado, string direccionRemitente, string nombreRemitente)
    {
        _mensajeCorreo = new System.Web.Mail.MailMessage();
        _mensajeCorreo.BodyFormat = System.Web.Mail.MailFormat.Text;
        _mensajeCorreo.BodyEncoding = Encoding.UTF8;
        _mensajeCorreo.Priority = System.Web.Mail.MailPriority.Alta; //Prioridad
        _mensajeCorreo.From = direccionRemitente ?? nombreRemitente;

        _mensajeCorreo.Fields.Add("server", servidor);
        _mensajeCorreo.Fields.Add("http://schemas.microsoft.com/cdo/configuration/smtpauthenticate", "1");
        _mensajeCorreo.Fields.Add("http://schemas.microsoft.com/cdo/configuration/sendusername", usuario); //Nombre de usuario
        _mensajeCorreo.Fields.Add("http://schemas.microsoft.com/cdo/configuration/sendpassword", contrasena); //Contraseña
        _mensajeCorreo.Fields.Add("http://schemas.microsoft.com/cdo/configuration/smtpserverport", puerto); //Puerto
        _mensajeCorreo.Fields.Add("http://schemas.microsoft.com/cdo/configuration/smtpusessl", sslHabilitado.ToString().ToLower());
    }
    #endregion

    #region Métodos privados

    /// <summary>
    /// Callback cuando se completa el envío asíncrono de SmtpClient
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void EnvioCompletado(object sender, AsyncCompletedEventArgs e)
    {
        if (_manejadorCompletadoEnvio != null)
        {
            this._manejadorCompletadoEnvio.Invoke(sender, e);
        }
    }

    /// <summary>
    /// Formatea múltiples direcciones de correo
    /// </summary>
    /// <param name="correoDestinatario"></param>
    /// <returns></returns>
    private string FormatearDireccionCorreo(string correoDestinatario)
    {
        return string.Join(";", Regex.Replace(correoDestinatario, @"[;;,]", "|").Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries));
    }
    #endregion

    #region Propiedades públicas
    /// <summary>
    /// 
    /// </summary>
    public System.Web.Mail.MailMessage MensajeCorreo
    {
        get { return _mensajeCorreo; }
    }
    
    /// <summary>
    /// Evento de callback cuando se completa el envío del correo
    /// </summary>
    public event EventHandler<AsyncCompletedEventArgs> CompletadoEnvioAsincrono
    {
        add { _manejadorCompletadoEnvio += value; }
        remove { _manejadorCompletadoEnvio -= value; }
    }

    /// <summary>
    /// Información del remitente
    /// </summary>
    public string Desde
    {
        get { return _mensajeCorreo.From; }
        set { _mensajeCorreo.From = value; }
    }

    /// <summary>
    /// Asunto del correo
    /// </summary>
    public string Asunto
    {
        get { return _mensajeCorreo.Subject; }
        set { _mensajeCorreo.Subject = value; }
    }

    /// <summary>
    /// Contenido del correo
    /// </summary>
    public string Cuerpo
    {
        get { return _mensajeCorreo.Body; }
        set { _mensajeCorreo.Body = value; }
    }

    /// <summary>
    /// Codificación del cuerpo
    /// </summary>
    public Encoding CodificacionCuerpo
    {
        get { return _mensajeCorreo.BodyEncoding; }
        set { _mensajeCorreo.BodyEncoding = value; }
    }

    /// <summary>
    /// Si el contenido es HTML
    /// </summary>
    public bool EsCuerpoHtml
    {
        get { return _mensajeCorreo.BodyFormat == System.Web.Mail.MailFormat.Html; }
        set { _mensajeCorreo.BodyFormat = value ? System.Web.Mail.MailFormat.Html : System.Web.Mail.MailFormat.Text; }
    }

    /// <summary>
    /// Prioridad del correo: baja, normal, urgente, por defecto normal
    /// </summary>
    public System.Web.Mail.MailPriority Prioridad
    {
        get { return _mensajeCorreo.Priority; }
        set { _mensajeCorreo.Priority = value; }
    }

    /// <summary>
    /// Información de destinatarios
    /// </summary>
    public string Para
    {
        get { return _mensajeCorreo.To; }
        set { _mensajeCorreo.To = FormatearDireccionCorreo(value); }
    }

    /// <summary>
    /// Información de destinatarios en copia
    /// </summary>
    public string CCO
    {
        get { return _mensajeCorreo.Cc; }
        set { _mensajeCorreo.Cc = FormatearDireccionCorreo(value); }
    }
    #endregion

    #region Métodos públicos

    ///<summary>
    /// Agregar adjuntos
    ///</summary>
    ///<param name="archivosAdjuntos">Colección de rutas de archivos adjuntos</param>
    public void AgregarAdjuntos(IDictionary<string, string> archivosAdjuntos)
    {
        if (archivosAdjuntos != null && archivosAdjuntos.Count > 0)
        {
            foreach (var item in archivosAdjuntos)
            {
                var bytes = System.IO.File.ReadAllBytes(item.Value);
                var datos = new System.Web.Mail.MailAttachment(Convert.ToBase64String(bytes), System.Web.Mail.MailEncoding.Base64);
                _mensajeCorreo.Attachments.Add(datos);
            }
        }
    }

    /// <summary>
    /// Limpiar adjuntos
    /// </summary>
    public void LimpiarAdjuntos()
    {
        _mensajeCorreo.Attachments.Clear();
    }

    /// <summary>
    /// Enviar correo (método síncrono, lanza excepción si hay error)
    /// </summary>
    public void Enviar()
    {
        Enviar(_mensajeCorreo.To, _mensajeCorreo.Cc);
    }
    
    /// <summary>
    /// Enviar correo (método síncrono, lanza excepción si hay error)
    /// </summary>
    /// <param name="correoDestinatario">Destinatario</param>
    /// <param name="correoDestinatarioCC">Destinatario en copia</param>
    public void Enviar(string correoDestinatario, string correoDestinatarioCC)
    {
        _mensajeCorreo.To = FormatearDireccionCorreo(correoDestinatario);
        _mensajeCorreo.Cc = FormatearDireccionCorreo(correoDestinatarioCC);
        System.Web.Mail.SmtpMail.SmtpServer = _mensajeCorreo.Fields["server"].ToString();
        System.Web.Mail.SmtpMail.Send(_mensajeCorreo);
    }

    /// <summary>
    /// Enviar correo (método asíncrono, el error se devuelve en el callback)
    /// </summary>
    /// <param name="correoDestinatario">Destinatario</param>
    /// <param name="correoDestinatarioCC">Destinatario en copia</param>
    /// <returns></returns>
    public Task EnviarAsync(string correoDestinatario, string correoDestinatarioCC)
    {
        Task tarea = Task.Factory.StartNew(() =>
        {
            _mensajeCorreo.To = FormatearDireccionCorreo(correoDestinatario);
            _mensajeCorreo.Cc = FormatearDireccionCorreo(correoDestinatarioCC);
            System.Web.Mail.SmtpMail.SmtpServer = _mensajeCorreo.Fields["server"].ToString();
            System.Web.Mail.SmtpMail.Send(_mensajeCorreo);
        });
        tarea.GetAwaiter().OnCompleted(() => {
            this.EnvioCompletado(tarea, new AsyncCompletedEventArgs(tarea.Exception, tarea.IsCanceled, null));
        });
        return tarea;
    }
    #endregion
}

Clase de cliente de correo electrónico System.Net.Mail

Clase de utilidad para enviar correos electrónicos usando System.Net.Mail

/// <summary>
/// Cliente de correo electrónico System.Net
/// Adecuado para servicios de correo sin SSL implícito, puertos distintos a 465 (ej. 25, 993)
/// </summary>
public class CorreoElectronicoNet
{
    #region Miembros privados
    private readonly System.Net.Mail.MailMessage _mensajeCorreo;   //Procesa el contenido del correo (destinatarios, asunto, cuerpo, imágenes, adjuntos)
    private readonly System.Net.Mail.SmtpClient _clienteSmtp;     //Procesa la configuración para enviar correos mediante SMTP (servidor, puerto, autenticación)
    private EventHandler<AsyncCompletedEventArgs> _manejadorCompletadoEnvio = null;
    #endregion

    #region Constructor
    /// <summary>
    /// Constructor
    /// </summary>
    /// <param name="usuario">Correo del remitente</param>
    /// <param name="contrasena">Contraseña del correo del remitente</param>
    /// <param name="servidor">Dirección del servidor de correo del remitente</param>
    /// <param name="puerto">Número de puerto para enviar correos (predeterminado 25 para SMTP)</param>
    /// <param name="sslHabilitado">true indica cifrado SSL para el contenido del correo, false sin cifrado</param>
    public CorreoElectronicoNet(string usuario, string contrasena, string servidor, int puerto, bool sslHabilitado)
    {
        _clienteSmtp = new System.Net.Mail.SmtpClient(servidor, puerto);
        _clienteSmtp.EnableSsl = sslHabilitado;
        _clienteSmtp.UseDefaultCredentials = false;
        _clienteSmtp.Credentials = new System.Net.NetworkCredential(usuario, contrasena); //Usuario y contraseña
        _clienteSmtp.DeliveryMethod = System.Net.Mail.SmtpDeliveryMethod.Network; //Método de envío
        _clienteSmtp.SendCompleted += new System.Net.Mail.SendCompletedEventHandler(EnvioCompletado);

        _mensajeCorreo = new System.Net.Mail.MailMessage();
        _mensajeCorreo.IsBodyHtml = true;
        _mensajeCorreo.BodyEncoding = Encoding.UTF8;
        _mensajeCorreo.Priority = System.Net.Mail.MailPriority.Normal; //Prioridad
        _mensajeCorreo.From = new System.Net.Mail.MailAddress(usuario);
    }

    /// <summary>
    /// Constructor
    /// </summary>
    /// <param name="usuario">Correo del remitente</param>
    /// <param name="contrasena">Contraseña del correo del remitente</param>
    /// <param name="servidor">Dirección del servidor de correo del remitente</param>
    /// <param name="puerto">Número de puerto para enviar correos (predeterminado 25 para SMTP)</param>
    /// <param name="sslHabilitado">true indica cifrado SSL para el contenido del correo, false sin cifrado</param>
    /// <param name="direccionRemitente">Dirección del correo del remitente</param>
    /// <param name="nombreRemitente">Nombre del remitente</param>
    public CorreoElectronicoNet(string usuario, string contrasena, string servidor, int puerto, bool sslHabilitado, string direccionRemitente, string nombreRemitente)
    {
        _clienteSmtp = new System.Net.Mail.SmtpClient(servidor, puerto);
        _clienteSmtp.EnableSsl = sslHabilitado;
        _clienteSmtp.UseDefaultCredentials = false;
        _clienteSmtp.Credentials = new System.Net.NetworkCredential(usuario, contrasena); //Usuario y contraseña
        _clienteSmtp.DeliveryMethod = System.Net.Mail.SmtpDeliveryMethod.Network; //Método de envío
        _clienteSmtp.SendCompleted += new System.Net.Mail.SendCompletedEventHandler(EnvioCompletado);

        _mensajeCorreo = new System.Net.Mail.MailMessage();
        _mensajeCorreo.IsBodyHtml = true;
        _mensajeCorreo.BodyEncoding = Encoding.UTF8;
        _mensajeCorreo.Priority = System.Net.Mail.MailPriority.Normal; //Prioridad
        if (string.IsNullOrEmpty(nombreRemitente))
            _mensajeCorreo.From = new System.Net.Mail.MailAddress(direccionRemitente);
        else
            _mensajeCorreo.From = new System.Net.Mail.MailAddress(direccionRemitente, nombreRemitente, Encoding.UTF8);
    }
    #endregion

    #region Métodos privados

    /// <summary>
    /// Callback cuando se completa el envío asíncrono de SmtpClient
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void EnvioCompletado(object sender, AsyncCompletedEventArgs e)
    {
        if (_manejadorCompletadoEnvio != null)
        {
            this._manejadorCompletadoEnvio.Invoke(sender, e);
        }
    }

    /// <summary>
    /// Formatea múltiples direcciones de correo
    /// </summary>
    /// <param name="correoDestinatario"></param>
    /// <returns></returns>
    private IEnumerable<System.Net.Mail.MailAddress> FormatearDireccionCorreo(string correoDestinatario)
    {
        return Regex.Replace(correoDestinatario, @"[;;,]", "|").Split(new char[] { '|' }, StringSplitOptions.RemoveEmptyEntries).Select(x => new System.Net.Mail.MailAddress(x, x));
    }
    #endregion

    #region Propiedades públicas
    /// <summary>
    /// 
    /// </summary>
    public System.Net.Mail.MailMessage MensajeCorreo
    {
        get { return _mensajeCorreo; }
    }
    
    /// <summary>
    /// Evento de callback cuando se completa el envío asíncrono del correo
    /// </summary>
    public event EventHandler<AsyncCompletedEventArgs> CompletadoEnvioAsincrono
    {
        add { _manejadorCompletadoEnvio += value; }
        remove { _manejadorCompletadoEnvio -= value; }
    }

    /// <summary>
    /// Información del remitente
    /// </summary>
    public System.Net.Mail.MailAddress Desde
    {
        get { return _mensajeCorreo.From; }
        set { _mensajeCorreo.From = value; }
    }

    /// <summary>
    /// Asunto del correo
    /// </summary>
    public string Asunto
    {
        get { return _mensajeCorreo.Subject; }
        set { _mensajeCorreo.Subject = value; }
    }

    /// <summary>
    /// Contenido del correo
    /// </summary>
    public string Cuerpo
    {
        get { return _mensajeCorreo.Body; }
        set { _mensajeCorreo.Body = value; }
    }

    /// <summary>
    /// Codificación del cuerpo
    /// </summary>
    public Encoding CodificacionCuerpo
    {
        get { return _mensajeCorreo.BodyEncoding; }
        set { _mensajeCorreo.BodyEncoding = value; }
    }

    /// <summary>
    /// Si el contenido es HTML
    /// </summary>
    public bool EsCuerpoHtml
    {
        get { return _mensajeCorreo.IsBodyHtml; }
        set { _mensajeCorreo.IsBodyHtml = value; }
    }

    /// <summary>
    /// Prioridad del correo: baja, normal, urgente, por defecto normal
    /// </summary>
    public System.Net.Mail.MailPriority Prioridad
    {
        get { return _mensajeCorreo.Priority; }
        set { _mensajeCorreo.Priority = value; }
    }

    /// <summary>
    /// Información de destinatarios
    /// </summary>
    public string Para
    {
        get { return string.Join(";", _mensajeCorreo.To?.Select(x => x.Address)); }
        set
        {
            _mensajeCorreo.To.Clear();
            var listaCorreos = FormatearDireccionCorreo(value);
            foreach (var item in listaCorreos)
            {
                _mensajeCorreo.To.Add(item);
            }
        }
    }

    /// <summary>
    /// Información de destinatarios en copia
    /// </summary>
    public string CCO
    {
        get { return string.Join(";", _mensajeCorreo.CC?.Select(x => x.Address)); }
        set
        {
            _mensajeCorreo.CC.Clear();
            var listaCorreos = FormatearDireccionCorreo(value);
            foreach (var item in listaCorreos)
            {
                _mensajeCorreo.CC.Add(item);
            }
        }
    }
    #endregion

    #region Métodos públicos

    ///<summary>
    /// Agregar adjuntos
    ///</summary>
    ///<param name="archivosAdjuntos">Colección de rutas de archivos adjuntos</param>
    public void AgregarAdjuntos(IDictionary<string, string> archivosAdjuntos)
    {
        if (archivosAdjuntos != null && archivosAdjuntos.Count > 0)
        {
            foreach (var item in archivosAdjuntos)
            {
                var datos = new System.Net.Mail.Attachment(item.Value, System.Net.Mime.MediaTypeNames.Application.Octet);
                datos.Name = item.Key;
                var disposicion = datos.ContentDisposition;
                disposicion.CreationDate = System.IO.File.GetCreationTime(item.Value);
                disposicion.ModificationDate = System.IO.File.GetLastWriteTime(item.Value);
                disposicion.ReadDate = System.IO.File.GetLastAccessTime(item.Value);
                _mensajeCorreo.Attachments.Add(datos);
            }
        }
    }

    ///<summary>
    /// Agregar adjuntos incrustados
    /// No se muestran como adjuntos, se pueden usar directamente en HTML con el id, generalmente para imágenes adjuntas
    /// Se puede usar el id del archivo en HTML ![](\"cid:webimg\")
    ///</summary>
    ///<param name="archivosAdjuntos">Colección de rutas de archivos adjuntos</param>
    public void AgregarAdjuntosIncrustados(IDictionary<string, string> archivosAdjuntos)
    {
        if (archivosAdjuntos != null && archivosAdjuntos.Count > 0)
        {
            foreach (var item in archivosAdjuntos)
            {
                var datos = new System.Net.Mail.Attachment(item.Value, System.Net.Mime.MediaTypeNames.Application.Octet);
                datos.Name = item.Key;
                var disposicion = datos.ContentDisposition;
                datos.ContentDisposition.CreationDate = System.IO.File.GetCreationTime(item.Value);
                datos.ContentDisposition.ModificationDate = System.IO.File.GetLastWriteTime(item.Value);
                datos.ContentDisposition.ReadDate = System.IO.File.GetLastAccessTime(item.Value);
                datos.ContentId = System.IO.Path.GetFileNameWithoutExtension(item.Value);
                _mensajeCorreo.Attachments.Add(datos);
            }
        }
    }

    /// <summary>
    /// Limpiar adjuntos
    /// </summary>
    public void LimpiarAdjuntos()
    {
        _mensajeCorreo.Attachments.Clear();
    }
    
    /// <summary>
    /// Enviar correo (método síncrono, lanza excepción si hay error)
    /// </summary>
    public void Enviar()
    {
        Enviar(_mensajeCorreo.To, _mensajeCorreo.CC);
    }
    
    /// <summary>
    /// Enviar correo (método síncrono, lanza excepción si hay error)
    /// </summary>
    /// <param name="correoDestinatario">Destinatario</param>
    /// <param name="correoDestinatarioCC">Destinatario en copia</param>
    public void Enviar(string correoDestinatario, string correoDestinatarioCC)
    {
        Enviar(FormatearDireccionCorreo(correoDestinatario), FormatearDireccionCorreo(correoDestinatarioCC));
    }

    /// <summary>
    /// Enviar múltiples correos (método síncrono, lanza excepción si hay error)
    /// </summary>
    /// <param name="listaDestinatarios">Colección de destinatarios</param>
    /// <param name="listaDestinatariosCC">Colección de destinatarios en copia</param>
    public void Enviar(IEnumerable<System.Net.Mail.MailAddress> listaDestinatarios, IEnumerable<System.Net.Mail.MailAddress> listaDestinatariosCC)
    {
        _mensajeCorreo.To.Clear();
        foreach (var item in listaDestinatarios)
        {
            _mensajeCorreo.To.Add(item);
        }
        _mensajeCorreo.CC.Clear();
        foreach (var item in listaDestinatariosCC)
        {
            _mensajeCorreo.CC.Add(item);
        }
        _clienteSmtp.Send(_mensajeCorreo);
    }

    /// <summary>
    /// Enviar correo (método asíncrono, el error se devuelve en el callback)
    /// </summary>
    /// <returns></returns>
    public Task EnviarAsync()
    {
        return EnviarAsync(_mensajeCorreo.To, _mensajeCorreo.CC);
    }

    /// <summary>
    /// Enviar correo (método asíncrono, el error se devuelve en el callback)
    /// </summary>
    /// <param name="correoDestinatario">Destinatario</param>
    /// <param name="correoDestinatarioCC">Destinatario en copia</param>
    public Task EnviarAsync(string correoDestinatario, string correoDestinatarioCC)
    {
        return EnviarAsync(FormatearDireccionCorreo(correoDestinatario), FormatearDireccionCorreo(correoDestinatarioCC));
    }

    /// <summary>
    /// Enviar múltiples correos (método asíncrono, el error se devuelve en el callback)
    /// </summary>
    /// <param name="listaDestinatarios">Colección de destinatarios</param>
    /// <returns></returns>
    public Task EnviarAsync(IEnumerable<System.Net.Mail.MailAddress> listaDestinatarios, IEnumerable<System.Net.Mail.MailAddress> listaDestinatariosCC)
    {
        _mensajeCorreo.To.Clear();
        foreach (var item in listaDestinatarios)
        {
            _mensajeCorreo.To.Add(item);
        }
        _mensajeCorreo.CC.Clear();
        foreach (var item in listaDestinatariosCC)
        {
            _mensajeCorreo.CC.Add(item);
        }
        return _clienteSmtp.SendMailAsync(_mensajeCorreo);
    }

    /// <summary>
    /// Enviar correo (método asíncrono, el error se devuelve en el callback)
    /// </summary>
    /// <param name="correoDestinatario">Destinatario</param>
    /// <param name="correoDestinatarioCC">Destinatario en copia</param>
    /// <param name="tokenUsuario">Token de usuario para la operación asíncrona</param>
    public void EnviarAsync(string correoDestinatario, string correoDestinatarioCC, object tokenUsuario)
    {
        EnviarAsync(FormatearDireccionCorreo(correoDestinatario), FormatearDireccionCorreo(correoDestinatarioCC), tokenUsuario);
    }

    /// <summary>
    /// Enviar múltiples correos (método asíncrono, el error se devuelve en el callback)
    /// </summary>
    /// <param name="listaDestinatarios">Colección de destinatarios</param>
    /// <param name="tokenUsuario">Token de usuario para la operación asíncrona</param>
    public void EnviarAsync(IEnumerable<System.Net.Mail.MailAddress> listaDestinatarios, IEnumerable<System.Net.Mail.MailAddress> listaDestinatariosCC, object tokenUsuario)
    {
        _mensajeCorreo.To.Clear();
        foreach (var item in listaDestinatarios)
        {
            _mensajeCorreo.To.Add(item);
        }
        _mensajeCorreo.CC.Clear();
        foreach (var item in listaDestinatariosCC)
        {
            _mensajeCorreo.CC.Add(item);
        }
        _clienteSmtp.SendAsync(_mensajeCorreo, tokenUsuario);
    }
    #endregion
}

Clase de entidad genérica para correo electrónico

/// <summary>
/// Clase de entidad básica para contenido de correo electrónico
/// </summary>
[Serializable]
public class ModeloParametrosCorreo
{
    private string _servidorSmtp = "smtp.qq.com";
    private int _puerto = 587;
    private string _usuario = string.Empty;
    private string _contrasena = string.Empty;
    private string _nombreRemitente = string.Empty;
    private string _correoRemitente = string.Empty;
    private string _correoDestinatario = string.Empty;
    private string _nombreDestinatario = string.Empty;
    private string _correoCC = null;
    private string _asunto = string.Empty;
    private string _cuerpo = string.Empty;
    private Encoding _codificacionCuerpo = System.Text.Encoding.Default;
    private bool _esCuerpoHtml = true;
    private int _prioridad = 0;
    private Dictionary<string, string> _archivosAdjuntos = null;
    
    public ModeloParametrosCorreo()
    {
    }
    
    /// <summary>
    /// Servidor SMTP
    /// </summary>
    public string Servidor
    {
        get { return _servidorSmtp; }
        set { _servidorSmtp = value; }
    }
    
    /// <summary>
    /// Número de puerto
    /// </summary>
    public int Puerto
    {
        get { return _puerto; }
        set { _puerto = value; }
    }
    
    /// <summary>
    /// Nombre de usuario
    /// </summary>
    public string Usuario
    {
        get { return _usuario; }
        set { _usuario = value; }
    }
    
    /// <summary>
    /// Contraseña
    /// </summary>
    public string Contrasena
    {
        get { return _contrasena; }
        set { _contrasena = value; }
    }
    
    public bool SslHabilitado { get; set; }
    
    /// <summary>
    /// Nombre del remitente
    /// </summary>
    public string NombreRemitente
    {
        get { return _nombreRemitente; }
        set { _nombreRemitente = value; }
    }
    
    /// <summary>
    /// Correo del remitente
    /// </summary>
    public string CorreoRemitente
    {
        get { return _correoRemitente; }
        set { _correoRemitente = value; }
    }
    
    /// <summary>
    /// Correo del destinatario
    /// </summary>
    public string CorreoDestinatario
    {
        get { return _correoDestinatario; }
        set { _correoDestinatario = value; }
    }
    
    /// <summary>
    /// Nombre del destinatario
    /// </summary>
    public string NombreDestinatario
    {
        get { return _nombreDestinatario; }
        set { _nombreDestinatario = value; }
    }
    
    /// <summary>
    /// Asunto
    /// </summary>
    public string Asunto
    {
        get { return _asunto; }
        set { _asunto = value; }
    }
    
    /// <summary>
    /// Contenido
    /// </summary>
    public string Cuerpo
    {
        get { return _cuerpo; }
        set { _cuerpo = value; }
    }

    /// <summary>
    /// Codificación del cuerpo
    /// </summary>
    public Encoding CodificacionCuerpo
    {
        get { return _codificacionCuerpo; }
        set { _codificacionCuerpo = value; }
    }

    /// <summary>
    /// Si el contenido es HTML
    /// </summary>
    public bool EsCuerpoHtml
    {
        get { return _esCuerpoHtml; }
        set { _esCuerpoHtml = value; }
    }

    /// <summary>
    /// Prioridad del correo: 0 normal; 1 bajo; 2 urgente; por defecto 0 normal
    /// </summary>
    public int Prioridad
    {
        get { return _prioridad; }
        set { _prioridad = value; }
    }
    
    /// <summary>
    /// Destinatarios en copia
    /// </summary>
    public string CorreoCC
    {
        get { return _correoCC; }
        set { _correoCC = value; }
    }
    
    /// <summary>
    /// Archivos adjuntos del correo 
    /// clave: nombre del archivo; valor: ruta física absoluta del archivo
    /// </summary>
    public Dictionary<string, string> ArchivosAdjuntos
    {
        get { return _archivosAdjuntos; }
        set { _archivosAdjuntos = value; }
    }
}

Clase de ayuda unificada para envío de correos

/// <summary>
/// Clase de ayuda para el envío de correos electrónicos
/// </summary>
public class AyudaCorreoElectronico
{
    /// <summary>
    /// Enviar correo
    /// </summary>
    /// <param name="parametrosCorreo">Contenido del correo</param>
    /// <param name="error">Información de error</param>
    public static bool EnviarCorreoNet(ModeloParametrosCorreo parametrosCorreo, out Exception error)
    {
        error = null;
        try
        {
            CorreoElectronicoNet clienteCorreo = new CorreoElectronicoNet(parametrosCorreo.Usuario, parametrosCorreo.Contrasena, 
                parametrosCorreo.Servidor, parametrosCorreo.Puerto, parametrosCorreo.SslHabilitado, 
                parametrosCorreo.CorreoRemitente, parametrosCorreo.NombreRemitente);
            clienteCorreo.Asunto = parametrosCorreo.Asunto; //Asunto
            clienteCorreo.Cuerpo = parametrosCorreo.Cuerpo; //Contenido
            clienteCorreo.CodificacionCuerpo = System.Text.Encoding.Default; //Codificación del cuerpo
            clienteCorreo.EsCuerpoHtml = parametrosCorreo.EsCuerpoHtml; //Formato HTML
            clienteCorreo.Prioridad = System.Net.Mail.MailPriority.Normal; //Prioridad
            clienteCorreo.AgregarAdjuntos(parametrosCorreo.ArchivosAdjuntos);
            clienteCorreo.Enviar(parametrosCorreo.CorreoDestinatario, parametrosCorreo.CorreoCC);
        }
        catch (Exception ex)
        {
            error = ex;
            return false;
        }
        return true;
    }

    /// <summary>
    /// Enviar correo
    /// </summary>
    /// <param name="parametrosCorreo">Contenido del correo</param>
    /// <param name="error">Información de error</param>
    public static bool EnviarCorreoWeb(ModeloParametrosCorreo parametrosCorreo, out Exception error)
    {
        error = null;
        try
        {
            CorreoElectronicoWeb clienteCorreo = new CorreoElectronicoWeb(parametrosCorreo.Usuario, parametrosCorreo.Contrasena, 
                parametrosCorreo.Servidor, parametrosCorreo.Puerto, parametrosCorreo.SslHabilitado, 
                parametrosCorreo.CorreoRemitente, parametrosCorreo.NombreRemitente);
            clienteCorreo.Asunto = parametrosCorreo.Asunto; //Asunto
            clienteCorreo.Cuerpo = parametrosCorreo.Cuerpo; //Contenido
            clienteCorreo.CodificacionCuerpo = parametrosCorreo.CodificacionCuerpo; //Codificación del cuerpo
            clienteCorreo.EsCuerpoHtml = parametrosCorreo.EsCuerpoHtml; //Formato HTML
            clienteCorreo.Prioridad = (System.Web.Mail.MailPriority)parametrosCorreo.Prioridad; //Prioridad
            clienteCorreo.AgregarAdjuntos(parametrosCorreo.ArchivosAdjuntos);
            clienteCorreo.Enviar(parametrosCorreo.CorreoDestinatario, parametrosCorreo.CorreoCC);
        }
        catch (Exception ex)
        {
            error = ex;
            return false;
        }
        return true;
    }
    
    /// <summary>
    /// Enviar correo
    /// </summary>
    /// <param name="parametrosCorreo">Contenido del correo</param>
    /// <param name="completadoEvento">Callback al completar el envío</param>
    public static void EnviarCorreoNetAsync(ModeloParametrosCorreo parametrosCorreo, EventHandler<AsyncCompletedEventArgs> completadoEvento)
    {
        CorreoElectronicoNet clienteCorreo = new CorreoElectronicoNet(parametrosCorreo.Usuario, parametrosCorreo.Contrasena, 
            parametrosCorreo.Servidor, parametrosCorreo.Puerto, parametrosCorreo.SslHabilitado, 
            parametrosCorreo.CorreoRemitente, parametrosCorreo.NombreRemitente);
        clienteCorreo.Asunto = parametrosCorreo.Asunto; //Asunto
        clienteCorreo.Cuerpo = parametrosCorreo.Cuerpo; //Contenido
        clienteCorreo.CodificacionCuerpo = System.Text.Encoding.Default; //Codificación del cuerpo
        clienteCorreo.EsCuerpoHtml = parametrosCorreo.EsCuerpoHtml; //Formato HTML
        clienteCorreo.Prioridad = (System.Net.Mail.MailPriority)parametrosCorreo.Prioridad; //Prioridad
        clienteCorreo.CompletadoEnvioAsincrono += new EventHandler<AsyncCompletedEventArgs>(completadoEvento);
        clienteCorreo.AgregarAdjuntos(parametrosCorreo.ArchivosAdjuntos);
        clienteCorreo.EnviarAsync(parametrosCorreo.CorreoDestinatario, parametrosCorreo.CorreoCC);
    }

    /// <summary>
    /// Enviar correo
    /// </summary>
    /// <param name="parametrosCorreo">Contenido del correo</param>
    /// <param name="completadoEvento">Callback al completar el envío</param>
    public static void EnviarCorreoWebAsync(ModeloParametrosCorreo parametrosCorreo, EventHandler<AsyncCompletedEventArgs> completadoEvento)
    {
        CorreoElectronicoWeb clienteCorreo = new CorreoElectronicoWeb(parametrosCorreo.Usuario, parametrosCorreo.Contrasena, 
            parametrosCorreo.Servidor, parametrosCorreo.Puerto, parametrosCorreo.SslHabilitado, 
            parametrosCorreo.CorreoRemitente, parametrosCorreo.NombreRemitente);
        clienteCorreo.Asunto = parametrosCorreo.Asunto; //Asunto
        clienteCorreo.Cuerpo = parametrosCorreo.Cuerpo; //Contenido
        clienteCorreo.CodificacionCuerpo = parametrosCorreo.CodificacionCuerpo; //Codificación del cuerpo
        clienteCorreo.EsCuerpoHtml = parametrosCorreo.EsCuerpoHtml; //Formato HTML
        clienteCorreo.Prioridad = (System.Web.Mail.MailPriority)parametrosCorreo.Prioridad; //Prioridad
        clienteCorreo.CompletadoEnvioAsincrono += new EventHandler<AsyncCompletedEventArgs>(completadoEvento);
        clienteCorreo.AgregarAdjuntos(parametrosCorreo.ArchivosAdjuntos);
        clienteCorreo.EnviarAsync(parametrosCorreo.CorreoDestinatario, parametrosCorreo.CorreoCC);
    }
}

Etiquetas: .NET SMTP correo electrónico System.Web.Mail System.Net.Mail

Publicado el 6-26 22:59