30分鐘實(shí)現(xiàn)node批量定時(shí)發(fā)送郵件

? ? 在年前摸魚的時(shí)候, 想著怎么把天氣等信息定時(shí)發(fā)送到我的郵箱, 讓我每天早上起床能準(zhǔn)時(shí)收到今天天氣, 同時(shí)我也想讓關(guān)心的人同樣收到, 于是整理了一下思路:

需求一: 開通SMTP服務(wù);

需求二: 天氣信息獲取;?

需求三:?批量發(fā)送郵件功能;

需求四: 定時(shí)發(fā)送;

我這里使用的egg框架, 因?yàn)楹?jiǎn)單好用, 接下來(lái)就開始一步一步實(shí)現(xiàn)

快速創(chuàng)建一個(gè)egg項(xiàng)目, 我使用的官方推薦:

我們推薦直接使用腳手架,只需幾條簡(jiǎn)單指令,即可快速生成項(xiàng)目(npm >=6.1.0), 框架默認(rèn)啟動(dòng)端口7001

$ mkdir egg-example && cd egg-example

$ npm init egg --type=simple

$ npm i

啟動(dòng)項(xiàng)目:

$ npm run dev

$ open http://localhost:7001

一.開通SMTP服務(wù)

我這里用的是qq郵箱

具體流程我就不多說(shuō), 可參考【SMTP服務(wù)】開啟郵箱smtp服務(wù)教程

二. 天氣信息的獲取

去高德開放平臺(tái)免費(fèi)注冊(cè)一個(gè)開發(fā)者, 創(chuàng)建應(yīng)用, 申請(qǐng)key, 然后就擁有了很多api接口權(quán)限, 這里我使用的是v3接口高德開放平臺(tái)https://lbs.amap.com/

因?yàn)楸救四壳霸谏钲? 所以就直接在高德拿到了城市的代碼: 440300; 其他地區(qū)請(qǐng)通過高德接口自行獲取;

獲取天氣信息接口為:?https://restapi.amap.com/v3/weather/weatherInfo

參數(shù): key和city? ? ? ? 完整請(qǐng)求路徑: https://restapi.amap.com/v3/weather/weatherInfo?key=你的key&city=440300

具體返回內(nèi)容請(qǐng)以高德為準(zhǔn).

三.?批量發(fā)送郵件功能;

需要用到 nodemailer 插件和 smtpTransport 方法來(lái)實(shí)現(xiàn)批量郵件發(fā)送, 我這里將主要代碼放在了 業(yè)務(wù)邏輯層 Service目錄, 創(chuàng)建weather.js

const Service = require('egg').Service;

const nodemailer = require('nodemailer')

const smtpTransport = require('nodemailer-smtp-transport');

class WeatherService extends Service {

? ? async send(data) {

? ? ? ? const transporter = nodemailer.createTransport(smtpTransport({

? ? ? ? ? ? host: 'smtp.qq.com', //郵件服務(wù)供應(yīng)商

? ? ? ? ? ? pool: true,

? ? ? ? ? ? port: 465,

? ? ? ? ? ? secure: true, // use TLS使用HTTPS port可以是 465 也可以是 994

? ? ? ? ? ? auth: {

? ? ? ? ? ? ? ? user: 'xxx@qq.com', //發(fā)送方

? ? ? ? ? ? ? ? pass: 'xxx'//密碼或授權(quán)碼

? ? ? ? ? ? }

? ? ? ? }));

? ? ? ? // 發(fā)送給誰(shuí)以及發(fā)送內(nèi)容

? ? ? ? const mailOptions = {

? ? ? ? ? ? from: 'xxx@qq.com',//發(fā)送方

? ? ? ? ? ? to: '123456789@qq.com,987654321@qq.com',//接收方

? ? ? ? ? ? subject: '請(qǐng)注意查收天氣信息!', // 標(biāo)題

? ? ? ? ? ? html: `<div>

? ? ? ? ? ? <h1>今日天氣</h1>

? ? ? ? ? ? <p>省份: ${data.province}</p>

? ? ? ? ? ? <p>城市: ${data.city}</p>

? ? ? ? ? ? <p>溫度: ${data.temperature}°C</p>

? ? ? ? ? ? <p>天氣: ${data.weather}</p>

? ? ? ? ? ? <p>風(fēng)向: ${data.winddirection}</p>

? ? ? ? ? ? <p>風(fēng)力: ${data.windpower}級(jí)</p>

? ? ? ? ? ? <p>濕度: ${data.humidity}RH</p>

? ? ? ? ? ? <p>天氣時(shí)間: ${data.reporttime}</p>

? ? ? ? </div>`

? ? ? ? }

? ? ? ? async function sendEmails(transporter,mailOptions) {

? ? ? ? ? ? try {

? ? ? ? ? ? ? ? const verifypass = await transporter.verify();//驗(yàn)證郵件發(fā)送者transporter是否配置正確

? ? ? ? ? ? ? ? const sendSucess = await transporter.sendMail(mailOptions);//配置無(wú)誤,發(fā)送發(fā)送郵件

? ? ? ? ? ? ? ? if (sendSucess) {

? ? ? ? ? ? ? ? ? ? console.log('發(fā)送成功');

? ? ? ? ? ? ? ? }

? ? ? ? ? ? } catch (error) {

? ? ? ? ? ? ? console.log(error); ?

? ? ? ? ? ? }

? ? ? ? }

? ? ? ? sendEmails(transporter,mailOptions);

? ? }

}

module.exports = WeatherService;

通過router輸出一個(gè)api可測(cè)試是否發(fā)送成功

四.?定時(shí)發(fā)送

這里用到了egg自帶的插件schedule, 在schedule目錄創(chuàng)建update_cache.js; 想要了解更多請(qǐng)參考?egg定時(shí)任務(wù)

主要邏輯就是定時(shí)執(zhí)行 從高德獲取到的天氣信息, 然后批量發(fā)送郵件

const Subscription = require('egg').Subscription;

class UpdateCache extends Subscription {

? // 通過 schedule 屬性來(lái)設(shè)置定時(shí)任務(wù)的執(zhí)行間隔等配置

? static get schedule() {

? ? return {

? ? ? cron: '0 0 8 * * *',

? ? ? type: 'all', // 指定所有的 worker 都需要執(zhí)行

? ? };

? }

? // subscribe 是真正定時(shí)任務(wù)執(zhí)行時(shí)被運(yùn)行的函數(shù)

? async subscribe() {

? ? const res = await this.ctx.curl('https://restapi.amap.com/v3/weather/weatherInfo?key=你的key&city=440300', {

? ? ? dataType: 'json',

? ? });

? ? if(res){

? ? ? const data = res.data.lives[0] || {}

? ? ? const info = await this.ctx.service.weather.send(data);

? ? ? console.log('發(fā)送成功',info);

? ? }

? }

}

module.exports = UpdateCache;

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容