EWS API多流订阅场景下如何识别日历变更事件对应的SMTP账号
问题根因
你复用了同一个ExchangeService实例创建多个订阅,每次修改ImpersonatedUserId属性都会覆盖实例内的存储值,两个StreamingSubscriptionConnection关联的都是同一个service实例,最终保存的是最后设置的user2@mydomain.com,事件触发时读取到的自然都是同一个ID。
解决方案
方案1:每个账号创建独立的ExchangeService实例(最稳妥)
不要共享service实例,每个订阅账号单独初始化自己的service,保证每个connection绑定的service的模拟账号互不影响,修改后代码如下:
static bool isRunning = true; static void Main(string[] args) { // user1单独初始化service var service1 = EWService(); service1.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress, "user1@mydomain.com"); var StreamingSubscription1 = service1.SubscribeToStreamingNotifications( new FolderId[] { WellKnownFolderName.Calendar }, EventType.FreeBusyChanged); StreamingSubscriptionConnection connection1 = new StreamingSubscriptionConnection(service1, 30); connection1.AddSubscription(StreamingSubscription1); connection1.OnNotificationEvent += OnNotificationEvent; connection1.OnDisconnect += OnDisconnect; connection1.OnSubscriptionError += OnSubscriptionError; connection1.Open(); // user2单独初始化service var service2 = EWService(); service2.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress, "user2@mydomain.com"); var StreamingSubscription2 = service2.SubscribeToStreamingNotifications( new FolderId[] { WellKnownFolderName.Calendar }, EventType.FreeBusyChanged); StreamingSubscriptionConnection connection2 = new StreamingSubscriptionConnection(service2, 30); connection2.AddSubscription(StreamingSubscription2); connection2.OnNotificationEvent += OnNotificationEvent; connection2.OnDisconnect += OnDisconnect; connection2.OnSubscriptionError += OnSubscriptionError; connection2.Open(); Console.WriteLine("Waiting..."); while (isRunning) { Thread.Sleep(1000); // 避免空转占用CPU } StreamingSubscription1.Unsubscribe(); connection1.Close(); StreamingSubscription2.Unsubscribe(); connection2.Close(); } private static void OnNotificationEvent(object sender, NotificationEventArgs args) { // 直接从当前connection关联的service取模拟账号,不同实例互不影响 var connection = (StreamingSubscriptionConnection)sender; var userSmtp = connection.CurrentSubscriptions.First().Service.ImpersonatedUserId.Id; Console.WriteLine($"Event for: {userSmtp} "); foreach (var item in args.Events) { Console.WriteLine(item.EventType); if (item.EventType == EventType.FreeBusyChanged) { Console.WriteLine(((ItemEvent)item).ItemId); } } }
方案2:字典映射订阅ID和账号(无需创建多个service实例)
如果你不想为每个账号创建独立service,可以提前把每个订阅的唯一ID和对应SMTP账号存储在全局字典中,事件触发时通过订阅ID查询字典即可获取对应账号:
static bool isRunning = true; // 全局字典存储:订阅ID -> 对应SMTP账号 static Dictionary<string, string> SubscriptionAccountMap = new Dictionary<string, string>(); static void Main(string[] args) { var service = EWService(); service.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress, "user1@mydomain.com"); var StreamingSubscription = service.SubscribeToStreamingNotifications( new FolderId[] { WellKnownFolderName.Calendar }, EventType.FreeBusyChanged); // 存入映射关系 SubscriptionAccountMap.Add(StreamingSubscription.Id, "user1@mydomain.com"); StreamingSubscriptionConnection connection = new StreamingSubscriptionConnection(service, 30); connection.AddSubscription(StreamingSubscription); connection.OnNotificationEvent += OnNotificationEvent; connection.OnDisconnect += OnDisconnect; connection.OnSubscriptionError += OnSubscriptionError; connection.Open(); service.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress, "user2@mydomain.com"); var StreamingSubscription2 = service.SubscribeToStreamingNotifications( new FolderId[] { WellKnownFolderName.Calendar }, EventType.FreeBusyChanged); // 存入映射关系 SubscriptionAccountMap.Add(StreamingSubscription2.Id, "user2@mydomain.com"); StreamingSubscriptionConnection connection2 = new StreamingSubscriptionConnection(service, 30); connection2.AddSubscription(StreamingSubscription2); connection2.OnNotificationEvent += OnNotificationEvent; connection2.OnDisconnect += OnDisconnect; connection2.OnSubscriptionError += OnSubscriptionError; connection2.Open(); Console.WriteLine("Waiting..."); while (isRunning) { Thread.Sleep(1000); } StreamingSubscription.Unsubscribe(); connection.Close(); SubscriptionAccountMap.Remove(StreamingSubscription.Id); StreamingSubscription2.Unsubscribe(); connection2.Close(); SubscriptionAccountMap.Remove(StreamingSubscription2.Id); } private static void OnNotificationEvent(object sender, NotificationEventArgs args) { // 直接通过订阅ID查字典获取对应账号 var userSmtp = SubscriptionAccountMap[args.Subscription.Id]; Console.WriteLine($"Event for: {userSmtp} "); foreach (var item in args.Events) { Console.WriteLine(item.EventType); if (item.EventType == EventType.FreeBusyChanged) { Console.WriteLine(((ItemEvent)item).ItemId); } } }
内容的提问来源于stack exchange,提问作者bmoolman
相关产品推荐
相关产品推荐

