You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Protractor E2E测试中mailListener报Cannot read property 'on' of undefined错误

Fix: Cannot read property 'on' of undefined with mail-listener2 in Protractor

The error Failed: Cannot read property 'on' of undefined pops up because you’re trying to use mailListener as a pre-built, ready-to-use instance—but the mail-listener2 library doesn’t export a pre-configured listener. You need to create and initialize your own listener instance with your email server’s IMAP settings first.

Here’s how to fix this step by step:

1. Correctly Import the Library & Initialize the Listener

First, import the MailListener constructor (not a pre-made instance) and configure it with your email account details. Most providers (like Gmail) require app-specific passwords if 2FA is enabled:

import MailListener from 'mail-listener2';

// Initialize the mail listener with your IMAP settings
const mailListener = new MailListener({
  username: 'your-email@example.com',
  password: 'your-email-password-or-app-password',
  host: 'imap.example.com', // e.g., 'imap.gmail.com' for Gmail
  port: 993, // Standard IMAP SSL port
  tls: true,
  tlsOptions: { rejectUnauthorized: false },
  mailbox: 'INBOX', // Which mailbox to monitor
  searchFilter: ['UNSEEN'], // Optional: Only target unread emails
  markSeen: true, // Mark emails as seen after processing
  fetchUnreadOnStart: false, // Skip old unread emails on startup
});

// Start the listener
mailListener.start();

// Catch initialization errors
mailListener.on('error', (err) => {
  console.error('Mail listener error:', err);
});

2. Update the getLastEmail() Function

Modify your function to use the initialized instance, and use once instead of on to avoid duplicate event bindings (this ensures each call captures only one email):

function getLastEmail() {
  const deferred = protractor.promise.defer();
  console.log("Waiting for an email...");

  // Listen for the next incoming email only once
  mailListener.once("mail", function(mail){
    deferred.fulfill(mail);
  });

  return deferred.promise;
}

3. Adjust Your Test Case

Add cleanup logic to stop the listener after tests finish, preventing resource leaks:

describe('Sales App', () => {
  afterAll(() => {
    // Stop the mail listener when tests complete
    mailListener.stop();
  });

  it('Should send confirmation email', () => {
    return browser.controlFlow().wait(getLastEmail())
      .then((email) => {
        // Verify email details
        expect(email.subject).toContain('Confirmation');
        expect(email.to[0].address).toBe('test-user@example.com');
        // Add your post-email validation logic here
      });
  });
});

Key Notes

  • IMAP Settings: Double-check your provider’s IMAP server details (e.g., Gmail uses imap.gmail.com, port 993 with TLS enabled).
  • Security: Never hardcode credentials—use environment variables like process.env.EMAIL_USERNAME instead.
  • Protractor Control Flow: Returning the promise from getLastEmail() ensures the test waits for the email before moving forward.

内容的提问来源于stack exchange,提问作者k.vincent

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 03:11:30