How can i send email one after one in a row? - c#

In Form1 in the backgroundworkerdowork event I did:
se.SendPhotos(photofilesDir + "\\" + "photofiles.zip");
se.SendPhotos(photofilesDir1 + "\\" + "photofiles.zip");
se.SendPhotos(photofilesDir2 + "\\" + "photofiles.zip");
se.SendPhotos(photofilesDir3 + "\\" + "photofiles.zip");
In the se class SendEmail I did:
public void SendPhotos(string fileNameToSend)
{
try
{
MailAddress from = new MailAddress("test#gmail.com", "User " + (char)0xD8 + " Name",
System.Text.Encoding.UTF8);
MailAddress to = new MailAddress("test#test");
photosmessage = new MailMessage(from, to);
photosmessage.Body = "Please check the log file attachment I have some bugs.";
string someArrows = new string(new char[] { '\u2190', '\u2191', '\u2192', '\u2193' });
photosmessage.Body += Environment.NewLine + someArrows;
photosmessage.BodyEncoding = System.Text.Encoding.UTF8;
photosmessage.Subject = "Log File For Checking Bugs" + someArrows;
photosmessage.SubjectEncoding = System.Text.Encoding.UTF8;
Attachment myAttachment = new Attachment(fileNameToSend, MediaTypeNames.Application.Octet);
photosmessage.Attachments.Add(myAttachment);
SmtpClient photossend = new SmtpClient("smtp.gmail.com", 587);
photossend.SendCompleted += new SendCompletedEventHandler(photossend_SendCompleted);
photossend.EnableSsl = true;
photossend.Timeout = 10000;
photossend.DeliveryMethod = SmtpDeliveryMethod.Network;
photossend.UseDefaultCredentials = false;
photossend.Credentials = new NetworkCredential("usern", "userpass");
string userState = "test message1";
photossend.SendAsync(photosmessage, userState);
SendLogFile.Enabled = false;
fname = fileNameToSend;
}
catch (Exception errors)
{
Logger.Write("Error sending message :" + errors);
}
}
private void photossend_SendCompleted(object sender, AsyncCompletedEventArgs e)
{
photosmessage.Dispose();
if (fname == #"C:\Users\Simbalip\AppData\Local\outputphotos\photosfiles3" + "\\" + "photofiles.zip")
{
photossendended = true;
}
}
The problem in the backgroundworkerdowork it never send the last one photofilesDir3.
I used a breakpoint and its getting to : photossendended = true;
But in my email im getting only 3 files sent for me and not 4.
When I used a breakpoint on the backgroundworker and did F11 I saw that its doing the 4 sendings one after one without waiting .
Each time the photofiles.zip have different files inside.
Now I check did a breakpoint on the line:
if (fname == #"C:\Users\Simbalip\AppData\Local\outputphotos\photosfiles3" + "\\" + "photofiles.zip")
And when it get there its all the time true it does ==
fname never C:\Users\Simbalip\AppData\Local\outputphotos\photosfiles2 or 1 or photosfiles
But in the end im getting 3 different photofiles.zip files each contain different files but one of the files never sent.
Myabe I need to make somehow that when it send email it will somehow untill the first one is sent then send the next one like in Process there is WaitForExit() so maybe something like that with the emails ?

The documentation for SmtpClient alludes to the fact that it doesn't support parallel operations.
If there is an e-mail transmission in progress and you call SendAsync or Send again, you will receive an InvalidOperationException.
http://msdn.microsoft.com/en-us/library/system.net.mail.smtpclient.aspx
I would recommend not sending the next email until the SendCompleted event has been raised. This means a drastic change in your code (where each call to SendPhotos really just adds something to a collection of pending send mail operations that your process in the background)

Related

Appended strings in message body not being sent in email using SMTPClient() and StringBuilder()

First and foremost I am very new to C# and am sure most of my code could be cleaned up so please don't suggest it unless you are also offering help with my issue.
I am sending an email via SmtpClient(). I am trying to build the body of the email using strings which are returned from functions in loops. My issue is that the string for the body isn't building how I thought it should.
Currently, I am creating a new StringBuilder() with some default text in it. I am then running some functions and trying to add the results to the StringBuilder() object via StringBuilder.AppendLine().
Here is (some of) my code:
// Setup SMTP Client for sending mail updates
//-----------------------------------
String from_addr_text = "<removed>";
String to_addr_text = "<removed>";
String msg_subject = "Updates to USPTO searches";
StringBuilder msg_body = new StringBuilder("The following searches have received updated results:" + Environment.NewLine);
SmtpClient AlertMail = new SmtpClient
{
Port = 587,
Host = "<removed>",
EnableSsl = true,
Timeout = 10000,
DeliveryMethod = SmtpDeliveryMethod.Network,
UseDefaultCredentials = false,
Credentials = new System.Net.NetworkCredential("<removed>", "<removed>")
};
MailMessage update = new MailMessage(from_addr_text, to_addr_text, msg_subject, msg_body.ToString())
{
BodyEncoding = UTF8Encoding.UTF8,
IsBodyHtml = false,
DeliveryNotificationOptions = DeliveryNotificationOptions.OnFailure
};
...
// Process data from api for Assignor
//-----------------------------------
bool isUpdated = false;
foreach (String url in searchesByAssignorUSPTO)
{
try
{
String longName = <removed>);
String name = <removed>;
String thisHash = await GetSearchData(url, name, "Assignor");
if (DoesHashExist(thisHash))
{
Debug.WriteLine(thisHash + " already exists. No update to " + name + " search.");
}
else
{
Debug.WriteLine(thisHash + " does not exist. There is an update to " + name + " search.");
isUpdated = true;
msg_body.AppendLine(name + " as " + "Assignor" + Environment.NewLine);
}
}
catch
{
Console.WriteLine("something is broken with ASSIGNOR search dummy!");
}
}
// Process data from api for Assignee
foreach (String url in searchesByAssigneeUSPTO)
{
try
{
String longName = <removed>;
String name = <removed>;
String thisHash = await GetSearchData(url, name, "Assignee");
if (DoesHashExist(thisHash))
{
Debug.WriteLine(thisHash + " already exists. No update to " + name + " search.");
}
else
{
Debug.WriteLine(thisHash + " does not exist. There is an update to " + name + " search.");
isUpdated = true;
msg_body.AppendLine(name + " as " + "Assignee" + Environment.NewLine);
}
}
catch
{
Console.WriteLine("something is broken with ASSIGNEE search dummy!");
}
}
// Send email is search results are updated
if (isUpdated)
{
AlertMail.Send(update);
Debug.WriteLine(msg_body.ToString());
}
When the program runs and there are results returned from the loops, msg_body is printed to the output window correctly but, when the email is received the body is only: "The following searches have received updated results:".
I have tried:
changing the value of isBodyHtml to true and used <br />
instead of Environment.NewLine.
adding \n to end of stringing and removing Environment.NewLine.
changing msg_body to type String and concatenating results to msg_body using =+.
using the Append() method instead of AppendLine().
Here is a snip of the output window:
Be sure to watch the assignment of variables in your code. When you assign msg_body to the update MailMessage object, it's only inputting the one line mentioned that is being returned in the email and doesn't include the information generated by the API.
Try moving the intialization of your SmtpClient and MailMessage variables to right before the if (isUpdated) block and you should be good to go.
per #tym32167, I needed to move the instantiation of MailMessage() to AFTER my loops and functions were completed. I was creating the object before the AppendLines() methods were called and therefore they weren't being included.

How to send picture to email body in WinForms?

I have a C# Winforms application I'm working on in Visual Studio 2010, the page in question is a bug reporting form - I have all the details set, email sends fine etc. My issue is attaching a screenshot to the email in the body, I have code set up to allow users to find and select a screenshot they take and attach to the form, but in the body itself it just gives me the text "System.Windows.Forms.Picturebox", or various similarities to that if I try .image.
I've had a look around via Google and here, but can only find topics that are to do with embedding the image or attaching it (and thus require to enter in a specific folder/image etc), whereas my users will be attaching their own image and name from different places. Is there anyway to get the image to be picked up without having to hardcode a location and name that my users will have to follow each time?
Code below:
private void btnBugEmail_Click(object sender, EventArgs e)
{
Cursor.Current = Cursors.WaitCursor;
try
{
SmtpClient client = new SmtpClient("details here");
MailMessage message = new MailMessage();
message.From = new MailAddress("email here");
string mailBox = txtBugAdd.Text.Trim();
message.To.Add(mailBox);
string mailFrom = txtEmailFromBug.Text.Trim();
message.CC.Add(mailFrom);
string mailCC = txtMailCCBug.Text.Trim();
message.Bcc.Add(mailCC);
message.IsBodyHtml = true;
message.Body = "Bug Report - please see below: " +
"\n" + "<br>" + "<b>" + "1. What were you doing at the time of the error?" + "</b>" +
"\n" + "<br>" + rtbTimeOfError.Text +
"\n" + "<br>" + "<b>" + "2. Are you able to repeat the steps and achieve the same error?" + "</b>" +
"\n" + "<br>" + rtbCanRepeat.Text +
"\n" + "<br>" + "<b>" + "3. Does this problem happen again if you change any of the details you have entered?" + "</b>" +
"\n" + "<br>" + rtbChangeDetails.Text;
message.Subject = "Bug Report";
var image = pboxBugImage.Image;
using(var ms = new MemoryStream())
{
image.Save(ms, ImageFormat.Jpeg);
message.Attachments.Add(new Attachment(ms, "Screenshot.jpg"));
client.Credentials = new System.Net.NetworkCredential("credentials here");
client.Port = System.Convert.ToInt32(25);
client.Send(message);
}
new Endpage().Show();
this.Close();
}
catch
{
MessageBox.Show("my comment here");
}
}
Take a look to the following link
system.net.mail.mailmessage.attachments
You cannot put a winforms control inside the mailmessage :) it is outputted with ToString()... that is what you see in mail
Example
private void btnBugEmail_Click(object sender, EventArgs e)
{
Cursor.Current = Cursors.WaitCursor;
try
{
SmtpClient client = new SmtpClient("details here");
MailMessage message = new MailMessage();
message.From = new MailAddress("email here");
string mailBox = txtBugAdd.Text.Trim();
message.To.Add(mailBox);
string mailFrom = txtEmailFromBug.Text.Trim();
message.CC.Add(mailFrom);
string mailCC = txtMailCCBug.Text.Trim();
message.Bcc.Add(mailCC);
message.IsBodyHtml = true;
message.Body = "Bug Report - please see below: " +
"\n" + "<br>" + "<b>" + "1. What were you doing at the time of the error?" + "</b>" +
"\n" + "<br>" + rtbTimeOfError.Text +
"\n" + "<br>" + "<b>" + "2. Are you able to repeat the steps and achieve the same error?" + "</b>" +
"\n" + "<br>" + rtbCanRepeat.Text +
"\n" + "<br>" + "<b>" + "3. Does this problem happen again if you change any of the details you have entered?" + "</b>" +
"\n" + "<br>" + rtbChangeDetails.Text;
message.Subject = "Bug Report";
var image = pboxBugImage.Image;
using(var ms = new MemoryStream())
{
image.Save(ms, ImageFormat.Jpeg);
message.Attachments.Add(new Attachment(ms, "Screenshot.jpg"));
client.Credentials = new System.Net.NetworkCredential("credentials here");
client.Port = System.Convert.ToInt32(25);
client.Send(message);
}
new Endpage().Show();
this.Close();
}
catch
{
MessageBox.Show("my comment here");
}
}
Take a look at your resources and dispose the memorystream. I didnt for the example, because i wrote it here in editor

how to use session variables in email

The Title does not make brilliant sense but essentially I want to use session variables and include them within an email body within the c# code. Sending the email without session variables works fine. Is it even possible to do what I want?
REVISED CODE:
public partial class Success : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
MembershipUser userName = Membership.GetUser(User.Identity.Name);
ListBox order = (ListBox)(Session["order"]);
string name = (String)(Session["name"]);
string addressLine1 = (String)(Session["addressLine1"]);
string addressLine2 = (String)(Session["addressLine2"]);
string addressLine3 = (String)(Session["addressLine3"]);
string county = (String)(Session["county"]);
string postCode = (String)(Session["postcode"]);
SmtpClient SmtpServer = new SmtpClient("smtp.live.com");
var mail = new MailMessage();
mail.From = new MailAddress("my email");
mail.To.Add("recipient email");
mail.Subject = "Your Reciept";
mail.IsBodyHtml = true;
string htmlBody;
htmlBody = "Hi "+ userName + Environment.NewLine + Environment.NewLine +
"Here's your details: " + Environment.NewLine + Environment.NewLine
+ order + Environment.NewLine + Environment.NewLine
+ name + Environment.NewLine
+ addressLine1 + Environment.NewLine
+ addressLine2 + Environment.NewLine
+ addressLine3 + Environment.NewLine
+ county + Environment.NewLine
+ postCode + Environment.NewLine + Environment.NewLine;
mail.Body = htmlBody;
SmtpServer.Port = 587;
SmtpServer.UseDefaultCredentials = false;
SmtpServer.Credentials = new System.Net.NetworkCredential("my email", "password");
SmtpServer.EnableSsl = true;
SmtpServer.Send(mail);
}
}
also to note, Environment.NewLine does not work.
Your help would be most appreciated
It's not clear from your question where you are trying to access Session, but it is available from any code running in the web worker process (see my answer here). However, I prefer to put email logic in a separate class or even separate project.
The class can then take the input values as strings, or a type that represents your data.
// good
public void SendMail( string name, string address, etc etc )
{
// mail code here
}
// better
public void SendMail( UserInfo info )
{
}
// best
public void SendMail( UserInfo info, string template )
{
// insert the user values into a template of some sort...no hardcoding format/HTML
}
Regarding Environment.NewLine. Your string name is htmlBody, which implies you are sending an HTML email. You should use the appropriate markup instead of a newline.
for those who helped me, sorry for wasting your time. I figured it out... really stupid but I was setting the session variables incorrectly in a previous webform before therefore the session variables were null.
the reason that there was no error was (my guess), I was setting the session variables on button_click function yet also having a postbackurl. the postbackurl must have overridden the button_click function.
So, For future reference. Originally I had
string name = Session["name"].ToString();
lblName.Text = name; //this didnt work
I corrected this by
Session["name"] = lblName.Text;

How to avoid sending duplicate mail in c#

I have written a code which sends mail to the admin for moderation whenever a user adds a content from front end.....the problem is sometimes the admin gets two mails of same content.
below is my code
MailMessage mail = new MailMessage();
string mailto = ConfigurationManager.AppSettings["adminStoryEmail"].ToString();
mail.To.Add(mailto);
//mail.To.Add("vidyasagar.patil#viraltech.in");
mail.From = new MailAddress(ConfigurationManager.AppSettings["fromEmail"]);
mail.Subject = ConfigurationManager.AppSettings["email_subject"];
if (uploadedpath != "")
{
mail.Body = "Email ID : " + txtEmail.Text + "<br /> Title : " + txtStoryTitle.Text + "<br />" + " Download : " + " http://www.achievewithdell.in/uploads/" + uploadedpath + "<br />";
if (story != "")
{
mail.Body += "New story has been added" + " http://www.achievewithdell.in/admin/ManageStory.aspx";
}
}
else
{
mail.Body = "Email ID : " + txtEmail.Text + "<br /> Title : " + txtStoryTitle.Text + " <br />";
if (story != "")
{
mail.Body += "New story has been added" + " http://www.achievewithdell.in/admin/ManageStory.aspx";
}
}
mail.IsBodyHtml = true;
SmtpClient smtp = new SmtpClient();
smtp.Host = ConfigurationManager.AppSettings["smtp_host"]; //Or Your SMTP Server Address
smtp.Port = 25;
smtp.Credentials = new System.Net.NetworkCredential(ConfigurationManager.AppSettings["smtp_userid"], ConfigurationManager.AppSettings["smtp_password"]); //Or your Smtp Email ID and Password
smtp.DeliveryMethod = SmtpDeliveryMethod.Network;
smtp.Send(mail);
You say sometimes the email gets sent twice. This would suggest the code you've given us is fine, the problem probably lies with what calls that code.
One way you could eliminate duplicates is to queue up your mails to be sent, perhaps in a database (storing: to, from, subject, body etc). Then periodically, iterate through mails to be sent, ignoring duplicates and marking sent mails so they don't get sent again.
Failing a refactor to your application like that, as the other poster suggested, get out your debugger and set a breakpoint. Depending on your version of Visual Studio, you could use the Breakpoint Hit Count so you only land at the breakpoint on the 2nd time.
Debug and make sure smtp Send() method is not called twice, put a break point on that line.

How to attach a file to an email in c#

Hi I believe I am pretty close to figuring out what is wrong with my code, but was hoping someone could help me out or point me in the right direction. I am able to run my program and on the page where the user is going to be uploading a file it gives me the option to choose a file. But when I press submit other information gets sent to me but the file never comes. I think this is because I am having trouble figuring out where to temporarily save the file when it send to my email. Here is my code at the moment:
Also what this code is for is a comment / request page on my website where the user can comment and also add a screen shot.
private string SendMessage(string strTo, string strFrom, string strSubject, string strMessage, string strAttachment, string strBCC)
{
try
{
MailMessage mailMsg;
string strEmail = "";
string strSmtpClient = ConfigurationManager.AppSettings["SmtpClient"];
string[] arrEmailAddress = strTo.Split(';');
for (int intCtr = 0; intCtr < arrEmailAddress.Length; intCtr++)
{
strEmail = "";
if (arrEmailAddress[intCtr].ToString().Trim() != "")
{
strEmail = arrEmailAddress[intCtr].ToString().Trim();
mailMsg = new MailMessage(strFrom, strEmail, strSubject, strMessage);
mailMsg.IsBodyHtml = true;
if (!strBCC.Trim().Equals(string.Empty))
mailMsg.Bcc.Add(strBCC);
SmtpClient smtpClient = new SmtpClient(strSmtpClient);
smtpClient.UseDefaultCredentials = true;
smtpClient.Port = 25;
smtpClient.Send(mailMsg);
mailMsg.Dispose();
}
}
return "Message sent to " + strTo + " at " + DateTime.Now.ToString() + ".";
}
catch (Exception objEx)
{
return objEx.Message.ToString();
}
string strUpLoadDateTime = System.DateTime.Now.ToString("yyyyMMddHHmmss");
string strFileName1 = string.Empty;
if ((File1.PostedFile != null) && (File1.PostedFile.ContentLength > 0))
{
string strUploadFileName1 = File1.PostedFile.FileName;
strFileName1 = strUpLoadDateTime + "." + Path.GetFileNameWithoutExtension(strUploadFileName1) + Path.GetExtension(strUploadFileName1);
strFileName1 = strFileName1.Replace("'", "");
string strSaveLocation = Server.MapPath("") + "\\" + strFileName1;
File1.PostedFile.SaveAs(strSaveLocation);
txtComments.Text = "The file has been uploaded";
}
My question is where am I going wrong where in this code do I put where I want the file to be saved.
The below part of the code is what I am using to format the email when it is sent. And pick what will be sent in the email.
protected void Submit_Click1(object sender, EventArgs e)
{
try
{
string dandt = System.DateTime.Now.ToString("yyyyMMddHHmmss");
string strMessage = "Bug Name: " + txtBugName.Text.Trim() + "<br/>" +
"Module Name: " + ddlModule.SelectedValue + "<br/>" +
"Page Name: " + ddlPage.SelectedValue + "<br/>" +
"Description: " + txtComments.Text.Trim() + "<br/>" +
File1.f + "<br/>" +
"Email is" + " " + txtemail.Text.Trim() + "<br/>" +
"The request was sent at" + dandt;
SendMessage(ConfigurationManager.AppSettings["EmailAddrTo"],
ConfigurationManager.AppSettings["EmailAddrFrom"],
txtBugName.Text.Trim(),
strMessage, "", "");
}
catch
{
}
}
For some reason now nothing is sending in my emails when I press submit. Also I was trying to figure out how to put in the email the time and date the email was sent. Even though obviously my email will have this information, incase the email is delayed for some reason I would like to have the time and date the user pressed the submit button. Where is says File.F in this part of the code this is where i was trying to figure out how to get the file attachment to go to the email, but I'm not sure what syntax should go there in the code.
It looks like you are trying to attach some file from the user's computer to the email you are sending. If that is the case, you need to upload your file first before you call SendMessage.
In your Submit_Click the first thing you need to do is the code the uploads the file somewhere. Also, remove that File1.f from strMessage which is where I suspect is causing your message to null out on you.
After you upload your file, pass strSavedLocation, which is the file location you saved the file, to your SendMessage() method.
In your SendMessage method you can attach the file with the following code where you are buliding your MailMessage. strAttachment is the path name to your uploaded file:
var attachment = new Attachment(strAttachment);
// Add time stamp information for the file.
ContentDisposition disposition = attachment.ContentDisposition;
disposition.CreationDate = System.IO.File.GetCreationTime(strAttachment);
disposition.ModificationDate = System.IO.File.GetLastWriteTime(strAttachment);
disposition.ReadDate = System.IO.File.GetLastAccessTime(strAttachment);
mailMsg.Attachments.Add(attachment);
It looks to me like you have the major parts here minus the handy, System.Net.Mail.Attachment.
If I were doing this, I'd move the file upload handling code into the Submit_Click handler, and then just add the Mail.Attachment code.
private string SendMessage(string strTo, string strFrom, string strSubject, string strMessage, string strAttachment, string strBCC)
{
try
{
System.Net.Mail.MailMessage mailMsg;
string strEmail = "";
string strSmtpClient = ConfigurationManager.AppSettings["SmtpClient"];
string[] arrEmailAddress = strTo.Split(';');
for (int intCtr = 0; intCtr < arrEmailAddress.Length; intCtr++)
{
strEmail = "";
if (arrEmailAddress[intCtr].ToString().Trim() != "")
{
strEmail = arrEmailAddress[intCtr].ToString().Trim();
mailMsg = new MailMessage(strFrom, strEmail, strSubject, strMessage);
mailMsg.IsBodyHtml = true;
if (!strBCC.Trim().Equals(string.Empty))
mailMsg.Bcc.Add(strBCC);
/*** Added mail attachment handling ***/
System.Net.Mail.Attachment attachment;
attachment = new System.Net.Mail.Attachment(strAttachment);
mailMsg.Attachments.Add(attachment);
SmtpClient smtpClient = new SmtpClient(strSmtpClient);
smtpClient.UseDefaultCredentials = true;
smtpClient.Port = 25;
smtpClient.Send(mailMsg);
mailMsg.Dispose();
}
}
return "Message sent to " + strTo + " at " + DateTime.Now.ToString() + ".";
}
catch (Exception objEx)
{
return objEx.Message.ToString();
}
}
protected void Submit_Click1(object sender, EventArgs e)
{
try
{
/*** Moved from SendMessage function ****/
string strUpLoadDateTime = System.DateTime.Now.ToString("yyyyMMddHHmmss");
string strFileName1 = string.Empty;
if ((File1.PostedFile != null) && (File1.PostedFile.ContentLength > 0))
{
string strUploadFileName1 = File1.PostedFile.FileName;
strFileName1 = strUpLoadDateTime + "." + Path.GetFileNameWithoutExtension(strUploadFileName1) + Path.GetExtension(strUploadFileName1);
strFileName1 = strFileName1.Replace("'", "");
string strSaveLocation = Server.MapPath("") + "\\" + strFileName1;
File1.PostedFile.SaveAs(strSaveLocation);
txtComments.Text = "The file has been uploaded";
}
string dandt = System.DateTime.Now.ToString("yyyyMMddHHmmss");
string strMessage = "Bug Name: " + txtBugName.Text.Trim() + "<br/>" +
"Module Name: " + ddlModule.SelectedValue + "<br/>" +
"Page Name: " + ddlPage.SelectedValue + "<br/>" +
"Description: " + txtComments.Text.Trim() + "<br/>" +
strSaveLocation + "<br/>" +
"Email is" + " " + txtemail.Text.Trim() + "<br/>" +
"The request was sent at" + dandt;
SendMessage(ConfigurationManager.AppSettings["EmailAddrTo"],
ConfigurationManager.AppSettings["EmailAddrFrom"],
txtBugName.Text.Trim(),
strMessage, strSaveLocation, "");
}
catch
{
}
}
As for the note about using StringBuilder, I agree, and I would use it like this:
System.Text.StringBuilder sb = new System.Text.StringBuilder();
sb.AppendFormat("Bug Name: {0}<br/>", txtBugName.Text.Trim());
sb.AppendFormat("Module Name: {0}<br/>", ddlModule.SelectedValue);
Edited To Add:
Also, see Brad's answer above about using ContentDisposition.

Categories

Resources