Search code examples
c#.netseleniumgmailmailkit

MailKit: How to iterate through recent emails to get the email with a given subject


I’m creating a framework using .NET core 2.1. I used MailKit and tried several methods as explained in their pages and also in StackOverflow but still no luck.

So far, I was able to get the UIDs of the recent messages but can’t seem to iterate through the list to get the email with the specific subject.

Test calling the method:

                 Core core = new Core(driver);

                 bool isEmailPresent = core.EnsureUnreadEmailExists("Your application details" , "emailAddress");

                 Assert.True(isEmailPresent);

Core (Class):

          public bool EnsureUnreadEmailExists(string emailSubject, string emailBox)

          {

                 bool emailExists = true;

                 //start stopwatch to monitor elapsed time

                 Stopwatch sw = Stopwatch.StartNew();

                 //long maximumTimeout = 180000; //exit loop when maximumTimeout is reached

                 long maximumTimeout = 10000; //exit loop when maximumTimeout is reached



                 int sleepWait = 500;

                 //check if email exists and is readable

                 while (CheckEmailExistsAndIsReadable(GetGmailMessage(emailBox), emailSubject) && sw.ElapsedMilliseconds <= maximumTimeout)

                 {

                       //loop until email has arrived and is activated or maximumTimeout exceeded

                       Thread.Sleep(sleepWait);

                       Console.WriteLine("Time elapsed : {0}ms", sw.ElapsedMilliseconds);

                 }



                 try

                 {

                        //try

                       emailExists = false;

                 }

                 catch (Exception ae)

                 {
                     //exception message
                       emailExists = false;

                 }

                 sw.Stop();

                 return emailExists;

          }

          private IList<UniqueId> GetGmailMessage(string emailBox)

          {

                 // Switch on the string - emailBox.

                 switch (emailBox.ToUpper())

                 {

                        case "emailAddress1":

                              GMailHandler gmh1 = new GMailHandler("imap.gmail.com", 993, true,

                              "emailAddress", "password");

                              return gmh1.GetRecentEmails();

                       default:

                              throw new Exception("Mail box not defined");

                 }



          }

GMailHandler (Class)

          public GMailHandler(string mailServer, int port, bool ssl, string login, string password)

          {

                 if (ssl)

                       Client.Connect(mailServer, port);

                 else

                       Client.Connect(mailServer, port);

                 Client.Authenticate(login, password);

                 Client.Inbox.Open(FolderAccess.ReadOnly);

          }



          public IList<UniqueId> GetRecentEmails()

          {

                 IList<UniqueId> uids = client.Inbox.Search(SearchQuery.Recent);

                 return uids;

          }

Method (in Core class) I'm unable to complete to iterate through UIDs to get email with the given subject

          public static bool CheckEmailExistsAndIsReadable(IList<UniqueId> uids, string emailSubject)

          {

                 try

                 {

                       Console.WriteLine("Attempt to read email messages .....");

                       string htmlBody = "";

                       string Subject = "";

                       bool EmailExists = false;

                       foreach (UniqueId msgId in uids)

                       {

                        //Incomplete
                              if (msgId.)

                              {

                                     htmlBody = email.BodyHtml.Text;

                                     Subject = email.Subject.ToString();

                                     Console.WriteLine("Subject: " + Subject);

                                     Match match = Regex.Match(Subject, emailSubject);

                                     Console.WriteLine("match: " + match.Groups[0].Value.ToString());

                                     if (match.Success)

                                     {

                                            Console.WriteLine("Email exists with subject line: " + emailSubject);

                                            EmailExists = true;

                                     }

                                     break;

                              }



                       }

                       if (EmailExists)

                       {

                              //email found so exit poll

                              Console.WriteLine("email found return false ");

                              return false;

                       }

                       else

                       {

                              //email not found so contiue to poll

                              Console.WriteLine("email not found return true ");

                              return true;

                       }





                 }

                 catch (IOException)

                 {

                       //the email with specific subject line has not yet arrived:

                       //may be still in transit

                       //or being processed by another thread

                       //or does not exist (has already been processed)

                       Console.WriteLine("Email has not arrived or still in transit. Continue to poll ... ");

                       return true;

                 }



          }

What I want to do is to add a class or two and have reusable methods, so that I can use these in any of my future tests. 1. Access gmail and validate email with a certain subject is present 2. Extract certain content (e.g. security pin) from that email and add it into a text file. 3. Check content of the email


Solution

  • You can try something like

              public GMailHandler(string mailServer, int port, bool ssl, string login, string password)
    
              {
    
                      if (ssl)
    
                      {
    
                             client.Connect(mailServer, port);
    
                      }
    
                      else
    
                             client.Connect(mailServer, port);
    
                      client.Authenticate(login, password);
    
                      inbox = client.Inbox;
    
              }
    
    
    
              public IEnumerable<string> GetEmailWithSubject (string emailSubject)
    
              {
    
                      var messages = new List<string>();
    
    
    
                      inbox.Open(FolderAccess.ReadWrite);
    
                      var results = inbox.Search(SearchOptions.All, SearchQuery.Not(SearchQuery.Seen));
    
                      foreach (var uniqueId in results.UniqueIds)
    
                      {
    
                             var message = client.Inbox.GetMessage(uniqueId);
    
    
    
                             if (message.Subject.Contains(emailSubject))
    
                             {
    
                                    messages.Add(message.HtmlBody);
    
                             }
    
    
    
                             //Mark message as read
    
                             inbox.AddFlags(uniqueId, MessageFlags.Seen, true);
    
                      }
    
    
    
                      client.Disconnect(true);
    
    
    
                      return messages;
    
              }