Search code examples
javascriptemailseleniumprotractoremail-client

Mail listener ocassionally fails to authenticate


The Problem:

We have multiple tests where we need to actually check the test user's email as a test case step. This is used for two factor authentication and email notification tests.

At the moment, we use the solution provided here which is based on the mail-listener2 node package. Here is the configuration that we use:

email: {
    username: "user email here",
    password: "user password here",
    host: "smtp server address here",
    port: 993,
    tls: true,
    mailbox: "Inbox",
    markSeen: true
},

We initialize the mail listener in the Protractor config inside the onPrepare() function:

var MailListener = require("mail-listener2");
var mailListener = new MailListener(config.email);

mailListener.start();

mailListener.on("server:connected", function(){
    console.log("Mail listener initialized");
});

global.mailListener = mailListener;

The problem is - in about 10% of the times, the mail listener fails with the following error message:

Timed out while authenticating with server

The Question:

What can cause the problem and what can we do to make the mail listener work? Also, would it be possible to retry authenticating on a failure?


Solution

  • This is an async problem. Your mail listener is trying to check for an event "server:connected". Since this is asynchronous, this may or may not happen in time. What you should try to do is wrap this it in a promise and resolve after the event "server:connected".

    onPrepare: {
      return new Promise((resolve, reject) => {
        var MailListener = require("mail-listener2");
        var mailListener = new MailListener(config.email);
    
        mailListener.start();
    
        mailListener.on("server:connected", function(){
          console.log("Mail listener initialized");
          resolve();
        });
    
        // if you run into an error on connecting to the server,
        // maybe reject the promise here.
        mailListener.on("error", (err) => {
          reject(err);
        });
    
        global.mailListener = mailListener;
      });
    }