如何使用node-imap读取和保存附件

 小甜甜龌龊的华丽 发布于 2022-12-28 18:32

我正在使用node-imap,我找不到一个简单的代码示例,说明如何使用fs将使用node-imap获取的电子邮件中的附件保存到磁盘.

我已经阅读了几次文档.在我看来,我应该进行另一次获取,并引用作为附件的消息的特定部分.我从基本的例子开始:

var Imap = require('imap'),
    inspect = require('util').inspect;

var imap = new Imap({
  user: 'mygmailname@gmail.com',
  password: 'mygmailpassword',
  host: 'imap.gmail.com',
  port: 993,
  tls: true
});

function openInbox(cb) {
  imap.openBox('INBOX', true, cb);
}

imap.once('ready', function() {
  openInbox(function(err, box) {
    if (err) throw err;
    var f = imap.seq.fetch('1:3', {
      bodies: 'HEADER.FIELDS (FROM TO SUBJECT DATE)',
      struct: true
    });
    f.on('message', function(msg, seqno) {
      console.log('Message #%d', seqno);
      var prefix = '(#' + seqno + ') ';
      msg.on('body', function(stream, info) {
        var buffer = '';
        stream.on('data', function(chunk) {
          buffer += chunk.toString('utf8');
        });
        stream.once('end', function() {
          console.log(prefix + 'Parsed header: %s', inspect(Imap.parseHeader(buffer)));
        });
      });
      msg.once('attributes', function(attrs) {
        console.log(prefix + 'Attributes: %s', inspect(attrs, false, 8));

        //Here's were I imagine to need to do another fetch for the content of the message part...

      });
      msg.once('end', function() {
        console.log(prefix + 'Finished');
      });
    });
    f.once('error', function(err) {
      console.log('Fetch error: ' + err);
    });
    f.once('end', function() {
      console.log('Done fetching all messages!');
      imap.end();
    });
  });
});

imap.once('error', function(err) {
  console.log(err);
});

imap.once('end', function() {
  console.log('Connection ended');
});

imap.connect();

这个例子有效.这是附件部分的输出:

 [ { partID: '2',
     type: 'application',
     subtype: 'octet-stream',
     params: { name: 'my-file.txt' },
     id: null,
     description: null,
     encoding: 'BASE64',
     size: 44952,
     md5: null,
     disposition:
      { type: 'ATTACHMENT',
        params: { filename: 'my-file.txt' } },
     language: null } ],

如何使用节点的fs模块读取该文件并将其保存到磁盘?

1 个回答
  • 感谢@arnt和mscdex的帮助,我想通了.这是一个完整且有效的脚本,它将所有附件作为文件流式传输到磁盘,而base64则动态解码它们.在内存使用方面相当可扩展.

    var inspect = require('util').inspect;
    var fs      = require('fs');
    var base64  = require('base64-stream');
    var Imap    = require('imap');
    var imap    = new Imap({
      user: 'mygmailname@gmail.com',
      password: 'mygmailpassword',
      host: 'imap.gmail.com',
      port: 993,
      tls: true
      //,debug: function(msg){console.log('imap:', msg);}
    });
    
    function toUpper(thing) { return thing && thing.toUpperCase ? thing.toUpperCase() : thing;}
    
    function findAttachmentParts(struct, attachments) {
      attachments = attachments ||  [];
      for (var i = 0, len = struct.length, r; i < len; ++i) {
        if (Array.isArray(struct[i])) {
          findAttachmentParts(struct[i], attachments);
        } else {
          if (struct[i].disposition && ['INLINE', 'ATTACHMENT'].indexOf(toUpper(struct[i].disposition.type)) > -1) {
            attachments.push(struct[i]);
          }
        }
      }
      return attachments;
    }
    
    function buildAttMessageFunction(attachment) {
      var filename = attachment.params.name;
      var encoding = attachment.encoding;
    
      return function (msg, seqno) {
        var prefix = '(#' + seqno + ') ';
        msg.on('body', function(stream, info) {
          //Create a write stream so that we can stream the attachment to file;
          console.log(prefix + 'Streaming this attachment to file', filename, info);
          var writeStream = fs.createWriteStream(filename);
          writeStream.on('finish', function() {
            console.log(prefix + 'Done writing to file %s', filename);
          });
    
          //stream.pipe(writeStream); this would write base64 data to the file.
          //so we decode during streaming using 
          if (toUpper(encoding) === 'BASE64') {
            //the stream is base64 encoded, so here the stream is decode on the fly and piped to the write stream (file)
            stream.pipe(base64.decode()).pipe(writeStream);
          } else  {
            //here we have none or some other decoding streamed directly to the file which renders it useless probably
            stream.pipe(writeStream);
          }
        });
        msg.once('end', function() {
          console.log(prefix + 'Finished attachment %s', filename);
        });
      };
    }
    
    imap.once('ready', function() {
      imap.openBox('INBOX', true, function(err, box) {
        if (err) throw err;
        var f = imap.seq.fetch('1:3', {
          bodies: ['HEADER.FIELDS (FROM TO SUBJECT DATE)'],
          struct: true
        });
        f.on('message', function (msg, seqno) {
          console.log('Message #%d', seqno);
          var prefix = '(#' + seqno + ') ';
          msg.on('body', function(stream, info) {
            var buffer = '';
            stream.on('data', function(chunk) {
              buffer += chunk.toString('utf8');
            });
            stream.once('end', function() {
              console.log(prefix + 'Parsed header: %s', Imap.parseHeader(buffer));
            });
          });
          msg.once('attributes', function(attrs) {
            var attachments = findAttachmentParts(attrs.struct);
            console.log(prefix + 'Has attachments: %d', attachments.length);
            for (var i = 0, len=attachments.length ; i < len; ++i) {
              var attachment = attachments[i];
              /*This is how each attachment looks like {
                  partID: '2',
                  type: 'application',
                  subtype: 'octet-stream',
                  params: { name: 'file-name.ext' },
                  id: null,
                  description: null,
                  encoding: 'BASE64',
                  size: 44952,
                  md5: null,
                  disposition: { type: 'ATTACHMENT', params: { filename: 'file-name.ext' } },
                  language: null
                }
              */
              console.log(prefix + 'Fetching attachment %s', attachment.params.name);
              var f = imap.fetch(attrs.uid , { //do not use imap.seq.fetch here
                bodies: [attachment.partID],
                struct: true
              });
              //build function to process attachment message
              f.on('message', buildAttMessageFunction(attachment));
            }
          });
          msg.once('end', function() {
            console.log(prefix + 'Finished email');
          });
        });
        f.once('error', function(err) {
          console.log('Fetch error: ' + err);
        });
        f.once('end', function() {
          console.log('Done fetching all messages!');
          imap.end();
        });
      });
    });
    
    imap.once('error', function(err) {
      console.log(err);
    });
    
    imap.once('end', function() {
      console.log('Connection ended');
    });
    
    imap.connect();
    

    2022-12-28 18:34 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有