IMAP Node.js执行两次,保存两次电子邮件,不会保存来自发射器的电子邮件

问题描述 投票:0回答:1

我有一个mailListenerWrapper.js,我在其中定义了imap类:

mailListenerWrapper.js

const simpleParser = require("mailparser").simpleParser;
const Imap = require("imap");
const striptags = require("striptags");
const BlackListModel = require("./models/blacklist");
const RecEmailConfigModel = require("./models/emailConfig");
const ReceivedEmailModel = require("./models/receivedMail");
const Base64 = require("js-base64").Base64;
const _ = require("lodash");
const logger = require("./helpers/logger");
require("dotenv").config();

class MailListenerWrapper {
  constructor() {
    this.imap = null;
    this.init();
  }

  async init() {
    try {
      const getRecEmailConfig = await RecEmailConfigModel.findOne({});

      if (getRecEmailConfig) {
        getRecEmailConfig.password = Base64.decode(getRecEmailConfig.password);
        this.imap = new Imap({
          user: getRecEmailConfig.user,
          password: getRecEmailConfig.password,
          host: getRecEmailConfig.host,
          port: getRecEmailConfig.port,
          tls: getRecEmailConfig.tls,
          tlsOptions: {
            rejectUnauthorized: false,
            authTimeout: 10000
          }
        });
      } else {
        return false;
      }

      let lastMessage = 0;

      const openInbox = cb => {
        this.imap.openBox("INBOX", true, cb);
      };
      const regEmail = /[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?/g;

      this.imap.once("ready", () => {
        openInbox((err, box) => {
          if (err) {
            logger.log({ level: "error", message: err });
            return false;
          }
          lastMessage = box.messages.total;

          this.imap.on("mail", numberOfNewMessages => {
            const newEmail = {};
            // const numberOfNewMessages = 0
            lastMessage = lastMessage + numberOfNewMessages;

            const f = this.imap.seq.fetch(lastMessage + ":" + lastMessage, {
              bodies: ["HEADER.FIELDS (SUBJECT FROM)", ""],
              struct: true
            });

            f.on("message", msg => {
              msg.on("body", async stream => {
                try {
                  const parsed = await simpleParser(stream);
                  if (parsed.headers.get("subject")) {
                    // ################ HEADER ################ \\
                    newEmail.title = parsed.headers.get("subject");
                    const getFrom = parsed.headers.get("from").text.split(" <");

                    // ############################ //

                    console.log(getFrom); // executes twice here already

                    // ########################### //

                    if (getFrom.length === 2) {
                      newEmail.name = getFrom[0];
                      newEmail.email = getFrom[1].match(regEmail).join("\n");
                    }
                    // ################ HEADER ################ \\
                  }
                  if (parsed.text) {
                    // ################ TEXT ################ \\
                    newEmail.text = striptags(parsed.text).toString("utf8");
                    // ################ TEXT ################ \\
                  }
                  if (
                    newEmail.name &&
                    newEmail.email &&
                    newEmail.title &&
                    newEmail.text
                  ) {
                    const getEmailHostname = newEmail.email.replace(/.*@/, "");
                    const blacklists = await BlackListModel.find({
                      hostname: new RegExp(".*" + getEmailHostname + ".*", "i")
                    });
                    if (blacklists.length > 0) {
                      logger.log({
                        level: "info",
                        message:
                          "A BLACKLIST ENTRY WAS TRYING TO SUBMIT AN APPLICATION"
                      });
                      return false;
                    }

                    const savedEmail = new ReceivedEmailModel(newEmail);
                    await savedEmail.save();

                    logger.log({
                      level: "info",
                      message:
                        "SAVED RECEIVED EMAIL =>" + JSON.stringify(savedEmail)
                    });
                  }
                } catch (err) {
                  logger.log({ level: "error", message: err });
                }
              }); // msg on body
            });
          }); // on mail

          this.imap.once("error", err => {
            logger.log({
              level: "error",
              message: err
            });
          }); // on error
        }); // openInbox
      }); // ready

      this.imap.connect();
    } catch (err) {
      logger.log({
        level: "error",
        message: err
      });
    }
  }

  close() {
    if (this.imap) this.imap.end();
  }
}

module.exports = MailListenerWrapper;

app.js

global.mailListenerWrapper = new mailListenerWrapper();

The receivedEmail.js模型:

const mongoose = require("mongoose");

// Schema variable
const Schema = mongoose.Schema;

// Tags
const receivedMailSchema = new Schema(
  {
    title: {
      type: String,
      required: true
    },
    from: {
      name: {
        type: String
      },
      email: {
        type: String
      }
    },
    text: {
      type: String
    }
  },
  {
    collection: "receivedEmail",
    timestamps: true
  }
);

const ReceivedEmail = mongoose.model("ReceivedEmail", receivedMailSchema);

module.exports = ReceivedEmail;

问题

控制台日志执行两次,并且电子邮件两次保存在我的数据库中,并且不保存发送电子邮件的地址。我不知道为什么会这样。是否可以通过某种方式将imap类实例化两次?

node.js class express parsing imap
1个回答
0
投票

我想我来晚了,但也许对其他人还是有用的。我也遇到了这个问题。但是我意识到在示例代码中node-imap documetation指定使用.once()而不是.on()

尝试更改以下活动:

msg.on("body", async stream => {
    ....
}

收件人:

msg.once("body", async stream => {
    ....
}

它确实对我有用!

© www.soinside.com 2019 - 2024. All rights reserved.