diff --git a/Application/App.config b/Application/App.config
index e0826fc..a746db7 100644
--- a/Application/App.config
+++ b/Application/App.config
@@ -8,10 +8,11 @@
-
-
+
+
+
@@ -27,6 +28,7 @@
+
diff --git a/Application/Forms/MainForm.Designer.cs b/Application/Forms/MainForm.Designer.cs
index 1242a71..2494dbd 100644
--- a/Application/Forms/MainForm.Designer.cs
+++ b/Application/Forms/MainForm.Designer.cs
@@ -30,6 +30,7 @@ private void InitializeComponent()
this.viewInboxToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.checkMailNowToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.tellMeAgainToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.lastEmailInfoToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.optionsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.aboutToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripSeparator();
@@ -41,12 +42,13 @@ private void InitializeComponent()
// notifyIcon
//
this.notifyIcon.BalloonTipIcon = System.Windows.Forms.ToolTipIcon.Info;
- this.notifyIcon.BalloonTipText = "You have no unread mail.";
+ this.notifyIcon.BalloonTipText = "n/a";
this.notifyIcon.BalloonTipTitle = "Gmail";
this.notifyIcon.ContextMenuStrip = this.contextMenuStrip;
this.notifyIcon.Icon = ((System.Drawing.Icon)(resources.GetObject("notifyIcon.Icon")));
- this.notifyIcon.Text = "No unread mail";
+ this.notifyIcon.Text = "No info available";
this.notifyIcon.Visible = true;
+ this.notifyIcon.BalloonTipClicked += new System.EventHandler(this.notifyIcon_BalloonTipClicked);
this.notifyIcon.DoubleClick += new System.EventHandler(this.notifyIcon_DoubleClick);
//
// contextMenuStrip
@@ -55,6 +57,7 @@ private void InitializeComponent()
this.viewInboxToolStripMenuItem,
this.checkMailNowToolStripMenuItem,
this.tellMeAgainToolStripMenuItem,
+ this.lastEmailInfoToolStripMenuItem,
this.optionsToolStripMenuItem,
this.aboutToolStripMenuItem,
this.toolStripMenuItem1,
@@ -84,6 +87,13 @@ private void InitializeComponent()
this.tellMeAgainToolStripMenuItem.Text = "Tell Me A&gain";
this.tellMeAgainToolStripMenuItem.Click += new System.EventHandler(this.tellMeAgainToolStripMenuItem_Click);
//
+ // lastEmailInfoToolStripMenuItem
+ //
+ this.lastEmailInfoToolStripMenuItem.Name = "lastEmailInfoToolStripMenuItem";
+ this.lastEmailInfoToolStripMenuItem.Size = new System.Drawing.Size(161, 22);
+ this.lastEmailInfoToolStripMenuItem.Text = "&Last email info";
+ this.lastEmailInfoToolStripMenuItem.Click += new System.EventHandler(this.lastEmailInfoToolStripMenuItem_Click);
+ //
// optionsToolStripMenuItem
//
this.optionsToolStripMenuItem.Name = "optionsToolStripMenuItem";
@@ -140,6 +150,7 @@ private void InitializeComponent()
private System.Windows.Forms.Timer timer;
private System.Windows.Forms.ToolStripSeparator toolStripMenuItem1;
private System.Windows.Forms.ToolStripMenuItem exitToolStripMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem lastEmailInfoToolStripMenuItem;
}
}
diff --git a/Application/Forms/MainForm.cs b/Application/Forms/MainForm.cs
index b5afdc5..f0a1071 100644
--- a/Application/Forms/MainForm.cs
+++ b/Application/Forms/MainForm.cs
@@ -15,8 +15,17 @@ public partial class MainForm : Form
// Logger
private static readonly ILog Logger = LogManager.GetLogger(typeof(MainForm));
+ // Settings defaults
+ private const int m_notificationDelay_Min = 1; //seconds
+ private const int m_notificationDelay_Max = 60;
+ private const int m_notificationDelay_Default = 5;
+ private const int m_CheckInterval_Min = 1; //minutes
+ private const int m_CheckInterval_Max = 60;
+ private const int m_CheckInterval_Default = 1;
+
// These settings are configurable via the app.config file
private int notificationDelay;
+ private String gmailUrl;
// The current state of the inbox
private int unreadCount;
@@ -36,14 +45,15 @@ public MainForm()
InitializeComponent();
// Load the configuration
- this.notificationDelay = Convert.ToInt32(ConfigurationManager.AppSettings["NotificationDelay"]);
+ LoadConfig();
// Initialize the ATOM client
+ if (ConfigurationManager.AppSettings["AtomFeedUrl"].ToString() == string.Empty)
+ {
+ throw new ArgumentNullException("[AtomFeedUrl]", "Invalid config: [AtomFeedUrl] not set !");
+ }
this.atomMailChecker = new AtomMailChecker(ConfigurationManager.AppSettings["AtomFeedUrl"]);
- // Set the timer interval from the config (convert minutes to milliseconds)
- timer.Interval = Convert.ToInt32(ConfigurationManager.AppSettings["CheckInterval"]) * 60 * 1000;
-
// Have we set the username/password already?
if (string.IsNullOrEmpty(UserSettings.Default.Username))
{
@@ -57,6 +67,39 @@ public MainForm()
}
}
+ // Loads the configuration
+ private void LoadConfig()
+ {
+ // Set the notification baloon delay
+ int a_notificationDelay = Convert.ToInt32(ConfigurationManager.AppSettings["NotificationDelay"]);
+ if (a_notificationDelay > m_notificationDelay_Max || a_notificationDelay < m_notificationDelay_Min)
+ {
+ Logger.Warn("Invalid config: [NotificationDelay] = " + a_notificationDelay.ToString() + " ! ...using default");
+ a_notificationDelay = m_notificationDelay_Default;
+ }
+ this.notificationDelay = a_notificationDelay * 1000; // (convert seconds to milliseconds)
+
+ // Set the timer interval from the config
+ int a_CheckInterval = Convert.ToInt32(ConfigurationManager.AppSettings["CheckInterval"]);
+ if (a_CheckInterval > 60 || a_CheckInterval < 1)
+ {
+ Logger.Warn("Invalid config: [CheckInterval] = " + a_CheckInterval.ToString() + " ! ...using default");
+ a_CheckInterval = m_CheckInterval_Default;
+ }
+ timer.Interval = a_CheckInterval * 60 * 1000; // (convert seconds to milliseconds)
+
+ //Gmail url
+ if (ConfigurationManager.AppSettings["GoogleMailUrl"].ToString().Length == 0)
+ {
+ Logger.Warn("Invalid config: [GoogleMailUrl] = " + ConfigurationManager.AppSettings["GoogleMailUrl"].ToString() + " ! ...using default");
+ this.gmailUrl = "https://www.google.com/accounts/ServiceLogin?service=mail";
+ }
+ else
+ {
+ this.gmailUrl = ConfigurationManager.AppSettings["GoogleMailUrl"].ToString();
+ }
+ }
+
// This makes sure that this window is always hidden
protected override void SetVisibleCore(bool value)
{
@@ -70,7 +113,7 @@ protected override void SetVisibleCore(bool value)
}
// Downloads the latest Atom feed to check for new mail
- private void CheckMail()
+ private void CheckMail(bool showLast = false)
{
Logger.Debug("Checking mail...");
@@ -84,6 +127,12 @@ private void CheckMail()
Logger.Warn("Missing credentials");
notifyIcon.Icon = SystrayIcons.SystrayIconError;
notifyIcon.Text = "Please set username/password in Options";
+ if (showLast)
+ {
+ notifyIcon.BalloonTipTitle = "Gmail";
+ notifyIcon.BalloonTipText = "Please set username/password in Options";
+ notifyIcon.ShowBalloonTip(notificationDelay);
+ }
return;
}
@@ -101,20 +150,32 @@ private void CheckMail()
// Show a notification
if (unreadCount > 0)
{
+ if (showLast)
+ lastMail = null;
+
var newEmails = atomMailChecker.GetNewEmails(lastMail);
- if (newEmails.Count() == 1)
+ if (showLast)
{
- notifyIcon.BalloonTipTitle = "New mail from: " + newEmails.Single().From;
- notifyIcon.BalloonTipText = newEmails.Single().Subject + Environment.NewLine + newEmails.Single().Preview;
+ notifyIcon.BalloonTipTitle = "Last mail from: " + newEmails.First().From;
+ notifyIcon.BalloonTipText = "[Subject:] " + newEmails.First().Subject + Environment.NewLine + "[Preview:] " + newEmails.First().Preview;
notifyIcon.ShowBalloonTip(notificationDelay);
}
- if (newEmails.Count() > 1)
+ else
{
- notifyIcon.BalloonTipTitle = "You've got mail";
- notifyIcon.BalloonTipText = string.Format("You have {0} new emails", unreadCount);
- notifyIcon.ShowBalloonTip(notificationDelay);
- }
+ if (newEmails.Count() == 1)
+ {
+ notifyIcon.BalloonTipTitle = "New mail from: " + newEmails.Single().From;
+ notifyIcon.BalloonTipText = "[Subject:] " + newEmails.Single().Subject + Environment.NewLine + "[Preview:] " + newEmails.Single().Preview;
+ notifyIcon.ShowBalloonTip(notificationDelay);
+ }
+ if (newEmails.Count() > 1)
+ {
+ notifyIcon.BalloonTipTitle = "You've got mail";
+ notifyIcon.BalloonTipText = string.Format("You have {0} new emails", unreadCount);
+ notifyIcon.ShowBalloonTip(notificationDelay);
+ }
+ }
}
else
{
@@ -158,6 +219,12 @@ private void ShowOptions()
{
if (optionsForm.DialogResult == DialogResult.OK)
CheckMail();
+ else if (string.IsNullOrEmpty(UserSettings.Default.Username) || string.IsNullOrEmpty(UserSettings.Default.Password))
+ {
+ Logger.Warn("Missing credentials");
+ notifyIcon.Icon = SystrayIcons.SystrayIconError;
+ notifyIcon.Text = "Please set username/password in Options";
+ }
optionsForm = null;
};
@@ -186,13 +253,13 @@ private void ShowAbout()
private void notifyIcon_DoubleClick(object sender, EventArgs e)
{
Logger.Debug("System tray icon: double click");
- Process.Start("https://mail.google.com");
+ Process.Start(gmailUrl);
}
private void viewInboxToolStripMenuItem_Click(object sender, EventArgs e)
{
Logger.Debug("Context menu: view inbox");
- Process.Start("https://mail.google.com");
+ Process.Start(gmailUrl);
}
private void checkMailNowToolStripMenuItem_Click(object sender, EventArgs e)
@@ -224,6 +291,21 @@ private void exitToolStripMenuItem_Click(object sender, EventArgs e)
Application.Exit();
}
+ private void lastEmailInfoToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ Logger.Debug("Context menu: show last email");
+ CheckMail(true);
+ }
+
+ private void notifyIcon_BalloonTipClicked(object sender, EventArgs e)
+ {
+ Logger.Debug("Baloon tooltip: clicked");
+ if (unreadCount > 0)
+ {
+ Process.Start(gmailUrl);
+ }
+ }
+
#endregion
}
}
diff --git a/Application/Forms/OptionsForm.Designer.cs b/Application/Forms/OptionsForm.Designer.cs
index c79d010..90fb398 100644
--- a/Application/Forms/OptionsForm.Designer.cs
+++ b/Application/Forms/OptionsForm.Designer.cs
@@ -102,9 +102,9 @@ private void InitializeComponent()
this.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(91, 61);
this.label3.Name = "label3";
- this.label3.Size = new System.Drawing.Size(212, 26);
+ this.label3.Size = new System.Drawing.Size(217, 26);
this.label3.TabIndex = 6;
- this.label3.Text = "Make sure you use an \r\nIt will not work with your account password!";
+ this.label3.Text = "Make sure you use an \r\nIt may not work with your account password!";
//
// appPasswordLink
//
@@ -119,6 +119,7 @@ private void InitializeComponent()
//
// OptionsForm
//
+ this.AcceptButton = this.okButton;
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.CancelButton = this.cancelButton;
diff --git a/Application/Program.cs b/Application/Program.cs
index ef14266..70c015b 100644
--- a/Application/Program.cs
+++ b/Application/Program.cs
@@ -21,7 +21,15 @@ static void Main()
Application.ThreadException += HandleError;
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
- Application.Run(new MainForm());
+ try
+ {
+ Application.Run(new MainForm());
+ }
+ catch (Exception ex)
+ {
+ Logger.Error("Error while running program!", ex);
+ MessageBox.Show("Error while running program!\nSee log for details.\nProgram will close.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
Logger.Info("Program closed.");
}
diff --git a/Application/Properties/AssemblyInfo.cs b/Application/Properties/AssemblyInfo.cs
index 2ec8f1c..a45105c 100644
--- a/Application/Properties/AssemblyInfo.cs
+++ b/Application/Properties/AssemblyInfo.cs
@@ -31,8 +31,8 @@
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
-[assembly: AssemblyVersion("1.2.0")]
-[assembly: AssemblyFileVersion("1.2.0")]
+[assembly: AssemblyVersion("1.2.1")]
+[assembly: AssemblyFileVersion("1.2.1")]
// Initialize log4net
[assembly: log4net.Config.XmlConfigurator(Watch = false)]
\ No newline at end of file
diff --git a/ReadMe.md b/ReadMe.md
index 11948e0..29b2b2f 100644
--- a/ReadMe.md
+++ b/ReadMe.md
@@ -46,6 +46,22 @@ On the first run, you will be asked for credentials (these will be stored [secur
Change Log
===============================
+**1.2.1 - Mar 3, 2015**
+ [by yanoschik]
+ - (minor) added few comments to code and config
+ - config modifications:
+ - NotificationDelay key changed to represent seconds
+ - added key for Google mail url, which replaces the previously hardcoded one (used for opening mailbox in browser)
+ - default logging level set to INFO
+ - reading config moved to a separate method
+ - important config variables are checked for reasonable values, defaults used if failed
+ - added option to show last mail -info in baloon tooltip
+ - clicking on baloon now also opens the browser (like doubleclick on icon or menuitem)
+ - config dialog has the accept button OK assigned (pressing Enter = clicking OK)
+ - minor text changes in baloon tooltips
+ - general handling of exceptions from MainForm -> log & show message before exit
+ - some minor changes (initial texts for icon and baloontip; notification improved when credentials error occurs; etc.)
+
**1.2 - Mar 3, 2014**
- Credentials now set via the Options dialog instead of directly in the config file, and stored securely using the Windows Data Protection API.