SmtpClient超时不工作(SmtpClient Timeout doesn't wor

2019-06-24 05:03发布

我已经设置SmtpClient类的Timeout属性,但它似乎没有工作,当我给它一个1毫秒值,则执行代码时的超时实际上是15secs。 该代码我从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);

我试着单的实现,它也不起作用。

难道没有人遇到过同样的问题?

Answer 1:

再现测试 - 它为我工作

你问是否有人也遇到了同样的问题 - 我只是想你的代码在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 ,我没有得到超时错误unti L5S以后。

为什么Smtp.Timeout没有效果,如果连接无法进行

如果没有在听在端口25,或者主机不可达,超时不会发生,直到至少20秒,当system.net.tcpclient层超时。 这是下面system.net.mail层。 从描述问题和解决方案精彩文章 :

你会发现,无论是两类,System.Net.Sockets.TcpClient也不System.Net.Sockets.Socket有超时连接套接字。 我的意思是,你可以设置一个超时。 调用connect / BeginConnect方法时,同时建立一个同步/异步套接字连接.NET套接字不提供连接超时 。 取而代之的是,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.");
}


Answer 2:

添加到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
    }
}

该解决方案自带的权衡,你没有得到的task.Wait情况异常的详细信息,但也许这值得吗?



文章来源: SmtpClient Timeout doesn't work
标签: c# smtp timeout