Reading emails from Gmail in C#

99,022

Solution 1

Using the library from: https://github.com/pmengal/MailSystem.NET

Here is my complete code sample:

Email Repository

using System.Collections.Generic;
using System.Linq;
using ActiveUp.Net.Mail;

namespace GmailReadImapEmail
{
    public class MailRepository
    {
        private Imap4Client client;

        public MailRepository(string mailServer, int port, bool ssl, string login, string password)
        {
            if (ssl)
                Client.ConnectSsl(mailServer, port);
            else
                Client.Connect(mailServer, port);
            Client.Login(login, password);
        }

        public IEnumerable<Message> GetAllMails(string mailBox)
        {
            return GetMails(mailBox, "ALL").Cast<Message>();
        }

        public IEnumerable<Message> GetUnreadMails(string mailBox)
        {
            return GetMails(mailBox, "UNSEEN").Cast<Message>();
        }

        protected Imap4Client Client
        {
            get { return client ?? (client = new Imap4Client()); }
        }

        private MessageCollection GetMails(string mailBox, string searchPhrase)
        {
            Mailbox mails = Client.SelectMailbox(mailBox);
            MessageCollection messages = mails.SearchParse(searchPhrase);
            return messages;
        }
    }
}

Usage

[TestMethod]
public void ReadImap()
{
    var mailRepository = new MailRepository(
                            "imap.gmail.com",
                            993,
                            true,
                            "[email protected]",
                            "yourPassword"
                        );

    var emailList = mailRepository.GetAllMails("inbox");

    foreach (Message email in emailList)
    {
        Console.WriteLine("<p>{0}: {1}</p><p>{2}</p>", email.From, email.Subject, email.BodyHtml.Text);
        if (email.Attachments.Count > 0)
        {
            foreach (MimePart attachment in email.Attachments)
            {
                Console.WriteLine("<p>Attachment: {0} {1}</p>", attachment.ContentName, attachment.ContentType.MimeType);
            }
        }
    }
}

Another example, this time using MailKit

public class MailRepository : IMailRepository
{
    private readonly string mailServer, login, password;
    private readonly int port;
    private readonly bool ssl;

    public MailRepository(string mailServer, int port, bool ssl, string login, string password)
    {
        this.mailServer = mailServer;
        this.port = port;
        this.ssl = ssl;
        this.login = login;
        this.password = password;
    }

    public IEnumerable<string> GetUnreadMails()
    {
        var messages = new List<string>();

        using (var client = new ImapClient())
        {
            client.Connect(mailServer, port, ssl);

            // Note: since we don't have an OAuth2 token, disable
            // the XOAUTH2 authentication mechanism.
            client.AuthenticationMechanisms.Remove("XOAUTH2");

            client.Authenticate(login, password);

            // The Inbox folder is always available on all IMAP servers...
            var inbox = client.Inbox;
            inbox.Open(FolderAccess.ReadOnly);
            var results = inbox.Search(SearchOptions.All, SearchQuery.Not(SearchQuery.Seen));
            foreach (var uniqueId in results.UniqueIds)
            {
                var message = inbox.GetMessage(uniqueId);

                messages.Add(message.HtmlBody);

                //Mark message as read
                //inbox.AddFlags(uniqueId, MessageFlags.Seen, true);
            }

            client.Disconnect(true);
        }

        return messages;
    }

    public IEnumerable<string> GetAllMails()
    {
        var messages = new List<string>();

        using (var client = new ImapClient())
        {
            client.Connect(mailServer, port, ssl);

            // Note: since we don't have an OAuth2 token, disable
            // the XOAUTH2 authentication mechanism.
            client.AuthenticationMechanisms.Remove("XOAUTH2");

            client.Authenticate(login, password);

            // The Inbox folder is always available on all IMAP servers...
            var inbox = client.Inbox;
            inbox.Open(FolderAccess.ReadOnly);
            var results = inbox.Search(SearchOptions.All, SearchQuery.NotSeen);
            foreach (var uniqueId in results.UniqueIds)
            {
                var message = inbox.GetMessage(uniqueId);

                messages.Add(message.HtmlBody);

                //Mark message as read
                //inbox.AddFlags(uniqueId, MessageFlags.Seen, true);
            }

            client.Disconnect(true);
        }

        return messages;
    }
}

Usage

[Test]
public void GetAllEmails()
{
    var mailRepository = new MailRepository("imap.gmail.com", 993, true, "[email protected]", "YOURPASSWORDHERE");
    var allEmails = mailRepository.GetAllMails();

    foreach(var email in allEmails)
    {
        Console.WriteLine(email);
    }

    Assert.IsTrue(allEmails.ToList().Any());
}

Solution 2

You don't need any extra 3rd Party Libraries if a summary of the 20 most recent emails is sufficient for you. You can read the data from API that Gmail has provided here: https://mail.google.com/mail/feed/atom

The response in XML format can be handled by the code below:

try {
   System.Net.WebClient objClient = new System.Net.WebClient();
   string response;
   string title;
   string summary;

   //Creating a new xml document
   XmlDocument doc = new XmlDocument();

   //Logging in Gmail server to get data
   objClient.Credentials = new System.Net.NetworkCredential("Email", "Password");
   //reading data and converting to string
   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>");

   //loading into an XML so we can get information easily
   doc.LoadXml(response);

   //nr of emails
   var nr = doc.SelectSingleNode(@"/feed/fullcount").InnerText;

   //Reading the title and the summary for every email
   foreach (XmlNode node in doc.SelectNodes(@"/feed/entry")) {
      title = node.SelectSingleNode("title").InnerText;
      summary = node.SelectSingleNode("summary").InnerText;
   }
} catch (Exception exe) {
   MessageBox.Show("Check your network connection");
}

Solution 3

Have you tried POP3 Email Client with full MIME Support ?

If you don't it's a very good example for you. As an alternativ;

OpenPop.NET

.NET class library in C# for communicating with POP3 servers. Easy to use but yet powerful. Includes a robust MIME parser backed by several hundred test cases. For more information, visit our project homepage.

Lumisoft

Share:
99,022
Seany84
Author by

Seany84

Updated on June 02, 2020

Comments

  • Seany84
    Seany84 almost 4 years

    I am trying to read emails from Gmail. I have tried every API / open source project I can find, and can not get any of them working.

    Does anyone have a sample of working code that will allow me to authenticate and download emails from a Gmail account?

    Final working version posted below: https://stackoverflow.com/a/19570553/550198

  • Seany84
    Seany84 almost 13 years
    Thanks, somehow I managed to try every C# non-working POP3 email client :) thanks
  • Seany84
    Seany84 almost 13 years
    I have no budget to pay for this as there are open-source and free alternatives available.
  • Eric
    Eric over 10 years
    The only problem with this approach, and it's important to many people, is that you can't get the full text of the message body via the ATOM route.
  • E-Riddie
    E-Riddie over 10 years
    There is another method of getting the route of ATOM with XML. You just have to create a namespace for XML form and you can access it easily! Read about that and you will understand because its no difference from this! :)
  • Kiquenet
    Kiquenet over 10 years
    any free version, not premium? Any open source alternative ?
  • newman
    newman over 9 years
    Just tried your code, it compiles okay. But when I try to run, it got stuck for more than 5 minutes at the line mails.SearchParse(searchPhrase) via call GetUnreadMails. I only have 53 unread emails in my inbox. Any explanation?
  • Seany84
    Seany84 over 9 years
    I have not used this code since around the time of the OP. However, I fired up my unit test and it did retrieve my unreal emails (count=12). Test took approximately 66 seconds to run.
  • Gurpreet Singh
    Gurpreet Singh over 7 years
    I have build the console application in c# using above code, everything fixed but gmail not allowing to login. Here is my error message:- ** failed : * NO [WEBALERT accounts.google.com/signin/… Web login required. 161116082452398 NO [ALERT] Please log in via your web browser: support.google.com/mail/accounts/answer/78754 (Failure)**
  • Kjensen
    Kjensen about 7 years
    In order for this to work, you need to enable "Less secure apps" with your gmail account, if that is an option for you. I did that, and now the code works. Read more here: google.com/settings/security/lesssecureapps
  • Nulle
    Nulle over 6 years
    Then please illustrate how you would retrieve the message body.
  • Nulle
    Nulle over 6 years
    I have copy pasted your code. Exception thrown: 'System.IndexOutOfRangeException' in ActiveUp.Net.Imap4.dll when it tries get mail via GetAllMails("inbox");
  • Nulle
    Nulle over 6 years
    what is ? IMailRepository. Mailkit does not have that Interface.
  • Seany84
    Seany84 over 6 years
    @Nulle This was from my code base. You can remove that interface for your own use-case.
  • Bengi Besçeli
    Bengi Besçeli over 6 years
    nr is undefined
  • Toolkit
    Toolkit over 5 years
    can I limit GetAllMails by date?
  • Seany84
    Seany84 over 5 years
    @Toolkit Yes, it is definitely possible. You should really post a different question on this site though.
  • Mr. B
    Mr. B about 5 years
    Love your answer - Does every single thing need a NuGet package to be viable these days. Is that what we've become :(
  • MohaMad
    MohaMad over 4 years
    @Seany84 thanks for your nice sample codes. I tried to use MailSystem.NET , but has error on Client.Log() : BAD Too many arguments provided . My password contains spaces and this login fails!
  • Yijun Yuan
    Yijun Yuan over 4 years
    I got a 401 Unauthorized error. How should I fix that?
  • Albert Arul prakash
    Albert Arul prakash about 4 years
    another problem with this model is that, you cannot get entire mailbox information. max 20 email details. No more than that.
  • Ashok kumar Ganesan
    Ashok kumar Ganesan almost 4 years
    When I try to read the UnreadEmail I get the exception on GetMail method with exception like index out of exception