SmtpClient超时不起作用

cro*_*arp 9 c# timeout smtp

我已经设置了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);
Run Code Online (Sandbox Code Playgroud)

我试过单声道的实现,它也行不通.

有人遇到过同样的问题吗?

ckh*_*han 16

再现你的测试 - 它对我有用

你问过是否有人遇到过同样的问题 - 我刚刚在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
Run Code Online (Sandbox Code Playgroud)

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

c:\> tclsh
% socket -server foo 25
Run Code Online (Sandbox Code Playgroud)

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

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

如果没有任何东西正在侦听端口25,或者主机无法访问,则超时不会发生,直到至少20秒,此时system.net.tcpclient图层超时.这是在system.net.mail图层下面.从描述问题和解决方案优秀文章:

您会注意到,System.Net.Sockets.TcpClient和System.Net.Sockets.Socket这两个类都没有连接套接字的超时.我的意思是你可以设置超时.在建立同步/异步套接字连接时调用Connect/BeginConnect方法时,.NET套接字不提供连接超时.相反,如果它尝试连接的服务器没有监听或者有任何网络错误,则在抛出异常之前,连接会被迫等待很长时间.默认超时为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.");
}
Run Code Online (Sandbox Code Playgroud)