/// <summary> /// Load free busy information from the public folder /// </summary> /// <param name="exchangeServerUrl">The exchange server to use</param> /// <param name="users">The set of users to get free busy info for</param> /// <param name="window">The DateTime range to get free busy info for</param> /// <returns>A set of FreeBusy information for each user</returns> public Dictionary <ExchangeUser, FreeBusy> LoadFreeBusy( string exchangeServerUrl, ExchangeUserDict users, DateTimeRange window) { DateTimeRange roundedWindow = DateUtil.RoundRangeToInterval(window, kFreeBusyInterval); string url = FreeBusyUrl.GenerateFreeBusyLookupUrl(exchangeServerUrl, users, roundedWindow, kFreeBusyInterval); Stream response = IssueRequest(url, Method.GET, string.Empty); Dictionary <ExchangeUser, FreeBusy> result = null; try { result = ParseRasterFreeBusyResponse(users, roundedWindow.Start, response); } finally { response.Close(); } return(result); }
/// <summary> /// Returns the free busy times for the specified exchange users /// </summary> /// <param name="users">The user which free/busy blocks will be looked up for</param> /// <param name="window">The time period to look up FB info for</param> /// <returns></returns> public Dictionary<ExchangeUser, FreeBusy> LookupFreeBusyTimes( ExchangeUserDict users, DateTimeRange window ) { /* Create an array of mailboxes to retrieve from exchange */ Dictionary<ExchangeUser, FreeBusy> result = new Dictionary<ExchangeUser, FreeBusy>(); try { using (BlockTimer bt = new BlockTimer("LookupFreeBusyTimes")) { /* Perform the retrieval of free busy times through WebDav */ result = webDavQuery.LoadFreeBusy(exchangeServerUrl, users, window); } } catch (Exception ex) { throw new GCalExchangeException( GCalExchangeErrorCode.ExchangeUnreachable, "Error occured while retrieving free busy ranges", ex); } return result; }
private static void ParseFreeBusyRaster( ExchangeUserDict users, DateTime baseTime, string emailAddress, string freeBusyRaster, Dictionary <ExchangeUser, FreeBusy> result) { ExchangeUser user = null; if (emailAddress == null || !users.TryGetValue(emailAddress, out user)) { return; } FreeBusy freeBusy = new FreeBusy(); freeBusy.User = user; FreeBusyConverter.ParseRasterFreeBusy(baseTime, kFreeBusyInterval, freeBusyRaster, freeBusy); FreeBusyConverter.CondenseFreeBusyTimes(freeBusy.All); result[user] = freeBusy; }
protected void ButtonQueryExchFB_Click(object sender, EventArgs e) { verifyAllowed(); try { ExchangeUserDict users = ExchangeTester.QueryFreeBusy(TextBoxQueryExchEmail.Text); if (users.Count > 0) { LabelExchFBSummary.Text = "Verified"; WebServiceFreeBusy.CssClass = "verified"; StringBuilder sb = new StringBuilder(); foreach (ExchangeUser user in users.Values) { sb.AppendFormat("<ul>"); sb.AppendFormat("<li>Common Name: {0}</li>", user.CommonName); sb.AppendFormat("<li>Email: {0}</li>", user.Email); sb.AppendFormat("<li>Account Name: {0}</li>", user.AccountName); sb.AppendFormat("<li>Mail Nickname: {0}</li>", user.MailNickname); sb.AppendFormat("<li>Busy Times:"); sb.AppendFormat("<ul>"); foreach (FreeBusyTimeBlock tb in user.BusyTimes.Values) { sb.AppendFormat("<li>{0} to {1}</li>", tb.StartDate.ToLocalTime(), tb.EndDate.ToLocalTime()); } sb.AppendFormat("</ul></li></ul>"); } LabelExchFBDetail.Text = sb.ToString(); } else { LabelExchFBSummary.Text = string.Format("User not found - {0}", TextBoxQueryExchEmail.Text); LabelExchFBDetail.Text = ""; WebServiceFreeBusy.CssClass = "failed"; } } catch (Exception ex) { LabelExchFBSummary.Text = ex.Message; WebServiceFreeBusy.CssClass = "failed"; LabelExchFBDetail.Text = string.Format("<blockquote>{0}</blockquote>", ex.ToString()); } }
public void FreeBusyUrls() { Assert.AreEqual(FreeBusyTestUrl, FreeBusyUrl.GenerateUrl(ExchangeServer, Organization, OrgUnit)); Assert.AreEqual(FreeBusyFromDNUrl, FreeBusyUrl.GenerateUrlFromDN(ExchangeServer, LegacyDN)); Assert.AreEqual(AdminGroupUrl, FreeBusyUrl.GenerateAdminGroupUrl(ExchangeServer, AdminGroup)); ExchangeUserDict users = new ExchangeUserDict(); users.Add(User1Email, createFauxUser("User1", User1Email)); DateTimeRange range = new DateTimeRange(start, end); Assert.AreEqual(SingleUserFreeBusyUrl, FreeBusyUrl.GenerateFreeBusyLookupUrl(ExchangeServer, users, range, 15)); users.Add(User2Email, createFauxUser("User2", User2Email)); Assert.AreEqual(MultiUserFreeBusyUrl, FreeBusyUrl.GenerateFreeBusyLookupUrl(ExchangeServer, users, range, 15)); }
protected void ButtonLdapQuery_Click(object sender, EventArgs e) { verifyAllowed(); try { ExchangeUserDict users = ExchangeTester.QueryActiveDirectory(TextBoxLdapQuery.Text); if (users.Count > 0) { WebServiceLdap.CssClass = "verified"; LabelLdapSummary.Text = string.Format("Verified - Located {0} users", users.Count); StringBuilder sb = new StringBuilder(); int count = 0; sb.Append("<ul>"); foreach (string userKey in users.Keys) { sb.AppendFormat("<li>User: {0}</li>", userKey); count++; if (count > 20) { sb.AppendFormat("<li><Truncated></li>"); break; } } sb.Append("</ul>"); LabelLdapDetail.Text = sb.ToString(); } else { LabelLdapSummary.Text = "No users returned"; WebServiceLdap.CssClass = "failed"; LabelLdapDetail.Text = ""; } } catch (Exception ex) { LabelLdapSummary.Text = ex.Message; WebServiceLdap.CssClass = "failed"; LabelLdapDetail.Text = string.Format("<blockquote>{0}</blockquote>", ex.ToString()); } }
public AppointmentLookupFuture( ExchangeService exchange, ExchangeUserDict users, DateTimeRange window) { this.exchange = exchange; this.users = users; this.syncWindow = window; // Only do this if appointment // lookup is enabled if (ConfigCache.EnableAppointmentLookup) { this.start(); } }
public void TestFastFreeBusyLookup() { _requestor.ValidMethod = Method.GET; _requestor.ResponseBody = getResponseXML("FreeBusyResponse.xml"); // These dates correspond to when the response XML was captured DateTime start = DateUtil.ParseDateToUtc("2007-12-25T01:46:50Z"); DateTime end = DateUtil.ParseDateToUtc("2008-01-08T01:42:50Z"); DateTimeRange range = new DateTimeRange(start, end); ExchangeUserDict users = new ExchangeUserDict(); users.Add(_user.Email, _user); Dictionary <ExchangeUser, FreeBusy> result = _webdav.LoadFreeBusy(exchangeServer, users, range); Assert.AreEqual(1, result.Count); FreeBusy fb = result[_user]; Assert.AreEqual(6, fb.All.Count); Assert.AreEqual(6, fb.Busy.Count); Assert.AreEqual(0, fb.OutOfOffice.Count); Assert.AreEqual(0, fb.Tentative.Count); //dumpFreeBusy(fb.Busy); Assert.AreEqual(DateUtil.ParseDateToUtc("2007-12-26T18:00:00Z"), fb.Busy[0].Start); Assert.AreEqual(DateUtil.ParseDateToUtc("2007-12-26T18:30:00Z"), fb.Busy[0].End); Assert.AreEqual(DateUtil.ParseDateToUtc("2007-12-26T20:30:00Z"), fb.Busy[1].Start); Assert.AreEqual(DateUtil.ParseDateToUtc("2007-12-26T21:00:00Z"), fb.Busy[1].End); Assert.AreEqual(DateUtil.ParseDateToUtc("2007-12-31T17:30:00Z"), fb.Busy[2].Start); Assert.AreEqual(DateUtil.ParseDateToUtc("2007-12-31T18:00:00Z"), fb.Busy[2].End); Assert.AreEqual(DateUtil.ParseDateToUtc("2007-12-31T21:00:00Z"), fb.Busy[3].Start); Assert.AreEqual(DateUtil.ParseDateToUtc("2007-12-31T21:30:00Z"), fb.Busy[3].End); Assert.AreEqual(DateUtil.ParseDateToUtc("2007-12-26T18:00:00Z"), fb.All[0].Start); Assert.AreEqual(DateUtil.ParseDateToUtc("2007-12-26T18:30:00Z"), fb.All[0].End); Assert.AreEqual(DateUtil.ParseDateToUtc("2007-12-26T20:30:00Z"), fb.All[1].Start); Assert.AreEqual(DateUtil.ParseDateToUtc("2007-12-26T21:00:00Z"), fb.All[1].End); Assert.AreEqual(DateUtil.ParseDateToUtc("2007-12-31T17:30:00Z"), fb.All[2].Start); Assert.AreEqual(DateUtil.ParseDateToUtc("2007-12-31T18:00:00Z"), fb.All[2].End); Assert.AreEqual(DateUtil.ParseDateToUtc("2007-12-31T21:00:00Z"), fb.All[3].Start); Assert.AreEqual(DateUtil.ParseDateToUtc("2007-12-31T21:30:00Z"), fb.All[3].End); }
public static void WriteFreeBusyMessage(string commonName) { ExchangeService gw = new ExchangeService( ConfigCache.ExchangeFreeBusyServerUrl, ConfigCache.ExchangeUserLogin, ConfigCache.ExchangeUserPassword); SchedulePlusFreeBusyWriter writer = new SchedulePlusFreeBusyWriter(); ExchangeUserDict users = QueryFreeBusy(commonName); if (users.Count < 1) { string msg = string.Format("User {0} not found", commonName); throw new Exception(msg); } if (users.Count > 1) { string msg = string.Format("More than one user matches {0}", commonName); throw new Exception(msg); } string userFreeBusyUrl = FreeBusyUrl.GenerateUrlFromDN( ConfigCache.ExchangeFreeBusyServerUrl, users[commonName].LegacyExchangeDN); List <string> emtpyList = new List <string>(); string nowMinus30Days = FreeBusyConverter.ConvertToSysTime(DateUtil.NowUtc.AddDays(-30)).ToString(); string nowPlus60Days = FreeBusyConverter.ConvertToSysTime(DateUtil.NowUtc.AddDays(60)).ToString(); gw.FreeBusy.CreateFreeBusyMessage(userFreeBusyUrl, commonName, emtpyList, emtpyList, emtpyList, emtpyList, nowMinus30Days, nowPlus60Days); }
/// <summary> /// Generate a URL for the new Free Busy Lookup format which is a replacement /// for public folders - documented here: http://support.microsoft.com/kb/813268 /// </summary> /// <param name="exchangeServer">The exchange server to use</param> /// <param name="users">The set of users to lookup</param> /// <param name="range">The datetime range to lookup for</param> /// <param name="interval">The time interval to use</param> /// <returns>The URL to obtain FB info for the set of users</returns> public static string GenerateFreeBusyLookupUrl( string exchangeServer, ExchangeUserDict users, DateTimeRange range, int interval) { StringBuilder result = new StringBuilder(256); result.AppendFormat("{0}/public/?cmd=freebusy&start={1}&end={2}&interval={3}", exchangeServer, DateUtil.FormatDateForISO8601(range.Start), DateUtil.FormatDateForISO8601(range.End), interval); foreach (ExchangeUser user in users.Values) { result.AppendFormat("&u={0}", user.Email); } return(result.ToString()); }
public static void WriteAppointment( string email, DateTime appointmentStart) { DateTime appointmentEnd = appointmentStart.AddHours(1); ExchangeService gw = new ExchangeService( ConfigCache.ExchangeServerUrl, ConfigCache.ExchangeAdminLogin, ConfigCache.ExchangeAdminPassword); ExchangeUserDict users = gw.QueryActiveDirectory(string.Format("mail={0}", email)); if (users.Count != 0) { foreach (ExchangeUser user in users.Values) { Appointment appt = new Appointment(); appt.Subject = "GCalExchangeSync test appt"; appt.Location = "test"; appt.StartDate = appointmentStart; appt.EndDate = appointmentEnd; appt.MeetingStatus = MeetingStatus.Confirmed; appt.Created = DateUtil.NowUtc; appt.InstanceType = InstanceType.Single; List <Appointment> list = new List <Appointment>(); list.Add(appt); gw.Appointments.WriteAppointments(user, list); } } else { string msg = string.Format("User {0} not found", email); throw new Exception(msg); } }
private ExchangeUserDict CreateExchangeUserCollection( SearchResultCollection searchResults ) { ExchangeUserDict userCollection = new ExchangeUserDict(); if ( searchResults != null ) { /* For each result set in the result set */ foreach ( System.DirectoryServices.SearchResult result in searchResults ) { /* Extract the property collection and create a new exchange user with it * Add the new user to the result set and use the account name as the index for * the dictionary collection */ ResultPropertyCollection property = result.Properties; ExchangeUser user = new ExchangeUser( property ); if ( !user.IsValid ) { log.WarnFormat( "User '{0}' is invalid and will not be synchronized.", user.CommonName ); } else if ( userCollection.ContainsKey( user.Email.ToLower() ) ) { log.WarnFormat( "User '{0}' was returned multiple times in the LDAP query. " + "Only the first instance was added.", user.Email ); } else { userCollection.Add( user.Email.ToLower(), user ); log.InfoFormat("Found and added '{0}' as an ExchangeUser.", user.Email); } log.DebugFormat("LDAP object debug info: {0}", user); } } return userCollection; }
private static Dictionary<ExchangeUser, FreeBusy> ParseRasterFreeBusyResponse( ExchangeUserDict users, DateTime baseTime, Stream response) { Dictionary<ExchangeUser, FreeBusy> result = new Dictionary<ExchangeUser, FreeBusy>(); string emailAddress = null; string freeBusyRaster = null; string elementName = null; XmlReaderSettings settings = new XmlReaderSettings(); settings.XmlResolver = null; settings.IgnoreComments = true; settings.IgnoreWhitespace = true; settings.ValidationType = ValidationType.None; settings.ValidationFlags = XmlSchemaValidationFlags.None; XmlReader reader = XmlReader.Create(response, settings); reader.MoveToContent(); while (reader.Read()) { switch (reader.NodeType) { case XmlNodeType.Element: elementName = reader.LocalName; if (elementName == "item") { emailAddress = null; freeBusyRaster = null; } break; case XmlNodeType.Text: if (elementName == "email") { emailAddress = reader.Value.ToLower(); } else { if (elementName == "fbdata") { freeBusyRaster = reader.Value; } } break; case XmlNodeType.EndElement: if (reader.LocalName == "item") { ParseFreeBusyRaster(users, baseTime, emailAddress, freeBusyRaster, result); emailAddress = null; freeBusyRaster = null; } elementName = string.Empty; break; } } return result; }
/// <summary> /// Load free busy information from the public folder /// </summary> /// <param name="exchangeServerUrl">The exchange server to use</param> /// <param name="users">The set of users to get free busy info for</param> /// <param name="window">The DateTime range to get free busy info for</param> /// <returns>A set of FreeBusy information for each user</returns> public Dictionary<ExchangeUser, FreeBusy> LoadFreeBusy( string exchangeServerUrl, ExchangeUserDict users, DateTimeRange window) { DateTimeRange roundedWindow = DateUtil.RoundRangeToInterval(window, kFreeBusyInterval); string url = FreeBusyUrl.GenerateFreeBusyLookupUrl(exchangeServerUrl, users, roundedWindow, kFreeBusyInterval); Stream response = IssueRequest(url, Method.GET, string.Empty); Dictionary<ExchangeUser, FreeBusy> result = null; try { result = ParseRasterFreeBusyResponse(users, roundedWindow.Start, response); } finally { response.Close(); } return result; }
private static void ParseFreeBusyRaster( ExchangeUserDict users, DateTime baseTime, string emailAddress, string freeBusyRaster, Dictionary<ExchangeUser, FreeBusy> result) { ExchangeUser user = null; if (emailAddress == null || !users.TryGetValue(emailAddress, out user)) { return; } FreeBusy freeBusy = new FreeBusy(); freeBusy.User = user; FreeBusyConverter.ParseRasterFreeBusy(baseTime, kFreeBusyInterval, freeBusyRaster, freeBusy); FreeBusyConverter.CondenseFreeBusyTimes(freeBusy.All); result[user] = freeBusy; }
private void LogQueryResults( ExchangeUserDict userCollection, string[] searchTerms, string ldapAttribute ) { if ( userCollection.Count != searchTerms.Length ) { if ( ldapAttribute == "sAMAccountName" ) { foreach ( string term in searchTerms ) { if ( !userCollection.ContainsKey( term.ToLower() ) ) { log.InfoFormat( "Unable to find Active Directory user where '{0}'='{1}'.", ldapAttribute, term ); } } } else if ( ldapAttribute == "mail" ) { foreach ( string email in searchTerms ) { string login = email.Split( '@' )[ 0 ]; if ( !userCollection.ContainsKey( login.ToLower() ) ) { log.InfoFormat( "Unable to find Active Directory user where '{0}'='{1}'.", ldapAttribute, email ); } } } else { log.InfoFormat( "Unable to find all users in Active Directory. [Users={0}]", string.Join( ";", searchTerms ) ); } } }
/// <summary> /// Assigns free busy times to the exchange users that are passed into the method /// </summary> public virtual void GetCalendarInfoForUser(ExchangeUser user, DateTimeRange window) { ExchangeUserDict users = new ExchangeUserDict(); users.AddExchangeUser(user.Email, user); GetCalendarInfoForUsers(users, window); }
/// <summary> /// Assigns free busy times to the exchange users that are passed into the method /// </summary> public virtual void GetCalendarInfoForUsers(ExchangeUserDict users, DateTimeRange window) { // Perform appointment lookup in parallel with FB lookup using (AppointmentLookupFuture future = new AppointmentLookupFuture(this, users, window)) { Dictionary<ExchangeUser, FreeBusy> freeBusyBlocks = freebusy.LookupFreeBusyTimes(users, window); foreach (ExchangeUser user in users.Values) { // If the server gave us no data for a user, that's // fine. We just skip the user. if (!freeBusyBlocks.ContainsKey(user)) continue; /* Retrieve the free busy blocks */ FreeBusy freeBusy = freeBusyBlocks[user]; user.AccessLevel = GCalAccessLevel.ReadAccess; List<Appointment> appointments = future.getResult(user); MergeFreeBusyWithAppointments( user, freeBusy, appointments, window); } } }
/// <summary> /// Returns the free busy times for the specified exchange users /// </summary> /// <param name="user">The user which free/busy blocks will be looked up for</param> /// <param name="window">The date range to do the lookup</param> /// <returns>FreeBusy data for user in the daterange</returns> public FreeBusy LookupFreeBusyTimes( ExchangeUser user, DateTimeRange window ) { ExchangeUserDict users = new ExchangeUserDict(); users.Add( user.Email, user ); Dictionary<ExchangeUser, FreeBusy> result = LookupFreeBusyTimes ( users, window ); return result[user]; }
private static Dictionary <ExchangeUser, FreeBusy> ParseRasterFreeBusyResponse( ExchangeUserDict users, DateTime baseTime, Stream response) { Dictionary <ExchangeUser, FreeBusy> result = new Dictionary <ExchangeUser, FreeBusy>(); string emailAddress = null; string freeBusyRaster = null; string elementName = null; XmlReaderSettings settings = new XmlReaderSettings(); settings.XmlResolver = null; settings.IgnoreComments = true; settings.IgnoreWhitespace = true; settings.ValidationType = ValidationType.None; settings.ValidationFlags = XmlSchemaValidationFlags.None; XmlReader reader = XmlReader.Create(response, settings); reader.MoveToContent(); while (reader.Read()) { switch (reader.NodeType) { case XmlNodeType.Element: elementName = reader.LocalName; if (elementName == "item") { emailAddress = null; freeBusyRaster = null; } break; case XmlNodeType.Text: if (elementName == "email") { emailAddress = reader.Value.ToLower(); } else { if (elementName == "fbdata") { freeBusyRaster = reader.Value; } } break; case XmlNodeType.EndElement: if (reader.LocalName == "item") { ParseFreeBusyRaster(users, baseTime, emailAddress, freeBusyRaster, result); emailAddress = null; freeBusyRaster = null; } elementName = string.Empty; break; } } return(result); }
public void TestFastFreeBusyLookup() { _requestor.ValidMethod = Method.GET; _requestor.ResponseBody = getResponseXML("FreeBusyResponse.xml"); // These dates correspond to when the response XML was captured DateTime start = DateUtil.ParseDateToUtc("2007-12-25T01:46:50Z"); DateTime end = DateUtil.ParseDateToUtc("2008-01-08T01:42:50Z"); DateTimeRange range = new DateTimeRange(start, end); ExchangeUserDict users = new ExchangeUserDict(); users.Add(_user.Email, _user); Dictionary<ExchangeUser, FreeBusy> result = _webdav.LoadFreeBusy(exchangeServer, users, range); Assert.AreEqual(1, result.Count); FreeBusy fb = result[_user]; Assert.AreEqual(6, fb.All.Count); Assert.AreEqual(6, fb.Busy.Count); Assert.AreEqual(0, fb.OutOfOffice.Count); Assert.AreEqual(0, fb.Tentative.Count); //dumpFreeBusy(fb.Busy); Assert.AreEqual(DateUtil.ParseDateToUtc("2007-12-26T18:00:00Z"), fb.Busy[0].Start); Assert.AreEqual(DateUtil.ParseDateToUtc("2007-12-26T18:30:00Z"), fb.Busy[0].End); Assert.AreEqual(DateUtil.ParseDateToUtc("2007-12-26T20:30:00Z"), fb.Busy[1].Start); Assert.AreEqual(DateUtil.ParseDateToUtc("2007-12-26T21:00:00Z"), fb.Busy[1].End); Assert.AreEqual(DateUtil.ParseDateToUtc("2007-12-31T17:30:00Z"), fb.Busy[2].Start); Assert.AreEqual(DateUtil.ParseDateToUtc("2007-12-31T18:00:00Z"), fb.Busy[2].End); Assert.AreEqual(DateUtil.ParseDateToUtc("2007-12-31T21:00:00Z"), fb.Busy[3].Start); Assert.AreEqual(DateUtil.ParseDateToUtc("2007-12-31T21:30:00Z"), fb.Busy[3].End); Assert.AreEqual(DateUtil.ParseDateToUtc("2007-12-26T18:00:00Z"), fb.All[0].Start); Assert.AreEqual(DateUtil.ParseDateToUtc("2007-12-26T18:30:00Z"), fb.All[0].End); Assert.AreEqual(DateUtil.ParseDateToUtc("2007-12-26T20:30:00Z"), fb.All[1].Start); Assert.AreEqual(DateUtil.ParseDateToUtc("2007-12-26T21:00:00Z"), fb.All[1].End); Assert.AreEqual(DateUtil.ParseDateToUtc("2007-12-31T17:30:00Z"), fb.All[2].Start); Assert.AreEqual(DateUtil.ParseDateToUtc("2007-12-31T18:00:00Z"), fb.All[2].End); Assert.AreEqual(DateUtil.ParseDateToUtc("2007-12-31T21:00:00Z"), fb.All[3].Start); Assert.AreEqual(DateUtil.ParseDateToUtc("2007-12-31T21:30:00Z"), fb.All[3].End); }
/// <summary> /// Generate a URL for the new Free Busy Lookup format which is a replacement /// for public folders - documented here: http://support.microsoft.com/kb/813268 /// </summary> /// <param name="exchangeServer">The exchange server to use</param> /// <param name="users">The set of users to lookup</param> /// <param name="range">The datetime range to lookup for</param> /// <param name="interval">The time interval to use</param> /// <returns>The URL to obtain FB info for the set of users</returns> public static string GenerateFreeBusyLookupUrl( string exchangeServer, ExchangeUserDict users, DateTimeRange range, int interval) { StringBuilder result = new StringBuilder(256); result.AppendFormat("{0}/public/?cmd=freebusy&start={1}&end={2}&interval={3}", exchangeServer, DateUtil.FormatDateForISO8601(range.Start), DateUtil.FormatDateForISO8601(range.End), interval); foreach (ExchangeUser user in users.Values) { result.AppendFormat("&u={0}", user.Email); } return result.ToString(); }