Sending email with attachments; attachment arrives without extension in Microsoft Outlook - c#

I created an C# application using SMTPClient that emails out attachments used for debugging (so usually just images or text files, but other types can be sent out too). The attachments arrive fine in Outlook (web version) and Gmail, but for Microsoft Outlook 2013, the attachments arrive without extension. This is a problem since the majority of the target users are going to be using Outlook 2013, and I can't ask them to manually add the file extension when downloading the attachment.
I have already explicitly filled the ContentDisposition fields of the attachment, but it didn't work.
private MailMessage BuildEmail(Message msg)
{
MailMessage email = null;
email = new MailMessage();
email.Subject = msg.Subject.Trim();
email.SubjectEncoding = UTF8Encoding.UTF8;
email.From = new MailAdress(msg.Sender);
email.Body = msg.Body;
email.IsBodyHtml = msg.HasRichText;
email.BodyEncoding = UTF8Encoding.UTF8;
foreach(String to in msg.Recipients)
email.To.Add(new MailAddress(to));
email.Priority = msg.Priority == CatPriority.Urgent ? MailPriority.High : MailPriority.Normal;
foreach (MessageAttachment ma in msg.Attachments)
email.Attachments.Add(BuildAttachment(ma));
return email;
}
private Attachment BuildAttachment(MessageAttachment ma)
{
Attachment att = null;
if (ma == null || ma.FileContent == null)
return att;
att = new Attachment(new MemoryStream(ma.FileContent), ma.FileName, ma.FileType.GetMimeType());
att.ContentDisposition.CreationDate = ma.CreationDate;
att.ContentDisposition.ModificationDate = ma.ModificationDate;
att.ContentDisposition.ReadDate = ma.ReadDate;
att.ContentDisposition.FileName = ma.FileName;
att.ContentDisposition.Size = ma.FileSize;
return att;
}
Message and MessageAttachment are classes with the necessary information for creating the email and attachments. This is the method I'm using to get the MIME type information:
public static string GetMimeType(this string fileExtension)
{
string mimeType = "application/unknown";
string ext = fileExtension.ToLower();
Microsoft.Win32.RegistryKey regKey = Microsoft.Win32.Registry.ClassesRoot.OpenSubKey(ext);
if (regKey != null && regKey.GetValue("Content Type") != null)
mimeType = regKey.GetValue("Content Type").ToString();
return mimeType;
}
And to send it:
smtp = new SmtpClient(host);
smtp.Port = 587;
smtp.DeliveryMethod = SmtpDeliveryMethod.Network;
smtp.UseDefaultCredentials = false;
smtp.Credentials = new NetworkCredential(sender, password);
smtp.EnableSsl = true;
smtp.Timeout = 30000;
smtp.Send(email);

Okay, after some debugging I realized the mistake was with the name being passed as an argument in Attachment(...). The second argument should recieve the name of the file with the extension (e.g. "file.txt"), and my variable, ma.FileName, only had the name by itself. So even if I specified the MIME type in the third argument, the method didn't know the type of file it's supposed to handle. Or at least Outlook didn't.
att = new Attachment(new MemoryStream(ma.FileContent), ma.FileName + ma.FileType, ma.FileType.GetMimeType());
Adding the extension solved the problem.

Related

How to send an attachment from the main project

This is a class from my code.
string to = message.Text;
string from = "noreply#zayzaycorporation.onmicrosoft.com";
MailMessage messagex = new MailMessage(from, to);
string mailbody = "Welcome!";
messagex.Subject = "Hello";
messagex.Body = mailbody;
messagex.Attachments.Add(new System.Net.Mail.Attachment("C:\\doc\\start.pdf"));
messagex.BodyEncoding = Encoding.UTF8;
messagex.IsBodyHtml = true;
SmtpClient client = new SmtpClient("smtp.office365.com", 587);
System.Net.NetworkCredential basicCredential1 = new
System.Net.NetworkCredential("noreply#zayzaycorporation.onmicrosoft.com", "XXX");
client.EnableSsl = true;
client.UseDefaultCredentials = false;
client.Credentials = basicCredential1;
client.Send(messagex);
context.Done(string.Empty);
The class sends the email with an attachment, works good. But my problem is when it's published as a Web Service in azure because there doesn't find any folder named "doc" on "C:\\". How can it be referenced the attachment to a folder from the main solution?
Thanks.
The Attachment class can be constructed using a Stream, which can thus contain anything and come from anywhere.
So basically generate the attachment in memory and wrap it in a MemoryStream or similar.
Try this..
String path = Application.StartupPath + "\doc\test.xml";

C# Sending Email with attached file (image)

My method sends an email using a SMTP Relay Server.
Everything works fine (the email gets sent), except for that the attached file (the image) is somehow compressed/notexistent and not able to retrieve from the email.
The method looks like this:
public static bool SendEmail(HttpPostedFileBase uploadedImage)
{
try
{
var message = new MailMessage() //To/From address
{
Subject = "This is subject."
Body = "This is text."
};
if (uploadedImage != null && uploadedImage.ContentLength > 0)
{
System.Net.Mail.Attachment attachment;
attachment = new System.Net.Mail.Attachment(uploadedImage.InputStream, uploadedImage.FileName);
message.Attachments.Add(attachment);
}
message.IsBodyHtml = true;
var smtpClient = new SmtpClient();
//SMTP Credentials
smtpClient.Send(message);
return true;
}
catch (Exception ex)
{
//Logg exception
return false;
}
}
The uploadedImage is not null.
ContentLength is 1038946 bytes (correct size).
However, the email that is being sent contains the image as an attachment with correct filename, although it's size is 0 bytes.
What am I missing?
The second parameter of constructor of System.Net.Mail.Attachment is not the file name. It's the content type.
And perhaps ensure your stream position is 0 before to create attachment
#ChrisRun,
You should change the parameter HttpPostedFileBase as byte[] for example. This way you could re-use your class in more places.
Try changing FileName for ContentType and add the MediaTypeNames.Image.Jpeg.
Also, add the using directive for dispose the MailMessage and SmtpClient
using (var message = new MailMessage
{
From = new MailAddress("from#gmail.com"),
Subject = "This is subject.",
Body = "This is text.",
IsBodyHtml = true,
To = { "to#someDomain.com" }
})
{
if (imageFile != null && imageFile.ContentLength > 0)
{
message.Attachments.Add(new Attachment(imageFile.InputStream, imageFile.ContentType, MediaTypeNames.Image.Jpeg));
}
using (var client = new SmtpClient("smtp.gmail.com")
{
Credentials = new System.Net.NetworkCredential("user", "password"),
EnableSsl = true
})
{
client.Send(message);
}
}
Cheers

Asp.Net Email Attachment Displaying Inline on Mobile (iPhone)

I have an .Net 4.5 application that sends an email, with an attachment. It works as expected when the email is opened on a desktop, but when opened on a mobile (iPhone in this case) the attachment shows as inline HTML not as an attachment.
When however I forward the same email from my desktop to the phone, the attachment shows up correctly on my phone so I am almost certain that it has to do with how I am specifying mime or content-type, disposition etc. but I can't see what I am doing wrong.
Here is the code - note that
att.ContentType = new System.Net.Mime.ContentType("multipart/mixed");
does create an attachment on iPhone but it is of type = mime-attachment that will not open.
I'm stumped & client awaits - any help greatly appreciated !
private void SendNotice(string body, string attachment, string email, bool pdf = false)
{
MailMessage message = new MailMessage();
message.From = new MailAddress(ConfigurationManager.AppSettings["SMTP.SendFrom"]);
message.Subject = ConfigurationManager.AppSettings["MatchedNoticeSubject"];
message.To.Add(new MailAddress(email));
message.ReplyToList.Add(new MailAddress(ConfigurationManager.AppSettings["SMTP.ReplyTo"]));
message.Body = body;
message.IsBodyHtml = true;
Attachment att = Attachment.CreateAttachmentFromString(attachment, "SeniorInfo.html", System.Text.Encoding.ASCII, "text/html");
//specifying this creates an attachment of type "mime-attachment" that does not open
//att.ContentType = new System.Net.Mime.ContentType("multipart/mixed");
message.Attachments.Add(att);
SmtpClient server = new SmtpClient()
{
EnableSsl = (ConfigurationManager.AppSettings["SMTP.EnableSSL"].ToLower() == "true"),
Host = ConfigurationManager.AppSettings["SMTP.Server"],
Port = Convert.ToInt16(ConfigurationManager.AppSettings["SMTP.Port"]),
Credentials = new System.Net.NetworkCredential(ConfigurationManager.AppSettings["SMTP.Account"], ConfigurationManager.AppSettings["SMTP.Password"])
};
server.Send(message);
}
Solved after some trial and error fiddling.
Counter-intuitively the attachment ContentDisposition object is READONLY which lead me to believe that I couldn't meddle in it however the read object is apparently a reference to the actual Attachment.ContentDisposition since setting values on the read instance does (apparently) correct the problem. Also used the Enum for MediaTypeNames (System.Net.Mime.MediaTypeNames.Text.Html) tho I don't think that was the issue.
Email send now looks like this :
private void SendMatchNotice(string body, string attachment, string email, bool pdf = false)
{
MailMessage message = new MailMessage();
message.From = new MailAddress(ConfigurationManager.AppSettings["SMTP.SendFrom"]);
message.Subject = ConfigurationManager.AppSettings["MatchedNoticeSubject"];
message.To.Add(new MailAddress(email));
message.ReplyToList.Add(new MailAddress(ConfigurationManager.AppSettings["SMTP.ReplyTo"]));
message.Body = body;
message.IsBodyHtml = true;
// Create the file attachment for this e-mail message.
Attachment att = Attachment.CreateAttachmentFromString(attachment, "SeniorInfo.html", System.Text.Encoding.ASCII, System.Net.Mime.MediaTypeNames.Text.Html);
System.Net.Mime.ContentDisposition disposition = att.ContentDisposition;
disposition.DispositionType = "attachment";
disposition.Inline = false;
disposition.FileName = "SeniorInfo.html";
disposition.CreationDate = DateTime.Now;
disposition.ModificationDate = DateTime.Now;
disposition.ReadDate = DateTime.Now;
message.Attachments.Add(att);
SmtpClient server = new SmtpClient()
{
EnableSsl = (ConfigurationManager.AppSettings["SMTP.EnableSSL"].ToLower() == "true"),
Host = ConfigurationManager.AppSettings["SMTP.Server"],
Port = Convert.ToInt16(ConfigurationManager.AppSettings["SMTP.Port"]),
Credentials = new System.Net.NetworkCredential(ConfigurationManager.AppSettings["SMTP.Account"], ConfigurationManager.AppSettings["SMTP.Password"])
};
server.Send(message);
}

Implementing method error message

I'm working on a web service to send an email. When i run my application I get the following error:
The method or operation is not implemented.
My Code in my website looks like:
WebTestServiceApp.localhost.Service1 Send = new WebTestServiceApp.localhost.Service1();
Send.Sendemail(txtTo.Text, txtSubject.Text, txtbody.Text);
My code in my webService looks like:
[WebMethod]
public string Sendemail( String inValueTo, String inValueSub, String inValueBody)
{try
{
String valueTo = inValueTo;
String valueSub = inValueSub;
String valueBody = inValueBody;
// String valueAttachmentPostedfile = inValueAttachmentPostedfile; //FileUpload1.PostedFile.FileName
// String valueAttachmentFileContent = inValueAttachemtnFileContent; //FileUpload1.FileContent.fileName
System.Net.Mail.MailMessage message = new System.Net.Mail.MailMessage(); // Creating new message.
message.To.Add(valueTo);
message.Subject = valueSub;
message.From = new System.Net.Mail.MailAddress("shaunmossop#mweb.co.za");
message.Body = valueBody;
message.IsBodyHtml = true;
// string fileName = Path.GetFileName(valueAttachmentPostedfile); // Get attachment file
// Attachment myAttachment =
// new Attachment(valueAttachmentFileContent, fileName);
// if (fileName != "")
// {
// message.Attachments.Add(myAttachment); // Send attachment
// }
System.Net.Mail.SmtpClient smtp = new System.Net.Mail.SmtpClient("smtp.gmail.com"); //Properties.Settings.Default.MailSMTPServer
smtp.Port = 587;
smtp.EnableSsl = true;
smtp.UseDefaultCredentials = false;
NetworkCredential netC = new NetworkCredential(Properties.Settings.Default.username, Properties.Settings.Default.password); // Useing Projects defult settings.
smtp.Credentials = netC;
smtp.Send(message);
return "Message has been sent";
}
catch (Exception)
{
return "Message faild to send" ;
}}
The rest of the code in the webService works, i know this because i used it in a working website, my problem is just passing the values though or a step i'm missing in the webService.
Can anyone see a obvious problem and what am i doing wrong, iv used webservices in VB but not C# so is there a difference?
It could be possible that the Web Reference has not been updated for your current application and hence it might be linking to the case wherein the method was not implemented.
So the only way to get it checked and working would be to Try update the Web Reference.

Sending email with attachments from C#, attachments arrive as Part 1.2 in Thunderbird

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.
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);
}
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;
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#
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);
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);
}
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);
}
}
Try this:
private void btnAtt_Click(object sender, EventArgs e) {
openFileDialog1.ShowDialog();
Attachment myFile = new Attachment(openFileDialog1.FileName);
MyMsg.Attachments.Add(myFile);
}
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.
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."
};
}

Categories

Resources