System.Net.Mail.SmtpException : SMTP command timeout - closing connection - c#

I am having an error that is occurring sporadically. When I encounter this error, if I try again, the e-mail will send. I cannot reliably reproduce the error, but it is hapening frequently enough to be a problem.
System.Net.Mail.SmtpException : Service not available, closing transmission channel. The server response was: [Servername]: SMTP command timeout - closing connection
Stack Trace:
at System.Net.Mail.MailCommand.CheckResponse(SmtpStatusCode statusCode, String response) at System.Net.Mail.MailCommand.Send(SmtpConnection conn, Byte[] command, String from) at System.Net.Mail.SmtpTransport.SendMail(MailAddress sender, MailAddressCollection recipients, String deliveryNotify, SmtpFailedRecipientException& exception) at System.Net.Mail.SmtpClient.Send(MailMessage message)
Here's the code in question. It uses an HTML template (database driven with a web url default backup) to inject values and create an html e-mail.
public void AccountActivationEmail(Common.Request.Email.AccountActivation request)
{
var profile = profileRepository.GetOne(new ProfileByUsername(request.Username, request.SiteId));
var options = siteService.GetOptions(new GatewayOptionsRequest()
{
SiteId = request.SiteId
});
var site = options.Site;
ExpiringHMAC hmac = new ExpiringHMAC(request.ExpireOn, new string[] { request.AccountId.ToString(), request.AccountKey.ToString(), request.Username });
Dictionary<string, string> data = new Dictionary<string, string>();
data.Add("{{logourl}}", String.IsNullOrEmpty(options.FullyHostedGateway.LogoUrl) ? UrlHelper.ConvertRelativeToAbsolute("/content/images/spacer.png") : options.FullyHostedGateway.LogoUrl);
data.Add("{{name}}", profile.Name.DisplayName);
data.Add("{{sitename}}", site.Name.DisplayName);
data.Add("{{activationlink}}", String.Format(ActivationUrlFormat, options.UrlFriendlyName, Encryption.EncryptQueryString(request.Username), hmac.ToString()));
MailDefinition template = new MailDefinition();
MailMessage message = null;
var emailTemplate = options.GetEmailTemplate(EmailTemplateType.ActivateAccount);
string defaultSubject = "Activate Account";
bool hasTemplate = false;
if (emailTemplate != null)
{
hasTemplate = !String.IsNullOrEmpty(emailTemplate.Template);
}
if (!hasTemplate)
{
template.BodyFileName = activationDefaultTemplateUrl;
message = template.CreateMailMessage(request.EmailAddress, data, new System.Web.UI.LiteralControl());
message.IsBodyHtml = true;
message.Subject = defaultSubject;
}
else
{
message = template.CreateMailMessage(request.EmailAddress, data, emailTemplate.Template, new System.Web.UI.LiteralControl());
message.IsBodyHtml = emailTemplate.IsHtml;
if (!String.IsNullOrEmpty(emailTemplate.Subject))
message.Subject = emailTemplate.Subject;
else
message.Subject = defaultSubject;
}
if (options.ContactDetails != null)
{
if (!String.IsNullOrEmpty(options.ContactDetails.EmailAddress))
message.From = new MailAddress(options.ContactDetails.EmailAddress);
}
SmtpClient client = new SmtpClient();
client.Send(message);
}
This code is part of a class that is generated as a singleton using Structuremap. I thought maybe that might be causing the issue, but every time the method is called, a new SmtpClient object is created, which should eliminate the problems I have seen about using the same connection to send multiple e-mails.
We have nothing blocking or restricting the connection, which is the official stance our e-mail hosting is taking on this issue. I want to see if there's any way to do this better so I don't get these errors.
EDIT:
I do have my mail server defined in my web.config. I have confirmed with my e-mail hosting that my settings are correct.
<system.net>
<mailSettings>
<smtp deliveryMethod="Network" from="no-reply#mydomain.com">
<network host="smtp.emailhost.com" userName="someaddress#mydomain.com"
password="myPassword1" port="2500" />
</smtp>
</mailSettings>
</system.net>

Are you disposing of the Smtp Client object after sending? From http://connect.microsoft.com/VisualStudio/feedback/details/337557/smtpclient-does-not-close-session-after-sending-message it would appear that "...even if you are creating a new instance of the SmtpClient every time, it still uses the same unerlying session."
So perhaps
using (SmtpClient client = new SmtpClient())
{
client.Send(message);
}

Related

System.Net mail settings using Network Solutions hosted email

I am trying to use my email service through Network Solutions (NetSol) so that emails sent via the application come from our domains service#ourdomain address.
I cannot seem to make it work, and I am not sure it is even doable since its a webmail service which I can access in a browser using a url like http://mail.ourdomain.com.
According to their site, the smtp settings can be found here
NetSol smtp
Using that information I set up my mail settings as follows
<mailSettings>
<smtp deliveryMethod="Network">
<network host="smtp.ourdomain.com" port="587" userName="service#ourdomain.com" password="xxxxxxxx" enableSsl="true" />
</smtp>
</mailSettings>
I know the password is correct as I'm able to login to my mail in the webbrowser so I don't believe its a credentials error although the error in the method is erring on the credential piece.
private async Task SendMailMessageAsync(MailMessage msg)
{
var acct = Username;
var pwd = Password;
msg.IsBodyHtml = true;
using (var mailClient = new SmtpClient())
{
if (acct != string.Empty && pwd != string.Empty)
{
var credentials = new NetworkCredential(acct, pwd);
mailClient.Credentials = credentials; //ERRING HERE
}
await mailClient.SendMailAsync(msg);
}
}
Is anyone familiar with the proper setup for NetSol professional email?
UPDATE:
For some reason, my code edit in the answer I accepted wasn't accepted. So here is the code, in working order based on the comments in the accepted answer.
public void SendNetSolEmail()
{
var sender = "whatever#yourdomain.com";
var pass = "yourpassword";
var mailMessage = new MailMessage(sender, "sendto_emailaddress", "Hi there", "This method works fine!");
var mailClient = new SmtpClient("mail.yourdomain.com", 587)
{
Credentials = new NetworkCredential(sender,pass),
EnableSsl = false, //important for Network Solutions mail
DeliveryMethod = SmtpDeliveryMethod.Network
};
mailClient.Send(mailMessage);
}
A simple working example of connecting to NetSol's smtp
System.Net.Mail.SmtpClient mailMsg = new System.Net.Mail.SmtpClient("mail.domain.com", 587);
mailMsg.Credentials = new System.Net.NetworkCredential("username#domain.com", "password");
mailMsg.SendMailAsync("username#domain.com", "someone.somewhere#somedomain.com", "Hi Someone", "Body of the email");
and the last note as I see you have ssl enabled; Here it is direct from NetSol:
Note - Make sure you are not chosing and SSL type, this option should be turned off, or "None" should be selected.

Send mail with attachment

Edit: I'm able to send mail without attachment
Getting this error while trying to send mail:
System.Net.Mail.SmtpException: The operation has timed out.
Following is my code:
public static void SendMailMessage(string to, string subject, string body, List<string> attachment)
{
MailMessage mMailMessage = new MailMessage();
// string body; --> Compile time error, body is already defined as an argument
mMailMessage.From = new MailAddress("abc#gmail.com");
mMailMessage.To.Add(new MailAddress(to));
mMailMessage.Subject = subject;
mMailMessage.Body = body;
foreach (string s in attachment)
{
var att = new Attachment(s);
mMailMessage.Attachments.Add(att);
}
// Set the format of the mail message body as HTML
mMailMessage.IsBodyHtml = true;
// Set the priority of the mail message to normal
mMailMessage.Priority = MailPriority.High;
using (SmtpClient mSmtpClient = new SmtpClient())
{
mSmtpClient.Send(mMailMessage);
}
}
Web Config
<system.net>
<mailSettings>
<smtp from="mailid">
<network host="smtp.gmail.com" port="587" enableSsl="true" userName="username" password="pass" />
</smtp>
</mailSettings>
Note : Attachments not exceeding its limit(below than 25 mb)
What can I do to solve this problem, or what am I missing?
So basically we discovered during the chat that the problem occurs
because the upload of the attachments takes to long.
One way to solve it is to increase the timeout value of the SmtpClient:
mSmtpClient.Timeout = int.MaxValue;
Note: Use int.MaxValue for testing but use a more realistic value for the deployed solution.
Setup a local smtp server to relay through, or use something like http://aws.amazon.com/ses/. I don't think google is going to allow you to programtically relay through their servers.

error when send email

I am using the code as described in this question. However get following error when send an email.
Mailbox unavailable. The server response was: please authenticate to
use this mail server
Any ideas what could be wrong?
UPATE: Here is the code
System.Net.Mail.SmtpClient Client = new System.Net.Mail.SmtpClient();
MailMessage Message = new MailMessage("From", "To", "Subject", "Body");
Client.Send(Message);
With following in App.config.
<system.net>
<mailSettings>
<smtp from="support#MyDomain1.com">
<network host="smtp.MyDomain1.com" port="111" userName="abc" password="helloPassword1" />
</smtp>
</mailSettings>
</system.net>
The code posted there should work. if it doesn't, you might try setting the username and password in code-behind rather than reading them from the web.config.
Code sample from systemnetmail.com:
static void Authenticate()
{
//create the mail message
MailMessage mail = new MailMessage();
//set the addresses
mail.From = new MailAddress("me#mycompany.com");
mail.To.Add("you#yourcompany.com");
//set the content
mail.Subject = "This is an email";
mail.Body = "this is the body content of the email.";
//send the message
SmtpClient smtp = new SmtpClient("127.0.0.1");
//to authenticate we set the username and password properites on the SmtpClient
smtp.Credentials = new NetworkCredential("username", "secret");
smtp.Send(mail);
}
Yes, the smtp server is telling you that in order to relay email for you, you need to authenticate before attempting to send the email. If you have an account with the smptp server, you can set the credentials on the SmtpClient object accordingly. Depending on the authentication mechanism supported by the smtp server, the port, etc, will be different.
Example from MSDN:
public static void CreateTestMessage1(string server, int port)
{
string to = "jane#contoso.com";
string from = "ben#contoso.com";
string subject = "Using the new SMTP client.";
string body = #"Using this new feature, you can send an e-mail message from an application very easily.";
MailMessage message = new MailMessage(from, to, subject, body);
SmtpClient client = new SmtpClient(server, port);
// Credentials are necessary if the server requires the client
// to authenticate before it will send e-mail on the client's behalf.
client.Credentials = CredentialCache.DefaultNetworkCredentials;
try {
client.Send(message);
}
catch (Exception ex) {
Console.WriteLine("Exception caught in CreateTestMessage1(): {0}",
ex.ToString() );
}
}
The bottom line is that your credentials are not being passed to the Smtp server or else you wouldn't be getting that error.

SMTP email "Service" I can include in my C# project?

I've written several programs that send email from C#. This works great in winXP, but I find it breaks in Win7. My understanding is that even though the SMTP server I'm referencing is on another computer, the sending computer needs to have the SMTP service installed (and win7 does not).
I know its possible to install a third party SMTP server, but then I'd need to do that on every computer running my programs. Instead, I'd like to include a temporary SMTP server in my project that I can use entirely from code to do the same job. Does anyone know of a library (or sample code) on how I can include a temporary SMTP server in my project?
Here is my code:
public static void sendEmail(String[] recipients, String sender, String subject, String body, String[] attachments)
{
MailMessage message;
try
{
message = new MailMessage(sender, recipients[0]);
}
catch (Exception)
{
return;
}
foreach (String s in recipients)
{
if (!message.To.Contains(new MailAddress(s)))
message.To.Add(s);
}
message.From = new MailAddress(sender);
message.Subject = subject;
message.Body = body;
message.IsBodyHtml = true;
SmtpClient smtp = new SmtpClient("PRIVATE.PRIVATE.PRIVATE", 25);
smtp.DeliveryMethod = SmtpDeliveryMethod.PickupDirectoryFromIis;
//smtp.DeliveryMethod = SmtpDeliveryMethod.Network;
smtp.UseDefaultCredentials = true;
if (attachments.Length > 0)
{
foreach (String a in attachments)
{
message.Attachments.Add(new Attachment(a));
}
}
try
{
smtp.SendAsync(message, null);
To send emails from c#, you do not need a local SMTP service. You just need the System.Net.Mail library. Using a remote SMTP server (possibly one with valid PTR settings and not one in your network to avoid being regarded as a spammer) should definitely suffice.
It may be a credentials issue. Change SendAsync to Send to see if you are getting any exceptions. Or add a handler for the Async invocation
smtp.SendCompleted += delegate(object s, System.ComponentModel.AsyncCompletedEventArgs e)
{
if (e.Error != null)
{
System.Diagnostics.Trace.TraceError(e.Error.ToString());
}
};
Following changes to your code works for me in Win7
SmtpClient smtp = new SmtpClient("smtp.gmail.com", 587);
//smtp.DeliveryMethod = SmtpDeliveryMethod.PickupDirectoryFromIis;
smtp.DeliveryMethod = SmtpDeliveryMethod.Network;
smtp.Credentials = new NetworkCredential(GoogleUserEmail, GooglePassword);
smtp.EnableSsl = true;
// smtp.UseDefaultCredentials = true;
if (attachments != null && attachments.Length > 0)
{
foreach (String a in attachments)
{
message.Attachments.Add(new Attachment(a));
}
}
try
{
smtp.Send(message);
}
I have never found an embeddable SMTP server, but both of these are close and you could probably modify them to fit your needs.
http://www.codeproject.com/KB/IP/smtppop3mailserver.aspx
http://www.ericdaugherty.com/dev/cses/developers.html
I'm going to keep looking because this is also something I'd find useful. I'll post more if I find any.
If you just use an unconfigured service to send your emails you will definitely end up in the SPAM folder due to reverse DNS and SPF checks failing. So you'll want to configure your server properly. Alternatively you can use a 3rd party service like Elastic Email. Here is Elastic Email's sample code which uses HTTP to send the mail:
public static string SendEmail(string to, string subject, string bodyText, string bodyHtml, string from, string fromName)
{
WebClient client = new WebClient();
NameValueCollection values = new NameValueCollection();
values.Add("username", USERNAME);
values.Add("api_key", API_KEY);
values.Add("from", from);
values.Add("from_name", fromName);
values.Add("subject", subject);
if (bodyHtml != null)
values.Add("body_html", bodyHtml);
if (bodyText != null)
values.Add("body_text", bodyText);
values.Add("to", to);
byte[] response = client.UploadValues("https://api.elasticemail.com/mailer/send", values);
return Encoding.UTF8.GetString(response);
}
Have you tried specifying SMTP settings in an App.config file? Something like:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.net>
<mailSettings>
<smtp deliveryMethod="Network">
<specifiedPickupDirectory pickupDirectoryLocation="C:\tmp"/>
<network host="smtp.example.com"/>
</smtp>
</mailSettings>
</system.net>
</configuration>
If you change deliveryMethod="SpecifiedPickupDirectory" then it'll just write a file representing the email that would be sent to the directory you specify.

SmtpDeliveryMethod.PickupDirectoryFromIis strange behavior

I think i need some guru lights!
public void SendEndingMail(string fileName)
{
SmtpClient client;
client = new SmtpClient("smtp.myserver.com", 25);
//client = new SmtpClient();
if (!string.IsNullOrEmpty(""))
{
System.Net.NetworkCredential credential = new NetworkCredential("", "");
client.Credentials = credential;
}
client.UseDefaultCredentials = true;
client.DeliveryMethod = SmtpDeliveryMethod.Network;
//client.DeliveryMethod = SmtpDeliveryMethod.PickupDirectoryFromIis;
MailAddress fromAddress = new MailAddress("mailing#mydom.com", "Elec");
MailAddress toAdrress = new MailAddress("mailing#mydom.com");
using (System.Net.Mail.MailMessage mailMessage = new System.Net.Mail.MailMessage(fromAddress, toAdrress))
{
mailMessage.Attachments.Add(new System.Net.Mail.Attachment(fileName));
mailMessage.IsBodyHtml = false;
mailMessage.BodyEncoding = System.Text.Encoding.UTF8;
try
{
client.Send(mailMessage);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message.ToString());
}
}
}
Is that true that:
when i set
client.DeliveryMethod = SmtpDeliveryMethod.PickupDirectoryFromIis;
It does not matter whichever smtp server i use
client = new SmtpClient("smtp.myserver.com", 25);
//client = new SmtpClient();
The both lines are the same since it will use LOCAL IIS ?!!!
Is this is true, it is not normal that the API is build this way!? it is very confusing...
Thanks
Jonathan
IIRC, when the SmtpClient sends the email, it looks at the .DeliveryMethod value. If the value is Network, then it sends via network. If it is PickupDirectoryFromIis, then it ignores any specified SMTP server (because it just writes and the email to the filesystem), and writes it to the Pickup directory. No network communication takes place.
That is a bug in the Send routine - it creates an smtp server object even if one isn't specified, and when it later (after Send) tries to dispose it, it throws an exception. This happens AFTER the mail is successfully placed in the pickup directory, so the mail will be sent.
Workarounds:
Specify localhost as SMTP server. It won't be used, but prevents the exception.
A blind try/catch around the Send method (BAD solution).

Categories

Resources