preface

A while ago in a technology group, said see someone who wrote a program timing to send an email to his girlfriend every day, suddenly thought of, I can write a program to his girlfriend every day hair day of weather and remind remind regularly, and access to relevant data and to the bosses ordered him to write the program source code, in her spare time, I also began to practice.

The implementation process

Prerequisite knowledge reserve

  • Node Knowledge
  • Use of the AXIos library
  • Use of the NodeMailer library
  • Promise knowledge
  • Window Enables the periodic execution of script tasks

Directory structure

├─ config.js # Project Config.js ├─ Daily email.js # Code application file ├─ public # Later you will put the data generated every day in a Josn file or excel to see ├─ template.html ├─ Timing-task. batCopy the code

Writing static pages

<style>
    .container {
      background-color: rgb(165.115.140);
      background: url("http://cn.bing.com/th?id=OHR.GreatTits_ZH-CN0546267922_1920x1080.jpg&rf=LaDigue_1920x1080.jpg&pid=hp") center no-repeat;
      background-size: 100%;
      width: 960px;
      height: 540px;
      display: flex;
      justify-content: space-between;
      flex-direction: column;
      align-items: center;
      color: white;
    }

    .title {
      font-size: 22px;
      margin-top: 50px;
    }

    .description {
      color: white;
    }

    .content {
      background: rgba(255.255.255.0.5);
      margin: 0 auto;
      width: 100%;
      display: flex;
      align-items: center;
      justify-content: center;
      flex-direction: column;
      padding: 20px;
      box-sizing: border-box;
    }

    .content>p {
      text-align: left;
      font-size: 12px;
      color: white;
      width: 100%;
      margin: 5px auto;
      padding: 0;
    }
  </style>


<div class="container">
    <div class="title">Watch the World with You: Issue 1162</div>
    <a class="description" target="_blank" href="https://www.bing.com/search?q=%E5%A4%A7%E5%B1%B1%E9%9B%80&amp;form=hpcapt&amp;mkt=zh-cn" rel="noopener">Great tits on winter branches, France (© Eric Ferry/Alamy)</a>
    <div class="content">
      <p style="display: flex;">
        <span>😘 Today is:<span style="border-bottom: 1px dashed rgb(204, 204, 204); --darkreader-inline-border-bottom:#3e4446;" t="5" times="" data-darkreader-inline-border-bottom="">2022/2/18</span>Friday is the first time we are together: 1162 days ~🥰🎈🎈🎈 Today's weather: cloudy the highest temperature 18℃, the lowest temperature 10℃, today's wind direction is: east wind. ❤ ❤ ❤</span>
      </p>
      <p></p>
      <p>I love three things in this world.
        Sun,Moon and You.
        Sun for morning,Moon for night,
        and You forever.</p>
    </div>
  </div>
Copy the code

Get bing Wallpaper of the day

const fetchBingPictrue = async() = > {const BPicList = await axios.get("https://www.bing.com/HPImageArchive.aspx?format=js&idx=0&n=1")
  let bingInfo = {}
  if(! BPicList.images[0]) {
    console.error("Failed to get Bing wallpaper")
    return bingInfo
  }
  bingInfo.picUrl = `http://cn.bing.com${BPicList.images[0].url}`
  bingInfo.copyright = BPicList.images[0].copyright
  bingInfo.copyrightlink = BPicList.images[0].copyrightlink
  console.log('🚀 [Bing wallpaper information obtained] ', bingInfo);
  return bingInfo
}
Copy the code

Get weather information

const fetchWeaterByCity = async() = > {let weather = await axios.get(
    Guangzhou ` ` http://wthrcdn.etouch.cn/weather_mini?city=,);if (weather.data.forecast.length === 0) {
    console.error("Failed to obtain today's weather")
    return{}}console.log('🚀 [weather information obtained] ', weather.data.forecast[0]);
  return weather.data.forecast[0]}Copy the code

Get one local love sentence every day

const fetchSentence = async() = > {const sentence = await axios.get(`https://chp.shadiao.app/api.php`);
  console.log('🚀 ', sentence);
  return sentence
}
Copy the code

Get the data into the generated HTML

/ * * *@description: Sets the email content *@return {*}
 * @param {*} BingInfo Information about Bing, including pictures and text descriptions and links *@param {*} WeatherInfo: Today's weather information *@param {*} */
const setEmailContent = (bingInfo, weatherInfo, sentence) = > {
  const today = new Date().toLocaleDateString();  // Get today's date
  const weekday = new Date().toLocaleString("default", { weekday: "long" }) // Get what day it is today
  const dayCount = parseInt((new Date() - new Date('2000-01-01') / 1000 / 60 / 60 / 24)  // The day of the fetch
  const content = `
        <style>
        .container {
            background-color: rgb(165, 115, 140);
            background: url("${bingInfo.picUrl}") center no-repeat; background-size: 100%; width: 960px; height: 540px; display: flex; justify-content: space-between; flex-direction: column; align-items: center; color: white; } .title { font-size: 22px; margin-top: 50px; } .description { color: white; }. Content {background: rgba(255, 255, 255, 0.5); margin: 0 auto; width: 100%; display: flex; align-items: center; justify-content: center; flex-direction: column; padding: 20px; box-sizing: border-box; } .content>p { text-align: left; font-size: 12px; color: white; width: 100%; margin: 5px auto; padding: 0; </style> <div class="container"> <div class="title"${dayCount}</div> <a class="description" target="_blank" href=" _blank"${bingInfo.copyrightlink}">${bingInfo.copyright}</a> <div class="content"> <p style="display: flex;" > <span>😘 today is:${today}.${weekday}Is the first thing we have together:${dayCount}Day ~🥰🎈🎈🎈,${weatherInfo.type}${weatherInfo.high}, the most${ weatherInfo.low}Today's wind direction is:${weatherInfo.fengxiang}. ❤❤❤ </span> </p> </p> </p> <p>${sentence}</p>
            </div>
        </div>
  `;
  return content
}
Copy the code

Use Nodemailer to send E-mail

Refer to the article: segmentfault.com/a/119000001…

/ * * *@description: Send email via Nodemailer *@return {*}
 * @param {*} Content Email content */
const sendEmailByNodemailer = (content) = > {
  const transporter = nodemailer.createTransport({
    service: '163'./ / use the built-in email transmission check the support list: https://nodemailer.com/smtp/well-known/
    port: 465./ / SMTP port
    secureConnection: true.// SSL is used
    auth: {
      user: '[email protected]'.// Email account
      pass: 'xxxyyyxxxyyzxzxz'.// Not the email password, but the SMTP authorization code you set}});let mailOptions = {
    from: ' 'Email name "< email address >'.// Sender email address
    to: ' 'Message title "< email address of the sender >'.// A comma-separated list of recipients
    subject: 'Want to see the world with you: firstThe ${parseInt((new Date() - new Date('2000-01-01') / 1000 / 60 60 / / 24)},Period `.// The subject of the email
    // Send text or HTML
    // text: 'Hello world? ', // plain text body
    // The HTML content to send
    html: content,
  };

  // send mail with defined transport object
  transporter.sendMail(mailOptions, (error, info) = > {
    if (error) {
      return console.log("error", error);
    }
    console.log("Message sent: %s", info.messageId);
    console.log(info);
  });
}
Copy the code

The email sending operation is performed

const handleSendEmail = async() = > {try {
    const bingInfo = await fetchBingPictrue()
    const weatherInfo = await fetchWeaterByCity()
    const sentence = await fetchSentence()
    const emailContent = setEmailContent(bingInfo, weatherInfo, sentence)
    sendEmailByNodemailer(emailContent)
  } catch (error) {
    // Here you can catch related errors and send the error information to the mailbox for notification
    console.error("Failed to send message")}}Copy the code

Implementation effect

Optimize – Consolidate project-related configurations into configuration files

// config.js
// Configure related information
exports.config = {
  CITY: 'shenzhen'.// Get city weather
  TOGETHER_TIME: '2000-01-01'.// Time together
  EMAIL_NAME: 'Watch the World Series with you'.// The name of the mailbox
  EMALI_SERVICE: '163'./ / using 163 service https://nodemailer.com/smtp/well-known/
  EMAIL_ACCOUNT: '[email protected]'.// Use the account that sends the email
  EMAIL_PASS:  'xxxyyyxxxyyzxzxz'.// Not the email password, but the SMTP authorization code you set
  TO_EMAIL: '[email protected]'.// Pick up the mailbox
  TO_TITLE: 'Yours only'./ / title
} 
Copy the code

Writing DOS commands

// timing-task.bat
// Bat batch file is a text file, each line of which is a DOS command (most of the time like the command line we execute at the DOS prompt), You can create and modify batch files using any text file editing tool, such as Edit for DOS or Notepad for Windows

node D:/node/daily-email.js   // Where to write the project execution file
Copy the code

How to execute the program regularly

  • The first way, using cloud functions, is to set up a scheduled execution program;
  • The second way, the purchase of lightweight server, using the server to achieve the periodic execution of the program;
  • The third way is to turn your computer into a server (if you leave it on for a long time), or when the program is set to start up automatically, automatically execute the script to send email every day when you start up.

Window The system periodically executes the BAT file

Enter the system task planning program

Creating basic Tasks

Create a basic task name and description

Select the trigger and set the execution time

To start the program, select the bat file address

Check whether the scheduled task is set successfully

Save the generated data to a JSON file

const fs = require("fs")
const path = require('path')
const dataFilePath = path.resolve(__dirname, './public/data.json')

/ * * *@description: Writes data to a JSON file@return {*}
 * @param {*} Data ObJ data to be written */
const writeData = (data) = > {
  try {
    const oldFileData = fs.readFileSync(dataFilePath, 'UTF-8').toString()
    const oldData = JSON.parse(oldFileData)
    oldData.push(data)
    fs.writeFileSync(dataFilePath, JSON.stringify(oldData))
  } catch (err) {
    console.log('🚀 [Error writing data] ', err); }}Copy the code

Problems encountered

Mobile phone wechat preview QQ email, the background picture is not displayed

  • Reason: Some HTML email clients do not render web pages consistently according to W3C specifications, so the rendering will be inconsistent, such as some tags are not supported, CSS compatibility issues, and the<head>Label in writingstyleThe support is not that good, JS doesn’t work or doesn’t support embedded video and audio.
  • Solution: Use inline CSS to learn about CSS compatibility of common mailboxes and refer to the documentation.

When using email 163 to send an email to QQ mailbox, the background picture cannot be displayed, and it will prompt that it is not an official email of Tencent

  • The solution, both sides use QQ mailbox, and QQ friends can avoid the second problem, can display the content normally, at present, the first problem has not thought of a good solution.

conclusion

  • With fragmented learning accumulation, I will record the implementation process, problems encountered and corresponding solutions. I believe accumulated knowledge can help me master programming technology better and faster, achieve better business at work, and expand my knowledge breadth.
  • Related source: github.com/sean-lgt/ti…
  • The above is all the content of this article, I hope this article is helpful to you, welcome to like and favorites, if you find any mistakes or better solutions and suggestions, welcome to contact at any time.