How to avoid sending duplicate mail in c# - 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.

Related

Mailbox unavailable. The server response was: 5.7.1 Unable to relay

Same ASP.NET MVC 4 website, same mail send code. Sending e-mail messages from AccountController is not working anymore, from all the other controllers it is.
Here is the error I get from AccountController actions:
Cannot send e-mail from noreply#domain.com to bill#microsoft.com
Exception: Mailbox unavailable. The server response was: 5.7.1 Unable to relay.
mail.domain.com, SMTPSVC/mail.domain.com, 25,
What should I check? It worked from years but with a recent Windows Server 2008 / Exchange 2010 update is not working anymore.
MailMessage message = new MailMessage(fromAddress, toAddress)
{
Subject = subject,
Body = body,
IsBodyHtml = isHtml
};
try
{
smtpClient.Send(message);
string errorMsg = "Sending e-mail from " + fromAddress.Address + " to " + originalAddresses[i];
errorMsg += Environment.NewLine;
errorMsg += smtpClient.Host + ", " + smtpClient.TargetName + ", " + smtpClient.Port + ", " + smtpClient.ClientCertificates + ", " + smtpClient.EnableSsl + ", " + smtpClient.UseDefaultCredentials + ", " + smtpClient.Timeout;
sw.WriteLine(errorMsg)
}
catch (Exception ex)
{
string errorMsg = "Cannot send e-mail from " + fromAddress.Address + " to " + originalAddresses[i] + ", " + "Exception: " + ex.Message +
(ex.InnerException != null ? ", " + ex.InnerException.Message : string.Empty);
errorMsg += Environment.NewLine;
errorMsg += smtpClient.Host + ", " + smtpClient.TargetName + ", " + smtpClient.Port + ", " + smtpClient.ClientCertificates + ", " + smtpClient.EnableSsl + ", " + smtpClient.UseDefaultCredentials + ", " + smtpClient.Timeout;
sw.WriteLine(errorMsg);
return false;
}
Any idea of what should I check? Has AccountController something special I should care about? Is the [RequireHttps] controller action attribute somewhat involved?
Thanks.
EDIT1:
Here are our Exchange 2010 settings (please note that we can send the same e-mail message from other ASP.NET MVC controllers):
https://practical365.com/exchange-server/how-to-configure-a-relay-connector-for-exchange-server-2010/
EDIT2:
I was wrong, the problem is not ASP.NET MVC controller related but e-mail address domain related. I discovered that the all the times we include an e-mail address that doesn't belong to our company domain (the outer internet) we get the error above. So now the question is: why the Exchange 2010 Receive Connector is now unable to send e-mail notification to the outer internet?
The server farm changed the outgoing IP address of our server and this was blocking all e-mail messages that contain a recipient not in our company domain. Adding the new outgoing IP address to the Exchange 2010 Receive Connector under Properties->Network->Receive mail from remote servers that have these IP addresses solved the problem.

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 can i send email one after one in a row?

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)

Unstable Sending of email in asp.net

I am building a ecommerce site and after a purchase is done, I want to send the buyer an email first before I commit my database changes but somehow, the send failure rate is about 25 - 30 percent. I am using hotmail current as a temp email account, not sure if it's hotmail's issue, anyway this is my code, any advice? Thanks:
Code:
MembershipUser u = Membership.GetUser(HttpContext.Current.User.Identity.Name);
AccountProfile usercustomProfile = new AccountProfile();
var p = usercustomProfile.GetProfile(u.UserName);
MailMessage mail = new MailMessage();
mail.To.Add(u.Email);
mail.IsBodyHtml = true;
mail.From = new MailAddress("XXX#hotmail.com");
mail.Subject = ("Purchase invoice" + ' ' + newOrder.OrderID);
string mailBodyHeader =
"<table border=0> <tr> <td>Product ID</td><td>Model Number</td><td>Model Name</td><td> Unit Cost</td> <td>Quantity</td><td>Price</td></tr>";
System.Text.StringBuilder bodyContent = new System.Text.StringBuilder();
double unitQtyPrice = 0;
double totalPrice = 0;
foreach (var cItem in cartList)
{
unitQtyPrice = cItem.Quantity * (double)cItem.UnitCost;
totalPrice += unitQtyPrice;
bodyContent.Append("<tr>");
bodyContent.Append("<td>");
bodyContent.Append(cItem.ProductID.ToString());
bodyContent.Append("</td>");
bodyContent.Append("<td>");
bodyContent.Append(cItem.ModelNumber.ToString());
bodyContent.Append("</td>");
bodyContent.Append("<td>");
bodyContent.Append(cItem.ModelName);
bodyContent.Append("</td>");
bodyContent.Append("<td>");
bodyContent.Append(Math.Round(cItem.UnitCost, 2));
bodyContent.Append("</td>");
bodyContent.Append("<td>");
bodyContent.Append(cItem.Quantity.ToString());
bodyContent.Append("</td>");
bodyContent.Append("<td>");
bodyContent.Append("$" + Math.Round(unitQtyPrice, 2));
bodyContent.Append("</td>");
bodyContent.Append("</tr>");
}
Math.Round(totalPrice, 2);
mail.Body = "Thanks you for shopping with XXX. Your purchase details are as follow:"
+ "<br><br>" + "Name:" + p.FirstName + p.LastName
+ "<br>" + "Mailing Address:" + p.MailingAddress
+ "<br>" + "Billing Address:" + p.BillingAddress
+ "<br>" + "Contact No.:" + p.Contact
+ "<br><br>" + mailBodyHeader + bodyContent.ToString() + "</table>"
+ "<br>" + "Total Price:" + "$" + totalPrice
+ "<br>" + "Additional / Special instructions:"
+ "<br>" + SInfo
+ "<br><br>" + "Please blah blah blah";
SmtpClient client = new SmtpClient("smtp.live.com", 587);
client.EnableSsl = true; //ssl must be enabled for Gmail
NetworkCredential credentials = new NetworkCredential("XXX#hotmail.com", "ABCDE");
client.Credentials = credentials;
//Sends a message to from if email is not deliverable
mail.DeliveryNotificationOptions = DeliveryNotificationOptions.OnSuccess;
mail.DeliveryNotificationOptions = DeliveryNotificationOptions.OnFailure;
//Create the SMTPClient object and DO NOT specify the SMTP server name, it’s being pulled from config file
SmtpClient SMTPServer = new SmtpClient();
SMTPServer.DeliveryMethod = SmtpDeliveryMethod.PickupDirectoryFromIis;
try
{
client.Send(mail);
db.SaveChanges();
}
catch (SmtpException)
{
Server.Transfer("/CheckOutUnsuccessful.aspx", true);
}
}
return (true);
}
If you are using SQL Server on the backend you can set the database server up to handle the mail requests. The advantage of using SQL Server as opposed to ASP.NET code is the database can be configured to retry sending the messages several times on failure.
Here is a good resource on how to configure Database Mail: http://blog.sqlauthority.com/2008/08/23/sql-server-2008-configure-database-mail-send-email-from-sql-database/

Email Body Format Problem

i had a problem in format in email. I want to have a new line..
here's the format in email..
Name: sdds Phone: 343434 Fax: 3434 Email: valencia_arman#yahoo.com Address: dsds Remarks: dsds Giftwrap: Yes Giftwrap Instructions: sdds Details: PEOPLE OF THE BIBLE(SCPOTB-8101-05) 1 x Php 275.00 = Php 275.00 Total: Php275.00
here's my C# code..
mail.Body = "Name: " + newInfo.ContactPerson + Environment.NewLine
+ "Phone: " + newInfo.Phone + Environment.NewLine
+ "Fax: " + newInfo.Fax + Environment.NewLine
+ "Email: " + newInfo.Email + Environment.NewLine
+ "Address: " + newInfo.Address + Environment.NewLine
+ "Remarks: " + newInfo.Notes + Environment.NewLine
+ "Giftwrap: " + rbGiftWrap.SelectedValue + Environment.NewLine
+ "Giftwrap Instructions: " + newInfo.Instructions + Environment.NewLine + Environment.NewLine
+ "Details: " + Environment.NewLine
+ mailDetails;
If you're sending it in HTML, make sure you set the format.
mail.BodyFormat = MailFormat.Html;
And then you can use <br/> should you want to.
UPDATE:
Try this as an alternative:
using System.Net.Mail;
...
MailMessage myMail;
myMail = new MailMessage();
myMail.IsBodyHtml = true;
maybe you can try this...
We create seperate email templates (e.g. EmailTemplate.htm), it includes the message to be sent. You will have no problems for new line in message.
Then this is our Code behind:
private void SendEmail()
{
string emailPath = "../EmailTemplate.htm"; //Define your template path here
string emailBody = string.Empty;
StreamReader sr = new StreamReader(emailPath);
emailBody = sr.ReadToEnd();
sr.Close();
sr.Dispose();
//Send Email; you can refactor this out
MailMessage message = new MailMessage();
MailAddress address = new MailAddress("sender#domain.com", "display name");
message.From = address;
message.To.Add("to#domain.com");
message.Subject = "Your Subject";
message.IsBodyHtml = true; //defines that your email is in Html form
message.Body = emailBody;
//smtp is defined in web.config
SmtpClient smtp = new SmtpClient();
try
{
smtp.Send(message);
}
catch (Exception ex)
{
//catch errors here...
}
}
Did you try "+\n" instead of Environment.NewLine?

Categories

Resources