C# Sending Email with attached file (image) - c#

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

Related

Break apart email attachment if zip is too big to email

So I can send up to 25MB in an email attachment. I am looking for away to check how big the file size is and if its too big break it apart and send in two emails. (Or if there is a better way to do it)?
Here is where I am sending the email with the attachment:
public static void SendEmail(List<string> recipients, MemoryStream output, string from, string subject, string htmlMessage, bool isHtml = true)
{
var host = ConfigurationManager.AppSettings["emailHost"];
var emailFrom = ConfigurationManager.AppSettings["FromEmail"];
try
{
MailMessage mail = new MailMessage();
mail.From = new MailAddress(from);
foreach (var r in recipients)
{
mail.To.Add(r);
}
mail.Subject = subject;
mail.IsBodyHtml = isHtml;
mail.Body = htmlMessage;
//string result = System.Text.Encoding.UTF8.GetString(output.ToArray());
SmtpClient SmtpServer = new SmtpClient(host);
SmtpServer.Port = 25;
Attachment myZip = new Attachment(output, "ClientStatements.zip");
mail.Attachments.Add(myZip);
SmtpServer.Send(mail);
}
catch (Exception ex)
{
FMBUtilities.Logger.LogErrorToSql2012PrdAndEmailTeam("DBQueries", "SendEmail", ex);
}
}
Here is where i am creating the zip file to send:
if (emails.ToString() != "")
{
var allEmails = emails[0].Split(',');
foreach (var email in allEmails)
{
if (emailValid.IsMatch(email))
{
everyEmail.Add(email);
}
else
{
return Json(new { success = false, message = $"* Not valid email address: {email}.\n\n * Please double check and try again." });
}
}
MemoryStream output = new MemoryStream();
List<string> distinctFiles = allPaths
.GroupBy(x => x.Split(new char[] { '\\' }).Last())
.Select(x => x.First())
.ToList();
using (ZipFile zip = new ZipFile())
{
zip.AddFiles(distinctFiles, #"\");
zip.Save(output);
output.Position = 0;
DBQueries.SendEmail(everyEmail, output, fromAddress, "Client Statement Reports", "Here are your requested Client Statements", true);
}
I have found some things about setting the file size in the web.config file and things of that sort but just dont know the best way to go about this.

Email sending with attachment issue

I am trying to send an email message to different users (with an attachment). The email is being sent, but only one user receives the attachment (image file). Other recipients receive something like empty picture, or picture with name and zero bytes.
I don't really understand what is going wrong. Here is code that I used for sending emails:
public void SendWithFile(string recipientName, string body, string subject = null, HttpPostedFileBase emailFile = null)
{
using (var msg = new MailMessage())
{
msg.To.Add(recipientName);
msg.From = new MailAddress(ConfigurationManager.AppSettings["MailServerSenderAdress"]);
msg.Subject = subject;
msg.Body = body;
msg.SubjectEncoding = Encoding.UTF8;
msg.BodyEncoding = Encoding.UTF8;
msg.IsBodyHtml = true;
msg.Priority = MailPriority.Normal;
using (Attachment data = new Attachment(emailFile.InputStream, Path.GetFileName(emailFile.FileName), emailFile.ContentType))
{
msg.Attachments.Add(data);
using (var client = new SmtpClient())
{
//client configs
try
{
client.Send(msg);
}
catch (Exception ex)
{
throw ex;
}
}
}
}
}
and here is where I call the send email method:
foreach (var recipent in notesRecipients)
{
if (!string.IsNullOrEmpty(userEmail))
{
if (emailFile != null)
emailService.SendWithFile(userEmail, message, null, emailFile);
}
}
You have to seek the stream from the beginning like below before you send the attachment:
emailFile.InputStream.Position = 0;
For more info you can refer to this question here: link

Sending html page as message body of email in asp.net c#

I have written the below code to send an email wherein the message body is a html page.
I don't get any error when i run this code but do not get any mail. I tried putting body as simple message string then i received the email but not as message body as html page.
What is going wrong? please help.
protected void btnSend_Click(object sender, EventArgs e)
{
SendHTMLMail();
}
public void SendHTMLMail()
{
//var path = Server.MapPath("~/test/HTMLPage.htm");
StreamReader reader = new StreamReader(Server.MapPath("~/expo_crm/test/HTMLPage.htm"));
string readFile = reader.ReadToEnd();
string myString = "";
myString = readFile;
SmtpClient smtp = new SmtpClient
{
Host = "mail.abc.com", // smtp server address hereā€¦
Port = 25,
EnableSsl = false,
DeliveryMethod = SmtpDeliveryMethod.Network,
Credentials = new System.Net.NetworkCredential("abc#xyz.com", "xxxx"),
Timeout = 30000,
};
MailMessage message = new MailMessage("abc#xyz.com", "akshata#gmail.com", " html ", myString);
message.IsBodyHtml = true;
smtp.Send(message);
}
Most of the time mail server checks the html content and marks as SPAM mail based on the html tags like links, images etc in the mail. Make sure that you have low number of HTML tags probably no external links, images and try again to send mail.
Here is working code, if this helps
public void SendEmail(ListDictionary email)
{
try
{
var msg = new MailMessage {From = new MailAddress(_emailUsername, _emailFrom), BodyEncoding = Encoding.UTF8, Subject = Convert.ToString(email["SUBJECT"]), Priority = MailPriority.Normal};
//
var emailTo = (List<string>) email["TO"];
var emailCc = (List<string>) email["CC"];
var emailBcc = (List<string>) email["BCC"];
foreach (var to in emailTo.Where(to => to.Length > 1))
msg.To.Add(to);
foreach (var cc in emailCc.Where(cc => cc.Length > 1))
msg.CC.Add(cc);
foreach (var bcc in emailBcc.Where(bcc => bcc.Length > 1))
msg.Bcc.Add(bcc);
//
msg.AlternateViews.Add(AlternateView.CreateAlternateViewFromString(Convert.ToString(email["BODY_TEXT"]), Encoding.UTF8, "text/plain"));
msg.AlternateViews.Add(AlternateView.CreateAlternateViewFromString(Convert.ToString(email["BODY_HTML"]), Encoding.UTF8, "text/html"));
//
new SmtpClient
{
Credentials = new NetworkCredential(_emailUsername, _emailPassword),
DeliveryMethod = SmtpDeliveryMethod.Network,
EnableSsl = true,
Host = "smtp.gmail.com"
}.Send(msg);
}
catch (Exception e)
{
L.Get().Fatal("Failed", e);
}
}
Could it be that you're setting the body before you set it to Html?
Worth trying using the full object constructor (new MailMessage(){ IsBodyHtml = true, Body = myString}) or setting the properties one at a time to make sure...

Why image is not displaying in html mail in gmail?

I'm trying to add an image in HTML mail. It is displaying when I save that body as html file, but when I send that html body as an email through GMail, the image is not displaying. Can anyone tell me the reason?
I set the source of the image in this way:
var image = body.GetElementsByTagName("img");
string imageAttachmentPath = Path.Combine(Globals.NotificationTemplatesPath, "Header.png");
foreach (XmlElement img in image)
{
img.SetAttribute("src", imageAttachmentPath);
break;
}
//thats the method in which i am sending email.
public static void SendMessageViaEmailService(string from,
string sendTo,
string carbonCopy,
string blindCarbonCopy,
string subject,
string body,
bool isBodyHtml,
string imageAttachmentPath,
Hashtable images,
List<string> attachment,
string title = null,
string embeddedImages = null)
{
Attachment image = new Attachment(imageAttachmentPath);
MailMessage msg = new MailMessage();
msg.IsBodyHtml = true; // email body will allow html elements
msg.From = new MailAddress(from, "Admin"); // setting the Sender Email ID
msg.To.Add(sendTo); // adding the Recipient Email ID
if (!string.IsNullOrEmpty(carbonCopy)) // add CC email ids if supplied.
msg.CC.Add(carbonCopy);
msg.Subject = subject; //setting email subject and body
msg.Body = body;
msg.Attachments.Add(image);
//create a Smtp Mail which will automatically get the smtp server details
//from web.config mailSettings section
SmtpClient SmtpMail = new SmtpClient();
SmtpMail.Host = "smtp.gmail.com";
SmtpMail.Port = 587;
SmtpMail.EnableSsl = true;
SmtpMail.UseDefaultCredentials = false;
SmtpMail.Credentials = new System.Net.NetworkCredential(from, "password");
// sending the message.
try
{
SmtpMail.Send(msg);
}
catch (Exception ex) { }
}
More than likely your image SRC attribute is not an absolute, publicly-accessible URI. Any file-system or local URI's will not show the image in the email.
Specifically, these will not work:
c://test.png
test.png
/folder/test.png
http://localhost/test.png
http://internaldomain/test.png
Ensure that your image urls are
absolute (i.e. start with the protocol like http://)
includes a full path to the image
the domain is a public domain
Try the code part from this thread:
// creating the attachment
System.Net.Mail.Attachment inline = new System.Net.Mail.Attachment(#"c:\\test.png");
inline.ContentDisposition.Inline = true;
// sending the message
MailMessage email = new MailMessage();
// set the information of the message (subject, body ecc...)
// send the message
System.Net.Mail.SmtpClient smtp = new System.Net.Mail.SmtpClient("localhost");
smtp.Send(email);
email.Dispose();

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

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.

Categories

Resources