EWS交换有时不使用StreamingSubscription触发NewMail事件

时间:2015-04-15 08:52:35

标签: c# .net exchangewebservices

我有应用程序通知使用EWS托管api(v2.2)创建的新邮件。我正在使用StreamingSubscription来监听邮箱事件。我注意到有时NewMail事件没有被触发(我后面看到邮箱中未处理的邮件),没有引发连接/订阅异常,并且在一段时间后新邮件接收没有发生任何事情......什么可能导致这样的行为?在交换日志中没有任何可疑之处,事件只是没有被解雇......任何想法和建议都将不胜感激。

感谢。

来源:

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;
        }
    }
}

1 个答案:

答案 0 :(得分:5)

我想我可以自己回答这个问题 - 保证您续订订阅所需的持续工作。但这里是一个奇怪的部分:没有抛出异常(OnDisconnect事件中的SubscriptionErrorEventArgs中有一个异常对象: 无法检索此订阅的事件。必须重新创建订阅。),只有在您不会收到有关订阅事件的通知时才会超时,并且在一段时间后您将继续接收旧订阅的事件通知...

<强> UPD。 最终的解决方案是:如果OnDisconnect事件中的SubscriptionErrorEventArgss不包含异常 - 只需打开关闭连接,否则 - 引发DIsconnected事件,让父类决定 - 我们是否应该尝试重新连接(通过调用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;
        }
    }
}