2008-11-11 19 views
30

Estoy usando un componente de servicio a través de ASP.NET MVC. Me gustaría enviar el correo electrónico de manera asíncrona para que el usuario pueda hacer otras cosas sin tener que esperar el envío.¿Cómo enviar un correo electrónico con archivos adjuntos utilizando SmtpClient.SendAsync?

Cuando envío un mensaje sin archivos adjuntos funciona bien. Cuando envío un mensaje con al menos un archivo adjunto en memoria, falla.

Entonces, me gustaría saber si es posible utilizar un método asíncrono con archivos adjuntos en memoria.

Aquí es el método de envío


    public static void Send() { 

     MailMessage message = new MailMessage("[email protected]", "[email protected]"); 
     using (MemoryStream stream = new MemoryStream(new byte[64000])) { 
      Attachment attachment = new Attachment(stream, "my attachment"); 
      message.Attachments.Add(attachment); 
      message.Body = "This is an async test."; 

      SmtpClient smtp = new SmtpClient("localhost"); 
      smtp.Credentials = new NetworkCredential("foo", "bar"); 
      smtp.SendAsync(message, null); 
     } 
    } 

Aquí está mi error actual


System.Net.Mail.SmtpException: Failure sending mail. 
---> System.NotSupportedException: Stream does not support reading. 
    at System.Net.Mime.MimeBasePart.EndSend(IAsyncResult asyncResult) 
    at System.Net.Mail.Message.EndSend(IAsyncResult asyncResult) 
    at System.Net.Mail.SmtpClient.SendMessageCallback(IAsyncResult result) 
    --- End of inner exception stack trace --- 

Solución

public static void Send() 
    { 

      MailMessage message = new MailMessage("[email protected]", "[email protected]"); 
      MemoryStream stream = new MemoryStream(new byte[64000]); 
      Attachment attachment = new Attachment(stream, "my attachment"); 
      message.Attachments.Add(attachment); 
      message.Body = "This is an async test."; 
      SmtpClient smtp = new SmtpClient("localhost"); 
      //smtp.Credentials = new NetworkCredential("login", "password"); 

      smtp.SendCompleted += delegate(object sender, System.ComponentModel.AsyncCompletedEventArgs e) 
      { 
        if (e.Error != null) 
        { 
          System.Diagnostics.Trace.TraceError(e.Error.ToString()); 

        } 
        MailMessage userMessage = e.UserState as MailMessage; 
        if (userMessage != null) 
        { 
          userMessage.Dispose(); 
        } 
      }; 

      smtp.SendAsync(message, message); 
    } 

Respuesta

33

No utilice el "uso" aquí. Está destruyendo la secuencia de memoria inmediatamente después de llamar a SendAsync, p. probablemente antes de que SMTP lo lea (ya que es asíncrono). Destruye tu transmisión en la devolución de llamada.

0

He tratado de su función y que funciona incluso para el correo electrónico con archivos adjuntos de memoria. Pero aquí hay algunas observaciones:

  • ¿Qué tipo de archivos adjuntos intentó enviar? Exe ?
  • ¿Están el remitente y el receptor en el mismo servidor de correo electrónico?
  • Debe "atrapar" la excepción y no solo tragarla, entonces obtendrá más información sobre su problema.
  • ¿Qué dice la excepción?

  • ¿Funciona cuando se usa Send en lugar de SendAsync? Está utilizando la cláusula 'using' y cerrando Stream antes de que se envíe el correo electrónico.

aquí es bueno texto sobre este tema:

Sending Mail in .NET 2.0

+0

Debería poner más código, perdón por eso. Déjeme editar la muestra para darle más información. – labilbe

+0

Podría ser posible que las llamadas Async que se ejecutan en el servidor de VS Dev no se llamen realmente Async. Mi memoria borrosa está tratando de recordar algo que se dice en alguna parte sobre el servidor web VS Dev es de un solo hilo? –

+0

El enlace está muerto ahora. –

0

Una extensión de la Solución suministrada en la pregunta original también limpia correctamente los archivos adjuntos que también pueden necesitar eliminación.

public event EventHandler EmailSendCancelled = delegate { }; 

    public event EventHandler EmailSendFailure = delegate { }; 

    public event EventHandler EmailSendSuccess = delegate { }; 
    ... 

     MemoryStream mem = new MemoryStream(); 
     try 
     { 
      thisReport.ExportToPdf(mem); 

      // Create a new attachment and put the PDF report into it. 
      mem.Seek(0, System.IO.SeekOrigin.Begin); 
      //Attachment att = new Attachment(mem, "MyOutputFileName.pdf", "application/pdf"); 
      Attachment messageAttachment = new Attachment(mem, thisReportName, "application/pdf"); 

      // Create a new message and attach the PDF report to it. 
      MailMessage message = new MailMessage(); 
      message.Attachments.Add(messageAttachment); 

      // Specify sender and recipient options for the e-mail message. 
      message.From = new MailAddress(NOES.Properties.Settings.Default.FromEmailAddress, NOES.Properties.Settings.Default.FromEmailName); 
      message.To.Add(new MailAddress(toEmailAddress, NOES.Properties.Settings.Default.ToEmailName)); 

      // Specify other e-mail options. 
      //mail.Subject = thisReport.ExportOptions.Email.Subject; 
      message.Subject = subject; 
      message.Body = body; 

      // Send the e-mail message via the specified SMTP server. 
      SmtpClient smtp = new SmtpClient(); 
      smtp.SendCompleted += SmtpSendCompleted; 
      smtp.SendAsync(message, message); 
     } 
     catch (Exception) 
     { 
      if (mem != null) 
      { 
       mem.Dispose(); 
       mem.Close(); 
      } 
      throw; 
     } 
    } 

    private void SmtpSendCompleted(object sender, AsyncCompletedEventArgs e) 
    { 
     var message = e.UserState as MailMessage; 
     if (message != null) 
     { 
      foreach (var attachment in message.Attachments) 
      { 
       if (attachment != null) 
       { 
        attachment.Dispose(); 
       } 
      } 
      message.Dispose(); 
     } 
     if (e.Cancelled) 
      EmailSendCancelled?.Invoke(this, EventArgs.Empty); 
     else if (e.Error != null) 
     { 
      EmailSendFailure?.Invoke(this, EventArgs.Empty); 
      throw e.Error; 
     } 
     else 
      EmailSendSuccess?.Invoke(this, EventArgs.Empty); 
    } 
Cuestiones relacionadas