117

I have a C# application which emails out Excel spreadsheet reports via an Exchange 2007 server using SMTP. These arrive fine for Outlook users, but for Thunderbird and Blackberry users the attachments have been renamed as "Part 1.2".

I found this article which describes the problem, but doesn't seem to give me a workaround. I don't have control of the Exchange server so can't make changes there. Is there anything I can do on the C# end? I have tried using short filenames and HTML encoding for the body but neither made a difference.

My mail sending code is simply this:

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);
}

Thanks for any help.

davmos
  • 8,724
  • 4
  • 36
  • 41
Jon
  • 4,957
  • 5
  • 27
  • 38
  • Have you tried to define/change `Attachment.Name` property? – Alex May 13 '10 at 10:45
  • No, I haven't - "Gets or sets the MIME content type name value", do you have a suggestion as to what value to try? Thanks. – Jon May 13 '10 at 11:09
  • The `Name` is displayed as the attachment’s name when the email with the attachment is received. So you may try any value. – Alex May 13 '10 at 11:24

9 Answers9

119

Simple code to send email with attachement.

source: 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 mail@gmail.com");
    mail.To.Add("to_mail@gmail.com");
    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 mail@gmail.com", "your password");
    SmtpServer.EnableSsl = true;

    SmtpServer.Send(mail);

}
Ranadheer Reddy
  • 3,930
  • 11
  • 49
  • 73
  • 21
    You should wrap MailMessage and SmtpClient with using statements to ensure they are disposed correctly – Andrew Jan 14 '13 at 09:07
  • 1
    @Andrew - how do I do that? – Steam Dec 30 '13 at 19:09
  • I tried this code and I got the error shown in this post - http://stackoverflow.com/questions/20845469/finding-the-exact-cause-for-the-exception-system-net-sockets-socketexception – Steam Dec 30 '13 at 19:09
  • 2
    @Steam you can do like this `using(SmtpClient SmtpServer = new SmtpClient("smtp.gmail.com")) { //code goes here using(MailMessage mail = new MailMessage()){ //code goes here } }` – Shamseer K Feb 01 '17 at 11:07
94

Explicitly filling in the ContentDisposition fields did the trick.

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);                
}

BTW, in case of Gmail, you may have some exceptions about ssl secure or even port!

smtpClient.EnableSsl = true;
smtpClient.Port = 587;
shareef
  • 7,886
  • 12
  • 53
  • 80
Jon
  • 4,957
  • 5
  • 27
  • 38
  • 2
    Why would you not use a `FileInfo` object to get `CreationTime`, `LastWriteTime`, and `LastAccessTime` properties? You're creating one to get the `Length` property anyway. – sampathsris Dec 17 '15 at 12:31
  • 1
    Dont forget attachment.Dispose() or this file remains locked and you will can not write data on it. – Pau Dominguez Nov 12 '19 at 12:20
7

Here is a simple mail sending code with attachment

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

    mailServer.Credentials = new System.Net.NetworkCredential("myemail@gmail.com", "mypassword");  

    string from = "myemail@gmail.com";  
    string to = "reciever@gmail.com";  
    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);  
}

Read more Sending emails with attachment in C#

Pankaj Prakash
  • 1,875
  • 21
  • 27
4

Completing the solution of Ranadheer, using Server.MapPath to locate the file

System.Net.Mail.Attachment attachment;
attachment = New System.Net.Mail.Attachment(Server.MapPath("~/App_Data/hello.pdf"));
mail.Attachments.Add(attachment);
Nuno Ribeiro
  • 1,732
  • 2
  • 19
  • 26
  • Where does `Server.MapPath` come from and when should it be used? – Kimmax Jul 05 '16 at 15:03
  • The person writing that was probably an ASP.NET programmer, and I think it just helps to give a full qualified filename from a relative filename. The original question did not mention ASP.NET; you can just put a full reference to a filename there. – NealWalters Dec 17 '20 at 19:40
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);
}
Tunaki
  • 116,530
  • 39
  • 281
  • 370
Khang Pham
  • 11
  • 1
1

I've made a short code to do that and I want to share it with you.

Here the main code:

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);
  }

}

In your button do stuff like this
you can add your jpg or pdf files and more .. this is just an example

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

}
}
Lewis86
  • 481
  • 6
  • 15
elaz
  • 111
  • 1
  • 5
0

Try this:

private void btnAtt_Click(object sender, EventArgs e) {

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

    MyMsg.Attachments.Add(myFile);


}
AstroCB
  • 11,800
  • 20
  • 54
  • 68
0

I tried the code provided by Ranadheer Reddy (above) and it worked great. If you’re using a company computer that has a restricted server you may need to change the SMTP port to 25 and leave your username and password blank since they will auto fill by your admin.

Originally, I tried using EASendMail from the nugent package manager, only to realize that it’s a pay for version with 30-day trial. Don’t waist your time with it unless you plan on buying it. I noticed the program ran much faster using EASendMail, but for me, free trumped fast.

Just my 2 cents worth.

Aubrey Love
  • 552
  • 4
  • 9
0

Use this method it under your email service it can attach any email body and attachments to Microsoft outlook

using Outlook = Microsoft.Office.Interop.Outlook; // Reference Microsoft.Office.Interop.Outlook from local or nuget if you will user a build agent later

 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 = "con@def.com";//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."
                    };
                }