EWS 交换有时不会使用 StreamingSubscription 触发 NewMail 事件
EWS exchange sometimes not firing NewMail event using StreamingSubscription
我有一个通知新邮件的应用程序,使用 EWS 托管 api (v2.2) 创建。我正在使用 StreamingSubscription 来监听邮箱事件。我注意到有时 NewMail 事件没有触发(稍后我在邮箱中看到未处理的邮件),没有引发 connection/subscription 异常,并且在一段时间后接收新邮件时什么也没发生……是什么导致了这种行为?交换日志没有任何可疑之处,事件只是没有被触发...任何想法和建议将不胜感激。
谢谢。
来源:
public class ExchangeClient : IDisposable
{
private ExchangeService _exchange;
private SubscriptionBase _subscription;
private StreamingSubscriptionConnection _connection;
private bool _disposed;
private bool _disposing;
public event EventHandler<ExchangeEventArgs> ExchangeEvent;
public ExchangeClient(string userName, string password, string domain, ExchangeVersion version)
{
_exchange = new ExchangeService(version);
_exchange.Credentials = new WebCredentials(userName, password);
_exchange.AutodiscoverUrl(userName + "@" + domain);
var ids = new FolderId[2] { new FolderId(WellKnownFolderName.Root), new FolderId(WellKnownFolderName.Inbox) };
var events = new List<EventType>();
events.Add(EventType.NewMail);
_subscription = _exchange.SubscribeToStreamingNotifications(ids, events.ToArray());
_connection = new StreamingSubscriptionConnection(_exchange, 30);
_connection.AddSubscription((StreamingSubscription)_subscription);
_connection.OnNotificationEvent += OnNotificationEvent;
_connection.OnSubscriptionError += OnSubscriptionError;
_connection.OnDisconnect += OnDisconnect;
_connection.Open();
}
private void OnDisconnect(object sender, SubscriptionErrorEventArgs args)
{
if (!_disposing && _connection != null)
{
_connection.Open();
}
}
private void OnSubscriptionError(object sender, SubscriptionErrorEventArgs args)
{
throw args.Exception;
}
private void OnNotificationEvent(object sender, NotificationEventArgs args)
{
if (_subscription != null)
{
if (args.Subscription.Id == _subscription.Id)
{
foreach (var notificationEvent in args.Events)
{
switch (notificationEvent.EventType)
{
case EventType.Status:
break;
case EventType.NewMail:
NotificationReceived(new ExchangeEventArgs(
notificationEvent.EventType,
((ItemEvent)notificationEvent).ItemId, ((ItemEvent)notificationEvent).ParentFolderId));
break;
default:
break;
}
}
}
}
}
public void Disconnect()
{
if (_connection.IsOpen)
_connection.Close();
}
private void NotificationReceived(ExchangeEventArgs e)
{
if (ExchangeEvent != null)
{
ExchangeEvent(this, e);
}
}
public void Dispose()
{
_disposing = true;
Dispose(_disposing);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposing && !_disposed)
{
if (_connection != null)
{
if (_connection.IsOpen)
_connection.Close();
_connection = null;
}
_exchange = null;
_disposed = true;
}
}
}
我想我可以自己回答这个问题 - 为保证连续工作,您需要续订。但这是奇怪的部分:没有抛出异常(OnDisconnect
事件处理程序中的 SubscriptionErrorEventArgs
中有一个异常对象:
Unable to retrieve events for this subscription. The subscription must be recreated.
当您不会收到有关订阅事件的通知时超时,一段时间后您将继续收到旧订阅的事件通知...
更新
我最终得到的解决方案是:如果 OnDisconnect
事件中的 SubscriptionErrorEventArgs
不包含异常 - 只需打开已关闭的连接,否则 - 引发 Disconnected
事件,并让父 [= 27=] 决定 - 我们是否应该尝试 Reconnect
(通过调用 Reconnect
)。
public class ExchangeEventArgs : EventArgs
{
public EventType Type { get; private set; }
public ItemId ItemId { get; private set; }
public FolderId FolderId { get; private set; }
public ExchangeEventArgs(EventType type, ItemId itemId, FolderId folderId)
{
Type = type;
ItemId = itemId;
FolderId = folderId;
}
}
public class ExchangeClient : IDisposable
{
private ExchangeService _exchange;
private SubscriptionBase _subscription;
private StreamingSubscriptionConnection _connection;
private bool _disposed;
private bool _disposing;
public event EventHandler<ExchangeEventArgs> ExchangeEvent;
public event EventHandler<DisconnectEventArgs> Disconnected;
public ExchangeClient(string userName, string password, string domain, ExchangeVersion version)
{
_exchange = new ExchangeService(version);
_exchange.Credentials = new WebCredentials(userName, password);
_exchange.AutodiscoverUrl(userName + "@" + domain);
_connection = new StreamingSubscriptionConnection(_exchange, 30);
CreateSubscription();
_connection.OnNotificationEvent += OnNotificationEvent;
_connection.OnSubscriptionError += OnSubscriptionError;
_connection.OnDisconnect += OnDisconnect;
_connection.Open();
}
private void CreateSubscription()
{
var ids = new FolderId[2] { new FolderId(WellKnownFolderName.Root), new FolderId(WellKnownFolderName.Inbox) };
var events = new List<EventType>();
events.Add(EventType.NewMail);
if (_subscription != null)
{
((StreamingSubscription)_subscription).Unsubscribe();
_connection.RemoveSubscription((StreamingSubscription)_subscription);
}
_subscription = _exchange.SubscribeToStreamingNotifications(ids, events.ToArray());
_connection.AddSubscription((StreamingSubscription)_subscription);
}
private void OnDisconnect(object sender, SubscriptionErrorEventArgs args)
{
if (args.Exception == null)
{
if (!_disposing && _connection != null)
{
_connection.Open();
}
}
else
{
if (Disconnected != null)
Disconnected(this, new DisconnectEventArgs("Exchange exception", args.Exception));
}
}
public bool Reconnect()
{
try
{
if (!_disposing && _connection != null)
{
CreateSubscription();
_connection.Open();
return true;
}
else
return false;
}
catch (Exception)
{
return false;
}
}
private void OnSubscriptionError(object sender, SubscriptionErrorEventArgs args)
{
OnDisconnect(sender, args);
}
private void OnNotificationEvent(object sender, NotificationEventArgs args)
{
if (_subscription != null)
{
if (args.Subscription.Id == _subscription.Id)
{
foreach (var notificationEvent in args.Events)
{
switch (notificationEvent.EventType)
{
case EventType.Status:
break;
case EventType.NewMail:
NotificationReceived(new ExchangeEventArgs(
notificationEvent.EventType,
((ItemEvent)notificationEvent).ItemId, ((ItemEvent)notificationEvent).ParentFolderId));
break;
default:
break;
}
}
}
}
}
public void Disconnect()
{
if (_connection.IsOpen)
_connection.Close();
}
private void NotificationReceived(ExchangeEventArgs e)
{
if (ExchangeEvent != null)
{
ExchangeEvent(this, e);
}
}
public void Dispose()
{
_disposing = true;
Dispose(_disposing);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposing && !_disposed)
{
if (_connection != null)
{
if (_connection.IsOpen)
_connection.Close();
_connection = null;
}
_exchange = null;
_disposed = true;
}
}
}
我有一个通知新邮件的应用程序,使用 EWS 托管 api (v2.2) 创建。我正在使用 StreamingSubscription 来监听邮箱事件。我注意到有时 NewMail 事件没有触发(稍后我在邮箱中看到未处理的邮件),没有引发 connection/subscription 异常,并且在一段时间后接收新邮件时什么也没发生……是什么导致了这种行为?交换日志没有任何可疑之处,事件只是没有被触发...任何想法和建议将不胜感激。
谢谢。
来源:
public class ExchangeClient : IDisposable
{
private ExchangeService _exchange;
private SubscriptionBase _subscription;
private StreamingSubscriptionConnection _connection;
private bool _disposed;
private bool _disposing;
public event EventHandler<ExchangeEventArgs> ExchangeEvent;
public ExchangeClient(string userName, string password, string domain, ExchangeVersion version)
{
_exchange = new ExchangeService(version);
_exchange.Credentials = new WebCredentials(userName, password);
_exchange.AutodiscoverUrl(userName + "@" + domain);
var ids = new FolderId[2] { new FolderId(WellKnownFolderName.Root), new FolderId(WellKnownFolderName.Inbox) };
var events = new List<EventType>();
events.Add(EventType.NewMail);
_subscription = _exchange.SubscribeToStreamingNotifications(ids, events.ToArray());
_connection = new StreamingSubscriptionConnection(_exchange, 30);
_connection.AddSubscription((StreamingSubscription)_subscription);
_connection.OnNotificationEvent += OnNotificationEvent;
_connection.OnSubscriptionError += OnSubscriptionError;
_connection.OnDisconnect += OnDisconnect;
_connection.Open();
}
private void OnDisconnect(object sender, SubscriptionErrorEventArgs args)
{
if (!_disposing && _connection != null)
{
_connection.Open();
}
}
private void OnSubscriptionError(object sender, SubscriptionErrorEventArgs args)
{
throw args.Exception;
}
private void OnNotificationEvent(object sender, NotificationEventArgs args)
{
if (_subscription != null)
{
if (args.Subscription.Id == _subscription.Id)
{
foreach (var notificationEvent in args.Events)
{
switch (notificationEvent.EventType)
{
case EventType.Status:
break;
case EventType.NewMail:
NotificationReceived(new ExchangeEventArgs(
notificationEvent.EventType,
((ItemEvent)notificationEvent).ItemId, ((ItemEvent)notificationEvent).ParentFolderId));
break;
default:
break;
}
}
}
}
}
public void Disconnect()
{
if (_connection.IsOpen)
_connection.Close();
}
private void NotificationReceived(ExchangeEventArgs e)
{
if (ExchangeEvent != null)
{
ExchangeEvent(this, e);
}
}
public void Dispose()
{
_disposing = true;
Dispose(_disposing);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposing && !_disposed)
{
if (_connection != null)
{
if (_connection.IsOpen)
_connection.Close();
_connection = null;
}
_exchange = null;
_disposed = true;
}
}
}
我想我可以自己回答这个问题 - 为保证连续工作,您需要续订。但这是奇怪的部分:没有抛出异常(OnDisconnect
事件处理程序中的 SubscriptionErrorEventArgs
中有一个异常对象:
Unable to retrieve events for this subscription. The subscription must be recreated.
当您不会收到有关订阅事件的通知时超时,一段时间后您将继续收到旧订阅的事件通知...
更新
我最终得到的解决方案是:如果 OnDisconnect
事件中的 SubscriptionErrorEventArgs
不包含异常 - 只需打开已关闭的连接,否则 - 引发 Disconnected
事件,并让父 [= 27=] 决定 - 我们是否应该尝试 Reconnect
(通过调用 Reconnect
)。
public class ExchangeEventArgs : EventArgs
{
public EventType Type { get; private set; }
public ItemId ItemId { get; private set; }
public FolderId FolderId { get; private set; }
public ExchangeEventArgs(EventType type, ItemId itemId, FolderId folderId)
{
Type = type;
ItemId = itemId;
FolderId = folderId;
}
}
public class ExchangeClient : IDisposable
{
private ExchangeService _exchange;
private SubscriptionBase _subscription;
private StreamingSubscriptionConnection _connection;
private bool _disposed;
private bool _disposing;
public event EventHandler<ExchangeEventArgs> ExchangeEvent;
public event EventHandler<DisconnectEventArgs> Disconnected;
public ExchangeClient(string userName, string password, string domain, ExchangeVersion version)
{
_exchange = new ExchangeService(version);
_exchange.Credentials = new WebCredentials(userName, password);
_exchange.AutodiscoverUrl(userName + "@" + domain);
_connection = new StreamingSubscriptionConnection(_exchange, 30);
CreateSubscription();
_connection.OnNotificationEvent += OnNotificationEvent;
_connection.OnSubscriptionError += OnSubscriptionError;
_connection.OnDisconnect += OnDisconnect;
_connection.Open();
}
private void CreateSubscription()
{
var ids = new FolderId[2] { new FolderId(WellKnownFolderName.Root), new FolderId(WellKnownFolderName.Inbox) };
var events = new List<EventType>();
events.Add(EventType.NewMail);
if (_subscription != null)
{
((StreamingSubscription)_subscription).Unsubscribe();
_connection.RemoveSubscription((StreamingSubscription)_subscription);
}
_subscription = _exchange.SubscribeToStreamingNotifications(ids, events.ToArray());
_connection.AddSubscription((StreamingSubscription)_subscription);
}
private void OnDisconnect(object sender, SubscriptionErrorEventArgs args)
{
if (args.Exception == null)
{
if (!_disposing && _connection != null)
{
_connection.Open();
}
}
else
{
if (Disconnected != null)
Disconnected(this, new DisconnectEventArgs("Exchange exception", args.Exception));
}
}
public bool Reconnect()
{
try
{
if (!_disposing && _connection != null)
{
CreateSubscription();
_connection.Open();
return true;
}
else
return false;
}
catch (Exception)
{
return false;
}
}
private void OnSubscriptionError(object sender, SubscriptionErrorEventArgs args)
{
OnDisconnect(sender, args);
}
private void OnNotificationEvent(object sender, NotificationEventArgs args)
{
if (_subscription != null)
{
if (args.Subscription.Id == _subscription.Id)
{
foreach (var notificationEvent in args.Events)
{
switch (notificationEvent.EventType)
{
case EventType.Status:
break;
case EventType.NewMail:
NotificationReceived(new ExchangeEventArgs(
notificationEvent.EventType,
((ItemEvent)notificationEvent).ItemId, ((ItemEvent)notificationEvent).ParentFolderId));
break;
default:
break;
}
}
}
}
}
public void Disconnect()
{
if (_connection.IsOpen)
_connection.Close();
}
private void NotificationReceived(ExchangeEventArgs e)
{
if (ExchangeEvent != null)
{
ExchangeEvent(this, e);
}
}
public void Dispose()
{
_disposing = true;
Dispose(_disposing);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposing && !_disposed)
{
if (_connection != null)
{
if (_connection.IsOpen)
_connection.Close();
_connection = null;
}
_exchange = null;
_disposed = true;
}
}
}