3

EWS でユーザーの複数の偽装を実行しているときに、偽装された各ユーザーのカレンダー (最大 100 人) で通知を受け取りたいときに問題が発生します。

現在、他のすべてのユーザーになりすます権限を持つ Outlook アカウントがあり、すべての ExchangeService オブジェクトがこのアカウントの資格情報を取得します。

短いバージョンは、一意の ID を介して予定にバインドしようとすると、スレッドが 1 つしか実行されていない限り機能します。独自のサブスクリプションを持つ新しい Exchangeservice を含む新しいスレッドを開始すると、Appointment.Bind() 要求に対する応答がありません。

プログラムの 2 つのインスタンスをそれぞれに 1 つのスレッドのみで実行すると正常に動作しますが、新しい ExchangeService で新しいスレッドを開始するとすぐに Appointment.Bind() は応答しません。

これの奇妙な点は、2 週間前には正常に機能していたのに、突然機能しなくなり、コードを変更しなかったことです。

私の問題の簡単なデモを作成しました:

class Program
{
    static void Main(string[] args)
    {
        var x = new OutlookListener("user1@server.com");
        var y = new OutlookListener("user2@server.com");
        new Thread(x.Start).Start();
        new Thread(y.Start).Start();
        while (true)
        {

        }
    }
}
class OutlookListener
{
    private ExchangeService _ExchangeService;
    private AutoResetEvent _Signal;
    public OutlookListener(string emailToImp)
    {
        _ExchangeService = new ExchangeService(ExchangeVersion.Exchange2010_SP1)
        {
            Credentials = new NetworkCredential("superuser@server.com", "password"),
            Url = new Uri("exchangeUrl"),
            ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress, emailToImp)
        };
    }
    public void Start()
    {
        var subscription = _ExchangeService.SubscribeToStreamingNotifications(new FolderId[] { WellKnownFolderName.Calendar },
                                                                  EventType.Created);
        var connection = CreateStreamingSubscription(_ExchangeService, subscription);
        Console.Out.WriteLine("Subscription created.");
        _Signal = new AutoResetEvent(false);
        _Signal.WaitOne();
        subscription.Unsubscribe();
        connection.Close();
    }

    private StreamingSubscriptionConnection CreateStreamingSubscription(ExchangeService service, StreamingSubscription subscription)                                                                         
    {
        var connection = new StreamingSubscriptionConnection(service, 30);
        connection.AddSubscription(subscription);
        connection.OnNotificationEvent += OnNotificationEvent;
        connection.OnSubscriptionError += OnSubscriptionError;
        connection.OnDisconnect += OnDisconnect;
        connection.Open();

        return connection;
    }
    private void OnNotificationEvent(object sender, NotificationEventArgs args)
    {
        // Extract the item ids for all NewMail Events in the list.
        var newMails = from e in args.Events.OfType<ItemEvent>()
                       where e.EventType == EventType.Created
                       select e.ItemId;

        foreach (var newMail in newMails)
        {
            var appointment= Appointment.Bind(_ExchangeService, newMail); //This is where I dont get a response!
            Console.WriteLine(appointment.Subject);
        }
    }
    private void OnSubscriptionError(object sender, SubscriptionErrorEventArgs args)
    {
    }
    private void OnDisconnect(object sender, SubscriptionErrorEventArgs args)
    {
    }
}

助言がありますか?

4

2 に答える 2

1

なぜ複数のスレッドが必要なのですか?

私の場合、なりすましたい各メールの smtpaddress に基づいてサービスの辞書を作成し、それらすべてを購読しています。すべてが 1 つのスレッドで発生する可能性があり、ユーザーからのすべての通知は OnNotificationEvent で処理されます。[このコードはロジックを示すためのものであり、完全にコンパイルして実行するための完全なものではありません]

            var service = new ExchangeService(exchangeVersion);

            var serviceCred = ((System.Net.NetworkCredential)(((WebCredentials)(Services.First().Value.Credentials)).Credentials));

            service.Credentials = new WebCredentials(serviceCred.UserName, serviceCred.Password);

            service.AutodiscoverUrl(userSmtp, RedirectionUrlValidationCallback);

            service.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress, userSmtp);

            Services.Add(userSmtp, service);

Services.First().Value は、他のすべてのユーザーを偽装できるサービスであり、ここではユーザーの番号として複製されていることに注意してください。

その後、すべてのサービスのサブスクリプション (各サービスが異なるユーザーになりすますことに注意してください)

foreach (var service in Services.Values)
            {
                SubscribeToService(service);
            }

SubscribeToService の定義は次のとおりです。

private void SubscribeToService(ExchangeService service)
        {

                if (service.ImpersonatedUserId == null)
                    return;
                if (service.Url == null)
                    return;

                var serviceName = service.ImpersonatedUserId.Id;


                var streamingSubscription =
                                      service.SubscribeToStreamingNotifications(new FolderId[] { WellKnownFolderName.DeletedItems, WellKnownFolderName.Calendar },
                                                    EventType.FreeBusyChanged, EventType.Moved, EventType.Created, EventType.Modified);

                if (!Connections.ContainsKey(service.Url))
                {
                    Connections.Add(service.Url, new StreamingSubscriptionConnection(service, 30));

                }
                var connection = Connections[service.Url];

                CloseConnection(connection);

                if (!_subscriptions.ContainsKey(serviceName))
                {
                    _subscriptions.Add(serviceName, streamingSubscription);
                    connection.AddSubscription(streamingSubscription);
                }

            }

        }

これはすべて 1 つのスレッドで発生する可能性があります。私の回答が役に立てば幸いです。乾杯

于 2013-01-22T10:02:43.793 に答える