2012-10-04 50 views
2

背景: 我們已經寫在的內部網系統 - 可是沒有安裝服務器(看在PHP一些漂亮的解決方案,如this但我們無法真正使用這些) - 我們需要向用戶展示他們在他們的imap郵箱中有多少封未讀郵件。他們的imap郵箱在內部託管在運行postfix和dovecot imap的Linux機器上。獲取.NET IMAP未讀電子郵件計數,而臃腫的第三方庫

我的問題: 如何將一個通過達夫科特連接的imap到Postfix郵件系統在.NET(VB或C#),並確定未讀郵件的數量?

我已經嘗試過: 我們使用Limilabs mail dll及以下:

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 

然而,儘管這個作品,這個方法是受一個第三方的依賴,DLL將失敗許可不到位/最新&因我們需要做的事情而臃腫不堪。我們只是好奇,如果這可以在本地.NET代碼完成。

回答

2

你不需要第三方DLL;一個簡單的TcpClient會做。

您可以將正確的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("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"); 
    } 
} 

如果你想使用SSL,你必須換流sSslStream並調用AuthenticateAsClient第一(和可能使用端口993)。

+0

''RECENT''可能不是特別有用,特別是當他們的郵件被其他連接訪問時。你可以做一個'SEARCH UNREAD',並計算響應,這可能更接近OP的要求。 – Max

+0

@Max我認爲它是'SEARCH UNSEEN'而不是'SEARCH UNREAD'。否則,你是對的。 – sloth

+0

你是對的,對不起:) – Max