我已经设置了 SmtpClient 类的超时属性,但它似乎不起作用,当我给它一个 1 毫秒的值时,执行代码时超时实际上是 15 秒。我从 msdn 获取的代码。
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("1.2.3.4");
Console.WriteLine("Changing time out from {0} to 100.", client.Timeout);
client.Timeout = 1;
// 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;
client.Send(message);
我尝试了单声道的实现,它也不起作用。
有人遇到同样的问题吗?
重现您的测试 - 它对我有用
你问是否有人遇到过同样的问题 - 我刚刚在Windows 7,VS 2008和.NET 2.0上尝试了你的代码 - 它工作得很好。超时设置为 1
,就像您一样,我几乎立即收到此错误:
Unhandled Exception: System.Net.Mail.SmtpException: The operation has timed out
at System.Net.Mail.SmtpClient.Send(MailMessage message)
at mailtimeout.Program.Main(String[] args) in c:testmailtimeoutProgram.cs:line 29
我认为问题可能是您期望与超时不同的东西。超时意味着连接已成功建立,但响应未从服务器返回。这意味着您实际上需要有一个服务器侦听目的地的端口 25,但它没有响应。对于此测试,我使用 Tcl 在 25 上创建一个不执行任何操作的套接字:
c:> tclsh
% socket -server foo 25
当我将时序更改为 15000
时,我后来没有收到超时错误 l5s。
为什么 Smtp.Timeout 在无法建立连接时不起作用
如果端口 25 上没有侦听任何内容,或者无法访问主机,则至少要到 20 秒(system.net.tcpclient
层超时(才会发生超时。这低于system.net.mail
层。来自一篇描述问题和解决方案的优秀文章:
您会注意到,System.Net.Sockets.TcpClient 和 System.Net.Sockets.Socket 这两个类都没有连接套接字的超时。我的意思是您可以设置超时。.NET 套接字在建立同步/异步套接字连接时调用 Connect/BeginConnect 方法时不提供连接超时。相反,如果尝试连接的服务器未侦听或存在任何网络错误,则 connect 将强制等待很长时间,然后引发异常。默认超时为 20 - 30 秒。
无法更改邮件的超时(这是有道理的,邮件服务器通常会启动(,实际上无法从system.net.socket
更改连接,这真的很令人惊讶。但是,您可以执行异步连接,然后可以判断主机是否已启动以及端口是否已打开。从这个 MSDN 线程,特别是这篇文章,这段代码工作:
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IAsyncResult result = socket.BeginConnect("192.168.1.180", 25, null, null);
// Two second timeout
bool success = result.AsyncWaitHandle.WaitOne(2000, true);
if (!success) {
socket.Close();
throw new ApplicationException("Failed to connect server.");
}
除了 ckhan 的回答之外,我还想与您分享一个实现更短超时的建议:
var task = Task.Factory.StartNew(() => SendEmail(email));
if (!task.Wait(6000))
// error handling for timeout on TCP layer (but you don't get the exception object)
然后在发送电子邮件((:
using (var client = new SmtpClient(_serverCfg.Host, _serverCfg.Port))
{
try
{
client.Timeout = 5000; // shorter timeout than the task.Wait()
// ...
client.Send(msg);
}
catch (Exception ex)
{
// exception handling
}
}
此解决方案附带的权衡是,您不会在任务中获取异常详细信息。等等,但也许这是值得的?