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
Related
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.
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
Trying to send email to multiple recipient using below code gives me this error:
The specified string is not in the form required for an e-mail
address.
string[] email = {"emailone#gmail.com","emailtow#gmail.com"};
using (MailMessage mm = new MailMessage("teset123321#gmail.com", email.ToString()))
{
try
{
mm.Subject = "sub;
mm.Body = "msg";
mm.Body += GetGridviewData(GridView1);
mm.IsBodyHtml = true;
SmtpClient smtp = new SmtpClient();
smtp.Host = "smtpout.server.net";
smtp.EnableSsl = false;
NetworkCredential NetworkCred = new NetworkCredential("email", "pass");
smtp.UseDefaultCredentials = true;
smtp.Credentials = NetworkCred;
smtp.Port = 80;
smtp.Send(mm);
ClientScript.RegisterStartupScript(GetType(), "alert", "alert('Email sent.');", true);
}
catch (Exception ex)
{
Response.Write("Could not send the e-mail - error: " + ex.Message);
}
}
Change your using line to this:
using (MailMessage mm = new MailMessage())
Add the from address:
mm.From = new MailAddress("myaddress#gmail.com");
You can loop through your string array of e-mail addresses and add them one by one like this:
string[] email = { "emailone#gmail.com", "emailtwo#gmail.com", "emailthree#gmail.com" };
foreach (string address in email)
{
mm.To.Add(address);
}
Example:
string[] email = { "emailone#gmail.com", "emailtwo#gmail.com", "emailthree#gmail.com" };
using (MailMessage mm = new MailMessage())
{
try
{
mm.From = new MailAddress("myaddress#gmail.com");
foreach (string address in email)
{
mm.To.Add(address);
}
mm.Subject = "sub;
// Other Properties Here
}
catch (Exception ex)
{
Response.Write("Could not send the e-mail - error: " + ex.Message);
}
}
Presently your code:
new NetworkCredential("email", "pass");
treats "email" as an email address which eventually is not an email address rather a string array which contains the email address.
So you can try like this:
foreach (string add in email)
{
mm.To.Add(new MailAddress(add));
}
I was having this issue while working with SMTP.js but the issues were coming from the whitespace so please try and trim it off when working with emails. I hope this helps someone.
I am working on a page where I have to send an email in C#.
I followed the codes on
http://blogs.msdn.com/b/mariya/archive/2006/06/15/633007.aspx
and came upon this two exceptions
A first chance exception of type 'System.Net.Mail.SmtpException' occurred in System.dll. A first chance exception of type
'System.Threading.ThreadAbortException' occurred in mscorlib.dll
Here are the codes I implemented. I can't seem to figure what went wrong.
//Send email notification - removed actual email for this question
SmtpClient client = new SmtpClient("smtp.gmail.com", 587);
client.EnableSsl = true;
MailAddress from = new MailAddress("myemail#gmail.com", "My name is here");
MailAddress to = new MailAddress("anotherpersonsemail#gmail.com", "Subject here");
MailMessage message = new MailMessage(from, to);
message.Body = "Thank you";
message.Subject = "Successful submission";
NetworkCredential myCreds = new NetworkCredential("myemail#gmail.com",
"mypassword", "");
client.Credentials = myCreds;
try
{
client.Send(message);
Console.Write(ex.Message.ToString());
}
catch (Exception ex)
{
Console.Write(ex.Message.ToString());
}
For sharing purposes, I managed to resolve my problem by enabling access for less secure apps in Gmail.
It works like a charm now! https://www.google.com/settings/security/lesssecureapps
To authenticate SMTP in Outlook, the articles below are very useful too.
http://www.tradebooster.com/web-hosting-articles/how-to-enable-smtp-authentication-in-outlook-2010/
https://www.authsmtp.com/outlook-2010/default-port.html
//bulk Emails using mailkit you have to import it by nuget manager
//set in gmail https://myaccount.google.com/lesssecureapps?pli=1 to be on
// Read Text File
public void ReadFileAndSend()
{
using (StreamReader reader = new StreamReader(#"d:\Email.txt"))
{
while (!(reader.ReadLine() == null))
{
String line = reader.ReadLine();
if (line != "")
{
try
{
Send("", line.Trim());
Thread.Sleep(500);
}
catch
{
}
}
}
Console.ReadLine();
}
}
public void Send(String FromAddress,String ToAddress)
{
try
{
string FromAdressTitle = "";
string ToAdressTitle = "";
string Subject = "";
string BodyContent = "";
string SmtpServer = "smtp.gmail.com";
int SmtpPortNumber = 587;
var mimeMessage = new MimeMessage();
mimeMessage.From.Add(new MailboxAddress(FromAdressTitle, FromAddress));
mimeMessage.To.Add(new MailboxAddress(ToAdressTitle, ToAddress));
mimeMessage.Subject = Subject;
mimeMessage.Body = new TextPart("html")
{
Text = BodyContent
};
using (var client = new MailKit.Net.Smtp.SmtpClient())
{
client.Connect(SmtpServer, SmtpPortNumber, false);
client.Authenticate("your email", "pass");
client.Send(mimeMessage);
Console.WriteLine("The mail has been sent successfully !!");
client.Disconnect(true);
}
}
catch (Exception ex)
{
throw ex;
}
}
Answer Update 2023
After Google introduced a Two-step verification system in Google Accounts, it's not easy to use Gmail for your own personal usage so to solve this problem, I figured out a way to use Gmail as an email medium to send emails using C#.
The C# code for email service is included here: https://www.techaeblogs.live/2022/06/how-to-send-email-using-gmail.html
Following just the 2-step tutorial from the above link, you can fix your issue in no time.
I've written a mail sending code for asp.net. it is working fine. I can attach files that are saved on disk. Now I want to attach a file that is on the internet. I can download the file and save it somewhere on disk and attach the file. but I don't want to save the file on disk. I just need to download the file in memory and attach it to my mail. need help to do that.
here is my code for sending email
public void SendMail(string To, string Subject, string Body)
{
MailMessage mail = new MailMessage();
mail.From = new MailAddress("noreply#xyz.com", "xyz");
mail.To.Add(new MailAddress(To));
mail.Subject = Subject;
mail.Body = Body;
mail.IsBodyHtml = true;
using (SmtpClient smtpClient = new SmtpClient())
{
try
{
smtpClient.Send(mail);
}
catch (Exception ex)
{
throw ex;
}
}
}
I want some thing like this
public void SendMail(string To, string Subject, string Body, URI onlineFileURI)
{
MailMessage mail = new MailMessage();
mail.From = new MailAddress("noreply#xyz.com", "xyz");
mail.To.Add(new MailAddress(To));
mail.Subject = Subject;
mail.Body = Body;
mail.IsBodyHtml = true;
//Create the attachment from URL
var attach = [Attachemnt from URL]
mail.Attachments.Add(attach)
using (SmtpClient smtpClient = new SmtpClient())
{
try
{
smtpClient.Send(mail);
}
catch (Exception ex)
{
throw ex;
}
}
}
How I can download the file in memory and attach it?
This is how I ended up doing it based of previous posts:
var url = "myurl.com/filename.jpg"
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
using (HttpWebResponse HttpWResp = (HttpWebResponse)req.GetResponse())
using (Stream responseStream = HttpWResp.GetResponseStream())
using (MemoryStream ms = new MemoryStream())
{
responseStream.CopyTo(ms);
ms.Seek(0, SeekOrigin.Begin);
Attachment attachment = new Attachment(ms, filename, MediaTypeNames.Image.Jpeg);
message.Attachments.Add(attachment);
_smtpClient.Send(message);
}
You can do it by converting page into Stream/byte array and send it
Here is the code
string strReportUser = "RSUserName";
string strReportUserPW = "MySecretPassword";
string strReportUserDomain = "DomainName";
string sTargetURL = "http://SqlServer/ReportServer?" +
"/MyReportFolder/Report1&rs:Command=Render&rs:format=PDF&ReportParam=" +
ParamValue;
HttpWebRequest req =
(HttpWebRequest)WebRequest.Create( sTargetURL );
req.PreAuthenticate = true;
req.Credentials = new System.Net.NetworkCredential(
strReportUser,
strReportUserPW,
strReportUserDomain );
HttpWebResponse HttpWResp = (HttpWebResponse)req.GetResponse();
Stream fStream = HttpWResp.GetResponseStream();
HttpWResp.Close();
//Now turn around and send this as the response..
ReadFullyAndSend( fStream );
ReadFullyAnd send method. NB: the SendAsync call so your not waiting for the server to send the email completely before you are brining the user back out of the land of nod.
public static void ReadFullyAndSend( Stream input )
{
using ( MemoryStream ms = new MemoryStream() )
{
input.CopyTo( ms );
MailMessage message = new MailMessage("from#foo.com", "too#foo.com");
Attachment attachment = new Attachment(ms, "my attachment",, "application/vnd.ms-excel");
message.Attachments.Add(attachment);
message.Body = "This is an async test.";
SmtpClient smtp = new SmtpClient("localhost");
smtp.Credentials = new NetworkCredential("foo", "bar");
smtp.SendAsync(message, null);
}
}
courtesy:Get file to send as attachment from byte array