I have an application that sends emails via SMTP, however it is slower than sin. Two recipients can take over 20 seconds. I believe the problem is the program logic.
The program opens a csv with email addresses and display names then using a for loop sends each recipient the message.
The problem is, I fear it is re-establishing SMTP connection every time it sends to the next person in the list.
My question is, how do I setup an SMTP connection and reuse that connection for every user? (unless that's not why its slow, and someone can tell me why its running so slow)
void DoWork(object sender, DoWorkEventArgs e)
{
// Get User List
List<string[]> mycsv = csvRead();
int total = mycsv.Count;
// Send Message to each user
for (int x = 0; x < total; x++)
{
//Actual send message
sendMail(mycsv[x][0], mycsv[x][1]);
}
}
private void sendMail(string toEmail, string toName)
{
string email = Properties.SMTP.Default.Email;
string name = Properties.SMTP.Default.DisplayName;
MailMessage mail = new MailMessage();
mail.From = new MailAddress(email, name);
//Recipient Address
mail.To.Add(new MailAddress(toEmail, toName));
//Formatted mail
mail.IsBodyHtml = true;
// htmlMessage and Subject are global
mail.Body = htmlMessage;
mail.Subject = htmlSubject;
SmtpClient smtp = smtpDetails();
smtp.Send(mail);
}
private SmtpClient smtpDetails()
{
int port = Convert.ToInt32(Properties.SMTP.Default.ServerPort);
string email = Properties.SMTP.Default.Email;
string username = Properties.SMTP.Default.Username;
string password = Properties.SMTP.Default.Password;
string host = Properties.SMTP.Default.ServerAdd;
SmtpClient smtp = new SmtpClient();
smtp.Port = port;
smtp.EnableSsl = true;
smtp.DeliveryMethod = SmtpDeliveryMethod.Network;
smtp.UseDefaultCredentials = false;
smtp.Credentials = new System.Net.NetworkCredential(username, password);
smtp.Host = host;
return smtp;
}
VS: 2013 - 4.5 .net - WPF app
One way to improve the speed could be to make a static class for the mail delivery. Eg. a mail handler class with the static method SendMail (where you put your smtpDetails() into.
So there won't be a need to create new instances of the SmtpClient for every call in the loop - just reuse the static method.
You could also use a using:
using(SmtpClient smtp = new SmtpClient())
{
Port = port
//etc
}
This will dispose of all your smtp connections.
Related
Sending an email seems to be a common problem :-) But the other Q&As do not fit my situation, or I am stupid :D
My class:
public class Sender
{
private Setting _setting;
public Sender(Setting setting)
{
_setting = setting;
}
public void Send(string receiverAddress, string message) => Send(new MailAddress(receiverAddress), message);
public void Send(MailAddress receiverAddress, string message)
{
using(MailMessage mail = new MailMessage())
{
MailAddress senderAddress = new MailAddress(_setting.SenderAddress);
mail.From = senderAddress;
mail.To.Add(receiverAddress);
mail.Subject = "Integration Test";
mail.SubjectEncoding = System.Text.Encoding.UTF8;
mail.Body = "Hello, World!";
mail.BodyEncoding = System.Text.Encoding.UTF8;
using(SmtpClient smtpClient = new SmtpClient(_setting.SmtpServer, _setting.SmtpPort)){
smtpClient.EnableSsl = true;
smtpClient.DeliveryMethod = SmtpDeliveryMethod.Network;
// smtpClient.UseDefaultCredentials= false;
smtpClient.Credentials = new NetworkCredential(_setting.SenderAddress, _setting.Password);
smtpClient.Timeout = 20000;
smtpClient.Send(mail);
}
}
}
}
My Test
[Test]
public void SendEmailGmail()
{
Setting setting = new Setting();
setting.SmtpServer = "smtp.google.com";
setting.SmtpPort = 587; // also tried 465
setting.SenderAddress = "my#googlemail.com";
setting.Username = "Display Name";
setting.Password = "GoogleGeneratedAppPassword";
Sender sender = new Sender(setting);
sender.Send("i#dont.tell", "Hello, World!");
}
When I execute the test, the test doesn't finish. It even exceeds the timeout of 20 seconds.
I have no idea what I have done wrong; please help me
I am thankfully for your time :-)
Dear peni4142
A way I made those king of code work with Gmail was to install postfix smtp server localy and replay your test
Do not use Gmail SMTP directly
In postfix, set in /etc/postfix/main.cf :
relayhost = [smtp.google.fr]
And restart postfix :
systemctl restart postfix
In your google account, allow the public IP of your postfix server to login without credential on smtp.google.com for your gmail managed domain (your sender domain)
Next, change your code to use the local IP of your Postfix server in replacement of smtp.google.fr
setting.SmtpServer = "local.ip.address.of.your.postfix.server";
setting.SmtpPort = 25;
Postfix will have no troubles to deal with SMTP transactions, TLS, and whatever security google ask when connecting to smtp.google.fr
The code I currently have is:
public void SendEmail(string to, string cc, string bcc, string subject, string body, string attachmentPath = "", System.Net.Mail.MailPriority emailPriority = MailPriority.Normal, BodyType bodyType = BodyType.HTML)
{
try
{
var client = new System.Net.Mail.SmtpClient();
{
client.Host = "smtp-mail.outlook.com";
client.Port = 587;
client.UseDefaultCredentials = false;
client.EnableSsl = true;
client.DeliveryMethod = System.Net.Mail.SmtpDeliveryMethod.Network;
client.Credentials = new NetworkCredential("[my company email]", "[my password]");
client.Timeout = 600000;
}
MailMessage mail = new MailMessage("[insert my email here]", to);
mail.Subject = subject;
mail.Body = body;
client.Send(mail);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
The email address I'm trying to send to is hosted on Office 365's Outlook. We might have to change the specific address later, but they'd likely be configured the same.
However, whenever I try to run the client.Send(mail); command, I receive the same error. The full text of the error is:
The SMTP server requires a secure connection or the client was not authenticated. The server response was: 5.7.57 SMTP; Client was not authenticated to send anonymous mail during MAIL FROM
I've tried a few different things, like switching the port between 25 and 587, changing the host to Office365's, or toggling UseDefaultCredentials and EnableSssl to true or false. But I always see the same error. Is there something else I'm missing?
I found an example code block elsewhere on this site and replacing everything I had with it made the difference.
The function name and parameters were the same, but here's what I replaced the body of it with.
var _mailServer = new SmtpClient();
_mailServer.UseDefaultCredentials = false;
_mailServer.Credentials = new NetworkCredential("my email", "my password");
_mailServer.Host = "smtp.office365.com";
_mailServer.TargetName = "STARTTLS/smtp.office365.com";
_mailServer.Port = 587;
_mailServer.EnableSsl = true;
var eml = new MailMessage();
eml.Sender = new MailAddress("my email");
eml.From = eml.Sender;
eml.To.Add(new MailAddress(to));
eml.Subject = subject;
eml.IsBodyHtml = (bodyType == BodyType.HTML);
eml.Body = body;
_mailServer.Send(eml);
I don't know for certain but I think that replacing the Host value with the smtp Office 365 link rather than an outlook one, as well as remembering to add a Target Name which I did not have before, both did the trick and solved the authorization issue (I had previously confirmed it wasn't a credentials issue with our tech support).
I wrote a simple application for windows to send some emails to members of my mailing list.
The program uses my gmail account to send via SMTP. I do not want my customers having that account however, I want them to see instead the corporate email.
I sent myself some emails to test, but the emails I am recieving are showing sent from the email account Ive logged in with at google. Any ideas?
The mail function:
public void SendEmail()
{
//smtp host and port for gmail
string host = txtHost.Text;
int port;
if (!Int32.TryParse(txtPort.Text, out port))
{
MessageBox.Show("Please enter a valid port number.");
return;
}
//compose email
MailMessage msg = new MailMessage();
msg.Sender = new MailAddress(txtFrom.Text, txtFrom.Text);
msg.From = new MailAddress(txtFrom.Text, txtFrom.Text);
msg.To.Add(txtTo.Text);
msg.Subject = txtSubject.Text;
msg.Body = rTxtMessage.Text;
msg.IsBodyHtml = chkHtml.Checked;
//msg.From = new MailAddress(txtFrom.Text, txtFrom.Text);
//create smtp client
SmtpClient smtp = new SmtpClient(host, port);
//TODO: Move constants to the NetworkCredentials call
string username = SMTP_USERNAME;
string password = SMTP_PASSWORD;
smtp.UseDefaultCredentials = false;
smtp.Credentials = new NetworkCredential(username, password);
smtp.EnableSsl = true;
try
{
//Send email
smtp.Send(msg);
}
catch (Exception exp)
{
//Log if any errors occur
MessageBox.Show(exp.Message);
}
}
And the application and result screenshots:
You should set:
msg.Sender
to your Company address.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Sending email in .NET through Gmail
This mail code is working in localhost i.e on my computer but when i uopload it on server it is not working.
The error is : Failure sending mail. please tell me where is the problem.
if (Session["userinfo"] != null)
{
lblTest.Text = Session["userinfo"].ToString();
MailMessage msg = new MailMessage();
msg.From = new MailAddress("shop.bcharya#gmail.com");
msg.To.Add(new MailAddress("bcc#dr.com"));
msg.To.Add(new MailAddress("info#yzentech.com"));
msg.Subject = "Mail from BcharyaCorporation.online shopping site";
msg.Body = ""+lblTest.Text+" wants to buy some products. please contact with him/her";
SmtpClient sc = new SmtpClient();
sc.Host = "smtp.gmail.com";
// sc.Port = 25;
sc.Credentials = new NetworkCredential("shop.bcharya#gmail.com", "mypassword");
sc.EnableSsl = true;
try
{
sc.Send(msg);
lblPayment.Text = "Sorry. Currently we are out of online payment service. We will contact you for payment process. Thank you for buying this product.";
}
catch (Exception ex)
{
lblPayment.Text=ex.Message.ToString();
Response.Write(ex.Message);
}
}
For gmail mail settings add Port number too
sc.Port = 587;
after this line
sc.Host = "smtp.gmail.com";
Only use port 587 and SSL if the SMTP server supports that (GMail and Hotmail for example). Some servers just use port 25 and no SSL.
Use below method and then check :
SmtpClient sc = new SmtpClient(string); //sends e-mail by using the specified SMTP server
You can use this below given code for sending email. Here sending the error details through email is one method. Try this code for sending email.
using System.Web.Mail
public static bool SendErrorEmail(string to, string cc, string bcc, string subject, string body, MailPriority priority, bool isHtml)
{
try
{
using (SmtpClient smtpClient = new SmtpClient())
{
using (MailMessage message = new MailMessage())
{
MailAddress fromAddress = new MailAddress(“yourmail#domain.com”, “Your name”);
// You can specify the host name or ipaddress of your server
smtpClient.Host = “mail.yourdomain.com”; //you can specify mail server IP address here
//Default port is 25
smtpClient.Port = 25;
NetworkCredential info = new NetworkCredential(“yourmail#domain.com”, “your password”);
smtpClient.DeliveryMethod = SmtpDeliveryMethod.Network;
smtpClient.UseDefaultCredentials = false;
smtpClient.Credentials = info;
//From address will be given as a MailAddress Object
message.From = from;
message.Priority = priority;
// To address collection of MailAddress
message.To.Add(to);
message.Subject = subject;
// CC and BCC optional
if (cc.Length > 0)
{
message.CC.Add(cc);
}
if (bcc.Length > 0)
{
message.Bcc.Add(bcc);
}
//Body can be Html or text format;Specify true if it is html message
message.IsBodyHtml = isHtml;
// Message body content
message.Body = body;
// Send SMTP mail
smtpClient.Send(message);
}
}
return true;
}
catch (Exception ee)
{
Logger.LogError(ee, “Error while sending email to ” + toAddress);
throw;
}
}
I use this code to try and send an email. After a few seconds, it shows me an error message claiming the operation has timed out. How can I resolve this issue?
try
{
MailAddress from = new MailAddress("from#yahoo.com", "name", Encoding.UTF8);
MailAddress to = new MailAddress("to#yahoo.com");
MailMessage message = new MailMessage(from, to);
message.Subject = "Test";
message.SubjectEncoding = Encoding.UTF8;
message.Body = "Test";
message.BodyEncoding = Encoding.UTF8;
SmtpClient client = new SmtpClient();
client.Host = "smtp.mail.yahoo.com";
client.Port = 465;
client.EnableSsl = true;
client.Credentials = new NetworkCredential("example#yahoo.com", "Password");
client.Send(message);
MessageBox.Show("sending Successfully!!!");
}
catch (SmtpException ex)
{
MessageBox.Show(ex.ToString());
}
Are you sure that you can reach smtp.mail.yahoo.com on port 465? Sounds pretty much like a network related issue. Generally when something times out, it means that it tries to connect to the server for a certain amount of time and them stops and gives you an error.
One easy way to test this is to telnet to smtp.mail.yahoo.com on port 465 and see if it times out. You can use Putty or the built in telnet-client in windows, if you have it installed.
As per my understanding, your code won't work because yahoo.com does not provide you access via SMTP. For that you need to upgrade to Yahoo! Mail Plus.
Couldn't find any sort of kb from Yahoo! on this. I got the information from a Yahoo! article on How to read Yahoo! Mail Plus using Outlook Express. The first two lines of the article are very relevant.
Do you want to read and send your Yahoo! email with Outlook Express?
If you are a Yahoo! Mail Plus user you can.
And also, the outgoing SMTP server should be
client.Host = "plus.smtp.mail.yahoo.com";
i had the same problem
you have to set the clietn.port as 25 and you have to specify your login an password in client.Credentials = new NetworkCredential(login,password)
when i did that i can send mail without problem
there is the code
{
SmtpClient client = new SmtpClient("188.125.69.59");//you can put the ip adress or the dns of smtp server (smtp.mail.yahoo.com as exemple)
// Specify the e-mail sender.
// Create a mailing address that includes a UTF8 character
// in the display name.
MailAddress from = new MailAddress("from#yahoo.fr");
// Set destinations for the e-mail message.
MailAddress to = new MailAddress("to#gmail.com");
// Specify the message content.
MailMessage message = new MailMessage(from, to);
message.Body = "This is a test e-mail message sent by an application. ";
// Include some non-ASCII characters in body and subject.
string someArrows = new string(new char[] {'\u2190', '\u2191', '\u2192', '\u2193'});
message.Body ="cc";
message.BodyEncoding = System.Text.Encoding.UTF8;
message.Subject = "test message 1";
message.SubjectEncoding = System.Text.Encoding.UTF8;
string userState = "test message1";
MessageBox.Show("sending");
client.Port = 25;
// client.Timeout = 40000;
client.ServicePoint.MaxIdleTime = 1;
client.Credentials = new System.Net.NetworkCredential("from#yahoo.fr", "pass");
//client.SendAsync(message, userState);
client.Send(message);
MessageBox.Show("Sending message... press c to cancel mail. Press any other key to exit.");
string answer = Console.ReadLine();
// If the user canceled the send, and mail hasn't been sent yet,
// then cancel the pending operation.
// if (answer.StartsWith("c") && mailSent == false)
//{
// client.SendAsyncCancel();
//}
// Clean up.
message.Dispose();
MessageBox.Show("Goodbye.");
}
Use following setting for domain #yahoo.co.in.
var smtp = new System.Net.Mail.SmtpClient();
{
smtp.Host ="smtp.mail.yahoo.co.in";
smtp.Port = 25;
smtp.EnableSsl = true;
smtp.DeliveryMethod = System.Net.Mail.SmtpDeliveryMethod.Network;
smtp.Credentials = new NetworkCredential(fromAddress, fromPassword);
smtp.Timeout = 20000;
}