5

Ich versuche, einen Dienst zu erstellen, Exchange-Benachrichtigungen zu asp.net-Anwendungen zu schieben, schließlich SignalR verwenden.EWS Notification Hub für mehrere Benutzer

Mein Plan ist es, einen Benachrichtigungs-Hub zu erstellen, der jeden Benutzer bei der Anmeldung bei der ASP-Anwendung abonniert und auf Benachrichtigungen für sie wartet. Wenn eine Benachrichtigung empfangen wird, soll der zweite Teil des Projekts dann signalR verwenden, um nur die korrekten Benachrichtigungen an jeden Benutzer zu senden. Sobald sie sich abgemeldet haben oder eine Zeitüberschreitung haben, wird der Benachrichtigungs-Hub sie abbestellen.

Bisher habe ich ein wenig grundlegende Tests gemacht und kann Benachrichtigungen in einer kleinen Konsole App für mich mit meinen Anmeldeinformationen hart codiert erhalten. Womit ich kämpfe ist, wie man das für mehrere Menschen gleichzeitig macht. Zum Beispiel müsste ich für jeden Benutzer separate Threads erstellen oder gibt es einen besseren Weg?

Ich denke, unabhängig davon werde ich Identitätswechsel verwenden, anstatt die Berechtigungen jedes Benutzers richtig zu halten? Ich werde auch eine Möglichkeit finden, das Timeout für jeden Benutzer automatisch zu aktualisieren, wenn sie eine aktive Sitzung haben.

Unten ist ein kleiner Code, den ich gefunden habe und mit dem ich gespielt habe. Ich wäre dankbar für irgendwelche Ideen oder Beispiele, die jeder teilen könnte, wie ich das am besten erreichen könnte.

Vielen Dank

Andy

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Net; 
using System.Threading.Tasks; 
using Microsoft.Exchange.WebServices.Data; 

namespace ConsoleApplication1 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 

       ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2010_SP2); 
       service.Url = new Uri("https://server/EWS/Exchange.asmx"); 
       service.Credentials = new NetworkCredential("user", "pass", "domain"); 
       SetStreamingNotifications(service); 
       while (true) 
       { } 


     } 

     static void SetStreamingNotifications(ExchangeService service) 
     { 
      // Subscribe to streaming notifications on the Inbox folder, and listen 
      // for "NewMail", "Created", and "Deleted" events. 
      StreamingSubscription streamingsubscription = service.SubscribeToStreamingNotifications(
       new FolderId[] { WellKnownFolderName.Calendar, WellKnownFolderName.Inbox }, 
       EventType.Created, 
       EventType.Modified); 

      StreamingSubscriptionConnection connection = new StreamingSubscriptionConnection(service, 9); 

      connection.AddSubscription(streamingsubscription); 
      // Delegate event handlers. 
      connection.OnNotificationEvent += 
       new StreamingSubscriptionConnection.NotificationEventDelegate(OnEvent); 
      connection.OnSubscriptionError += 
       new StreamingSubscriptionConnection.SubscriptionErrorDelegate(OnError); 
      connection.OnDisconnect += 
       new StreamingSubscriptionConnection.SubscriptionErrorDelegate(OnDisconnect); 
      connection.Open(); 

      Console.WriteLine("--------- StreamSubscription event -------"); 
     } 

     static private void OnDisconnect(object sender, SubscriptionErrorEventArgs args) 
     { 
      // Cast the sender as a StreamingSubscriptionConnection object.   
      StreamingSubscriptionConnection connection = (StreamingSubscriptionConnection)sender; 
      // Ask the user if they want to reconnect or close the subscription. 
      ConsoleKeyInfo cki; 
      Console.WriteLine("The connection to the subscription is disconnected."); 
      Console.WriteLine("Do you want to reconnect to the subscription? Y/N"); 
      while (true) 
      { 
       cki = Console.ReadKey(true); 
       { 
        if (cki.Key == ConsoleKey.Y) 
        { 
         connection.Open(); 
         Console.WriteLine("Connection open."); 
         break; 
        } 
        else if (cki.Key == ConsoleKey.N) 
        { 
         // The ReadKey in the Main() consumes the E. 
         Console.WriteLine("\n\nPress E to exit"); 
         break; 
        } 
       } 
      } 
     } 

     static void OnEvent(object sender, NotificationEventArgs args) 
     { 
      StreamingSubscription subscription = args.Subscription; 

      // Loop through all item-related events. 
      foreach (NotificationEvent notification in args.Events) 
      { 

       switch (notification.EventType) 
       { 
        case EventType.NewMail: 
         Console.WriteLine("\n-------------Mail created:-------------"); 
         break; 
        case EventType.Created: 
         Console.WriteLine("\n-------------Item or folder created:-------------"); 
         break; 
        case EventType.Deleted: 
         Console.WriteLine("\n-------------Item or folder deleted:-------------"); 
         break; 
       } 
       // Display the notification identifier. 
       if (notification is ItemEvent) 
       { 
        // The NotificationEvent for an e-mail message is an ItemEvent. 
        ItemEvent itemEvent = (ItemEvent)notification; 
        Console.WriteLine("\nItemId: " + itemEvent.ItemId.UniqueId); 

       } 
       else 
       { 
        // The NotificationEvent for a folder is an FolderEvent. 
        //FolderEvent folderEvent = (FolderEvent)notification; 
        //Console.WriteLine("\nFolderId: " + folderEvent.FolderId.UniqueId); 
       } 
      } 
     } 
     static void OnError(object sender, SubscriptionErrorEventArgs args) 
     { 
      // Handle error conditions. 
      Exception e = args.Exception; 
      Console.WriteLine("\n-------------Error ---" + e.Message + "-------------"); 
     } 
    } 
} 

Antwort

3

So wie ich dieses Problem gelöst ist durch:

  1. ein Konto zu haben, das das Recht, alle Benutzer zu verkörpern hat.
  2. Ich erstelle einen Dienst für dieses Konto mit einem Benutzernamen und Passwort.
  3. ich imitieren einen Benutzer und fügen Sie das Abonnement des Benutzers an die Verbindung
  4. ich erstellen Sie einen anderen Dienst, der mit die gleichen Benutzernamen und das Passwort ein enger für die Hauptleistung ist, die einen anderen Benutzer ausgeben und dann hinzufügen das Abonnement für die gleiche Verbindung vor

Hier sind zwei Teile meines Codes. Vergiss das LogDevice, es ist nur etwas internes. Der erste Teil ist der detaillierte Identitätswechsel und Hinzufügen des Dienstes zur Liste der Dienste die Liste der Dienste in meinem Fall ist ein Wörterbuch mit dem BenutzerSMTP ist der Schlüssel, der UserSMTP-Schlüssel ist hier das imitierte Konto.

/// <summary> 
    /// Impersonate one user at a time and without using the autodiscovery method to find the proper url for the userSmtp, 
    /// and copy the provided url to the usersmtp. 
    /// </summary> 
    /// <param name="url"> </param> 
    /// <param name="userSmtp">user smtp</param> 
    /// <param name="enableTrace">to enable logging from the XML tracing </param> 
    /// <param name="exchangeVersion">Exchange server version used</param> 
    private Uri ImpersonateUser(Uri url, string userSmtp, bool enableTrace, ExchangeVersion exchangeVersion) 
    { 
     Uri result = url; 
     var log = "ImpersonateUser \n"; 
     try 
     { 
      log += "0/8 Checking services redundancy\n"; 
      if (Services.ContainsKey(userSmtp)) 
      { 
       Services.Remove(userSmtp); 
      } 
      log += "1/8 Create a new service for " + userSmtp + "\n"; 
      var service = new ExchangeService(exchangeVersion); 

      log += "2/8 Get credentials for the service\n"; 
      var serviceCred = ((System.Net.NetworkCredential)(((WebCredentials)(Services.First().Value.Credentials)).Credentials)); 

      log += "3/8 Assign credentials to the new service\n"; 
      service.Credentials = new WebCredentials(serviceCred.UserName, serviceCred.Password); 

      log += "4/8 TraceEnabled is" + enableTrace.ToString() + "\n"; 
      service.TraceEnabled = enableTrace; 

      log += "5/8 Get the Url for the service with AutodiscoverUrl \n"; 
      service.Url = url; 

      log += "6/8 Assign a new ImpersonatedUserId to the new service for" + userSmtp + "\n"; 
      service.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress, userSmtp); 

      try 
      { 
       log += "7/8 Validating the impersonation\n"; 
       RuleCollection rulecoll = service.GetInboxRules(); 
      } 
      catch (Exception ex) 
      { 
       _logDevice.LogSrvMessage(1, "ExchangeLiteService: ImpersonateUser: failed to validate the impersonation for {0}\n Exception: {1}\n", userSmtp, ex.Message); 
       int hr = System.Runtime.InteropServices.Marshal.GetHRForException(ex); 

       if (hr == -2146233088) // We do not have right to impersonate this user. 
       { 
        result = null; 
        return result; 
       } 
       else 
       { 
        _logDevice.LogSrvMessage(1, "ExchangeLiteService: ImpersonateUser(2): trying to resolve {0} with Autodiscover instead...", userSmtp); 
        result = ImpersonateUser(userSmtp, enableTrace, exchangeVersion); 
       } 

      } 

      log += "8/8 Adding the service \n"; 
      if (!Services.ContainsKey(userSmtp)) 
      { 
       Services.Add(userSmtp, service); 
       _logDevice.LogSrvMessage(1, "ExchangeLiteService: ImpersonateUser(2): {0} has been impersonated\n", service.ImpersonatedUserId.Id); 
      } 
     } 
     catch (Exception ex) 
     { 
      _logDevice.LogSrvMessage(1, "ExchangeLiteService: ImpersonateUser(2): exception {0}\n The exception occured after the following steps: \n{1}", ex.Message, log); 
     } 
     return result; 
    } 

Und hier ist der Code, der die vorherige Funktion (das heißt für alle Benutzer) daran setzen Anrufe, die Sie irgendwie die E-Mail-Adresse zu speichern sollte für jedes Konto, das Sie ausgeben möchten.

/// <summary> 
     /// To Impersonate users in order to get the info from them. 
     /// </summary> 
     /// <param name="userSmtps">List of users to be impersonated</param> 
     /// <param name="enableTrace"> To enable logging from the XML tracing</param> 
     /// <param name="exchangeVersion">Exchange server version used </param> 
     public void ImpersonateUsers(ICollection<string> userSmtps) 
     { 
      var log = "ImpersonateUsers\n"; 
      var firstUserSmtp = ""; 
      if (userSmtps != null) 

       if (userSmtps.Count > 0) 
       { 

        //the url for the first smtp 
        try 
        { 
         log += "1/2 Impersonating the first userSmtp\n"; 
         _logDevice.LogSrvMessage(1, "ExchangeLiteService: ImpersonateUsers: Getting the Url from the autodiscovery for the first smtp {0} ", userSmtps.First()); 
         bool enableTrace = Services.First().Value.TraceEnabled; 

         ExchangeVersion exchangeVersion = Services.First().Value.RequestedServerVersion; 
         firstUserSmtp = userSmtps.First(); 
         var commonSmtpUrl = ImpersonateUser(userSmtps.First(), enableTrace, exchangeVersion); 
         if (commonSmtpUrl == null) userSmtps.Remove(firstUserSmtp); 
         // If the list contains other than the first one 
         log += "2/2 Impersonating " + (userSmtps.Count - 1) + " userSmtps\n"; 

         if (userSmtps.Count >= 1) 
         { 
          foreach (var userSmtp in userSmtps) 
          { 
           try 
           { //skip ther first one because it is already impersonated. 
            if (userSmtp == firstUserSmtp) 
            { 
             continue; 
            } 
            // Impersonate the users 
            _logDevice.LogSrvMessage(1, "ExchangeLiteService: ImpersonateUsers: Impersonating {0} ...", userSmtp); 

             commonSmtpUrl = ImpersonateUser(userSmtp, enableTrace, exchangeVersion); 

           } 
           catch (Exception ex) 
           { 
            _logDevice.LogSrvMessage(1, "ExchangeLiteService: ImpersonateUsers: Impersonating {1}\n exception {0}\n", ex.Message, userSmtp); 
           } 
          } 
         } 
        } 
        catch (Exception ex) 
        { 
         _logDevice.LogSrvMessage(1, "ExchangeLiteService: ImpersonateUsers: exception {0}\n The exception occured after the following steps: \n{1}", ex.Message, log); 
        } 
       } 
     } 

Ich hätte das Abonnement Teil und Hinzufügen der Verbindung, aber es ist ein bisschen hässlich und schwer zu bekommen. aber die Idee ist einfach, dass Sie eine Verbindung haben sollten, und dann gehen Sie zu jedem Dienst, den Sie gemacht haben und dann `connection.AddSubscription (streamingSubscription); Wo streamingSubscription aus dem Dienst extrahiert wird.

+0

Danke das ist großartig! Kannst du ein wenig ausarbeiten ...So bekomme ich den Identitätswechsel-Plan auf die Art und Weise, wie Sie die Anmeldeinformationen für das "Anwendungskonto" fest codieren und das E-Mail-Konto weitergeben, das Sie sich ausgeben. Wie gehen Sie mit der Erstellung der 2., 3., 100. Verbindung um? Werden alle Abonnements als Teil von 1 Verbindung beendet? Vielen Dank, Andy – mcinnes01

+0

ja du hast es richtig gemacht, alle Abos gehen auf die selbe Verbindung, ich habe die Antwort modifiziert und Teile meines Codes eingefügt. Ich habe den Code der Verbindungen nicht angegeben, weil es hässlich ist: D ich habe jedenfalls beschrieben, wie ich darüber dachte. WARNUNG, ich weiß nicht, ob dies der empfohlene Weg ist oder wie sicher es ist, aber zumindest funktioniert es und erledigt die Arbeit. – BraveHeart

+0

Danke BraveHeart, das ist großartig. Ich muss ein Identitätswechsel-Konto einrichten, also werde ich es versuchen und es Ihnen mitteilen, sobald ich es getan habe. – mcinnes01