Build a Simple Gmail Notifier using Windows Forms

Posted by: Shoban Kumar , on 3/26/2009, in Category WinForms & WinRT
Views: 132447
Abstract: Google does not have an official Gmail API. Having one would have made it very easy to create a notification application. In this article, I will show you how to exploit the Feed facility of Gmail to build our own Gmail Notifier.
Build a Simple Gmail Notifier using Windows Forms
 
Google does not have an official Gmail API. Having one would have made it very easy to create a notification application. In this article, I will show you how to exploit the Feed facility of Gmail to build our own Gmail Notifier.
Gmail Feed is an useful feature provided by Gmail using which we can subscribe to emails using a Feed reader supporting authentication. You have feeds for your unread mails as well as feeds for your labels.
Before starting to build the application, let’s see how our final product will look like. Below are the screenshots of Login and Notifier screens.

 
GMail Notifier Login
Notifier
Let’s get started.
Step 1: Fire up Visual Studio 2008 and Create a new Windows Application by going to File > New Project > Windows > Windows Form Application
 
Step 2: Add a new form ‘Login form’ to the project by Right Click > Add > New Item. Add 2 textboxes and 1 Button control to the Form. Name the Textboxes as ‘UsernameTextBox’ and ‘PasswordTextBox’ respectively.
 
Step 3: Now go back to Form1 (default form which was added when you created this project) and add 2 labels and a Timer control and name the 2 labels as ‘lblFrom’ andlblMessage’respectively.
 
Step 4: Add a Class file to the project, to declare Global Variables used in the project using Right Click -> Add -> New Item
 
Add the following code to the class file:
 
C#
internal static class GlobalVariables
{
      public static string[] emailFrom = new string[2];
      public static string[] emailMessages = new string[2];
      public static Int16 tempCounter = 0;
      public static Int16 mailCount = 0;
}
 
 
VB.NET
Module GlobalVariables
    Public emailFrom(1), emailMessages(1) As String
    Public tempCounter As Int16 = 0
    Public mailCount As Int16 = 0
End Module
 
Step 5: Double Click the ‘OKbutton in the Login form and type in the following code to the Click event
 
VB.NET
Imports System.Xml
Imports System.Text
 
Public Class LoginForm1
    Private Sub OK_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles OK.Click
        Dim objClient As New System.Net.WebClient
        Dim nodelist As XmlNodeList
        Dim node As XmlNode
        Dim response As String
        Dim xmlDoc As New XmlDocument
        Try
 
            objClient.Credentials = New System.Net.NetworkCredential(UsernameTextBox.Text.Trim, PasswordTextBox.Text.Trim)
            response = Encoding.UTF8.GetString(objClient.DownloadData("https://mail.google.com/mail/feed/atom"))
            response = response.Replace("<feed version=""0.3"" xmlns=""http://purl.org/atom/ns#"">", "<feed>")
 
            xmlDoc.LoadXml(response)
            node = xmlDoc.SelectSingleNode("/feed/fullcount")
            mailCount = node.InnerText 'Get the number of unread emails
 
            If mailCount > 0 Then
                ReDim emailFrom(mailCount - 1)
                ReDim emailMessages(mailCount - 1)
                nodelist = xmlDoc.SelectNodes("/feed/entry")
                node = xmlDoc.SelectSingleNode("title")
 
                For Each node In nodelist
                    emailMessages(tempCounter) = node.ChildNodes.Item(0).InnerText
                    emailFrom(tempCounter) = node.ChildNodes.Item(6).ChildNodes(0).InnerText
                    tempCounter += 1
                Next
                tempCounter = 0
            End If
            Me.Hide()
            Form1.Show()
        Catch ex As Exception
            MsgBox(ex.Message)
        End Try
    End Sub
 
End Class
 
Explanation :  In the code shown above, we first create a new object of ‘Webclient’ class and then request feed from Gmail using the Username and Password as the network credentials. ‘Gmail Feed’ is an useful feature provided by Gmail using which we can subscribe to emails using a Feed reader supporting authentication.
 
Gmail feed is an ATOM feed. Here is an article from MSDN about how we can parse ATOM feeds. But to make our job easier we remove the text <feed version="0.3"mlns="http://purl.org/atom/ns#"> which will help us to parse the response as a normal XML file using ‘XmlDocument’
 
Once the XML message is received, we use the /feed/fullcount to check for any new emails and assign the value to ‘mailCount’. If this value is greater than 0, we store the unread message details in an array.
 
 
Step 6: Now open the Form1 ‘Load’ event and add the folowing code which will position the window at the bottom right corner as shown in the screenshot at the beginning of the article.
 
C#
 
private void Form1_Load(object sender, System.EventArgs e)
{
            Timer1.Enabled = true;
            this.Hide();
            this.ShowInTaskbar = false;
            Left = (SystemInformation.WorkingArea.Size.Width - Size.Width);
            Top = (SystemInformation.WorkingArea.Size.Height - Size.Height);
}
 
VB.NET
 
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Timer1.Enabled = True
        Me.Hide()
        Me.ShowInTaskbar = False
        Left = (SystemInformation.WorkingArea.Size.Width - Size.Width)
        Top = (SystemInformation.WorkingArea.Size.Height - Size.Height)
    End Sub
 
Step 7: Now set the Timer’s interval to 2000 (2 seconds) and add the following code to the ‘Tickevent.
 
C#
 
   private void Timer1_Tick(object sender, System.EventArgs e)
   {
            this.Show();
            if (tempCounter >= mailCount)
            {
                  Timer1.Enabled = false;
                  this.Hide();
            }
            else
            {
                  lblFrom.Text = "From : " + emailFrom(tempCounter);
                  lblMessage.Text = "Subject : " + emailMessages(tempCounter);
                  tempCounter += 1;
            }
 
      }
 
 
VB.NET
 
   Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
        Me.Show()
        If tempCounter >= mailCount Then
            Timer1.Enabled = False
            Me.Hide()
        Else
            lblFrom.Text = "From : " & emailFrom(tempCounter)
            lblMessage.Text = "Subject : " & emailMessages(tempCounter)
            tempCounter += 1
        End If
 
    End Sub
 
That’s it. Now run the project and see your Gmail Notifier in action. The source code of this article can be downloaded from here.

This article has been editorially reviewed by Suprotim Agarwal.

Absolutely Awesome Book on C# and .NET

C# and .NET have been around for a very long time, but their constant growth means there’s always more to learn.

We at DotNetCurry are very excited to announce The Absolutely Awesome Book on C# and .NET. This is a 500 pages concise technical eBook available in PDF, ePub (iPad), and Mobi (Kindle).

Organized around concepts, this Book aims to provide a concise, yet solid foundation in C# and .NET, covering C# 6.0, C# 7.0 and .NET Core, with chapters on the latest .NET Core 3.0, .NET Standard and C# 8.0 (final release) too. Use these concepts to deepen your existing knowledge of C# and .NET, to have a solid grasp of the latest in C# and .NET OR to crack your next .NET Interview.

Click here to Explore the Table of Contents or Download Sample Chapters!

What Others Are Reading!
Was this article worth reading? Share it with fellow developers too. Thanks!
Share on LinkedIn
Share on Google+

Author
ShobanKumar is an ex-Microsoft MVP in SharePoint who currently works as a SharePoint Consultant. You can read more about his projects at http://shobankumar.com. You can also follow him on twitter @shobankr


Page copy protected against web site content infringement 	by Copyscape




Feedback - Leave us some adulation, criticism and everything in between!
Comment posted by isidro on Thursday, March 26, 2009 9:25 AM
Nice, very good
Comment posted by Burn on Friday, April 3, 2009 2:49 PM
Why is there no C# example in step 5?  Is it possible to get source for C#
Comment posted by Ken on Thursday, April 23, 2009 2:42 PM
For Step #5 you listed only VB.NET code.
Any chance on the C# equivalent?
Comment posted by SM on Friday, May 15, 2009 6:20 PM
Is there a way to view the message of the email as well as Sender and Subject?
Comment posted by SM on Friday, May 15, 2009 8:47 PM
Never mind, I figured it out:

node.ChildNodes.Item(1).ChildNodes(0).InnerText
Comment posted by D on Saturday, June 6, 2009 12:48 PM
You do not need C# for step 5, it is super simple to rewrite the vb code to C#. If you can't handle that, you should not be coding at all!
Great article!
Comment posted by danny waters on Sunday, July 12, 2009 12:46 PM
I have a question, do you need to re-authenticate every time you want to update your feed ?
Comment posted by M on Tuesday, August 18, 2009 8:59 AM
Getting the folowing error
"The remote server returned an error: (401) Unauthorized."

any clues?
Comment posted by Shoban Kumar on Sunday, August 23, 2009 12:05 PM
Hi M

Make sure your userid and password are correct and try again.

Shoban
Comment posted by John on Sunday, October 18, 2009 4:46 PM
Seams that it didnt work. idk why
Comment posted by cm on Wednesday, October 21, 2009 12:06 AM
Is there a way to view the attachment of the email
Comment posted by dariya on Sunday, November 8, 2009 11:59 PM
this is my code:::
response=Encoding.UTF8.GetString(objClient.DownloadData("https://mail.google.com/mail/feed/atom"));
            response = response.Replace("<feed version='0.3' xmlns=h-*ttp://purl.org/atom/ns#>", "<feed>");
            xmlDocument = new XmlDocument();
            xmlDocument.LoadXml(response);
            //string nodeValue = "";
            node = xmlDocument.SelectSingleNode("/feed/title/text()");

i am getting the node value null.it contains the data then also node value  is returning null.
Comment posted by Justin on Wednesday, June 2, 2010 2:55 PM
By chance, do you know the feed url scheme for a nested label? I cannot find this anywhere.
Comment posted by Kishor Sing on Friday, July 16, 2010 5:36 AM
Very Nice ...


Comment posted by shane on Friday, August 20, 2010 12:16 AM
Hi

could you please post the c# code for step 5 im very new and dont have a clue how to do it myself
Comment posted by Prajeesh on Wednesday, September 22, 2010 11:32 AM


private void btnOk_Click(object sender, EventArgs e)
        {
            System.Net.WebClient objClient = new System.Net.WebClient();
            XmlNodeList nodelist = default(XmlNodeList);
            XmlNode node = default(XmlNode);
            string response = null;
            XmlDocument xmlDoc = new XmlDocument();

            try
            {

                objClient.Credentials = new System.Net.NetworkCredential(txtUser.Text.Trim, txtPwd.Text.Trim);
                response = Encoding.UTF8.GetString(objClient.DownloadData("https://mail.google.com/mail/feed/atom"));
                response = response.Replace("<feed version=\"0.3\" xmlns=\"http://purl.org/atom/ns#\">", "<feed>");

                xmlDoc.LoadXml(response);
                node = xmlDoc.SelectSingleNode("/feed/fullcount");
                mailCount = node.InnerText;

                //Get the number of unread emails

                if (mailCount > 0)
                {
                    // ERROR: Not supported in C#: ReDimStatement

                    // ERROR: Not supported in C#: ReDimStatement

                    nodelist = xmlDoc.SelectNodes("/feed/entry");
                    node = xmlDoc.SelectSingleNode("title");

                    foreach (XmlNode node in nodelist)
                    {
                        emailMessages(tempCounter) = node.ChildNodes.Item(0).InnerText;
                        emailFrom(tempCounter) = node.ChildNodes.Item(6).ChildNodes(0).InnerText;
                        tempCounter += 1;
                    }
                    tempCounter = 0;
                }
                //this.Hide()

              
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                // Interaction.MsgBox(ex.Message);
            }
        }
Comment posted by sharad on Thursday, September 23, 2010 8:40 AM
after doing everything as u stated, when i run the project it doesn't even produce the window.. no window opens.. neither first nor the second one.. what should i do?
Comment posted by weng on Monday, September 27, 2010 2:09 AM
Very nice code. Is there other way also to retrieve the all read messages?

Thanks and regards,
Weng
Comment posted by ubaid on Monday, December 13, 2010 4:33 AM
any chance u will update the code.. gives me (401) Unauthorized..
Comment posted by henry on Wednesday, January 5, 2011 5:30 AM
Does anyone have full project in C#? I mean can anyone put attachment? I have problem with sting array emailFrom and emailMessages, there are always errors "The name 'emailFrom' does not exist in the current context" and   "The name 'emailMessages' does not exist in the current context". I have created class just as you said and I have no problems with tempCounter and mailCount variables.

Thanks in advance!   

Comment posted by mercury86 on Monday, January 31, 2011 4:28 PM
Great article man! I have implemented your code in c#.net and it is working!!! :)
Comment posted by Ravinder on Monday, April 11, 2011 8:07 AM

Hello,

what should i give network credentials .
if its gmail credentials or some other.
I have given gmail credentials .But I am getting "Unauthorized client"
If some other crendentials .Please provide steps.

Please give reoly.

Thanks&Regards
Ravinder
Comment posted by Sathinath Panda on Thursday, October 20, 2011 3:03 AM
Hi Friends

I am Sathinath Panda and i am From INDIA I have make a Group Which name is ( ASA-Products-2010 ) Currently my Group contains 3 members.I am looking for Members who can join my group and work with us.Since August 2010 I am making a Software and it will be launch on 2012 1st January.But before that i want more members in my Group to Strong it.If any One Join here then his / her Name will be taken listed in our Software

Our Aim is To create Lots of Helpful Software Program for Peoples and advertise it on most popular Site and Become a Successful Group in World.Please Send Your Opinion.Through Our Email as an early basis.I am waiting For Your Kind Reply.


Our Group Email ID - ( asaproducts2010@gmail.com )

Our Skype ID - ( asa.products.2010 )

My Personal Email ID ( sathinathpanda89@gmail.com )
Comment posted by Rohit on Monday, December 5, 2011 5:41 AM
You have not shown any code to invoke login form. Please complete the code.
"mailCount = node.InnerText" will never work there is no explicit conversion used. Unfortunately I cannot download .zip due to some security policy, but seems like your 5 min attention would help lots of developer productive hours to make your code workable.

Bythe way your code help me to get some direction on getting gmail notification.

Thanks!
Comment posted by Abe on Wednesday, February 22, 2012 10:56 PM
Hi,
Your software really helped me a lot. All I wanted is to get the email address and the subject of the email, & your code helped me not to get stock with pop3
Can u please tell me the which Node is the the senders email address, not only the display name?
Comment posted by Abe on Thursday, February 23, 2012 4:34 PM
Hi,
Your software really helped me a lot. All I wanted is to get the email address and the subject of the email, & your code helped me not to get stock with pop3
Can u please tell me the which Node is the the senders email address, not only the display name?
Comment posted by Abe on Thursday, February 23, 2012 9:31 PM
Hi,
Your software really helped me a lot. All I wanted is to get the email address and the subject of the email, & your code helped me not to get stock with pop3
Can u please tell me the which Node is the the senders email address, not only the display name?
Comment posted by Kishor Patil on Monday, March 5, 2012 6:28 AM
its wonderful article! I have implemented your code in vb.net and it is working!!! :) Thank you very much.......
Comment posted by Dan on Sunday, April 22, 2012 7:10 AM
This is excellent,  it helped me to understand how to access my data from Google. Many thanks for very useful tutorial/ example.
Comment posted by Ishthi on Wednesday, June 13, 2012 12:35 PM
Dear Shoban, this is the best article I come across regarding gmail checking, my question is, is there any algorithm to make a email message which we retrieve to mark as Read, and after thet if I check again using the atom method read mail should not be shown, possible?
Comment posted by auvy on Friday, August 10, 2012 11:34 AM
i need some more help. if it have the C# source code for download.
Comment posted by Madhu on Saturday, August 18, 2012 6:05 AM
Very Nice, Working Good, How to get time of the mail.
Comment posted by Kerry on Tuesday, September 11, 2012 1:07 AM
Your code works nicely. Thank you!

I used the vb.net version and the only changes I had to make was to change the startup form to the [Login] form: right-click project name > properties > 'Startup Form' dropdown box.

For those getting 401 errors, remember that you have to go to your gmail account settings and generate a verification code for your app. Use the 16-character code in the password box in place of your gmail password.
Comment posted by amit on Saturday, October 6, 2012 4:49 AM
Hi,
your article is great. Is there a way to get the sender mail id. or a way to get chat history ?
Comment posted by Muhammad Ali on Sunday, November 4, 2012 5:38 AM
Hello your code is great, it is running good on vb but when i run  it on c# it gives me error "index was out of bound of array" i am new to c# please guide me how to do it i am waiting for your help thanks .
Comment posted by Muhammad Ali on Sunday, November 4, 2012 5:54 AM
Hello your code is great, it is running good on vb but when i run  it on c# it gives me error "index was out of bound of array" i am new to c# please guide me how to do it i am waiting for your help thanks .
Comment posted by RB on Monday, February 11, 2013 11:28 AM
Thanks man ,its working .thanks a lot...

RB
Comment posted by Mohit Patel on Thursday, February 28, 2013 7:54 AM
Not working
"The remote server returned an error: (407) Proxy Authentication Required."

I tried it for two ids.
One have 2-step verification. For that also not working.
and another have simple authentication then also not working.

somebody please help me...
Comment posted by Aswin on Wednesday, May 29, 2013 3:59 PM
The  codes are nice...
But there is no C# code for step 5... could you please include that....

Comment posted by Hapani Ankit on Monday, June 24, 2013 5:50 AM
=>The name 'mailCount' does not exist in the current context   
=>A local variable named 'node' cannot be declared in this scope because it would give a different meaning to 'node', which is already used in a 'parent or current' scope to denote something else   
=> The name 'emailMessages' does not exist in the current context   
=? Non-invocable member 'System.Xml.XmlNode.ChildNodes' cannot be used like a method.   
Comment posted by Washington Morais on Wednesday, October 23, 2013 2:21 PM
Here is the C# code for step 5.
============================================================

var objClient = new System.Net.WebClient();
XmlNodeList nodelist;
string response;
XmlNode node;
var xmlDoc = new XmlDocument();

// use this two lines below for use proxy authentication
// var proxy = new System.Net.WebProxy();
// proxy.Address = new Uri("http://your_proxy_address:your_proxy_port");
// objClient.Proxy = proxy;

objClient.Credentials = new System.Net.NetworkCredential(UsernameTextBox.Text.Trim(), PasswordTextBox.Text.Trim());

response = Encoding.UTF8.GetString(objClient.DownloadData("https://mail.google.com/mail/feed/atom"));
response = response.Replace("<feed version=\"0.3\" xmlns=\"http://purl.org/atom/ns#\">", "<feed>");
xmlDoc.LoadXml(response);
node = xmlDoc.SelectSingleNode("/feed/fullcount");
GlobalVariables.mailCount = Convert.ToInt16(node.InnerText); //Get the number of unread emails

if( GlobalVariables.mailCount > 0)
{
  GlobalVariables.emailFrom = new string[GlobalVariables.mailCount -1];
  GlobalVariables.emailMessages = new string[GlobalVariables.mailCount -1];

  nodelist = xmlDoc.SelectNodes("/feed/entry");
  node = xmlDoc.SelectSingleNode("title");

  XmlDocument docTemp = new XmlDocument();

  foreach(XmlNode nodo in nodelist)
  {
     docTemp.LoadXml("<root>" + nodo.InnerXml + "</root>");
     var titulo = docTemp.SelectSingleNode("//title").InnerText;
     GlobalVariables.emailMessages[GlobalVariables.tempCounter] = node.ChildNodes.Item(0).InnerText;
     GlobalVariables.emailFrom[GlobalVariables.tempCounter] = node.ChildNodes.Item(6).ChildNodes[0].InnerText;
     GlobalVariables.tempCounter += 1;
  }

  GlobalVariables.tempCounter = 0;
}

Hide();
Form1.Show();
Comment posted by hrlyhry on Thursday, October 9, 2014 8:05 AM
not working
Comment posted by Anthony Norris on Friday, October 31, 2014 4:21 AM
This is more complicated than it used to be, I don't know if the number of new members to gmail have made it more difficult to get to?
Comment posted by rayan on Friday, November 7, 2014 5:34 AM
to chdkay  
Comment posted by Jiash Kassim on Thursday, February 5, 2015 4:53 AM
It is working Perfectly. Thank you so much. I really appreciate it