This question already has answers here:
Email messages going to spam folder
(7 answers)
Closed 9 years ago.
I've got a C# application going that needs to send out an html email via smtp. The email gets sent just fine, but the default security setting on outlook (Low) classifies it as junk email.
It's not exactly a showstopper issue, but this is rather annoying, especially since the junk folder turns off html. I don't want to have to make everyone at my company do something special to receive these emails in a readable fashion, does anyone know what I could be doing that makes outlook think this is junk email?
Code that makes the email (basic stuff.) Config is an object that holds strings related to the configuration of this stuff, toList is a list of email addresses, body/subject are filled by other function calls.
Edit: To add, at the moment I'm just sending it out to myself. In the live version, we'll be looking at less than a hundred people being sent to in a worst-case.
Another Edit: It turned out to be happening much much more often for the longer emails I was generating the other day (~200-300 lines at the worst), and not the shorter emails I'm generating now. That's a reasonable enough filter criteria, I suppose.
SmtpClient smtp = new SmtpClient(config.SmtpServer);
NetworkCredential net = new NetworkCredential();
net.UserName = config.SmtpLogin;
net.Password = config.SmtpPass;
smtp.Credentials = net;
MailMessage msg = new MailMessage();
msg.IsBodyHtml = true;
msg.Priority = MailPriority.Normal;
msg.To.Add(String.Join(",", toList.ToArray()));
msg.From = new MailAddress(fromAddr, "Build Server");
msg.Body = "Blah html is here";
msg.Subject = "Build successful: #numberhere and stuff";
try
{
smtp.Send(msg);
}
catch (SmtpException)
{
//stuff
}
I think this is less of a programming issue and more of a configuration issue. The recipients need to add fromAddr to their “Safe Senders List”.
The thing is, if there were a way to configure an e-mail to bypass the junk mail filter then all the spammers will be doing it.
If it's a matter of crafting the perfect non-junk-looking e-mail then it may work sometimes and not others. And all the spammers will be doing it.
You're going to have to tell everyone to allow e-mails from that account. And you probably shouldn't start that e-mail with any unnecessary anatomical or medicinal references.
If your message To contains a large list it may be seen as spam. Try sending a unique email to each person instead of a mass email.
However:
If you're going to loop through your list and send an email for each user, you might want to consider creating a queue that will be processed that allows for failure and retry.
We had a similar issue in our system where after about 20,00 messages sent in quick succession (ie: within a foreach loop) the outgoing mail server rejected any further attempt to relay.
We instead added outgoing messages to a database table, and wrote a service that would process a specified number of emails at a time and then pause for a specified time before going again.
In addition this allowed us to capture failures, and then setup retry rules. After X attempts we mark the message as failed for good and report the issue. We found that this provided a much more reliable system of users getting their messages, plus they were no longer marked as spam.
If you are sending out several mails at a time send them in small batches so you're not flooding the server.
Check the text of the email for words and symbols likely to be considered spam by some filters.
You might also want to look into things such as SPF to reduce the chance that your mails will be marked as spam.
Add following line in your code while creating MailMessage
msg.BodyEncoding = System.Text.Encoding.GetEncoding("utf-8");
Just a thought, try looping through your to list and send a separate email. Also, try experimenting with different wording and html structures.
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
The community reviewed whether to reopen this question last year and left it closed:
Original close reason(s) were not resolved
Improve this question
Everytime I google or search here "how to send an email" I get results like: use an smtp client, connect to a smtp server, send the mail over the smtp server.
I am looking for the code (or the idea) how the server it self sends the email to the other server. So the approach from the link above won't work for me.
Any hints what a smtp server library would do?
First you need to find out address of SMTP server for each of the recipients of your email. You do that by querying DNS of recipients domain for MX record(s). In .NET you can do that with, for example, ARSoft.Tools.Net library:
var resolver = new DnsStubResolver();
var records = resolver.Resolve<MxRecord>("gmail.com", RecordType.Mx);
foreach (var record in records.OrderByDescending(c => c.Preference)) {
Console.WriteLine(record.ExchangeDomainName + " : " + record.Preference);
}
Each MX record has preference value, and you should try them in order of preference (highest first, then if it's not available - next one etc).
Now when you have address of target SMTP server - you connect to it (usually on port 25, or if you want to use encrypted connection - on port 465) and perform regular SMTP conversation (smtp is text protocol), for example:
HELO < you start conversation
250 OK < server lets you proceed
MAIL FROM: <someuser#somedomain.com>
250 OK < server is fine with this sender
RCPT TO: <someuser#targetdomain.com>
250 OK < server is fine with recipient
DATA < you are going to send email body
250 OK < server is fine with that - proceed
Here you send your message
250 OK < server accepted message
QUIT
There are libraries which are capable of doing all this (MX discovery, SMTP conversations and more) in .NET, for example MailBee (not free). I used only mentioned library for this, so not aware if there are free libraries.
Now, while it might look easy - in reality it will not go as smooth as I described.
Target SMTP server will perform a series of checks agains your IP address, domain of the sender, and message contents. For example, when you do:
MAIL FROM: <someuser#somedomain.com>
Most decent SMTP servers will perform reverse DNS check to ensure that domain of a sender and IP from which you send your email are related. To pass that check you should of course own target domain (somedomain.com) and put specific DNS record there.
Most SMTP servers will "graylist" you on the first send. That means they will reject your email but encourage you to try later. So you cannot send emails without storing them, because it many cases - several tries are required to sucessfully send your email.
There are many more checks performed by SMTP servers (different kind of signatures for example), so some efforts are required to make this work reliably.
For the above reasons - most people do not implement their own smtp servers but instead relay all of the above work to already existing SMTP server.
To sum up - it's possible to perform direct send to target SMTP server, but doing that naively from your web api is not going to work reliably. You need to setup a service for that purpose, configure it correctly (not trivial) and store messages somewhere (in database), because several retries might be required.
To reliable send an email you need a server. Period. You can use a cloud service like SendGrid if you don't have or want one yourself.
An smtp server is needed because otherwise:
You will need to implement retries yourself of the other server is
down
Most mail servers have spam detection mechanisms in place and won't allow your mail
You will have to resolve the recipient mail servers manually.
Some background reading material about the reasons I listened:
https://superuser.com/questions/1006079/why-do-i-need-an-smtp-server
https://superuser.com/questions/753811/why-mail-clients-do-not-use-directly-the-smtp-server-of-recipient
https://superuser.com/questions/753811/why-mail-clients-do-not-use-directly-the-smtp-server-of-recipient
We are currently going through a proof of concept creating a Transport Agent that is derived from the Microsoft.Exchange.Data.Transport.Routing.RoutingAgent. We use the OnResolvedMessage event to reroute emails to our external Email server (non Exchange server). This all works fine, and we can reroute the emails to the external server. However, it appears that if an email contains both an internal and external recipient the email will be split into two separate emails and result in two emails going to the external email server. While the two emails contain the same content, just different RCPT TO headers, this will cause the external email server to process the same email twice which is less than desirable for our project.
This is my first time creating a transport agent, and I am trying to determine if there is some setting for exchange server that needs to be changed in order to stop emails that meet this criteria from being split into multiple emails?
The main goal of our transport agent will be to allow emails going to internal recipients to be processed by the external email server, as they currently will be placed into the internal user's mailbox unprocessed. It might have to do with our send/receive connectors, any guidance on any gotchas around those would be much appreciated. If a routing agent is not the correct solution for this problem, we are open to other possibilities.
Snippet of our event handler:
private void OnOnResolvedMessage(ResolvedMessageEventSource source, QueuedMessageEventArgs queuedMessageEventArgs)
{
var mailItem = queuedMessageEventArgs.MailItem;
var origSubject = mailItem.Message.Subject;
mailItem.Message.Subject = "RouteAgent: " + origSubject;
foreach (var recipient in mailItem.Recipients)
{
var newRouteDomain = new RoutingDomain("externalSendConnectorAddressSpace.com");
var dest = new RoutingOverride(newRouteDomain, DeliveryQueueDomain.UseOverrideDomain);
source.SetRoutingOverride(recipient, dest);
}
}
By the time OnResolved Message gets called in the Transport Pipeline the recipients will have been resolved and Bifurcation will have happened on the Message the rules for which are mostly explained in https://technet.microsoft.com/en-us/library/bb430743(v=exchg.150).aspx . EdgeTransport.exe.config is the place where the configuration of the Transport pipeline can be done but I don't believe there is any configuration option for what your trying to do.
If you catch the Message in OnSubmission event this will allow you to get the Message before any categorization has occurred. At that point you can more or less do what you want to the Message. However there are other things that occur as part of the Categorization process such as content conversion https://technet.microsoft.com/en-us/library/bb232174(v=exchg.150).aspx .
However, it appears that if an email contains both an internal and external recipient the email will be split into two separate emails and result in two emails going to the external email server. While the two emails contain the same content, just different RCPT TO headers, this will cause the external email server to process the same email twice which is less than desirable for our project.
This shouldn't really be a big deal for the external service as this should be something that would be expected in any process that was processing emails eg its easy for the external service correlate using the Internet MessageId etc. IMO your trying to solve the problem at the wrong end.
Cheers
Glen
We have an ASP.NET MVC application that sends a number of reports via e-mail to clients each month. Each e-mail attaches a monthly statement. Currently we have around 70 clients but this will hopefully increase over time. We have been seeing issues that a number of e-mails are not getting sent. We use the System.Net.Mail API.
Here is the code we are using, is there a better approach?
foreach(string client in clients){
SmtpClient client = new SmtpClient("server.com");
BackgroundWorker emailInvoker = new BackgroundWorker();
emailInvoker.DoWork += delegate
{
// Delay to prevent flow control, try later Relay error
Thread.Sleep(TimeSpan.FromSeconds(2));
client.Send(message);
}
emailInvoker.RunWorkerAsync();
}
We have been seeing issues that a number of e-mails are not getting
sent.
The larger (and more likely) problem than some of them aren't getting sent is that many of them are not getting delivered.
...is there a better approach?
In most cases. Jeff Atwood goes over many of the problems with sending email in this blog post. That post was almost 3 years ago and even then, the first comment recommends using postmark. I've used postmark and it reliably handles the problem of getting your emails out through code at a good price. That said, there are better solutions on the market now, the one my company is currently very tempted to switch to is mandrill. Slightly better pricing, awesome analytics.
Because this is an ASP.NET MVC application, you need to be aware of your application pool. Creating multiple threads will exhaust your app pool quickly, and IIS maybe doing some funky things to keep things from literally grinding to a halt while emails are being sent. I would take a look at Can I use threads to carry out long-running jobs on IIS? if you're interested on learning more.
If I were to rewrite that, I would create one thread with the foreach and email sending, instead of a thread for each customer.
BackgroundWorker emailInvoker = new BackgroundWorker();
emailInvoker.DoWork += delegate
{
// get your clients here somehow
foreach(string client in clients){
SmtpClient client = new SmtpClient("server.com");
// Delay to prevent flow control, try later Relay error
Thread.Sleep(TimeSpan.FromSeconds(2));
client.Send(message);
}
}
emailInvoker.RunWorkerAsync();
We are sending free newsletters to all users who have registered for this service. Since these newsletters are sent free of cost we expect at least 5000 subscribers within a month. I am worried whether bulk mailing using SMTP server concept will cause some issue. First we thought of developing a windows service which would automatically mail to subscribers on periodical basis but the business users have given requirement that the newsletters should be editable by the admin and then only mailed to users so we had to develop this functionality in website itself!. I get the subscribers for the particular user in data table and then mail to each user inside for loop, will this cause any performance issue?
The code is pasted below:
dsEmailds.Tables[0] has list of newsletter subscribers.
for (iCnt = 0; iCnt < dsEmailIds.Tables[0].Rows.Count; iCnt++)
{
MailMessage msg = new MailMessage();
msg.From = new MailAddress("newsletters#domainname.com", "test1");
msg.To.Add(dsEmailIds.Tables[0].Rows[iCnt]["mailid"]);
msg.IsBodyHtml = true;
msg.Subject = subject;
AlternateView av1 = AlternateView.CreateAlternateViewFromString(MailMsg, null, System.Net.Mime.MediaTypeNames.Text.Html);
av1.LinkedResources.Add(lnkResLogo);
av1.LinkedResources.Add(lnkResSalesProperty);
av1.LinkedResources.Add(lnkResLeaseProperty);
msg.AlternateViews.Add(av1);
SmtpClient objSMTPClient = new SmtpClient(System.Configuration.ConfigurationManager.AppSettings["mailserver"].ToString());
objSMTPClient.DeliveryMethod = SmtpDeliveryMethod.Network;
objSMTPClient.Send(msg);
}
Any suggestions would be great!
You should STOP and consider all sort of things:
Black List: with that amount you will for sure be balck listed in severeal ISP's / Mail Servers, and you need to prove that the received user asked for such email and wait 1 to 3 month process while they remove the flag
You need to send emails in blocks, not more than 250 at each time, use different IP's machines to send more emails (more blocks)
please read some nice guidelines for doing all this, you can find it in MailChimp and Campaign Monitor
Free Email Marketing Guides
You should use a service, like Mailchimp (now it's free to 1000 subscribes, 3000 sends a month) but prices are very cheap and they have an API that you can easily add, create, send and you will get all those nice reports on how opened, what did they do, etc ...
Campaign Monitor is fantastic as well, but a little bit more expensive but great as you can brand the entire UI and sell as a service to your customers (if you are thinking of doing such thing in the near future).
I hope it helps.
give them a try, I'm a happy customer.
The main problem i see is that you may encounter a page timeout. The best way to do it in my opinion would be to set up a service that will take care of mail-related uses (templating for example) by reading from a queue. Your website could just post the mails you expect to send in the queue, then offer a basic administration panel to manage the service and get some stats.
You can use open-source & xcopy-friendly systems for the queue like Rhino queue, or ServiceBus, and Topshelf for services if you want easy setup
But i'd recommend you not to send bulk emails in the webpage
There is a SendAsync method that will actually queue up these requests and send them async from your thread. This way you can prevent the timeout and you can probably send (ie. queue) 5000 emails within seconds.
Write to a pickup queue of an SMTP server running on the machine (IIS includes one). This is the fastest and most efficient method.
OR
Setup a custom thread pool in your code and offload the task to it. That way worker threads from ASP.NET thread pool are ready to serve incoming requests and won't be occupied with sending mails (that depends on how high your server load is, of course - go ahead with ASP.NET thread pool using async methods if you don't care about the load/can afford it).
I have written some simple code, to send en auto generated email, using the System.mail.Net namespace.
It works like a charm, but there is one little problem.
The mail does not get send, untill my whole application is terminated.
Does any of you have a workaround for this?
Here is the code I use (c#):
try
{
MailMessage mail = new MailMessage();
mail.From = new MailAddress("myEmail#mail.com");
mail.To.Add("targetEmail#mail.com");
mail.Subject = "Test test";
mail.Body = "blah blah";
mail.Attachments.Add(new Attachment("c:\\file.txt"));
SmtpClient smtp = new SmtpClient("myserver.mail.com");
smtp.Send(mail);
}
catch (SmtpFailedRecipientsException ex)
{
Console.WriteLine(ex);
}
As I said, everything works, but the mail is not send, untill I terminate the application.
Is there any way to force it to send the mail now?
The reason it is a problem, is both that I want the mail to be sent instantly without the user needing to reboot the application, but also because I want to delete the attachment after the mail has been sent, and when the mail isn't sent, the file is therefore marked as "in use" and can therefore not be deleted.
Best regards
/S
I've had the same problem, and using the workaround posted at http://social.msdn.microsoft.com/forums/en-US/netfxnetcom/thread/6ce868ba-220f-4ff1-b755-ad9eb2e2b13d/ seems to work:
For anyone interested, I've found a solution or at least a work around to the delay.
The ServicePoint member contains a member called MaxIdleTime. Setting this value to 0 seems to have the same affect as Timeout.Infinite (which I assume is also 0). Setting it to 1 caused my email to be sent out immediately.
See this link:
http://msdn2.microsoft.com/en-us/library/system.net.servicepoint.maxidletime.aspx
Example code:
SmtpClient smtp = new SmtpClient();
// setup the mail message
smtp.ServicePoint.MaxIdleTime = 1;
smtp.Send(myMailMessage);
Calling
smtp.Send(mail);
Sends the email to your smtp server immediately. If you're not seeing the email being sent as soon as that line executes, then I would check to see if your smtp server is functioning properly.
Here's more information on the SmtpClient.
I wonder if your application has a lock on the attachment which is preventing the mail component from doing its work until your application starts shutting down. Can you verify that all locks are cleared prior to sending the mail?
You might start with a new small app that only sends an email. Once that it working properly, add a hard coded attachment. Verify it's still working. If everything is good, add your code for how you are handling attachments. If it breaks, tweak your code. Rinse and repeat. ;)
I have seen this problem before. I had to turn off Norton Antivirus outgoing email scan to get emails to go right away.
HTH