SmtpClient超时不起作用

我已经设置了SmtpClient类的Timeout属性,但它似乎不起作用,当我给它一个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:\test\mailtimeout\Program.cs:line 29 

我认为问题可能是你期待与超时不同的东西。 超时意味着连接成功,但响应没有从服务器返回。 这意味着您需要实际让服务器侦听目的地的端口25,但它不响应。 对于这个测试,我使用Tcl在25上创建一个什么都不做的套接字:

 c:\> tclsh % socket -server foo 25 

当我将timout更改为15000 ,我没有在5天之后得到超时错误。

为什么如果无法建立连接,Smtp.Timeout无效

如果没有任何东西正在侦听端口25,或者主机无法访问,则在system.net.tcpclient层超时至少20 system.net.tcpclient时才会发生超时。 它位于system.net.mail层下面。 从描述问题和解决方案的优秀文章 :

您会注意到,System.Net.Sockets.TcpClient和System.Net.Sockets.Socket这两个类都没有超时来连接套接字。 我的意思是你可以设置超时。 在建立同步/异步套接字连接时调用Connect / BeginConnect方法时, .NET套接字不提供连接超时 。 相反,如果它尝试连接的服务器没有监听或者有任何网络错误,则在抛出exception之前强制连接等待很长时间。 默认超时为20 – 30秒

没有能力从邮件更改超时(这是有道理的,邮件服务器通常是up),实际上没有能力从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) 

然后在SendEmail()中:

 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 } } 

这个解决方案伴随着权衡,你没有得到任务中的exception细节。等等,但也许值得吗?