Node接收电子邮件的实例代码


Posted in Javascript onJuly 21, 2017

上一篇文章写了如何通过node发送电子邮件,有发送就会有接收嘛,所以这篇文章来说说关于在node中如何接收电子邮件。

邮件协议

在开始这篇文章之前我们首先了解三个协议smtp(Simple Mail Transfer Protocol)简单邮件传输协议,pop3(Post Office Protocol 3)邮局协议第三版本,imap(Internet Mail Access Protocol)internet消息访问协议。

smtp协议

简单邮件传输协议:是一种基于文本的电子邮件传输协议,用于从源地址到目的地址传输邮件的规范,通过它来控制邮件的中转方式,是因特网中用于在邮件服务器之间交换邮件的协议。SMTP是一个“推”的协议,它不允许根据需要从远程服务器上“拉”来消息。要做到这点,邮件客户端必须使用POP3或IMAP。所以发送邮件的时候我们需要简单的了解下面的这两种协议。

pop3协议

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

imap协议

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

接收邮件测试过程

接收邮件实际上做的是一个邮件客户端的东西,对于底层的实现在npm上有一个写好的第三的库node-imap(node.js的imap客户端模块)这个模块帮助我们封装了很多的底层操作,但是这个模块返回的数据像附件、消息、邮件头等都是未解码的原始数据,所以还需要对数据进行解码,解码的模块在npm上也找到了一个写好的库Mailparser它是一个node高级电子邮件解析器,能够解析即使非常大的数据(100MB+),而且开销相对比较低。

使用imap接收邮件的过程可以用下面一张图表示

Node接收电子邮件的实例代码

 imap接收邮件测试过程

本次测试的大概过程如下

  1. 在pc上登录qq邮箱
  2. 通过qq邮箱发邮件到gamil(不同邮件服务器之间发邮件过程比较复杂,过程略)
  3. 在pc上通过写好的基于imap的程序去拉取gmail的邮件,同时本地的修改(标记邮件,删除邮件)会同步到gmail服务器

安装node第三方包

npm install --save imap mailparser

邮件接收服务器我选择Gmail,发送邮件的服务器使用qq邮箱。

使用qq邮箱发送一封带有附件的邮件

Node接收电子邮件的实例代码

通过程序接收邮件

Node接收电子邮件的实例代码

查看附件保存时否正确

Node接收电子邮件的实例代码

核心代码

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

var imap = new Imap({
  user: 'yourname@gmail.com', //你的邮箱账号
  password: 'yourpassword', //你的邮箱密码
  host: 'imap.gmail.com', //邮箱服务器的主机地址
  port: 993, //邮箱服务器的端口地址
  tls: true, //使用安全传输协议
  tlsOptions: { rejectUnauthorized: false } //禁用对证书有效性的检查
});

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

imap.once('ready', function() {

  openInbox(function(err, box) {

    console.log("打开邮箱")

    if (err) throw err;

    imap.search(['UNSEEN', ['SINCE', 'May 20, 2017']], function(err, results) {//搜寻2017-05-20以后未读的邮件

      if (err) throw err;

      var f = imap.fetch(results, { bodies: '' });//抓取邮件(默认情况下邮件服务器的邮件是未读状态)

      f.on('message', function(msg, seqno) {

        var mailparser = new MailParser();

        msg.on('body', function(stream, info) {

          stream.pipe(mailparser);//将为解析的数据流pipe到mailparser

          //邮件头内容
          mailparser.on("headers", function(headers) {
            console.log("邮件头信息>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
            console.log("邮件主题: " + headers.get('subject'));
            console.log("发件人: " + headers.get('from').text);
            console.log("收件人: " + headers.get('to').text);
          });

          //邮件内容

          mailparser.on("data", function(data) {
            if (data.type === 'text') {//邮件正文
              console.log("邮件内容信息>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
              console.log("邮件内容: " + data.html);
            }
            if (data.type === 'attachment') {//附件
              console.log("邮件附件信息>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
              console.log("附件名称:"+data.filename);//打印附件的名称
              data.content.pipe(fs.createWriteStream(data.filename));//保存附件到当前目录下
              data.release();
            }
          });

        });
        msg.once('end', function() {
          console.log(seqno + '完成');
        });
      });
      f.once('error', function(err) {
        console.log('抓取出现错误: ' + err);
      });
      f.once('end', function() {
        console.log('所有邮件抓取完成!');
        imap.end();
      });
    });
  });
});

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

imap.once('end', function() {
  console.log('关闭邮箱');
});

imap.connect();

默认情况下抓取邮件后邮件服务器的邮件状态为未读,如果要在抓取后让邮箱服务器中的邮件状态变为已读,可以修改

var f = imap.fetch(results, { bodies: '' });

var f = imap.fetch(results, { bodies: '', markSeen: true });

参考文档

查看node-imap详细文档和api请点击这里

查看Mailparser详细文档请点击这里

后记

如果google邮箱如果开启了二次认证,那么你需要在google后台生成一个专用密码来登录google邮箱拉取邮件。

通过一个简单的例子实现了如何使用node和imap协议来接收邮件,结合上篇node发送电子邮件文章的内容,一个简单的邮件客户端的基本收信发信功能就有了,但是想实现一个功能完善用户体验好的邮件客户端就需要不断揣摩它,设计它,完善它,希望这篇文章能带给你启发,可以实现一个属于你自己的邮件客户端。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
关于javascript document.createDocumentFragment()
Apr 04 Javascript
如何使用Jquery获取Form表单中被选中的radio值
Aug 09 Javascript
jQuery+ajax的资源回收处理机制分析
Jan 07 Javascript
使用mint-ui实现省市区三级联动效果的示例代码
Feb 09 Javascript
新版vue-cli模板下本地开发环境使用node服务器跨域的方法
Apr 03 Javascript
js实现页面多个日期时间倒计时效果
Jun 20 Javascript
node.js使用fs读取文件出错的解决方案
Oct 23 Javascript
layUI的验证码功能及校验实例
Oct 25 Javascript
Vue实现点击当前元素以外的地方隐藏当前元素(实现思路)
Dec 04 Javascript
JavaScript ES6 Class类实现原理详解
May 08 Javascript
使用 Opentype.js 生成字体子集的实例代码详解
May 25 Javascript
JS常见内存泄漏及解决方案解析
May 30 Javascript
基于JavaScript实现无限加载瀑布流
Jul 21 #Javascript
原生JS实现自定义滚动条效果
Oct 27 #Javascript
JS HTML图片显示Canvas 压缩功能
Jul 21 #Javascript
JavaScript 用fetch 实现异步下载文件功能
Jul 21 #Javascript
详解vue 模版组件的三种用法
Jul 21 #Javascript
Vue单页式应用(Hash模式下)实现微信分享的实例
Jul 21 #Javascript
vue-resource调用promise取数据方式详解
Jul 21 #Javascript
You might like
修改jQuery.Autocomplete插件 支持中文输入法 避免TAB、ENTER键失效、导致表单提交
2009/10/11 Javascript
Javascript结合css实现网页换肤功能
2009/11/02 Javascript
javascript与CSS复习(二)
2010/06/29 Javascript
jQuery is()函数用法3例
2014/05/06 Javascript
jquery得到iframe src属性值的方法
2014/09/25 Javascript
js操作css属性实现div层展开关闭效果的方法
2015/05/11 Javascript
基于BootStrap Metronic开发框架经验小结【三】下拉列表Select2插件的使用
2016/05/12 Javascript
微信小程序之蓝牙的链接
2017/09/26 Javascript
使用Javascript简单计算器
2018/11/17 Javascript
JavaScript多种页面刷新方法小结
2019/04/04 Javascript
JQuery的加载和选择器用法简单示例
2019/05/13 jQuery
vue.js 打包时出现空白页和路径错误问题及解决方法
2019/06/26 Javascript
使用 webpack 插件自动生成 vue 路由文件的方法
2019/08/20 Javascript
jQuery HTML css()方法与css类实例详解
2020/05/20 jQuery
解决nuxt页面中mounted、created、watch执行两遍的问题
2020/11/05 Javascript
[26:24]完美副总裁、DOTA2负责人蔡玮专访:电竞如人生
2014/09/11 DOTA
Python字符串和文件操作常用函数分析
2015/04/08 Python
Python中的下划线详解
2015/06/24 Python
Django的信号机制详解
2017/05/05 Python
python机器学习库常用汇总
2017/11/15 Python
如何在python中使用selenium的示例
2017/12/26 Python
Python用csv写入文件_消除空余行的方法
2018/07/06 Python
python 运用Django 开发后台接口的实例
2018/12/11 Python
Django 1.10以上版本 url 配置注意事项详解
2019/08/05 Python
详解Python中的format格式化函数的使用方法
2019/11/20 Python
基于Django实现日志记录报错信息
2019/12/17 Python
解决pyCharm中 module 调用失败的问题
2020/02/12 Python
Python爬虫谷歌Chrome F12抓包过程原理解析
2020/06/04 Python
Mavi牛仔裤美国官网:土耳其著名牛仔品牌
2016/09/24 全球购物
怀俄明州飞钓:Platte River Fly Shop
2017/12/28 全球购物
LivingSocial英国:英国本地优惠
2019/02/22 全球购物
不开辟用于交换数据的临时空间,如何完成字符串的逆序
2012/12/02 面试题
大四自我鉴定范文
2013/10/06 职场文书
工人先锋号申报材料
2014/12/29 职场文书
个人年底工作总结
2015/03/10 职场文书
matplotlib之pyplot模块实现添加子图subplot的使用
2021/04/25 Python