Pregunta

Nuestra winforms aplicación ha permitido durante mucho tiempo una opción "imprimir", que básicamente utiliza RDLC.

El cliente ha solicitado que se añade una característica que permite a los usuarios enviar la salida "impreso" por correo electrónico.

Ahora, sabemos que se crea un archivo EMF (en la carpeta TEMP) como una especie de subproducto oculta de nuestro proceso de impresión actual.

Parece que nos podemos simplemente coger este archivo EMF y adjuntarlo a un nuevo correo electrónico y el trabajo está hecho.

  1. ¿Es esta la mejor opción?
  2. ¿Podemos confiar en un archivo EMF ser abierto por cualquier máquina de Windows?
  3. ¿Cómo identificamos el archivo EMF? ... sólo parece ser llamado %TEMP%\DiaryGrid_1.emf actualmente. Aceptar lo DiaryGrid es el nombre de nuestro archivo RDLC pero el _1 consigue algún lugar del camino añadieron.
¿Fue útil?

Solución

Lo hice antes. Lo hice exportar mediante programación el informe a un pdf a un lugar específico, entonces enviamos por correo electrónico el archivo PDF y eliminarlo. Voy a tratar de encontrar el código para usted (No en casa ahora)

Editado:

Lo siento por la tarde. Ahora estoy en casa y te daré algunos bloques de código que creo que le dará un poco de ayuda a acomplish su tarea. Voy a incluir algunos comentarios en el código para que pueda entender algunas cosas que son específicos en mi proyecto. Este código se ponen a prueba y están trabajando bien en mis clientes, pero estoy seguro de que se puede mejorar. Por favor, hágamelo saber si usted puede mejorar este código;)

En primer lugar, vamos a exportar el informe a PDF.

private string ExportReportToPDF(string reportName)
{
   Warning[] warnings;
   string[] streamids;
   string mimeType;
   string encoding;
   string filenameExtension;
   byte[] bytes = ReportViewer1.LocalReport.Render(
      "PDF", null, out mimeType, out encoding, out filenameExtension,
       out streamids, out warnings);

   string filename = Path.Combine(Path.GetTempPath(), reportName);
   using (var fs = new FileStream(filename, FileMode.Create))
   {
      fs.Write(bytes, 0, bytes.Length);
      fs.Close();
   }

   return filename;
}

Ahora, necesitamos una clase que controla el sistema de correo. Cada sistema electrónico tiene sus propias caracteristicas, así que tal vez necesitará modificar esta clase. El comportamiento de la clase es simple. Sólo tiene que rellenar las propiedades, y llamar al método Send. En mi caso, las ventanas no me deja borrar el archivo PDF una vez que lo envío (Windows dice que el archivo está en uso), por lo programo el archivo que desea eliminar en el siguiente reinicio. Echar un vistazo al método de eliminación. Por favor, tenga en cuenta que el método de envío utilizar una clase de cutom llamado MailConfig. Se trata de una pequeña clase que tiene algunas cadenas de configuración como host, nombre de usuario y contraseña. El correo se envía utilizando esta params.

public class Mail
{
   public string Title { get; set; }
   public string Text { get; set; }
   public string From { get; set; }
   public bool RequireAutentication { get; set; }
   public bool DeleteFilesAfterSend { get; set; }

   public List<string> To { get; set; }
   public List<string> Cc { get; set; }
   public List<string> Bcc { get; set; }
   public List<string> AttachmentFiles { get; set; }

   #region appi declarations

   internal enum MoveFileFlags
   {
      MOVEFILE_REPLACE_EXISTING = 1,
      MOVEFILE_COPY_ALLOWED = 2,
      MOVEFILE_DELAY_UNTIL_REBOOT = 4,
      MOVEFILE_WRITE_THROUGH = 8
   }

   [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
   static extern bool MoveFileEx(string lpExistingFileName,
                                 string lpNewFileName,
                                 MoveFileFlags dwFlags);

   #endregion

   public Mail()
   {
      To = new List<string>();
      Cc = new List<string>();
      Bcc = new List<string>();
      AttachmentFiles = new List<string>();
      From = MailConfig.Username;
   }

   public void Send()
   {
      var client = new SmtpClient
      {
         Host = MailConfig.Host,
         EnableSsl = false,
      };

      if (RequireAutentication)
      {
         var credentials = new NetworkCredential(MailConfig.Username, 
                                                 MailConfig.Password);
         client.Credentials = credentials;
      }

      var message = new MailMessage
      {
         Sender = new MailAddress(From, From),
         From = new MailAddress(From, From)
      };

      AddDestinataryToList(To, message.To);
      AddDestinataryToList(Cc, message.CC);
      AddDestinataryToList(Bcc, message.Bcc);

      message.Subject = Title;
      message.Body = Text;
      message.IsBodyHtml = false;
      message.Priority = MailPriority.High;

      var attachments = AttachmentFiles.Select(file => new Attachment(file));
      foreach (var attachment in attachments)
         message.Attachments.Add(attachment);

      client.Send(message);

      if (DeleteFilesAfterSend)
         AttachmentFiles.ForEach(DeleteFile);
   }

   private void AddDestinataryToList(IEnumerable<string> from,
      ICollection<MailAddress> mailAddressCollection)
   {
      foreach (var destinatary in from)
         mailAddressCollection.Add(new MailAddress(destinatary, destinatary));
   }

   private void DeleteFile(string filepath)
   {
      // this should delete the file in the next reboot, not now.
      MoveFileEx(filepath, null, MoveFileFlags.MOVEFILE_DELAY_UNTIL_REBOOT);
   }
}

Ahora, puede crear un formulario para solicitar los destinataries, añadir un poco de validación, etc., que regreso a una instancia de la clase Correo ... o puede simplemente "código duro" los valores y llenar la clase.

Este es el código que utilizo en un botón para llamar a esta forma, en mi ejemplo es nombrado SendMailView.

private void BtnSendByMail_Click(object sender, EventArgs e)
{
   SendMailView sendMailView = new SendMailView();

   if (sendMailView.ShowDialog()== DialogResult.OK)
   {
      Mail mail = sendMailView.CurrentItem;
      mail.AttachmentFiles.Add(ExportReportToPDF("Invoice.pdf"));
      mail.DeleteFilesAfterSend = true;
      mail.RequireAutentication = true;
      mail.Send();
   }
   sendMailView.Dispose();
}

En este ejemplo senMailView.CurrentItem es la instancia de la clase de correo. Simplemente tenemos que llamar a los Methis de envío y el trabajo está hecho.

Esta es la respuesta más grande que he escrito en SO ... espero que le ayude: D Si tiene cualquier problema para usarlo, llámame. Por cierto, no estoy muy orgulloso de mi Inglés, así que perdóname si el texto tiene ningún error.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top