private void saveSettings() { OOFSponderInsights.TrackInfo(OOFSponderInsights.CurrentMethod()); if (primaryToolStripMenuItem.Checked) { OOFData.Instance.PrimaryOOFExternalMessage = htmlEditorControl1.BodyHtml; OOFData.Instance.PrimaryOOFInternalMessage = htmlEditorControl2.BodyHtml; } else //since customer is editing Secondary message, save text in Secondary { OOFData.Instance.SecondaryOOFExternalMessage = htmlEditorControl1.BodyHtml; OOFData.Instance.SecondaryOOFInternalMessage = htmlEditorControl2.BodyHtml; } OOFData.Instance.WorkingHours = ScheduleString(); OOFData.Instance.WriteProperties(); toolStripStatusLabel1.Text = "Settings Saved"; OOFSponderInsights.TrackInfo("Settings saved"); //go implement the settings if possible System.Threading.Tasks.Task.Run(() => RunSetOofO365()); }
private async void timer_Elapsed(object sender, ElapsedEventArgs e) { OOFSponderInsights.TrackInfo(OOFSponderInsights.CurrentMethod()); await System.Threading.Tasks.Task.Run(() => RunSetOofO365()); //await checkOOFStatus(); }
public void WriteProperties(bool disposing = false) { OOFSponderInsights.TrackInfo(OOFSponderInsights.CurrentMethod()); System.Diagnostics.Trace.TraceInformation("Persisting properties"); Properties.Settings.Default.PrimaryOOFExternal = instance.PrimaryOOFExternalMessage; System.Diagnostics.Trace.TraceInformation("Persisting PrimaryOOFExternalMessage"); Properties.Settings.Default.PrimaryOOFInternal = instance.PrimaryOOFInternalMessage; System.Diagnostics.Trace.TraceInformation("Persisting PrimaryOOFInternalMessage"); Properties.Settings.Default.SecondaryOOFExternal = instance.SecondaryOOFExternalMessage; System.Diagnostics.Trace.TraceInformation("Persisting SecondaryOOFExternalMessage"); Properties.Settings.Default.SecondaryOOFInternal = instance.SecondaryOOFInternalMessage; System.Diagnostics.Trace.TraceInformation("Persisting SecondaryOOFInternalMessage"); Properties.Settings.Default.PermaOOFDate = instance.PermaOOFDate; System.Diagnostics.Trace.TraceInformation("Persisting PermaOOFDate"); Properties.Settings.Default.workingHours = instance.WorkingHours; System.Diagnostics.Trace.TraceInformation("Persisting WorkingHours"); Properties.Settings.Default.Save(); if (disposing) { Dispose(); } }
private void SetUIforSecondary() { OOFSponderInsights.TrackInfo(OOFSponderInsights.CurrentMethod()); primaryToolStripMenuItem.Checked = false; secondaryToolStripMenuItem.Checked = !primaryToolStripMenuItem.Checked; lblExternalMesage.Text = "Extended OOF External Message"; lblInternalMessage.Text = "Extended OOF Internal Message"; htmlEditorControl1.BodyHtml = OOFData.Instance.SecondaryOOFExternalMessage; htmlEditorControl2.BodyHtml = OOFData.Instance.SecondaryOOFInternalMessage; //update the UI if (OOFData.Instance.IsPermaOOFOn) { btnPermaOOF.Text = "Disable Extended OOF"; btnPermaOOF.Tag = "Disable"; dtPermaOOF.Enabled = false; } else { btnPermaOOF.Text = "Enable Extended OOF"; btnPermaOOF.Tag = "Enable"; dtPermaOOF.Value = DateTime.Now.AddDays(1); dtPermaOOF.Enabled = true; } //lastly, enable the permaOOF controls to help with some UI flow issues btnPermaOOF.Enabled = true; OOFSponderInsights.Track("Configured for secondary"); }
/// <summary> /// Perform an HTTP GET request to a URL using an HTTP Authorization header /// </summary> /// <param name="url">The URL</param> /// <returns>String containing the results of the GET operation</returns> public static async Task <string> GetHttpContentWithToken(string url) { OOFSponder.Logger.Info(OOFSponderInsights.CurrentMethod()); //check and refresh token if necessary await O365.MSALWork(O365.AADAction.SignIn); var httpClient = new System.Net.Http.HttpClient(); System.Net.Http.HttpResponseMessage response; try { var request = new System.Net.Http.HttpRequestMessage(System.Net.Http.HttpMethod.Get, UrlCombine(_graphAPIEndpoint, url)); //Add the token in Authorization header request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", authResult.AccessToken); response = await httpClient.SendAsync(request); var content = await response.Content.ReadAsStringAsync(); return(content); } catch (Exception ex) { OOFSponder.Logger.Error(ex); return(ex.ToString()); } }
private void secondaryToolStripMenuItem_Click(object sender, EventArgs e) { OOFSponder.Logger.Info(OOFSponderInsights.CurrentMethod()); //now, set up the UI for PermaOOF SetUIforSecondary(); }
private void primaryToolStripMenuItem_Click(object sender, EventArgs e) { OOFSponderInsights.TrackInfo(OOFSponderInsights.CurrentMethod()); //now, set up the UI for primary SetUIforPrimary(); }
private void SetUIforPrimary() { OOFSponderInsights.TrackInfo(OOFSponderInsights.CurrentMethod()); //since we are in the process of flipping from secondary to primary //we know that the UI is currently in Secondary mode (or first run) //so HTML controls have the Secondary messages //disable PermaOOF by setting date to time in the past OOFData.Instance.PermaOOFDate = DateTime.Now.AddMinutes(-1); primaryToolStripMenuItem.Checked = true; secondaryToolStripMenuItem.Checked = !primaryToolStripMenuItem.Checked; lblExternalMesage.Text = "Primary External Message"; lblInternalMessage.Text = "Primary Internal Message"; htmlEditorControl1.BodyHtml = OOFData.Instance.PrimaryOOFExternalMessage; htmlEditorControl2.BodyHtml = OOFData.Instance.PrimaryOOFInternalMessage; //lastly, disable the permaOOF controls to help with some UI flow issues btnPermaOOF.Enabled = false; dtPermaOOF.Enabled = false; dtPermaOOF.Value = DateTime.Now; OOFSponderInsights.Track("Configured for primary"); }
/// <summary> /// Perform an HTTP GET request to a URL using an HTTP Authorization header /// </summary> /// <param name="url">The URL</param> /// <param name="token">The token</param> /// <returns>String containing the results of the GET operation</returns> public static async Task <System.Net.Http.HttpResponseMessage> PatchHttpContentWithToken(string url, Microsoft.Graph.AutomaticRepliesSetting OOF) { OOFSponderInsights.TrackInfo(OOFSponderInsights.CurrentMethod()); //check and refresh token if necessary await O365.MSALWork(O365.AADAction.SignIn); var httpClient = new System.Net.Http.HttpClient(); System.Net.Http.HttpMethod method = new System.Net.Http.HttpMethod("PATCH"); System.Net.Http.HttpResponseMessage response; // var response = client.PostAsync("api/AgentCollection", new StringContent( //new JavaScriptSerializer().Serialize(user), Encoding.UTF8, "application/json")).Result; try { Microsoft.Graph.MailboxSettings mbox = new Microsoft.Graph.MailboxSettings(); mbox.AutomaticRepliesSetting = OOF; var request = new System.Net.Http.HttpRequestMessage(method, UrlCombine(_graphAPIEndpoint, url)); var jsonBody = Newtonsoft.Json.JsonConvert.SerializeObject(mbox); System.Net.Http.StringContent iContent = new System.Net.Http.StringContent(jsonBody, Encoding.UTF8, "application/json"); request.Content = iContent; //Add the token in Authorization header request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", authResult.AccessToken); response = await httpClient.SendAsync(request); return(response); } catch (Exception ex) { throw new Exception("Unable to set OOF: " + ex.Message, ex); } }
void Loopy() { OOFSponderInsights.TrackInfo(OOFSponderInsights.CurrentMethod()); //Every 10 minutes for automation var timer = new System.Timers.Timer(600000); timer.Enabled = true; timer.Elapsed += new ElapsedEventHandler(timer_Elapsed); timer.Start(); }
private void ReadProperties() { OOFSponderInsights.TrackInfo(OOFSponderInsights.CurrentMethod()); instance.PermaOOFDate = OOFScheduling.Properties.Settings.Default.PermaOOFDate; instance.WorkingHours = OOFScheduling.Properties.Settings.Default.workingHours == baseValue ? string.Empty : Properties.Settings.Default.workingHours; instance.PrimaryOOFExternalMessage = OOFScheduling.Properties.Settings.Default.PrimaryOOFExternal == baseValue ? string.Empty : Properties.Settings.Default.PrimaryOOFExternal; instance.PrimaryOOFInternalMessage = OOFScheduling.Properties.Settings.Default.PrimaryOOFInternal == baseValue ? string.Empty : Properties.Settings.Default.PrimaryOOFInternal; instance.SecondaryOOFExternalMessage = OOFScheduling.Properties.Settings.Default.SecondaryOOFExternal == baseValue ? string.Empty : Properties.Settings.Default.SecondaryOOFExternal; instance.SecondaryOOFInternalMessage = OOFScheduling.Properties.Settings.Default.SecondaryOOFInternal == baseValue ? string.Empty : Properties.Settings.Default.SecondaryOOFInternal; }
static void Main() { try { //http://covingtoninnovations.com/mc/SingleInstance.html bool gotMutex; //GUID is generated using the built-in VS capability System.Threading.Mutex m = new System.Threading.Mutex(true, "{6FE49292-F7B3-4EB7-B8F2-0CDDFE20B737}", out gotMutex); //http://covingtoninnovations.com/mc/SingleInstance.html if (gotMutex) { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new Form1()); GC.KeepAlive(m); } else { //http://www.codebetter.com/paullaudeman/2004/07/17/windows-forms-tip-ensure-only-one-instance-of-your-application-is-running-at-a-time/ // see if we can find the other app and Bring it to front //NOTE: the link referenced for this specifies a string for the first value, but //I ended up being able to just use the Window name IntPtr hWnd = NativeMethods.FindWindow(null, "OOFSponder"); if (hWnd != IntPtr.Zero) { NativeMethods.WINDOWPLACEMENT placement = new NativeMethods.WINDOWPLACEMENT(); placement.length = System.Runtime.InteropServices.Marshal.SizeOf(placement); NativeMethods.GetWindowPlacement(hWnd, ref placement); if (placement.showCmd != NativeMethods.SW_MINIMIZE) { placement.showCmd = NativeMethods.SW_RESTORE; NativeMethods.SetWindowPlacement(hWnd, ref placement); NativeMethods.SetForegroundWindow(hWnd); } } return; } } catch (Exception ex) { OOFSponderInsights.TrackException("Fatal error on startup", ex); MessageBox.Show("Uh oh! Fatal error for OOFSponder. Please try again."); return; } }
private async void btnPermaOOF_Click(object sender, EventArgs e) { OOFSponderInsights.TrackInfo(OOFSponderInsights.CurrentMethod()); //bail if permaOOF not in the future if (DateTime.Now >= dtPermaOOF.Value) { MessageBox.Show("You must pick a date in future", "OOFSponder", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } //only set up for permaOOF if we have OOF messages if (OOFData.Instance.SecondaryOOFExternalMessage == String.Empty | OOFData.Instance.SecondaryOOFInternalMessage == String.Empty) { MessageBox.Show("Unable to turn on extended OOF - Secondary OOF messages not set", "OOFSponder", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } bool result = false; if (((Button)sender).Tag.ToString() == "Enable") { OOFData.Instance.PermaOOFDate = dtPermaOOF.Value; } else { OOFData.Instance.PermaOOFDate = DateTime.Now; } //actually go OOF now result = await RunSetOofO365(); if (result) { if (((Button)sender).Tag.ToString() == "Enable") { OOFSponderInsights.Track("Enabled PermaOOF"); } else { OOFSponderInsights.Track("Disabled PermaOOF"); } } else { //if we fail to set OOF, disable PermaOOF to reset the UI OOFData.Instance.PermaOOFDate = DateTime.Now; } SetUIforSecondary(); }
private void fileToolStripMenuItem_DropDownOpening(object sender, EventArgs e) { OOFSponderInsights.TrackInfo(OOFSponderInsights.CurrentMethod()); if (!O365.isLoggedIn) { saveToolStripMenuItem.Tag = "LoggedOut"; saveToolStripMenuItem.Text = "Sign in"; } else { saveToolStripMenuItem.Tag = "LoggedIn"; saveToolStripMenuItem.Text = "Sign out"; } }
//common call for both controls, regardless of primary or secondary private void htmlEditorValidated(object sender, EventArgs e) { if (radPrimary.Checked) { OOFSponderInsights.Track("PermaOOF off - persisting primary messages"); OOFData.Instance.PrimaryOOFExternalMessage = htmlEditorControl1.BodyHtml; OOFData.Instance.PrimaryOOFInternalMessage = htmlEditorControl2.BodyHtml; } else { OOFSponderInsights.Track("PermaOOF on - persisting secondary messages"); OOFData.Instance.SecondaryOOFExternalMessage = htmlEditorControl1.BodyHtml; OOFData.Instance.SecondaryOOFInternalMessage = htmlEditorControl2.BodyHtml; } }
private void radPrimary_CheckedChanged(object sender, EventArgs e) { OOFSponderInsights.TrackInfo(OOFSponderInsights.CurrentMethod()); if (radPrimary.Checked) { //Persist the opposite message OOFData.Instance.SecondaryOOFExternalMessage = htmlEditorControl1.BodyHtml; OOFData.Instance.SecondaryOOFInternalMessage = htmlEditorControl2.BodyHtml; SetUIforPrimary(); } else { //Persist the opposite message OOFData.Instance.PrimaryOOFExternalMessage = htmlEditorControl1.BodyHtml; OOFData.Instance.PrimaryOOFInternalMessage = htmlEditorControl2.BodyHtml; SetUIforSecondary(); } }
void signOutToolStripMenuItem_Click(object sender, EventArgs e) { OOFSponderInsights.TrackInfo(OOFSponderInsights.CurrentMethod()); //prep for async work System.Threading.Tasks.Task AuthTask = null; if (saveToolStripMenuItem.Tag.ToString() == "LoggedIn") { AuthTask = System.Threading.Tasks.Task.Run((Action)(() => { O365.MSALWork(O365.AADAction.SignOut); })); } else { AuthTask = System.Threading.Tasks.Task.Run((Action)(() => { O365.MSALWork(O365.AADAction.SignIn); })); } //wait on async auth stuff if not null if (AuthTask != null) { AuthTask.Wait(); } }
/// <summary> /// Call AcquireTokenAsync - to acquire a token requiring user to sign-in /// </summary> internal async static Task <bool> MSALWork(AADAction action) { OOFSponderInsights.TrackInfo(OOFSponderInsights.CurrentMethod()); bool _result = false; if (action == AADAction.SignIn | action == AADAction.ForceSignIn) { try { authResult = await PublicClientApp.AcquireTokenSilentAsync(_scopes, PublicClientApp.Users.FirstOrDefault()); } catch (MsalUiRequiredException ex) { // A MsalUiRequiredException happened on AcquireTokenSilentAsync. This indicates you need to call AcquireTokenAsync to acquire a token //Don't track this one since it can basically be considered expected. //OOFSponderInsights.TrackException($"MsalUiRequiredException: {ex.Message}", ex); try { authResult = await PublicClientApp.AcquireTokenAsync(_scopes); } catch (MsalException msalex) { OOFSponderInsights.TrackException("MsalException", new Exception($"Error Acquiring Token:{System.Environment.NewLine}", msalex)); } } catch (Exception ex) { OOFSponderInsights.TrackException("Error Acquiring Token Silently", ex); return(false); } if (PublicClientApp.Users.Count() > 0) { //BuddyOptions.authResult = BuddyOptions.authResult; _result = true; //also, update the Application Insights info with the authenticated user OOFSponderInsights.AIClient.Context.User.Id = authResult.User.DisplayableId.Split('@')[0]; } else { _result = false; } } else { if (PublicClientApp.Users.Any()) { try { PublicClientApp.Remove(PublicClientApp.Users.FirstOrDefault()); _result = true; } catch (MsalException ex) { OOFSponder.Logger.Error($"Error signing-out user: {ex.Message}"); OOFSponderInsights.TrackException($"Error signing-out user: {ex.Message}", ex); } } } return(_result); }
/// <summary> /// Call AcquireTokenAsync - to acquire a token requiring user to sign-in /// </summary> internal async static Task <bool> MSALWork(AADAction action) { OOFSponder.Logger.Info(OOFSponderInsights.CurrentMethod()); bool _result = false; //lock this so we don't get multiple auth prompts OOFSponder.Logger.Info("Attempting to enter critical section for auth code"); await semaphoreSlim.WaitAsync(); OOFSponder.Logger.Info("Inside critical section for auth code"); OOFSponder.Logger.Info("Attempting to build PublicClientApp with multitenant endpoint"); lock (pcaInitLock) { PublicClientApp = PublicClientApplicationBuilder.Create(ClientId) .WithRedirectUri("https://login.microsoftonline.com/common/oauth2/nativeclient") .WithAuthority(logonUrl) .Build(); MSALTokenCacheHelper.EnableSerialization(PublicClientApp.UserTokenCache); } //grab the logged in user UPN so we can decide whether or not to force the prompt try { Task <IEnumerable <IAccount> > accountTask = PublicClientApp.GetAccountsAsync(); accountTask.Wait(10000); // give UserTokenCache a go IAccount account = null; try { account = accountTask.Result.FirstOrDefault(p => p.Username.ToLower() == DefaultUserUPN.ToLower()); } catch (Exception) { } if (account != null && account.Username.ToLower() == DefaultUserUPN.ToLower()) { try { Task <AuthenticationResult> authUITask = PublicClientApp.AcquireTokenSilent(_scopes, account) .ExecuteAsync(); authUITask.Wait(10000); authResult = authUITask.Result; if (authResult != null) { OOFSponder.Logger.Info("AcquireTokenSilent -> OK"); } _result = true; } catch (Exception x) { OOFSponder.Logger.Error("AcquireTokenSilent -> " + x.GetType().ToString()); } } try { Task <AuthenticationResult> authUITask = PublicClientApp.AcquireTokenInteractive(_scopes) .WithLoginHint(DefaultUserUPN) .WithPrompt(Prompt.NoPrompt) .ExecuteAsync(); authUITask.Wait(10000); authResult = authUITask.Result; _result = true; } catch (Exception ex) { if (ex is MsalUiRequiredException || ex.InnerException is MsalUiRequiredException || ex is MsalClientException || ex.InnerException is MsalClientException || ex is MsalServiceException || ex.InnerException is MsalServiceException) // MSAL service or client exception here is most likely down to need for UI // even if it is not MsalUiRequiredException { //try //{ // if (!UPN.ToLower().EndsWith("@microsoft.com")) // throw new Exception("Skip IWA for outsourcer logon"); // Task<AuthenticationResult> authIWATask = PublicClientApp.AcquireTokenByIntegratedWindowsAuth(scopes).ExecuteAsync(); // authIWATask.Wait(10000); // authResult = authIWATask.Result; //} //catch (Exception ex1) //{ try { Task <AuthenticationResult> authUITask = PublicClientApp.AcquireTokenInteractive(_scopes) .WithPrompt(Prompt.NoPrompt) .WithLoginHint(DefaultUserUPN).ExecuteAsync(); authUITask.Wait(10000); authResult = authUITask.Result; _result = true; } catch (Exception ex2) { string _error2 = "GetTokenFromAAD: Failed to get interactive auth token: " + ExceptionChain(ex2); OOFSponder.Logger.Error(new Exception(_error2, ex2)); } //} } else { string _error = "GetTokenFromAAD: UI might be required for MSAL logon: " + ExceptionChain(ex); OOFSponder.Logger.Error(new Exception(_error)); } } //} } catch (Exception ex) { OOFSponder.Logger.Error(new Exception("Generalized auth failure: ** ", ex)); } finally { //store the UPN for future use if (authResult != null) { DefaultUserUPN = authResult.Account.Username; } //release the critical section we are using to prevent multiple auth prompts OOFSponder.Logger.Info("Leaving critical section for auth code"); semaphoreSlim.Release(); OOFSponder.Logger.Info("Left critical section for auth code"); } return(_result); }
private void exitToolStripMenuItem_Click(object sender, EventArgs e) { OOFSponder.Logger.Info(OOFSponderInsights.CurrentMethod()); minimize = false; System.Windows.Forms.Application.Exit(); }
private void exitToolStripMenuItem_Click(object sender, EventArgs e) { OOFSponderInsights.TrackInfo(OOFSponderInsights.CurrentMethod()); minimize = false; Application.Exit(); }
private void saveToolStripMenuItem_Click(object sender, EventArgs e) { OOFSponderInsights.TrackInfo(OOFSponderInsights.CurrentMethod()); saveSettings(); }
/// <summary> /// Call AcquireTokenAsync - to acquire a token requiring user to sign-in /// </summary> internal async static Task <bool> MSALWork(AADAction action) { OOFSponder.Logger.Info(OOFSponderInsights.CurrentMethod()); //lock this so we don't get multiple auth prompts OOFSponder.Logger.Info("Attempting to enter critical section for auth code"); await semaphoreSlim.WaitAsync(); OOFSponder.Logger.Info("Inside critical section for auth code"); bool _result = false; var accounts = await PublicClientApp.GetAccountsAsync(); var firstAccount = accounts.FirstOrDefault(); try { if (action == AADAction.SignIn | action == AADAction.ForceSignIn) { try { //MSAL 1.0 style - deprecated //authResult = await PublicClientApp.AcquireTokenSilentAsync(_scopes, PublicClientApp.Users.FirstOrDefault()); //MSAL 3.0 style authResult = await PublicClientApp.AcquireTokenSilent(_scopes, firstAccount).ExecuteAsync(); } catch (MsalUiRequiredException ex) { // A MsalUiRequiredException happened on AcquireTokenSilentAsync. This indicates you need to call AcquireTokenAsync to acquire a token //Don't track this one since it can basically be considered expected. OOFSponder.Logger.Warning(new Exception($"Unable to acquire token silently: ", ex)); try { //MSAL 1.0 style //authResult = await PublicClientApp.AcquireTokenAsync(_scopes); //MSAL 3.0 style authResult = await PublicClientApp.AcquireTokenInteractive(_scopes).ExecuteAsync(); } catch (MsalException msalex) { OOFSponder.Logger.Error(new Exception($"Error acquiring token interactively: ", msalex)); } } catch (Exception ex) { OOFSponder.Logger.Error(new Exception($"Error acquiring token: ", ex)); return(false); } //MSAL 1.0 style //if (PublicClientApp.Users.Count() > 0) //MSAL 3.0 style if (authResult != null) { _result = true; //also, update the Application Insights info with the authenticated user //MSAL 1.0 style //OOFSponderInsights.AIClient.Context.User.Id = authResult.User.DisplayableId.Split('@')[0]; //MSAL 3.0 style OOFSponderInsights.AIClient.Context.User.Id = authResult.Account.Username; } else { _result = false; } } else { //MSAL 1.0 //if (PublicClientApp.Users.Any()) //MSAL 3.0 if (firstAccount != null) { try { //MSAL 1.0 //PublicClientApp.Remove(PublicClientApp.Users.FirstOrDefault()); //MSAL 3.0 await PublicClientApp.RemoveAsync(firstAccount); _result = true; } catch (MsalException ex) { OOFSponder.Logger.Error(new Exception("Error signing out user: "******"MSAL code failed miserably for user: "******"Leaving critical section for auth code"); semaphoreSlim.Release(); OOFSponder.Logger.Info("Left critical section for auth code"); } return(_result); }
public async System.Threading.Tasks.Task <bool> TrySetOOF365(string oofMessageExternal, string oofMessageInternal, DateTime StartTime, DateTime EndTime) { OOFSponderInsights.TrackInfo(OOFSponderInsights.CurrentMethod()); toolStripStatusLabel1.Text = DateTime.Now.ToString() + " - Sending to O365"; //need to convert the times from local datetime to DateTimeTimeZone and UTC DateTimeTimeZone oofStart = new DateTimeTimeZone { DateTime = StartTime.ToUniversalTime().ToString("u").Replace("Z", ""), TimeZone = "UTC" }; DateTimeTimeZone oofEnd = new DateTimeTimeZone { DateTime = EndTime.ToUniversalTime().ToString("u").Replace("Z", ""), TimeZone = "UTC" }; //create local OOF object AutomaticRepliesSetting localOOF = new AutomaticRepliesSetting(); localOOF.ExternalReplyMessage = oofMessageExternal; localOOF.InternalReplyMessage = oofMessageInternal; localOOF.ScheduledStartDateTime = oofStart; localOOF.ScheduledEndDateTime = oofEnd; localOOF.Status = AutomaticRepliesStatus.Scheduled; try { OOFSponderInsights.Track("Getting OOF settings from O365"); string getOOFraw = await O365.GetHttpContentWithToken(O365.AutomatedReplySettingsURL); AutomaticRepliesSetting remoteOOF = JsonConvert.DeserializeObject <AutomaticRepliesSetting>(getOOFraw); OOFSponderInsights.Track("Successfully got OOF settings"); bool externalReplyMessageEqual = remoteOOF.ExternalReplyMessage.CleanReplyMessage() == localOOF.ExternalReplyMessage.CleanReplyMessage(); bool internalReplyMessageEqual = remoteOOF.InternalReplyMessage.CleanReplyMessage() == localOOF.InternalReplyMessage.CleanReplyMessage(); //local and remote are both UTC, so just compare times //Not sure it can ever happen to have the DateTime empty, but wrap this in a TryCatch just in case //set both to false - that way, we don't care if either one blows up //because if one is false, the overall evaluation is false anyway bool scheduledStartDateTimeEqual = false; bool scheduledEndDateTimeEqual = false; try { scheduledStartDateTimeEqual = DateTime.Parse(remoteOOF.ScheduledStartDateTime.DateTime) == DateTime.Parse(localOOF.ScheduledStartDateTime.DateTime); scheduledEndDateTimeEqual = DateTime.Parse(remoteOOF.ScheduledEndDateTime.DateTime) == DateTime.Parse(localOOF.ScheduledEndDateTime.DateTime); } catch (Exception) { //do nothing because we will just take the initialized false values; } if (!externalReplyMessageEqual || !internalReplyMessageEqual || !scheduledStartDateTimeEqual || !scheduledEndDateTimeEqual ) { OOFSponderInsights.Track("Local OOF doesn't match remote OOF"); System.Net.Http.HttpResponseMessage result = await O365.PatchHttpContentWithToken(O365.MailboxSettingsURL, localOOF); if (result.StatusCode == System.Net.HttpStatusCode.OK) { UpdateStatusLabel(toolStripStatusLabel1, DateTime.Now.ToString() + " - OOF message set - Start: " + StartTime + " - End: " + EndTime); //report back to AppInsights OOFSponderInsights.Track("Successfully set OOF"); return(true); } else { OOFSponderInsights.Track("Unable to set OOF"); UpdateStatusLabel(toolStripStatusLabel1, DateTime.Now.ToString() + " - Unable to set OOF message"); return(false); } } else { OOFSponderInsights.Track("Remote OOF matches - no changes"); UpdateStatusLabel(toolStripStatusLabel1, DateTime.Now.ToString() + " - No changes needed, OOF Message not changed - Start: " + StartTime + " - End: " + EndTime); return(true); } } catch (Exception ex) { notifyIcon1.ShowBalloonTip(100, "OOF Exception", "Unable to set OOF: " + ex.Message, ToolTipIcon.Error); UpdateStatusLabel(toolStripStatusLabel1, DateTime.Now.ToString() + " - Unable to set OOF"); OOFSponderInsights.TrackException("Unable to set OOF: " + ex.Message, ex); return(false); } }
private async System.Threading.Tasks.Task <bool> RunSetOofO365() { OOFSponderInsights.TrackInfo(OOFSponderInsights.CurrentMethod()); bool haveNecessaryData = false; //if CredMan is turned on, then we don't need the email or password //but we still need the OOF messages and working hours //also, don't need to check SecondaryOOF messages for two reasons: //1) they won't always be set //2) the UI flow won't let you get here with permaOOF if they aren't set if (OOFData.Instance.PrimaryOOFExternalMessage != "" && OOFData.Instance.PrimaryOOFInternalMessage != "" && OOFData.Instance.WorkingHours != "") { haveNecessaryData = true; OOFSponderInsights.Track("HaveNecessaryData"); } bool result = false; if (haveNecessaryData) { DateTime[] oofTimes = getOofTime(OOFData.Instance.WorkingHours); ////if PermaOOF is turned on, need to adjust the end time //if (OOFData.Instance.PermaOOFDate < oofTimes[0]) //{ // //set all the UI stuff back to primary // //to set up for normal OOF schedule // SetUIforPrimary(); //} //persist settings just in case string oofMessageExternal = htmlEditorControl1.BodyHtml; string oofMessageInternal = htmlEditorControl2.BodyHtml; //if (!OOFData.Instance.IsPermaOOFOn) //{ // OOFData.Instance.PrimaryOOFExternalMessage = htmlEditorControl1.BodyHtml; // OOFData.Instance.PrimaryOOFInternalMessage = htmlEditorControl2.BodyHtml; //} //else //{ // OOFData.Instance.SecondaryOOFExternalMessage = htmlEditorControl1.BodyHtml; // OOFData.Instance.SecondaryOOFInternalMessage = htmlEditorControl2.BodyHtml; //} //if PermaOOF isn't turned on, use the standard logic based on the stored schedule if ((oofTimes[0] != oofTimes[1]) && !OOFData.Instance.IsPermaOOFOn) { OOFSponderInsights.Track("TrySetNormalOOF"); #if !NOOOF result = await System.Threading.Tasks.Task.Run(() => TrySetOOF365(oofMessageExternal, oofMessageInternal, oofTimes[0], oofTimes[1])); #else result = true; #endif } else //since permaOOF is on, need to adjust the end date such that is permaOOFDate //if permaOOF>oofTimes[0] and permaOOF<oofTimes[1], then AddDays((permaOOFDate - oofTimes[1]).Days //due to the way the math works out, need to add extra day if permaOOF>oofTimes[1] { int adjustmentDays = 0; if (OOFData.Instance.PermaOOFDate > oofTimes[0] && OOFData.Instance.PermaOOFDate < oofTimes[1]) { adjustmentDays = 1; } //in order to accomodate someone going OOF mid-schedule //check if now is before the next scheduled "OFF" slot //if it is, then adjust start time to NOW if (oofTimes[0] > DateTime.Now) { oofTimes[0] = DateTime.Now; } OOFSponderInsights.Track("TrySetPermaOOF"); #if !NOOOF result = await System.Threading.Tasks.Task.Run(() => TrySetOOF365(oofMessageExternal, oofMessageInternal, oofTimes[0], oofTimes[1].AddDays((OOFData.Instance.PermaOOFDate - oofTimes[1]).Days + adjustmentDays))); #else result = true; #endif } } return(result); }
public Form1() { OOFSponderInsights.TrackInfo(OOFSponderInsights.CurrentMethod()); InitializeComponent(); #region SetBuildInfo foreach (Assembly a in Thread.GetDomain().GetAssemblies()) { if (a.GetName().Name == "OOFScheduling") { OOFData.version = lblBuild.Text = a.GetName().Version.ToString(); break; } } #endregion OOFSponderInsights.ConfigureApplicationInsights(); OOFSponderInsights.Track("OOFSponderStart"); //Set icon in code this.Icon = Properties.Resources.OOFSponderIcon; #region Add to Startup // The path to the key where Windows looks for startup applications RegistryKey rkApp = Registry.CurrentUser.OpenSubKey( @"SOFTWARE\Microsoft\Windows\CurrentVersion\Run", true); //Path to launch shortcut string startPath = Environment.GetFolderPath(Environment.SpecialFolder.Programs) + @"\Microsoft\OOFSponder.appref-ms"; rkApp.SetValue("OOFSponder", startPath); #endregion #region Tray Menu Initialize // Create a simple tray menu with only one item. trayMenu = new ContextMenu(); trayMenu.MenuItems.Add("Exit", OnExit); // Add menu to tray icon and show it. notifyIcon1.ContextMenu = trayMenu; notifyIcon1.Icon = Properties.Resources.OOFSponderIcon; #endregion #region Read the list of teams to populate with templates //Read in the list of teams and build the dictionary list of team name //and template location //for each team, add an entry to the the Team Settings menu item (teamSettingsToolStripMenuItem) //If Use Team Settings is checked and a team is selected //then pull the remote files in as the text and then set the //controls to ReadOnly //Use a naming convention of "ExternalOOF.html" and "InternalOOF.html"? //Will also need to add some #Start/#End/#TimeZone logic //could even get fancy and have that be some sort of pop-up //so that each team could have its own //this is definitely future work :) #endregion //prep for async work System.Threading.Tasks.Task AuthTask = null; AuthTask = System.Threading.Tasks.Task.Run((Action)(() => { O365.MSALWork(O365.AADAction.SignIn); })); #if DEBUGFLOW MessageBox.Show("Attach now", "OOFSponder", MessageBoxButtons.OK); #endif if (OOFData.Instance.IsPermaOOFOn) { SetUIforSecondary(); } else { SetUIforPrimary(); } if (OOFData.Instance.WorkingHours != "") { string[] workingHours = OOFData.Instance.WorkingHours.Split('|'); //Zero means you are off that day (not working) therefore the box is checked string[] dayHours = workingHours[0].Split('~'); if (dayHours[2] == "0") { sundayOffWorkCB.Checked = true; } else { sundayOffWorkCB.Checked = false; } sundayStartTimepicker.Value = DateTime.Parse(dayHours[0]); sundayEndTimepicker.Value = DateTime.Parse(dayHours[1]); dayHours = workingHours[1].Split('~'); if (dayHours[2] == "0") { mondayOffWorkCB.Checked = true; } else { mondayOffWorkCB.Checked = false; } mondayStartTimepicker.Value = DateTime.Parse(dayHours[0]); mondayEndTimepicker.Value = DateTime.Parse(dayHours[1]); dayHours = workingHours[2].Split('~'); if (dayHours[2] == "0") { tuesdayOffWorkCB.Checked = true; } else { tuesdayOffWorkCB.Checked = false; } tuesdayStartTimepicker.Value = DateTime.Parse(dayHours[0]); tuesdayEndTimepicker.Value = DateTime.Parse(dayHours[1]); dayHours = workingHours[3].Split('~'); if (dayHours[2] == "0") { wednesdayOffWorkCB.Checked = true; } else { wednesdayOffWorkCB.Checked = false; } wednesdayStartTimepicker.Value = DateTime.Parse(dayHours[0]); wednesdayEndTimepicker.Value = DateTime.Parse(dayHours[1]); dayHours = workingHours[4].Split('~'); if (dayHours[2] == "0") { thursdayOffWorkCB.Checked = true; } else { thursdayOffWorkCB.Checked = false; } thursdayStartTimepicker.Value = DateTime.Parse(dayHours[0]); thursdayEndTimepicker.Value = DateTime.Parse(dayHours[1]); dayHours = workingHours[5].Split('~'); if (dayHours[2] == "0") { fridayOffWorkCB.Checked = true; } else { fridayOffWorkCB.Checked = false; } fridayStartTimepicker.Value = DateTime.Parse(dayHours[0]); fridayEndTimepicker.Value = DateTime.Parse(dayHours[1]); dayHours = workingHours[6].Split('~'); if (dayHours[2] == "0") { saturdayOffWorkCB.Checked = true; } else { saturdayOffWorkCB.Checked = false; } saturdayStartTimepicker.Value = DateTime.Parse(dayHours[0]); saturdayEndTimepicker.Value = DateTime.Parse(dayHours[1]); } bool haveNecessaryData = false; //we need the OOF messages and working hours if (OOFData.Instance.PrimaryOOFExternalMessage != "" && OOFData.Instance.PrimaryOOFInternalMessage != "" && OOFData.Instance.WorkingHours != "") { haveNecessaryData = true; } if (haveNecessaryData) { toolStripStatusLabel1.Text = "Ready"; OOFSponderInsights.TrackInfo("HaveNecessaryData"); } else { toolStripStatusLabel1.Text = "Please setup OOFsponder"; OOFSponderInsights.TrackInfo("MissingData"); } toolStripStatusLabel2.Text = ""; Loopy(); //set up handlers to persist OOF messages htmlEditorControl1.Validated += htmlEditorValidated; htmlEditorControl2.Validated += htmlEditorValidated; //wait on async auth stuff if not null if (AuthTask != null) { AuthTask.Wait(); } //trigger a check on current status System.Threading.Tasks.Task.Run(() => RunSetOofO365()); radPrimary.CheckedChanged += new System.EventHandler(radPrimary_CheckedChanged); fileToolStripMenuItem.DropDownOpening += fileToolStripMenuItem_DropDownOpening; }