精华内容
下载资源
问答
  • 初学VBA,看了一个多礼拜的自学视频,又花了四五天时间想做出一个在报表里自动发邮件的小程序 试了很多 也在网上找了许多案例 但是最后效果outlook中显示出附件图片而没有图片附件,收件后则是有图片附件,正文中...

    初学VBA,做出一个在报表里自动发邮件的小程序 ,但是最后效果outlook中显示出附件图片而没有图片附件,收件后则是有图片附件,正文中图片全白无法显示,解决如下(注意cid:是要小写的,否则不行):

    Dim newMlItem As Outlook.MailItem
        ms = "C:\Users\temp\Desktop\TEMP.BMP"
        FileName = "TEMP.BMP"
        Set newMlItem = Outlook.CreateItem(olMailItem)
        With newMlItem
            .Subject = "FW:"
            .Attachments.add ms
            .HTMLBody = "<p class=MsoNormal><span lang=EN-US style='font-size:10.0pt;font-family:""Arial"",sans-serif'><img id=""_TEMP.BMP"" src=""cid:TEMP.BMP""></span>"
            .To = "abc@sina.com"
            .send
            End With
    End Sub

    展开全文
  • 怎么将许多张照片打包到邮箱?所谓的打包,就是需要你把大量照片文件变成一个压缩文件,类似于放到一个文件夹内,也可以理解为把张纸质照片装订成一个相册,而在装订过程中需要相应工具才能完成。使用压缩包发送...
    be70a2cd89d3a307b9acca49cb90a9a5.png

    怎么将许多张照片打包发到邮箱?

    所谓的打包,就是需要你把大量照片文件变成一个压缩文件,类似于放到一个文件夹内,也可以理解为把多张纸质照片装订成一个相册,而在装订过程中需要相应工具才能完成。

    使用压缩包发送文件,可以节省一些你发送邮件时所使用的空间以及时间,而且也会很方便、简洁。

    2a0584920b2289f3c611fa12e5317040.png

    类似于这样直接发送的,就让人感觉很乱,下载也需要花费很多时间一个个点击。如果直接打包,那么就只有一个文件,对方只需要选择下载一次,之后鼠标右键选择解压,就能直接查看到你发过去的照片。

    1583f1970bace65270b95666c0bd2f22.png

    现在的一般个人邮箱都是有空间限制,有些邮箱单个文件只能发送200M或者1GB,在数量上也是有相应的限制。当然,如果你照片文件不多的话,发送过去也可,不过对方接收的时候就需要一个个下载,相对来说比较浪费时间,这样也显得你不够专业(如上面所提到)。

    而压缩打包则可以避免这样的尴尬。

    99b98df9511397242ca4de71149edb61.png

    一般压缩包可以把文件压缩至该文件的80-90%。网络不好的话,你上传下载会节省不少时间。因为我的照片是JPG格式的,因为该该格式是图片类的一种压缩标准,所以看起来与原来的并没有多少差别。

    a3b06874fd8fe15f630b52217491cf92.png

    文本文档类的,压缩率会更小。

    现在市面上的压缩工具很多,有收费和免费的,就不给你列举,你搜索一下就能找到。

    下载安装后都会直接集成到你的右键,全选照片后,点击右键就可以压缩到一个压缩包内。或者也可先压缩一个文件,之后再把其它文件拖动到已经压缩好的压缩包内都可。

    abe1380992a471d6ed6d160ee76121cf.png

    并且也可以对该压缩包进行加密,只有相应密码方可解压。

    b049a38c9caad6d01eaa2b583eeca99c.png

    学习和操作成本不高,使用一两次就能学会。之后的使用也会方便许多。

    当然有好处也坏处,压缩过程中也可能因为其它原因,使得压缩包损坏。建议还是要做好相应文件的备份,以免产生不必要的麻烦。

    至于怎么把压缩包用邮箱发送出去,就和你正常发送附件一样。

    如果邮箱有空间限制,而你的照片量过多过大,可以分开成几个压缩包,分批发送。

    也可以直接把照片上传到一些网盘内,之后把分享链接以邮件发送过去,让对方自己选择下载也可。

    这样也省下你把照片打包再上传的时间,当然还是有利有弊,利是会很方便,但是一些网盘可能会压制你的照片文件,对方收到的照片可能就不是原图了。

    当然,也可以直接让对方下载你上传的一个大压缩包文件,这个文件解压后都是原图。

    以上。

    展开全文
  • 自从用邮箱注册了很多账号后,便会收到诸如以下类似的邮件,刚开始还以为是一张图片,后来仔细一看不是图片呀,好像还是HTML呀,于是好奇宝宝我Google一下,查阅多篇资料后总结出怎么用前端知识和Node做一个这样的...

    本文首发于个人博客:Vince'Blog

    项目源码:NodeMail,欢迎star,说不定哪天脱单了就能用到了

    写在前面

    自从用邮箱注册了很多账号后,便会收到诸如以下类似的邮件,刚开始还以为是一张图片,后来仔细一看不是图片呀,好像还是HTML呀,于是好奇宝宝我Google一下,查阅多篇资料后总结出怎么用前端知识和Node做一个这样的“邮件网页”。

     

    image

     

     

    确认主题

    知道怎么实现功能后,思考着我该写什么主题呢,用一个HTML模板随便给小伙伴们发个邮件炫个技?不行,作为一个很cool的程序员怎么能这么low呢,最近天气变化幅度大,温度捉摸不定,女朋友总是抱怨穿少了又冷穿多了又热,嗨呀,要不我就写个每天定时给宝宝发送天气预报的邮件,另外想起宝宝喜欢看ONE·一个这个APP上的每日更新,要不发天气预报的同时,再附赠一个“ONE的每日订阅”?机智又浪漫,开始搬砖~

    剧透

    本来是想最后放效果图的,怕你们看到一半就没兴趣了,就在前面剧透一下我最后做出来的效果图吧~

     

    image

     

     

    待解决的问题

    1. 如何获取天气预报和ONE上的data?

    答:获取data有两种方法,第一种方法是获取天气预报和ONE的API,第二种是用node爬虫获取天气预报和ONE网页的信息。后来找了下,发现ONE并没有API接口,为了让两者统一,于是决定使用node上的一个插件叫cheerio,配合superagent能够很方便地爬取网页上的信息。

    2. 如何做出HTML的这种邮件?

    答:之前学过一段时间的express这个框架,接触到模版引擎这个概念,传入data便可获得html文件,再结合node的fs模块,获取到这个html文件,便可以结合node的邮件插件发送HTML邮件啦!

    3. 如何用node发送邮件?

    感谢无私的开源开发者,开发了一款发送邮件的Node插件nodemailer,兼容主流的Email厂商,只需要配置好邮箱账号和smtp授权码,便可以用你的邮箱账号在node脚本上发文件,很cool有没有~

    4. 如何做到每日定时发送?

    其实可以通过各种hack的方式写这么一个定时任务,但是既然node社区有这个定时的轮子,那我们直接用就好了,node-schedule是一个有着各种配置的定时任务发生器,可以定时每个月、每个礼拜、每天具体什么时候执行什么任务,这正符合每天早晨定时给宝宝发送邮件的需求。

    一切准备就绪,开始做一次浪漫的程序员

    编写代码

    网页爬虫

    这里我们使用到superagentcheerio组合来实现爬虫:

    • 分析网页DOM结构,如下图所示:

     

    image

     

     

    • 用superagent来获取指定网页的所有DOM:
    superagent.get(URL).end(function(err,res){
        //
    }
    复制代码
    • 用cheerio来筛选superagent获取到的DOM,取出需要的DOM
    imgUrl:$(todayOne).find('.fp-one-imagen').attr('src'),
    type:$(todayOne).find('.fp-one-imagen-footer').text().replace(/(^\s*)|(\s*$)/g, ""),
    text:$(todayOne).find('.fp-one-cita').text().replace(/(^\s*)|(\s*$)/g, "")
    复制代码

    以下就是爬取ONE的代码,天气预报网页也是一个道理:

    const superagent = require('superagent'); //发送网络请求获取DOM
    const cheerio = require('cheerio'); //能够像Jquery一样方便获取DOM节点
    
    const OneUrl = "http://wufazhuce.com/"; //ONE的web版网站
    
    superagent.get(OneUrl).end(function(err,res){
        if(err){
           console.log(err);
        }
        let $ = cheerio.load(res.text);
        let selectItem=$('#carousel-one .carousel-inner .item');
        let todayOne=selectItem[0]; //获取轮播图第一个页面,也就是当天更新的内容
        let todayOneData={  //保存到一个json中
            imgUrl:$(todayOne).find('.fp-one-imagen').attr('src'),
            type:$(todayOne).find('.fp-one-imagen-footer').text().replace(/(^\s*)|(\s*$)/g, ""),
            text:$(todayOne).find('.fp-one-cita').text().replace(/(^\s*)|(\s*$)/g, "")
        };
        console.log(todayOneData);
    })
    复制代码

    EJS模版引擎生成HTML

    通过爬虫获取到了数据,那么我们就能够通过将date输入到EJS渲染出HTML,我们在目录下创建js脚本和ejs模版文件:

    • app.js
    const ejs = require('ejs'); //ejs模版引擎
    const fs  = require('fs'); //文件读写
    const path = require('path'); //路径配置
    
    //传给EJS的数据
    let data={
        title:'nice to meet you~'
    }
    
    //将目录下的mail.ejs获取到,得到一个模版
    const template = ejs.compile(fs.readFileSync(path.resolve(__dirname, 'mail.ejs'), 'utf8'));
    //将数据传入模版中,生成HTML
    const html = template(data);
    
    console.log(html)
    
    复制代码
    • mail.ejs
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>Document</title>
    </head>
    <body>
        <h1>
            <%= title %>
        </h1>
    </body>
    </html>
    复制代码

    用Node发送邮件

    这里我们可以发送纯text也可以发送html,注意的是邮箱密码不是你登录邮箱的密码,而是smtp授权码,什么是smtp授权码呢?就是你的邮箱账号可以使用这个smtp授权码在别的地方发邮件,一般smtp授权码在邮箱官网的设置中可以看的到,设置如下注释。

    const nodemailer = require('nodemailer'); //发送邮件的node插件
    
    let transporter = nodemailer.createTransport({
        service: '126', // 发送者的邮箱厂商,支持列表:https://nodemailer.com/smtp/well-known/
        port: 465, // SMTP 端口
        secureConnection: true, // SSL安全链接
        auth: {   //发送者的账户密码
          user: '账户@126.com', //账户
          pass: 'smtp授权码', //smtp授权码,到邮箱设置下获取
        }
      });
    
    let mailOptions = {
        from: '"发送者昵称" <地址@126.com>', // 发送者昵称和地址
        to: 'like@vince.studio', // 接收者的邮箱地址
        subject: '一封暖暖的小邮件', // 邮件主题
        text: 'test mail',  //邮件的text
        // html: html  //也可以用html发送  
      };
      
    //发送邮件
    transporter.sendMail(mailOptions, (error, info) => {  
        if (error) {
        return console.log(error);
        }
        console.log('邮件发送成功 ID:', info.messageId);
    });  
    复制代码

    Node定时执行任务

    这里我们用到了node-schedule来定时执行任务,示例如下:

    var schedule = require("node-schedule");  
    
    //1. 确定的时间执行
    var date = new Date(2017,12,10,15,50,0);  
    schedule.scheduleJob(date, function(){  
       console.log("执行任务");
    });
    
    //2. 秒为单位执行 
    //比如:每5秒执行一次
    var rule1     = new schedule.RecurrenceRule();  
    var times1    = [1,6,11,16,21,26,31,36,41,46,51,56];  
    rule1.second  = times1;  
    schedule.scheduleJob(rule1, function(){
        console.log("执行任务");    
    });
    
    //3.以分为单位执行
    //比如:每5分种执行一次
    var rule2     = new schedule.RecurrenceRule();  
    var times2    = [1,6,11,16,21,26,31,36,41,46,51,56];  
    rule2.minute  = times2;  
    schedule.scheduleJob(rule2, function(){  
        console.log("执行任务");    
    });  
    
    //4.以天单位执行
    //比如:每天6点30分执行
    var rule = new schedule.RecurrenceRule();
    rule.dayOfWeek = [0, new schedule.Range(1, 6)];
    rule.hour = 6;
    rule.minute =30;
    var j = schedule.scheduleJob(rule, function(){
     &emsp;&emsp;&emsp;&emsp;console.log("执行任务");
            getData();
    });
    复制代码

    思路与步骤

    当所有的问题都解决后,便是开始结合代码成一段完整的程序,思路很简单,我们来逐步分析:

    1. 由于获取数据是异步的,并且不能判断出哪个先获取到数据,这个是可以将获取数据的函数封装成一个Promise对象,最后在一起用Promise.all来判断所有数据获取完毕,再发送邮件
    // 其中一个数据获取函数,其他的也是类似
    function getOneData(){
        let p = new Promise(function(resolve,reject){
            superagent.get(OneUrl).end(function(err, res) {
                if (err) {
                    reject(err);
                }
                let $ = cheerio.load(res.text);
                let selectItem = $("#carousel-one .carousel-inner .item");
                let todayOne = selectItem[0];
                let todayOneData = {
                  imgUrl: $(todayOne)
                    .find(".fp-one-imagen")
                    .attr("src"),
                  type: $(todayOne)
                    .find(".fp-one-imagen-footer")
                    .text()
                    .replace(/(^\s*)|(\s*$)/g, ""),
                  text: $(todayOne)
                    .find(".fp-one-cita")
                    .text()
                    .replace(/(^\s*)|(\s*$)/g, "")
                };
                resolve(todayOneData)
              });
        })
        return p
    }
    
    复制代码
    1. 将爬取数据统一处理,作为EJS的参数,发送邮件模板。
    
    function getAllDataAndSendMail(){
        let HtmlData = {};
        // how long with
        let today = new Date();
        let initDay = new Date(startDay);
        let lastDay = Math.floor((today - initDay) / 1000 / 60 / 60 / 24);
        let todaystr =
          today.getFullYear() +
          " / " +
          (today.getMonth() + 1) +
          " / " +
          today.getDate();
        HtmlData["lastDay"] = lastDay;
        HtmlData["todaystr"] = todaystr;
    
        Promise.all([getOneData(),getWeatherTips(),getWeatherData()]).then(
            function(data){
                HtmlData["todayOneData"] = data[0];
                HtmlData["weatherTip"] = data[1];
                HtmlData["threeDaysData"] = data[2];
                sendMail(HtmlData)
            }
        ).catch(function(err){
            getAllDataAndSendMail() //再次获取
            console.log('获取数据失败: ',err);
        })
    }
    
    复制代码
    1. 发送邮件具体代码
    
    function sendMail(HtmlData) {
        const template = ejs.compile(
          fs.readFileSync(path.resolve(__dirname, "email.ejs"), "utf8")
        );
        const html = template(HtmlData);
      
        let transporter = nodemailer.createTransport({
          service: EmianService,
          port: 465,
          secureConnection: true,
          auth: EamilAuth
        });
      
        let mailOptions = {
          from: EmailFrom,
          to: EmailTo,
          subject: EmailSubject,
          html: html
        };
        transporter.sendMail(mailOptions, (error, info={}) => {
          if (error) {
            console.log(error);
            sendMail(HtmlData); //再次发送
          }
          console.log("Message sent: %s", info.messageId);
        });
      }
    复制代码

    安装与使用

    如果你觉得这封邮件的内容适合你发送的对象,可以按照以下步骤,改少量参数即可运行程序;

    1. git clone github.com/Vincedream/…
    2. 打开main.js,修改配置项
    //纪念日
    let startDay = "2016/6/24";
    
    //当地拼音,需要在下面的墨迹天气url确认
    const local = "xiangtan";
    
    //发送者邮箱厂家
    let EmianService = "163";
    //发送者邮箱账户SMTP授权码
    let EamilAuth = {
      user: "xxxxxx@163.com",
      pass: "xxxxxx"
    };
    //发送者昵称与邮箱地址
    let EmailFrom = '"name" <xxxxxx@163.com>';
    
    //接收者邮箱地
    let EmailTo = "like@vince.studio";
    //邮件主题
    let EmailSubject = "一封暖暖的小邮件";
    
    //每日发送时间
    let EmailHour = 6;
    let EmialMinminute= 30;
    复制代码
    1. 终端输入npm install安装依赖,再输入node main.js,运行脚本,当然你的电脑不可能不休眠,建议你部署到你的云服务器上运行。

    最后

    冬天到了,是不是也该用程序员的专业知识给身边的人带来一些温暖呢,源代码与demo已经放到github上,要不试一试?

    GitHub:github.com/Vincedream/…


    作者:Vince_
    链接:https://juejin.im/post/5c75fa4af265da2d84109219
    来源:掘金
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

     

    -------------------------------------------    手动分割    -----------------------------------------

    知识点总结

    http请求模块  SuperAgent

    //请求方式    
    superagent.get('/api')
    // 地址栏带参数 ,相当于  /api?name=value
    superagent
        .get('/api')
        .query({name: value})//query方法
    //设置请求头 
    superagent
        .get('/api')
        .query({name: value})
        .set({'token':'xxxxxxxxx'})//set方法
    //post数据传参,content-type默认为application/json
    superagent
        .post('/api')
        .send({name: value})//send方法
        .set({'token':'xxxxxxxxx'})
    //设置content-type
    superagent
        .post('/api')
        .send({name: value})
        .set({//set方法
            'token':'xxxxxxxxx',
            'Content-Type': 'application/x-www-form-urlencoded'
        })
    //请求完成结果
    superagent
        .post('/api')
        .send({name: value})
        .set({
            'token':'xxxxxxxxx',
            'Content-Type': 'application/x-www-form-urlencoded'
        })
        .end(function(err, res){//end方法,err为错误信息,res为响应数据
            if(err) {
                console.log(err);
                return;
            }
            console.log(res.text);//res.text为响应结果
            console.log(res.status);//res.status为状态码
        })

    cheerio模块(可以理解为传入html字符串后,可以像jquery一样操作dom,非常方便的去获取我们想要的数据,可以不用写正则)

    //创建虚拟dom    load方法
    var $ = cheerio.load('<body><p>hello world</p></body>');//通常赋值给变量$,方便直接像写jquery一样的写法.
    //操作dom
    var text = $('body p').text();

    ejs模块 

    这篇文章写的不错

    <!-- template中 --> 
    <h1><%= title %></h1>
    
    <!-- js中 -->
    var data = {title: 'hello world'};
    ejs.render(html字符串, data);
    

    定时任务   node-schedule

    var j = schedule.scheduleJob('* * * * * *', function(){
        // 这里写需要执行的任务
    });
    // 取消定时器(用于单次任务)
    j.cancel();
    /*
    第一位参数是 Cron
    从左到右依次是  
    秒 0-59
    分 0-59
    时 0-23
    日 1-31
    月 1-12
    周 1-7 (1表示周一,7表示周日)
    
    
    举例
    每隔五分钟执行依次
    * */5 * * * *
    
    每天下午5点20执行
    * 20 17 * * *
    
    每周一周三周五的下午2点4点内每隔5分钟执行依次
    * */5 2,4 * * 1,3,5
    
    */

    发送邮件  nodemailer

    let transporter = nodemailer.createTransport({
        service: 'QQ', // 发送者的邮箱厂商,支持列表:https://nodemailer.com/smtp/well-known/
        port: 465, // SMTP 端口
        secureConnection: true, // SSL安全链接
        auth: {   //发送者的账户密码
          user: 'xxxx@qq.com', //账户
          pass: 'xxxx', //smtp授权码,到邮箱设置下获取
        }
    });
    let mailOptions = {
        from: '"昵称" <xxxx@qq.com>', // 发送者昵称和地址
        to: 'xxxx@qq.com', // 接收者的邮箱地址
        subject: '主题', // 邮件主题
        text: '邮件内容',  //邮件的text,
        // html: html  //用html发送时配置这一项,关掉text  
    };
    // 发送邮件
    transporter.sendMail(mailOptions, (error, info) => {  
        if (error) {
        return console.log(error);
        }
        console.log('邮件发送成功 ID:', info.messageId);
    });

     

    展开全文
  • 自从用邮箱注册了很多账号后,便会收到诸如以下类似的邮件,刚开始还以为是一张图片,后来仔细一看不是图片呀,好像还是HTML呀,于是好奇宝宝我Google一下,查阅多篇资料后总结出怎么用前端知识和Node做一个这样的...
        

    本文首发于个人博客:Vince'Blog

    项目源码:NodeMail,欢迎star,说不定哪天脱单了就能用到了

    写在前面

    自从用邮箱注册了很多账号后,便会收到诸如以下类似的邮件,刚开始还以为是一张图片,后来仔细一看不是图片呀,好像还是HTML呀,于是好奇宝宝我Google一下,查阅多篇资料后总结出怎么用前端知识和Node做一个这样的“邮件网页”。

    image

    确认主题

    知道怎么实现功能后,思考着我该写什么主题呢,用一个HTML模板随便给小伙伴们发个邮件炫个技?不行,作为一个很cool的程序员怎么能这么low呢,最近天气变化幅度大,温度捉摸不定,女朋友总是抱怨穿少了又冷穿多了又热,嗨呀,要不我就写个每天定时给宝宝发送天气预报的邮件,另外想起宝宝喜欢看ONE·一个这个APP上的每日更新,要不发天气预报的同时,再附赠一个“ONE的每日订阅”?机智又浪漫,开始搬砖~

    剧透

    本来是想最后放效果图的,怕你们看到一半就没兴趣了,就在前面剧透一下我最后做出来的效果图吧~

    image

    待解决的问题

    1. 如何获取天气预报和ONE上的data?

    答:获取data有两种方法,第一种方法是获取天气预报和ONE的API,第二种是用node爬虫获取天气预报和ONE网页的信息。后来找了下,发现ONE并没有API接口,为了让两者统一,于是决定使用node上的一个插件叫cheerio,配合superagent能够很方便地爬取网页上的信息。

    2. 如何做出HTML的这种邮件?

    答:之前学过一段时间的express这个框架,接触到模版引擎这个概念,传入data便可获得html文件,再结合node的fs模块,获取到这个html文件,便可以结合node的邮件插件发送HTML邮件啦!

    3. 如何用node发送邮件?

    感谢无私的开源开发者,开发了一款发送邮件的Node插件nodemailer,兼容主流的Email厂商,只需要配置好邮箱账号和smtp授权码,便可以用你的邮箱账号在node脚本上发文件,很cool有没有~

    4. 如何做到每日定时发送?

    其实可以通过各种hack的方式写这么一个定时任务,但是既然node社区有这个定时的轮子,那我们直接用就好了,node-schedule是一个有着各种配置的定时任务发生器,可以定时每个月、每个礼拜、每天具体什么时候执行什么任务,这正符合每天早晨定时给宝宝发送邮件的需求。

    一切准备就绪,开始做一次浪漫的程序员

    编写代码

    网页爬虫

    这里我们使用到superagentcheerio组合来实现爬虫:

    • 分析网页DOM结构,如下图所示:

    image

    • 用superagent来获取指定网页的所有DOM:
    superagent.get(URL).end(function(err,res){
        //
    }
    • 用cheerio来筛选superagent获取到的DOM,取出需要的DOM
    imgUrl:$(todayOne).find('.fp-one-imagen').attr('src'),
    type:$(todayOne).find('.fp-one-imagen-footer').text().replace(/(^\s*)|(\s*$)/g, ""),
    text:$(todayOne).find('.fp-one-cita').text().replace(/(^\s*)|(\s*$)/g, "")

    以下就是爬取ONE的代码,天气预报网页也是一个道理:

    const superagent = require('superagent'); //发送网络请求获取DOM
    const cheerio = require('cheerio'); //能够像Jquery一样方便获取DOM节点
    
    const OneUrl = "http://wufazhuce.com/"; //ONE的web版网站
    
    superagent.get(OneUrl).end(function(err,res){
        if(err){
           console.log(err);
        }
        let $ = cheerio.load(res.text);
        let selectItem=$('#carousel-one .carousel-inner .item');
        let todayOne=selectItem[0]; //获取轮播图第一个页面,也就是当天更新的内容
        let todayOneData={  //保存到一个json中
            imgUrl:$(todayOne).find('.fp-one-imagen').attr('src'),
            type:$(todayOne).find('.fp-one-imagen-footer').text().replace(/(^\s*)|(\s*$)/g, ""),
            text:$(todayOne).find('.fp-one-cita').text().replace(/(^\s*)|(\s*$)/g, "")
        };
        console.log(todayOneData);
    })

    EJS模版引擎生成HTML

    通过爬虫获取到了数据,那么我们就能够通过将date输入到EJS渲染出HTML,我们在目录下创建js脚本和ejs模版文件:

    • app.js
    const ejs = require('ejs'); //ejs模版引擎
    const fs  = require('fs'); //文件读写
    const path = require('path'); //路径配置
    
    //传给EJS的数据
    let data={
        title:'nice to meet you~'
    }
    
    //将目录下的mail.ejs获取到,得到一个模版
    const template = ejs.compile(fs.readFileSync(path.resolve(__dirname, 'mail.ejs'), 'utf8'));
    //将数据传入模版中,生成HTML
    const html = template(data);
    
    console.log(html)
    
    • mail.ejs
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>Document</title>
    </head>
    <body>
        <h1>
            <%= title %>
        </h1>
    </body>
    </html>

    用Node发送邮件

    这里我们可以发送纯text也可以发送html,注意的是邮箱密码不是你登录邮箱的密码,而是smtp授权码,什么是smtp授权码呢?就是你的邮箱账号可以使用这个smtp授权码在别的地方发邮件,一般smtp授权码在邮箱官网的设置中可以看的到,设置如下注释。

    const nodemailer = require('nodemailer'); //发送邮件的node插件
    
    let transporter = nodemailer.createTransport({
        service: '126', // 发送者的邮箱厂商,支持列表:https://nodemailer.com/smtp/well-known/
        port: 465, // SMTP 端口
        secureConnection: true, // SSL安全链接
        auth: {   //发送者的账户密码
          user: '账户@126.com', //账户
          pass: 'smtp授权码', //smtp授权码,到邮箱设置下获取
        }
      });
    
    let mailOptions = {
        from: '"发送者昵称" <地址@126.com>', // 发送者昵称和地址
        to: 'like@vince.studio', // 接收者的邮箱地址
        subject: '一封暖暖的小邮件', // 邮件主题
        text: 'test mail',  //邮件的text
        // html: html  //也可以用html发送  
      };
      
    //发送邮件
    transporter.sendMail(mailOptions, (error, info) => {  
        if (error) {
        return console.log(error);
        }
        console.log('邮件发送成功 ID:', info.messageId);
    });  

    Node定时执行任务

    这里我们用到了node-schedule来定时执行任务,示例如下:

    var schedule = require("node-schedule");  
    
    //1. 确定的时间执行
    var date = new Date(2017,12,10,15,50,0);  
    schedule.scheduleJob(date, function(){  
       console.log("执行任务");
    });
    
    //2. 秒为单位执行 
    //比如:每5秒执行一次
    var rule1     = new schedule.RecurrenceRule();  
    var times1    = [1,6,11,16,21,26,31,36,41,46,51,56];  
    rule1.second  = times1;  
    schedule.scheduleJob(rule1, function(){
        console.log("执行任务");    
    });
    
    //3.以分为单位执行
    //比如:每5分种执行一次
    var rule2     = new schedule.RecurrenceRule();  
    var times2    = [1,6,11,16,21,26,31,36,41,46,51,56];  
    rule2.minute  = times2;  
    schedule.scheduleJob(rule2, function(){  
        console.log("执行任务");    
    });  
    
    //4.以天单位执行
    //比如:每天6点30分执行
    var rule = new schedule.RecurrenceRule();
    rule.dayOfWeek = [0, new schedule.Range(1, 6)];
    rule.hour = 6;
    rule.minute =30;
    var j = schedule.scheduleJob(rule, function(){
         console.log("执行任务");
            getData();
    });

    思路与步骤

    当所有的问题都解决后,便是开始结合代码成一段完整的程序,思路很简单,我们来逐步分析:

    1. 由于获取数据是异步的,并且不能判断出哪个先获取到数据,这个是可以将获取数据的函数封装成一个Promise对象,最后在一起用Promise.all来判断所有数据获取完毕,再发送邮件
    // 其中一个数据获取函数,其他的也是类似
    function getOneData(){
        let p = new Promise(function(resolve,reject){
            superagent.get(OneUrl).end(function(err, res) {
                if (err) {
                    reject(err);
                }
                let $ = cheerio.load(res.text);
                let selectItem = $("#carousel-one .carousel-inner .item");
                let todayOne = selectItem[0];
                let todayOneData = {
                  imgUrl: $(todayOne)
                    .find(".fp-one-imagen")
                    .attr("src"),
                  type: $(todayOne)
                    .find(".fp-one-imagen-footer")
                    .text()
                    .replace(/(^\s*)|(\s*$)/g, ""),
                  text: $(todayOne)
                    .find(".fp-one-cita")
                    .text()
                    .replace(/(^\s*)|(\s*$)/g, "")
                };
                resolve(todayOneData)
              });
        })
        return p
    }
    
    1. 将爬取数据统一处理,作为EJS的参数,发送邮件模板。
    
    function getAllDataAndSendMail(){
        let HtmlData = {};
        // how long with
        let today = new Date();
        let initDay = new Date(startDay);
        let lastDay = Math.floor((today - initDay) / 1000 / 60 / 60 / 24);
        let todaystr =
          today.getFullYear() +
          " / " +
          (today.getMonth() + 1) +
          " / " +
          today.getDate();
        HtmlData["lastDay"] = lastDay;
        HtmlData["todaystr"] = todaystr;
    
        Promise.all([getOneData(),getWeatherTips(),getWeatherData()]).then(
            function(data){
                HtmlData["todayOneData"] = data[0];
                HtmlData["weatherTip"] = data[1];
                HtmlData["threeDaysData"] = data[2];
                sendMail(HtmlData)
            }
        ).catch(function(err){
            getAllDataAndSendMail() //再次获取
            console.log('获取数据失败: ',err);
        })
    }
    
    1. 发送邮件具体代码
    
    function sendMail(HtmlData) {
        const template = ejs.compile(
          fs.readFileSync(path.resolve(__dirname, "email.ejs"), "utf8")
        );
        const html = template(HtmlData);
      
        let transporter = nodemailer.createTransport({
          service: EmianService,
          port: 465,
          secureConnection: true,
          auth: EamilAuth
        });
      
        let mailOptions = {
          from: EmailFrom,
          to: EmailTo,
          subject: EmailSubject,
          html: html
        };
        transporter.sendMail(mailOptions, (error, info={}) => {
          if (error) {
            console.log(error);
            sendMail(HtmlData); //再次发送
          }
          console.log("Message sent: %s", info.messageId);
        });
      }

    安装与使用

    如果你觉得这封邮件的内容适合你发送的对象,可以按照以下步骤,改少量参数即可运行程序;

    1. git clone https://github.com/Vincedream...
    2. 打开main.js,修改配置项
    //纪念日
    let startDay = "2016/6/24";
    
    //当地拼音,需要在下面的墨迹天气url确认
    const local = "xiangtan";
    
    //发送者邮箱厂家
    let EmianService = "163";
    //发送者邮箱账户SMTP授权码
    let EamilAuth = {
      user: "xxxxxx@163.com",
      pass: "xxxxxx"
    };
    //发送者昵称与邮箱地址
    let EmailFrom = '"name" <xxxxxx@163.com>';
    
    //接收者邮箱地
    let EmailTo = "like@vince.studio";
    //邮件主题
    let EmailSubject = "一封暖暖的小邮件";
    
    //每日发送时间
    let EmailHour = 6;
    let EmialMinminute= 30;
    1. 终端输入npm install安装依赖,再输入node main.js,运行脚本,当然你的电脑不可能不休眠,建议你部署到你的云服务器上运行。

    最后

    冬天到了,是不是也该用程序员的专业知识给身边的人带来一些温暖呢,源代码与demo已经放到github上,要不试一试?

    GitHub:https://github.com/Vincedream/NodeMail

    展开全文
  • 很多时候,当我们的一批邮件发完之后,会发现销售量大增,于是有些商品就断货了。但是用户的邮件却没有显示断货,这就容易造成用户的误解。怎么处理呢?当然方法是有的。我们可以将已经断货的商品的图片进行一下处理...
  • Base64格式图片文件上传阿里云OSS

    千次阅读 2019-01-29 13:41:32
    也是第一次接触base64格式的东西,一开始并不知道它怎么显示,于是我用了很多图片转base64的工具来对里面的数据,通过这样来看我接受到的邮箱里面的数据到底是哪一部分,我该如何解析,通过半天的分析和测试...
  • 原来不只如此,很多网友都出现了这样的情况!花了心血辛辛苦苦写的Blog,就这样变得面目全非了!只有一个字:心痛...了好多邮件给CSDN的问题反馈的邮箱 webmaster@csdn.net ,石沉大海一样!本来就不怎么稳定的...
  • 15:需要有很多合作伙伴,其实整个项目里什么都一个人干不太实际,现在一个WEB系统需要的东西太多了,图片处理等我们有网络化的合作伙伴,要处理某个图片,网上一发过去需求讲好几个小时后就给处理好了,有的人专门...
  • 图床教程

    2020-12-08 23:55:00
    对于个人博客搭建、微信公众号的运营、邮件图片显示,图床都是方便的工具。 图床的原理 理解图床的原理能帮助我们更好的理解哪些工具能做图床,以及怎么用它们做图床。 <p><img alt="图床教程02" ...
  •  系统的广告管理位很多,所有广告图片内容均可以直接在线上传管理,同时支持FLASH滚动广告,管理员在后台只须上传广告图片,前台会自动生成各式各样的FLASH动态效果,给用户以美的视觉冲击。 十九、商品评论、留言...
  • 过期了

    2020-12-30 02:07:08
    很多“机密”都能搞清楚这是为什么,这个是怎么玩的,尤其是其内部的技术原理</li><li>除了必须满足以上这些要求之外,你还要能够证明你是一位学习能力非常强的人,因为互联网瞬息万变&#...
  • vc++ 应用源码包_1

    热门讨论 2012-09-15 14:22:12
    自绘了很多控件。自绘CTabCtrl、CToolBar、CMenu、CButton、CHtmlCtrl、CListCtrl。 hyperlink 自绘CStatic,实现超链接。 iconbutton_demo 演示了多种自绘Button。 IDocHostUIHandler Extended CHtmlView IM_...
  • vc++ 应用源码包_2

    热门讨论 2012-09-15 14:27:40
    自绘了很多控件。自绘CTabCtrl、CToolBar、CMenu、CButton、CHtmlCtrl、CListCtrl。 hyperlink 自绘CStatic,实现超链接。 iconbutton_demo 演示了多种自绘Button。 IDocHostUIHandler Extended CHtmlView IM_...
  • vc++ 应用源码包_6

    热门讨论 2012-09-15 14:59:46
    自绘了很多控件。自绘CTabCtrl、CToolBar、CMenu、CButton、CHtmlCtrl、CListCtrl。 hyperlink 自绘CStatic,实现超链接。 iconbutton_demo 演示了多种自绘Button。 IDocHostUIHandler Extended CHtmlView IM_...
  • vc++ 应用源码包_5

    热门讨论 2012-09-15 14:45:16
    自绘了很多控件。自绘CTabCtrl、CToolBar、CMenu、CButton、CHtmlCtrl、CListCtrl。 hyperlink 自绘CStatic,实现超链接。 iconbutton_demo 演示了多种自绘Button。 IDocHostUIHandler Extended CHtmlView IM_...
  • vc++ 应用源码包_4

    热门讨论 2012-09-15 14:38:35
    自绘了很多控件。自绘CTabCtrl、CToolBar、CMenu、CButton、CHtmlCtrl、CListCtrl。 hyperlink 自绘CStatic,实现超链接。 iconbutton_demo 演示了多种自绘Button。 IDocHostUIHandler Extended CHtmlView IM_...
  • vc++ 应用源码包_3

    热门讨论 2012-09-15 14:33:15
    自绘了很多控件。自绘CTabCtrl、CToolBar、CMenu、CButton、CHtmlCtrl、CListCtrl。 hyperlink 自绘CStatic,实现超链接。 iconbutton_demo 演示了多种自绘Button。 IDocHostUIHandler Extended CHtmlView IM_...
  • asp.net知识库

    2015-06-18 08:45:45
    鼠标放在一个连接上,会显示图片(类似tooltip) 使用microsoft.web.ui.webcontrols的TabStrip与IFame组件,达到页的切换效果 HttpModule 实现 ASP.Net (*.aspx) 中文简繁体的自动转换,不用修改原有的任何代码,直接部署...
  • 1、一些资料可以在github中搜索,很多,很方便 2、仓库内容下载 因为GitHub仓库容量为1G,而现在我仅仅是把王道和天勤的PDF收集起来就800M了,所以我将所有内容上传到我的博客中,可以去下载。 本仓库中有一个名为...
  • 如果有引导系统的计算机,必须保证是在包含 Windows 的驱动器上使用该命令。 Diskpart  创建和删除硬盘驱动器上的分区。diskpart 命令仅在使用故障恢复控制台时才可用。  diskpart [ /add |/delete] [device_...
  • 2.2.4 使用OPENROWSET和BULK插入或更新图片文件 68 2.2.5 在维护SQL Server事务控制时向文件系统存储非结构化数据 69 2.2.6 “就地”赋值并修改数据库值 73 2.3 DELETE 75 2.3.1 删除行 75 2.3.2 截断表...
  • <ul><li>分页</li><li>表格排序</li><li>搜索</li><li>控制每页显示数量</li><li>数据了之后,前端交互和后端数据的接口配合</li></ul> 不动戳大 <p><img alt="表格" src=...

空空如也

空空如也

1 2
收藏数 31
精华内容 12
关键字:

很多图片怎么发邮件