我正在使用 C# 3.0 和System.DirectoryServices
命名空间(不是System.DirectoryServices.AccountManagement
.NET 3.5 的较新命名空间)。如何找到本地域中的所有 SMTP 服务器?这甚至可能吗?还有另一种方法可以做到这一点吗?
5 回答
我怀疑域服务器是否明确发布了它们是 SMTP 服务器的事实(我可能错了),尽管解决方案应该非常简单。
- 查找活动域中的每台服务器。
- 尝试通过端口 25 (SMTP) 连接到服务器。
- 等待
220
响应,这表明服务器已准备好。(有关协议,请参阅RFC 文档。)如果您在连接后的某个时间(例如 3 秒)内收到此命令,则可以断定当前计算机是 SMTP 服务器。
希望有帮助。
我不认为您可以使用 DirectoryServices 做到这一点。
一种选择是尝试通过 SMTP 端口 (25) 连接到域上的每个服务器,并查看它们是否响应标准 SMTP 命令。如果您有域中的机器列表,则可以使用 TcpClient 类轻松完成此操作。
当然,这不会找到不使用标准端口的服务器(但如果服务器不使用标准端口,它可能一开始就没有兴趣找到 :-)
根据 Noldorin 的建议,这里有一些代码,注意我只是在 25 上连接,我不是在等待来自服务器的 220。这适用于我们的域。这是基于 LDAP 路径获取服务器名称的残酷正则表达式。
static void Main()
{
DirectorySearcher ds = new DirectorySearcher("");
ds.Filter = "objectCategory=computer";
SearchResultCollection results = ds.FindAll();
foreach (SearchResult result in results)
{
string pattern = @"(?<=LDAP://CN=)(?<serverName>\w*)(?=,*)";
Match m = Regex.Match(result.Path, pattern);
string serverName = m.Groups["serverName"].Value;
System.Net.Sockets.TcpClient tcp = new System.Net.Sockets.TcpClient();
try
{
tcp.Connect(serverName, 25);
if (tcp.Connected)
{
Console.WriteLine(String.Format("Connected to {0} on Port 25", serverName));
}
}
catch (Exception ex)
{
Console.WriteLine("Exception: " + ex.Message);
}
finally
{
tcp.Close();
}
}
Console.WriteLine("Done.");
Console.ReadLine();
}
另外,我认为 FindAll 受到通常的 AD 约束,即 1000 results ,因此如果您的域中有超过 1000 台服务器,则可能需要返工
如果您想查找某个域的邮件服务器以便将邮件发送到该域,那么使用 DNS MX 是可行的方法,正如 mjmarh 已经建议的那样。如果您想使用 AD 识别域中的所有任意 SMTP 服务,那么您可以利用大多数 SMTP 服务器将在 AD 中注册自己的事实,例如 Exchange,您可以询问 AD 服务以找出它们的位置。例如,本白皮书解释了 Outlook 客户端如何使用 Active Directory 发现他们的邮箱服务器:http://technet.microsoft.com/en-us/library/bb332063.aspx 在某些域上,对所有机器进行端口扫描将点亮任何他们拥有像圣诞树一样的入侵检测机制,您最终可能会关闭您的应用程序网络地址。