Al enviar correos electrónicos con archivos adjuntos desde C #, los archivos adjuntos llegan como Parte 1.2 en Thunderbird

113

Tengo una aplicación C # que envía por correo electrónico informes de hoja de cálculo de Excel a través de un servidor Exchange 2007 mediante SMTP. Estos llegan bien para los usuarios de Outlook, pero para los usuarios de Thunderbird y Blackberry los archivos adjuntos han sido renombrados como "Parte 1.2".

Encontré este artículo que describe el problema, pero no parece darme una solución. No tengo control del servidor Exchange, por lo que no puedo realizar cambios allí. ¿Hay algo que pueda hacer en el extremo de C #? Intenté usar nombres de archivo cortos y codificación HTML para el cuerpo, pero ninguno hizo una diferencia.

Mi código de envío de correo es simplemente esto:

public static void SendMail(string recipient, string subject, string body, string attachmentFilename)
{
    SmtpClient smtpClient = new SmtpClient();
    NetworkCredential basicCredential = new NetworkCredential(MailConst.Username, MailConst.Password);
    MailMessage message = new MailMessage();
    MailAddress fromAddress = new MailAddress(MailConst.Username);

    // setup up the host, increase the timeout to 5 minutes
    smtpClient.Host = MailConst.SmtpServer;
    smtpClient.UseDefaultCredentials = false;
    smtpClient.Credentials = basicCredential;
    smtpClient.Timeout = (60 * 5 * 1000);

    message.From = fromAddress;
    message.Subject = subject;
    message.IsBodyHtml = false;
    message.Body = body;
    message.To.Add(recipient);

    if (attachmentFilename != null)
        message.Attachments.Add(new Attachment(attachmentFilename));

    smtpClient.Send(message);
}

Gracias por cualquier ayuda.

Jon
fuente
¿Ha intentado definir / cambiar la Attachment.Namepropiedad?
Alex
No, no lo he hecho: "Obtiene o establece el valor del nombre del tipo de contenido MIME", ¿tiene alguna sugerencia sobre qué valor probar? Gracias.
Jon
Se Namemuestra como el nombre del archivo adjunto cuando se recibe el correo electrónico con el archivo adjunto. Entonces puedes probar cualquier valor.
Alex

Respuestas:

115

Código simple para enviar correo electrónico con adjunto.

fuente: http://www.coding-issues.com/2012/11/sending-email-with-attachments-from-c.html

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

public void email_send()
{
    MailMessage mail = new MailMessage();
    SmtpClient SmtpServer = new SmtpClient("smtp.gmail.com");
    mail.From = new MailAddress("your [email protected]");
    mail.To.Add("[email protected]");
    mail.Subject = "Test Mail - 1";
    mail.Body = "mail with attachment";

    System.Net.Mail.Attachment attachment;
    attachment = new System.Net.Mail.Attachment("c:/textfile.txt");
    mail.Attachments.Add(attachment);

    SmtpServer.Port = 587;
    SmtpServer.Credentials = new System.Net.NetworkCredential("your [email protected]", "your password");
    SmtpServer.EnableSsl = true;

    SmtpServer.Send(mail);

}
Ranadheer Reddy
fuente
21
Debe envolver MailMessage y SmtpClient con declaraciones de uso para asegurarse de que se eliminen correctamente
Andrew
1
@Andrew, ¿cómo hago eso?
Steam
Probé este código y recibí el error que se muestra en esta publicación - stackoverflow.com/questions/20845469/…
Steam
1
@Steam puedes hacer asíusing(SmtpClient SmtpServer = new SmtpClient("smtp.gmail.com")) { //code goes here using(MailMessage mail = new MailMessage()){ //code goes here } }
Shamseer K
92

Completar explícitamente los campos ContentDisposition funcionó.

if (attachmentFilename != null)
{
    Attachment attachment = new Attachment(attachmentFilename, MediaTypeNames.Application.Octet);
    ContentDisposition disposition = attachment.ContentDisposition;
    disposition.CreationDate = File.GetCreationTime(attachmentFilename);
    disposition.ModificationDate = File.GetLastWriteTime(attachmentFilename);
    disposition.ReadDate = File.GetLastAccessTime(attachmentFilename);
    disposition.FileName = Path.GetFileName(attachmentFilename);
    disposition.Size = new FileInfo(attachmentFilename).Length;
    disposition.DispositionType = DispositionTypeNames.Attachment;
    message.Attachments.Add(attachment);                
}

Por cierto , en el caso de Gmail, es posible que tenga algunas excepciones sobre ssl secure o incluso port.

smtpClient.EnableSsl = true;
smtpClient.Port = 587;
Jon
fuente
2
¿Por qué no utilizar un FileInfoobjeto para obtener CreationTime, LastWriteTimey LastAccessTimepropiedades? De Lengthtodos modos, está creando uno para obtener la propiedad.
sampathsris
1
No olvide el archivo adjunto. Dispose () o este archivo permanecerá bloqueado y no podrá escribir datos en él.
Pau Dominguez
7

Aquí hay un código de envío de correo simple con archivo adjunto

try  
{  
    SmtpClient mailServer = new SmtpClient("smtp.gmail.com", 587);  
    mailServer.EnableSsl = true;  

    mailServer.Credentials = new System.Net.NetworkCredential("[email protected]", "mypassword");  

    string from = "[email protected]";  
    string to = "[email protected]";  
    MailMessage msg = new MailMessage(from, to);  
    msg.Subject = "Enter the subject here";  
    msg.Body = "The message goes here.";
    msg.Attachments.Add(new Attachment("D:\\myfile.txt"));
    mailServer.Send(msg);  
}  
catch (Exception ex)  
{  
    Console.WriteLine("Unable to send email. Error : " + ex);  
}

Leer más Envío de correos electrónicos con archivos adjuntos en C #

Pankaj Prakash
fuente
4

Completando la solución de Ranadheer, usando Server.MapPath para ubicar el archivo

System.Net.Mail.Attachment attachment;
attachment = New System.Net.Mail.Attachment(Server.MapPath("~/App_Data/hello.pdf"));
mail.Attachments.Add(attachment);
Nuno Ribeiro
fuente
¿De dónde Server.MapPathviene y cuándo debe usarse?
Kimmax
1
private void btnSent_Click(object sender, EventArgs e)
{
    try
    {
        MailMessage mail = new MailMessage();
        SmtpClient SmtpServer = new SmtpClient("smtp.gmail.com");

        mail.From = new MailAddress(txtAcc.Text);
        mail.To.Add(txtToAdd.Text);
        mail.Subject = txtSub.Text;
        mail.Body = txtContent.Text;
        System.Net.Mail.Attachment attachment;
        attachment = new System.Net.Mail.Attachment(txtAttachment.Text);
        mail.Attachments.Add(attachment);

        SmtpServer.Port = 587;
        SmtpServer.Credentials = new System.Net.NetworkCredential(txtAcc.Text, txtPassword.Text);

        SmtpServer.EnableSsl = true;

        SmtpServer.Send(mail);
        MessageBox.Show("mail send");
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.ToString());
    }
}

private void button1_Click(object sender, EventArgs e)
{
    MailMessage mail = new MailMessage();
    openFileDialog1.ShowDialog();
    System.Net.Mail.Attachment attachment;
    attachment = new System.Net.Mail.Attachment(openFileDialog1.FileName);
    mail.Attachments.Add(attachment);
    txtAttachment.Text =Convert.ToString (openFileDialog1.FileName);
}
Khang Pham
fuente
1

He creado un código corto para hacer eso y quiero compartirlo contigo.

Aquí el código principal:

public void Send(string from, string password, string to, string Message, string subject, string host, int port, string file)
{

  MailMessage email = new MailMessage();
  email.From = new MailAddress(from);
  email.To.Add(to);
  email.Subject = subject;
  email.Body = Message;
  SmtpClient smtp = new SmtpClient(host, port);
  smtp.UseDefaultCredentials = false;
  NetworkCredential nc = new NetworkCredential(from, password);
  smtp.Credentials = nc;
  smtp.EnableSsl = true;
  email.IsBodyHtml = true;
  email.Priority = MailPriority.Normal;
  email.BodyEncoding = Encoding.UTF8;

  if (file.Length > 0)
  {
    Attachment attachment;
    attachment = new Attachment(file);
    email.Attachments.Add(attachment);
  }

  // smtp.Send(email);
  smtp.SendCompleted += new SendCompletedEventHandler(SendCompletedCallBack);
  string userstate = "sending ...";
  smtp.SendAsync(email, userstate);
}

private static void SendCompletedCallBack(object sender,AsyncCompletedEventArgs e) {
  string result = "";
  if (e.Cancelled)
  {    
    MessageBox.Show(string.Format("{0} send canceled.", e.UserState),"Message",MessageBoxButtons.OK,MessageBoxIcon.Information);
  }
  else if (e.Error != null)
  {
    MessageBox.Show(string.Format("{0} {1}", e.UserState, e.Error), "Message", MessageBoxButtons.OK, MessageBoxIcon.Information);
  }
  else {
    MessageBox.Show("your message is sended", "Message", MessageBoxButtons.OK, MessageBoxIcon.Information);
  }

}

En su botón hacer cosas como esta
, puede agregar sus archivos jpg o pdf y más ... esto es solo un ejemplo

using (OpenFileDialog attachement = new OpenFileDialog()
{
  Filter = "Exel Client|*.png",
  ValidateNames = true
})
{
if (attachement.ShowDialog() == DialogResult.OK)
{
  Send("[email protected]", "gmail_password", 
       "[email protected]", "just smile ", "mail with attachement",
       "smtp.gmail.com", 587, attachement.FileName);

}
}
Elaz
fuente
0

Prueba esto:

private void btnAtt_Click(object sender, EventArgs e) {

    openFileDialog1.ShowDialog();
    Attachment myFile = new Attachment(openFileDialog1.FileName);

    MyMsg.Attachments.Add(myFile);


}
Ashar Kashif
fuente
0

Probé el código proporcionado por Ranadheer Reddy (arriba) y funcionó muy bien. Si está utilizando una computadora de la empresa que tiene un servidor restringido, es posible que deba cambiar el puerto SMTP a 25 y dejar su nombre de usuario y contraseña en blanco, ya que su administrador los completará automáticamente.

Originalmente, intenté usar EASendMail desde el administrador de paquetes nugent, solo para darme cuenta de que es una versión de pago con una prueba de 30 días. No pierda su tiempo con él a menos que planee comprarlo. Me di cuenta de que el programa se ejecutaba mucho más rápido con EASendMail, pero para mí, lo gratuito superó rápidamente.

Solo mis 2 centavos.

Aubrey Love
fuente
0

Utilice este método en su servicio de correo electrónico, puede adjuntar cualquier cuerpo de correo electrónico y archivos adjuntos a Microsoft Outlook.

usando Outlook = Microsoft.Office.Interop.Outlook; // Haga referencia a Microsoft.Office.Interop.Outlook desde local o nuget si utilizará un agente de compilación más adelante

 try {
                    var officeType = Type.GetTypeFromProgID("Outlook.Application");
    
                    if(officeType == null) {//outlook is not installed
                        return new PdfErrorResponse {
                            ErrorMessage = "System cant start Outlook!, make sure outlook is installed on your computer."
                        };
                    } else {
                        // Outlook is installed.    
                        // Continue your work.
                        Outlook.Application objApp = new Outlook.Application();
                        Outlook.MailItem mail = null;
                        mail = (Outlook.MailItem)objApp.CreateItem(Outlook.OlItemType.olMailItem);
                        //The CreateItem method returns an object which has to be typecast to MailItem 
                        //before using it.
                        mail.Attachments.Add(attachmentFilePath,Outlook.OlAttachmentType.olEmbeddeditem,1,$"Attachment{ordernumber}");
                        //The parameters are explained below
                        mail.To = recipientEmailAddress;
                        //mail.CC = "[email protected]";//All the mail lists have to be separated by the ';'
    
                        //To send email:
                        //mail.Send();
                        //To show email window
                        await Task.Run(() => mail.Display());
                    }
    
                } catch(System.Exception) {
                    return new PdfErrorResponse {
                        ErrorMessage = "System cant start Outlook!, make sure outlook is installed on your computer."
                    };
                }
Vuminkosi Vincent Matibe
fuente