基于imap mailparser的node读取邮件
2024-11-20 19:08:56
node接受邮件服务 imap mailparser
3222

有朋友需要读取各个邮件的邮箱文件,所以我们先来看下各个邮件协议

smtp协议

简单邮件传输协议:是一种基于文本的电子邮件传输协议,用于从源地址到目的地址传输邮件的规范,通过它来控制邮件的中转方式,是因特网中用于在邮件服务器之间交换邮件的协议。SMTP是一个“推”的协议,它不允许根据需要从远程服务器上“拉”来消息。

pop3协议

POP3协议允许邮件客户端下载服务器上的邮件,但是在客户端的操作(如移动邮件、删除邮件、标记已读等),不会反馈到服务器上,比如通过客户端收取了邮箱中的3封邮件并移动到其他文件夹,邮箱服务器上的这些邮件是没有同时被移动的。也就是说POP3协议实际上是下载了一份邮件的副本到本地邮件客户端,而且对本地邮件副本的操作只会影响本地数据。多个邮件客户端里面的邮件的状态可能会不一致。

imap协议

IMAP(Internet消息访问协议)也是提供面向用户的邮件收取服务。常用的版本是IMAP4。与POP3协议类似允许电子邮件客户端下载服务器上的邮件,不同的是,开启了IMAP后,邮件仍然保留在服务器上,同时在客户端上的操作都会反馈到服务器上,如:删除邮件,标记已读等,服务器上的邮件也会做相应的动作。换句话说,IMAP把远程文件夹当成本地文件夹来操作,它们之间类似于双向同步。这样的好处是,当你在多个邮件客户端看见的邮件的状态是一致的。

实现方法

安装imap mailparser

npm install --save imap mailparserxi

详细代码

let Imap = require('imap')
let MailParser = require("mailparser").MailParser
let fs = require("fs");


/**
 * 外部调用:     
 * let getEmail =await email.connect({
      showTitle:true,
      showForm:true,
      showTo:true,
      showDate:true,
      showBody:true,
    });
 */
exports.connect = (config) => {


  let emailPromise = new Promise((resovle, reject) => {
    let imap = new Imap({
      user: 'yourname@gmail.com', //你的邮箱账号
      password: 'yourpassword', //imap对应的校验码
      host: 'imap.gmail.com', //对应邮箱服务器的主机地址
      port: 993, //邮箱服务器的端口地址
      tls: true, //使用安全传输协议
      tlsOptions: {
        rejectUnauthorized: false
      }, //禁用对证书有效性的检查
      debug: (log) => { //调试模式
        console.log(log)
      }
    });
    let _message = [];


    imap.once('ready', function () {
      imap.openBox('INBOX', true, function (err, box) {


        if (err) throw err;
        /**
        ---------------------------------------------------
        ['ALL', ['SINCE', 'March 20, 2021']]中的ALL
        'ALL' -所有信息。
        'ANSWERED' -带有已应答标志的消息。
        'DELETED' -设置了DELETED标志的消息。
        'DRAFT' -设置了DRAFT标志的消息。
        'FLAGGED' -设置了标记标记的消息。
        'NEW' -设置了Recent标志但未设置Seen标志的消息。
        'SEEN' -设置了SEEN标志的消息。
        'RECENT' -设置了RECENT标志的消息。
        'OLD' -没有设置最近标志的消息。这在功能上等同于“!”最近的”(与“!NEW”相对)。
        'UNANSWERED' -没有设置应答标志的消息。
        'UNDELETED' -未设置已删除标记的邮件。
        'UNDRAFT' -没有设置草稿标志的消息。
        'UNFLAGGED' -没有设置标记标记的消息。
        'UNSEEN' -没有设置Seen标志的消息。
        ---------------------------------------------------
        ['ALL', ['SINCE', 'March 20, 2021']]中的['SINCE', 'March 20, 2021']
        从2021年3月20日开始
         */


        imap.search(['ALL', ['SINCE', 'March 20, 2021']], function (err, results) {
          debugger
          if (err) throw err;
          let f = imap.fetch(results, {
            bodies: ''
          });


          f.on('message', function (msg, seqno) {
            let mailparser = new MailParser();
            let _obj = {};
            msg.on('body', function (stream, info) {
              stream.pipe(mailparser);
              mailparser.on("headers", function (headers) {
                console.log("exports.connect -> headers", headers)
                if (config.showTitle) {
                  _obj.title = headers.get('subject');
                };
                if (config.showForm) {
                  _obj.from = headers.get('from').text;
                };
                if (config.showTo) {
                  _obj.to = headers.get('to').text;
                };
                if (config.showDate) {
                  _obj.date = headers.get('date');
                };
              });
              if (config.showBody) {
                mailparser.on("data", function (data) {


                  if (data.type === 'text') {
                    _obj.body = data.html;
                  }
                  // if (data.type === 'attachment') {
                  //   console.log("附件名称:" + data.filename);
                  //   data.content.pipe(fs.createWriteStream(data.filename));


                  //   //保存附件到当前目录下
                  //   data.release();
                  // }
                });
              }


            });
            msg.once('end', function () {
              _message.push(_obj);
              //可以copy、addFlags、move、delFlags、setFlags等。但是需要查询邮件服务器准许的状态,比如有的服务器不允许标记已读
            });
          });
          f.once('error', function (err) {
            reject({
              err: err,
              desc: "fetchError"
            });
          });
          f.once('end', function () {
            imap.end();
          });
        });
      });
    });


    imap.once('error', function (err) {
      reject({
        err: err,
        desc: "imapError"
      });
    });


    imap.once('end', function () {
      resovle(_message);
    });


    imap.connect();
  });


  return emailPromise;
};

网易163邮箱会有对应报错详细处理方案见下一篇文章