Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/295.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 测试SMTP服务器正在通过C运行#_C#_Smtp - Fatal编程技术网

C# 测试SMTP服务器正在通过C运行#

C# 测试SMTP服务器正在通过C运行#,c#,smtp,C#,Smtp,如何在不发送消息的情况下通过C#测试SMTP是否已启动并运行 我当然可以尝试: try{ // send email to "nonsense@example.com" } catch { // log "smtp is down" } 必须有一个更整洁的方法来做到这一点 您可以使用套接字或TcpClient打开端口(25),然后查看它是否响应。在端口25上打开到smtp服务器的套接字连接,然后查看是否有任何结果。如果没有,则没有smtp服务器。您可以尝试访问您的服务器,看看它是否响应250

如何在不发送消息的情况下通过C#测试SMTP是否已启动并运行

我当然可以尝试:

try{
// send email to "nonsense@example.com"
}
catch
{
// log "smtp is down"
}

必须有一个更整洁的方法来做到这一点

您可以使用套接字或
TcpClient打开端口(25),然后查看它是否响应。

在端口25上打开到smtp服务器的套接字连接,然后查看是否有任何结果。如果没有,则没有smtp服务器。

您可以尝试访问您的服务器,看看它是否响应
250 OK
。当然,这个测试不能保证你以后会成功发送邮件,但它是一个很好的指示

下面是一个示例:

class Program
{
    static void Main(string[] args)
    {
        using (var client = new TcpClient())
        {
            var server = "smtp.gmail.com";
            var port = 465;
            client.Connect(server, port);
            // As GMail requires SSL we should use SslStream
            // If your SMTP server doesn't support SSL you can
            // work directly with the underlying stream
            using (var stream = client.GetStream())
            using (var sslStream = new SslStream(stream))
            {
                sslStream.AuthenticateAsClient(server);
                using (var writer = new StreamWriter(sslStream))
                using (var reader = new StreamReader(sslStream))
                {
                    writer.WriteLine("EHLO " + server);
                    writer.Flush();
                    Console.WriteLine(reader.ReadLine());
                    // GMail responds with: 220 mx.google.com ESMTP
                }
            }
        }
    }
}

这是我们所期待的。

这是一个不错的开源工具(比MX做得更多):

我使用此方法和类来验证凭据():

SmtpConnectorBase:

internal abstract class SmtpConnectorBase {
    protected string SmtpServerAddress { get; set; }
    protected int Port { get; set; }
    public const string EOF = "\r\n";

    protected SmtpConnectorBase(string smtpServerAddress, int port) {
        SmtpServerAddress = smtpServerAddress;
        Port = port;
    }

    public abstract bool CheckResponse(int expectedCode);
    public abstract void SendData(string data);
}
SMTPConnector不带SL:

internal class SmtpConnectorWithoutSsl : SmtpConnectorBase {
    private Socket _socket = null;

    public SmtpConnectorWithoutSsl(string smtpServerAddress, int port) : base(smtpServerAddress, port) {
        IPHostEntry hostEntry = Dns.GetHostEntry(smtpServerAddress);
        IPEndPoint endPoint = new IPEndPoint(hostEntry.AddressList[0], port);
        _socket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
        //try to connect and test the rsponse for code 220 = success
        _socket.Connect(endPoint);

    }

    ~SmtpConnectorWithoutSsl() {
        try {
            if (_socket != null) {
                _socket.Close();
                _socket.Dispose();
                _socket = null;
            }
        } catch (Exception) {
            ;
        }

    }

    public override bool CheckResponse(int expectedCode) {
        while (_socket.Available == 0) {
            System.Threading.Thread.Sleep(100);
        }
        byte[] responseArray = new byte[1024];
        _socket.Receive(responseArray, 0, _socket.Available, SocketFlags.None);
        string responseData = Encoding.UTF8.GetString(responseArray);
        int responseCode = Convert.ToInt32(responseData.Substring(0, 3));
        if (responseCode == expectedCode) {
            return true;
        }
        return false;
    }

    public override void SendData(string data) {
        byte[] dataArray = Encoding.UTF8.GetBytes(data);
        _socket.Send(dataArray, 0, dataArray.Length, SocketFlags.None);
    }
}
SMTPConnectorWithSL:

internal class SmtpConnectorWithSsl : SmtpConnectorBase {
    private SslStream _sslStream = null;
    private TcpClient _client = null;

    public SmtpConnectorWithSsl(string smtpServerAddress, int port) : base(smtpServerAddress, port) {
        TcpClient client = new TcpClient(smtpServerAddress, port);

        _sslStream = new SslStream(
            client.GetStream(),
            false,
            new RemoteCertificateValidationCallback(ValidateServerCertificate),
            null
            );
        // The server name must match the name on the server certificate.
        try {
            _sslStream.AuthenticateAsClient(smtpServerAddress);
        } catch (AuthenticationException e) {
            _sslStream = null;
            Console.WriteLine("Exception: {0}", e.Message);
            if (e.InnerException != null) {
                Console.WriteLine("Inner exception: {0}", e.InnerException.Message);
            }
            Console.WriteLine("Authentication failed - closing the connection.");
            client.Close();
        }
    }

    ~SmtpConnectorWithSsl() {
        try {
            if (_sslStream != null) {
                _sslStream.Close();
                _sslStream.Dispose();
                _sslStream = null;
            }
        } catch (Exception) {
            ;
        }

        try {
            if (_client != null) {
                _client.Close();
                _client = null;
            }
        } catch (Exception) {
            ;
        }
    }

    // The following method is invoked by the RemoteCertificateValidationDelegate.
    private static bool ValidateServerCertificate(
          object sender,
          X509Certificate certificate,
          X509Chain chain,
          SslPolicyErrors sslPolicyErrors) {
        if (sslPolicyErrors == SslPolicyErrors.None)
            return true;

        Console.WriteLine("Certificate error: {0}", sslPolicyErrors);

        // Do not allow this client to communicate with unauthenticated servers.
        return false;
    }

    public override bool CheckResponse(int expectedCode) {
        if (_sslStream == null) {
            return false;
        }
        var message = ReadMessageFromStream(_sslStream);
        int responseCode = Convert.ToInt32(message.Substring(0, 3));
        if (responseCode == expectedCode) {
            return true;
        }
        return false;
    }

    public override void SendData(string data) {
        byte[] messsage = Encoding.UTF8.GetBytes(data);
        // Send hello message to the server. 
        _sslStream.Write(messsage);
        _sslStream.Flush();
    }

    private string ReadMessageFromStream(SslStream stream) {
        byte[] buffer = new byte[2048];
        StringBuilder messageData = new StringBuilder();
        int bytes = -1;
        do {
            bytes = stream.Read(buffer, 0, buffer.Length);

            // Use Decoder class to convert from bytes to UTF8
            // in case a character spans two buffers.
            Decoder decoder = Encoding.UTF8.GetDecoder();
            char[] chars = new char[decoder.GetCharCount(buffer, 0, bytes)];
            decoder.GetChars(buffer, 0, bytes, chars, 0);
            messageData.Append(chars);
            // Check for EOF.
            if (messageData.ToString().IndexOf(EOF) != -1) {
                break;
            }
        } while (bytes != 0);

        return messageData.ToString();
    }
}

喜欢它-非常喜欢它!好的,达林@达林·迪米特洛夫·坦克斯,谢谢你的回答。。是否仍然需要检查用户名和密码(smtp身份验证)是否有效?我在……里问过。。请帮忙,这似乎不够。要正确测试SMTP设置,您至少应该使用一些外部电子邮件地址(例如
postmaster@example.com
),但在发送
数据之前先退出。这将实际测试您是否具有中继权限,实际上是验证您的用户名/密码和/或客户端证书。SMTPConnector WithoutsSL中存在无限循环。在CheckResponse方法中,行while(_socket.Available==0)应该有一个限制。我遇到了一个场景,其中_socket.Available永远不会等于0以外的任何值。但是,除此之外,这是完美的。已经使用了大约6个月,没有问题。@Samidjo我不确定您在哪里看到该变体,但我在产生无限循环的代码中没有看到它。在我的手机上写这封信。如果100是默认值,根据我的记忆,它不会停在100。在我的用例中是无限循环。@Samidjo我的建议是尝试一下。将我声明的行设置为always=0,然后打印一个计数。“我敢打赌它会超过100。”Heribertolougo接受新版本,上面是一个旧版本。转到git存储库,您将看到变量MAX\u ATTEMPTS\u COUNT。@Samidjo不确定您为什么删除了其他注释,看起来我在自言自语。代码并不重要。这是几年前的事了,我已经在需要的地方修好了。无需将代码更改为新代码。它起作用了,小问题也解决了。我发表评论是为了给其他人一个机会,他们可能会像我一样从这里获取代码。
internal class SmtpConnectorWithSsl : SmtpConnectorBase {
    private SslStream _sslStream = null;
    private TcpClient _client = null;

    public SmtpConnectorWithSsl(string smtpServerAddress, int port) : base(smtpServerAddress, port) {
        TcpClient client = new TcpClient(smtpServerAddress, port);

        _sslStream = new SslStream(
            client.GetStream(),
            false,
            new RemoteCertificateValidationCallback(ValidateServerCertificate),
            null
            );
        // The server name must match the name on the server certificate.
        try {
            _sslStream.AuthenticateAsClient(smtpServerAddress);
        } catch (AuthenticationException e) {
            _sslStream = null;
            Console.WriteLine("Exception: {0}", e.Message);
            if (e.InnerException != null) {
                Console.WriteLine("Inner exception: {0}", e.InnerException.Message);
            }
            Console.WriteLine("Authentication failed - closing the connection.");
            client.Close();
        }
    }

    ~SmtpConnectorWithSsl() {
        try {
            if (_sslStream != null) {
                _sslStream.Close();
                _sslStream.Dispose();
                _sslStream = null;
            }
        } catch (Exception) {
            ;
        }

        try {
            if (_client != null) {
                _client.Close();
                _client = null;
            }
        } catch (Exception) {
            ;
        }
    }

    // The following method is invoked by the RemoteCertificateValidationDelegate.
    private static bool ValidateServerCertificate(
          object sender,
          X509Certificate certificate,
          X509Chain chain,
          SslPolicyErrors sslPolicyErrors) {
        if (sslPolicyErrors == SslPolicyErrors.None)
            return true;

        Console.WriteLine("Certificate error: {0}", sslPolicyErrors);

        // Do not allow this client to communicate with unauthenticated servers.
        return false;
    }

    public override bool CheckResponse(int expectedCode) {
        if (_sslStream == null) {
            return false;
        }
        var message = ReadMessageFromStream(_sslStream);
        int responseCode = Convert.ToInt32(message.Substring(0, 3));
        if (responseCode == expectedCode) {
            return true;
        }
        return false;
    }

    public override void SendData(string data) {
        byte[] messsage = Encoding.UTF8.GetBytes(data);
        // Send hello message to the server. 
        _sslStream.Write(messsage);
        _sslStream.Flush();
    }

    private string ReadMessageFromStream(SslStream stream) {
        byte[] buffer = new byte[2048];
        StringBuilder messageData = new StringBuilder();
        int bytes = -1;
        do {
            bytes = stream.Read(buffer, 0, buffer.Length);

            // Use Decoder class to convert from bytes to UTF8
            // in case a character spans two buffers.
            Decoder decoder = Encoding.UTF8.GetDecoder();
            char[] chars = new char[decoder.GetCharCount(buffer, 0, bytes)];
            decoder.GetChars(buffer, 0, bytes, chars, 0);
            messageData.Append(chars);
            // Check for EOF.
            if (messageData.ToString().IndexOf(EOF) != -1) {
                break;
            }
        } while (bytes != 0);

        return messageData.ToString();
    }
}