Asp classic 在.net中获取imap未读电子邮件计数,而不使用臃肿的第三方LIB

Asp classic 在.net中获取imap未读电子邮件计数,而不使用臃肿的第三方LIB,asp-classic,asp.net,iis,php,c#,vb.net,imap,Asp Classic,Asp.net,Iis,Php,C#,Vb.net,Imap,背景: 我们有一个内部intranet系统,是用英文编写的,而且服务器还没有安装(看到了一些漂亮的php解决方案,例如,但我们不能真正使用它们。)我们需要向用户显示他们的imap邮箱中有多少未读的电子邮件。他们的imap邮箱位于运行postfix和dovecot imap的linux机箱内部 我的问题: 如何通过.net中的Dovecot Imap(vb或c#)连接到Postfix邮件系统并确定未读邮件的数量 我已经尝试过的: 我们使用了和以下内容: Imports System.Net.Sec

背景: 我们有一个内部intranet系统,是用英文编写的,而且服务器还没有安装(看到了一些漂亮的php解决方案,例如,但我们不能真正使用它们。)我们需要向用户显示他们的imap邮箱中有多少未读的电子邮件。他们的imap邮箱位于运行postfix和dovecot imap的linux机箱内部

我的问题: 如何通过.net中的Dovecot Imap(vb或c#)连接到Postfix邮件系统并确定未读邮件的数量

我已经尝试过的: 我们使用了和以下内容:

Imports System.Net.Security
Imports System
Imports Limilabs.Mail
Imports Limilabs.Client.IMAP
Imports Limilabs.Client

Function RetrieveUnread(_server, _user, _password)
    Using imap As New Limilabs.Client.IMAP.Imap
        '#### Handler needed because of self signed certificates
        RetrieveUnread = vbNull
        AddHandler imap.ServerCertificateValidate, AddressOf ValidateCertificate
        imap.ConnectSSL(_server)
        Try
            imap.Login(_user, _password)
        Catch ex As Exception
            RetrieveUnread = "Failed to login"
        End Try
        If CStr(RetrieveUnread) <> "Failed to login" Then
            imap.SelectInbox()
            Dim uids As List(Of Long) = imap.Search(Flag.Unseen)        'Find all unseen messages.
            'Console.WriteLine("Number of unseen messages is: " & CStr(uids.Count))
            RetrieveUnread = CStr(uids.Count)
        End If
        imap.Close()
    End Using
End Function

Private Sub ValidateCertificate(ByVal sender As Object, ByVal e As ServerCertificateValidateEventArgs)
    Const ignoredErrors As SslPolicyErrors = SslPolicyErrors.RemoteCertificateChainErrors Or SslPolicyErrors.RemoteCertificateNameMismatch        ' name mismatch
    Dim nameOnCertificate As String = e.Certificate.Subject
    If (e.SslPolicyErrors And Not ignoredErrors) = SslPolicyErrors.None Then
        e.IsValid = True
        Return
    End If
    e.IsValid = False
End Sub
导入System.Net.Security
导入系统
导入Limilabs.Mail
导入Limilabs.Client.IMAP
导入limilab.Client
函数检索未读(\u服务器、\u用户、\u密码)
将imap用作新的limilab.Client.imap.imap
“#####由于自签名证书,因此需要处理程序”
RetrieveUnread=vbNull
AddHandler imap.ServerCertificateValidate,ValidateCertificate的地址
imap.ConnectSSL(_服务器)
尝试
imap.Login(\u用户,\u密码)
特例
RetrieveUnread=“登录失败”
结束尝试
如果CStr(检索未读)“登录失败”,则
imap.SelectInbox()
Dim uids As List(长)=imap.Search(Flag.Unseen)'查找所有未查看的邮件。
'Console.WriteLine(“看不见的消息数为:”&CStr(uids.Count))
RetrieveUnread=CStr(uids.Count)
如果结束
imap.Close()
终端使用
端函数
私有子ValidateCertificate(ByVal发送方作为对象,ByVal e作为服务器CertificateValidateEventArgs)
常量IgnoreErrors为SslPolicyErrors=SslPolicyErrors.RemoteCertificateChainErrors或SslPolicyErrors.RemoteCertificateNameMismatch的名称不匹配
Dim NAME证书作为字符串=e.Certificate.Subject
如果(如SslPolicyErrors和Not IgnoreErrors)=SslPolicyErrors.None,则
e、 IsValid=True
返回
如果结束
e、 IsValid=False
端接头

然而,虽然这是可行的,但这种方法依赖于第三方,如果许可证不到位/最新,DLL将失败&对于我们需要做的事情来说,DLL严重膨胀。我们只是想知道这是否可以在本机.net代码中实现。

您不需要第三方dll;简单一点就行了

您只需向服务器发送正确的IMAP命令,并用正则表达式解析结果即可


LINQPad就绪示例:

Sub Main()
    Dim client = New System.Net.Sockets.TcpClient("hostname", 143)
    Using s = client.GetStream(), 
        reader = New StreamReader(s),
        writer = New StreamWriter(s)

            Dim send As Action(Of String) = Sub(command) 
                writer.WriteLine(command)
                writer.Flush()
            End Sub

            Dim recieve As Func(Of String, String) = Function(tag) 
                Dim response As String
                Dim str As String = ""
                response = reader.ReadLine()
                While response IsNot Nothing
                    str += response
                    If response.StartsWith(tag, StringComparison.Ordinal) Then
                        Exit While
                    End If
                    response = reader.ReadLine()
                End While
                Return str
            End Function

            send("a login username password"): recieve("a")
            send("b select inbox"): recieve("b")

            send("b2 SEARCH UNSEEN")
            Dim b2response = recieve("b2")
            Dim items = Regex.Match(b2response, "SEARCH (.*) OK").Groups(1).Value.Split(" "c)
            Console.WriteLine("Unread items: " + items.Count().ToString())

            send("c logout"): recieve("c")
    End Using
End Sub

void Main()
{
var client=new System.Net.Sockets.TcpClient(“主机名”,143);
使用(var s=client.GetStream())
使用(变量读取器=新的流读取器))
使用(var编写器=新的StreamWriter)
{
操作发送=(命令)=>
{
writer.WriteLine(命令);
writer.Flush();
};
Func receive=(标记)=>
{
字符串响应;
字符串str=“”;
而((response=reader.ReadLine())!=null)
{
str+=反应;
if(response.StartsWith(tag,StringComparison.Ordinal))
打破
}
返回str;
};
发送(“登录用户名密码”);接收(“a”);
发送(“b选择收件箱”);接收(“b”);
发送(“b2搜索不可见”);
风险值b2response=接收(“b2”);
var items=Regex.Match(b2response,@“SEARCH(.*)OK”).Groups[1]。Value.Split(“”);
Console.WriteLine(“未读项目:+items.Count().ToString());
发送(“c注销”);接收(“c”);
}
}

如果要使用SSL,则必须先将流
s
封装在一个and调用中(可能使用端口993)。

最近的
可能不是特别有用,尤其是当其他连接正在访问他们的邮件时。您可以执行
搜索未读
,并计算响应,这可能更接近OP想要的内容。@Max我认为它是
搜索未读
,而不是
搜索未读
。否则,你是对的。我不记得我是否给了你否决票;但是,我不建议OP从头开始编写IMAP客户机。协议中有很多微妙之处。仅获取一个计数就足够了,但要做得更多可能非常困难。@Max OP明确地询问了如何在没有第三方库的情况下确定未读项目的数量。我们决定采用PHP方法来实现这一点,这要容易得多。不管怎样,只要逻辑合理,就把你的帖子标记为答案——不明白为什么会被否决:s
void Main()
{
    var client = new System.Net.Sockets.TcpClient("hostname", 143);
    using (var s = client.GetStream())
    using (var reader = new StreamReader(s))
    using (var writer = new StreamWriter(s))
    {
        Action<string> send = (command) => 
        {
            writer.WriteLine(command);
            writer.Flush();
        };

        Func<String, String> recieve = (tag) =>
        {
            string response;
            string str="";
            while ((response = reader.ReadLine()) != null ) 
            {
                str+=response;
                if (response.StartsWith(tag, StringComparison.Ordinal))
                    break;
            }
            return str;
        };

        send("a login username password"); recieve("a");
        send("b select inbox"); recieve("b");

        send("b2 SEARCH UNSEEN");
        var b2response = recieve("b2");
        var items = Regex.Match(b2response, @"SEARCH (.*) OK").Groups[1].Value.Split(' ');
        Console.WriteLine("Unread items: " + items.Count().ToString());

        send("c logout"); recieve("c");
    }
}