「JavaScriptはわかるけどNode.jsは触ったことがない」
「Node.jsが流行っているけど使用するメリットやタイミングがよくわからない」
「JavaScriptでメール送信のようなバックエンドの処理ができることを知らない」
本日はそんな方に向けて、Node.jsに焦点を当ててその基本を詳しく解説していきます。
Node.jsはJavaScriptをサーバーサイドで実行できる素晴らしいプラットフォームであり、その柔軟性とパワーは多くの開発者に愛されています。
本記事では、Node.jsの基礎を固めるために必要な概念とツールに焦点を当てます。
Expressを使ったルーティングやNodemonによる自動リロード、EJSを使ったテンプレートエンジン、そしてNodeMailerを使ったメールの送信といった実用的な要素も触れていきます。
依存パッケージのインストールとインポート
まずはNodeをインストールしておく必要があります。
ReactやVueなどを触ったことのある人なら既に入っているはずですが、わからない人はどこでも良いのでターミナルを開いて以下のコマンドを実行して何が返ってくるか確認してみましょう。
node -v
上図のように数字が返ってくれば既にNodeがインストールされています。
一方で違った場合はインストールが必要ですので以下のサイトを参考にインストールしてみてください、WindowsとMacで方法が違うのを注意しましょう。
https://www.sejuku.net/blog/72545
続いてNodeがインストールされてから依存パッケージをコマンドによってインストールしていきます。
まずは以下を実行してpackage.jsonを入れます。
npm init -y
続いて以下のコマンドを実行します。
npm i express mongoose ejs
さらに以下のコマンドも実行します。
npm i --save-dev nodemon
ここまで来たら以下のようなディレクトリ構造になっているはずです。
- node_modules
- package.json
- package-lock.json
それではpackage.jsonを開いて以下の場所でコードを追加します。
{
"name": "demo",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
// ここを追加する
"start": "nodemon server.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"ejs": "^3.1.9",
"express": "^4.18.2",
"mongoose": "^8.0.3"
},
"devDependencies": {
"nodemon": "^3.0.2"
}
}
これによってnpm run startというコマンドで実行ができるようになります。
それではserver.jsというファイルを作っておきましょう。
- node_modules
- package.json
- package-lock.json
- server.js
console.log("テスト");
上記のようにコンソールログだけ書いてからnpm run startとコマンドで実行しましょう。
npm run start
上図のようにターミナル上にコンソールログのテキストが表示されていればOKです。
赤いログが表示されている場合はエラーですのでここまでの作業で飛ばしたものがあるか、そもそもNodeが入っていない可能性があります。
問題なければ冒頭のコマンドで色々と実行していた依存パッケージをコードで使用できるようにインポートしましょう。
// コンソールログを消して以下を追加
const express = require('express');
const mongoose = require('mongoose');
const nodemon = require('nodemon');
続いてexpressをインスタンス化することでいろんなメソッドを使うことができます。
ここから「JavaScriptでこんなメソッド見たことないな」というものが多く登場しますが、それらはexpressをインスタンス化することで使用できる特別なメソッドだと思ってください。
const express = require('express');
const mongoose = require('mongoose');
const nodemon = require('nodemon');
// ここを追加
const app = express();
例えばexpressを使用していなければ最初に以下のようなコードでサーバーの準備が必要になるはずです。
const http = require("http");
const server = http.createServer((req, res) => {
console.log('リクエスト!');
});
httpモジュールと言う標準に搭載されているモジュールにあるcreateServerと言うメソッドを使ってサーバーの構築が必要です。
const app = express();も中身としてはサーバーを準備していることになっているのですが、クラスをインスタンス化する1行だけで済んでいますね。
続いて先ほどはターミナルでコンソールログを実行しましたがブラウザの画面に表示させてみましょう。
const express = require('express');
const mongoose = require('mongoose');
const nodemon = require('nodemon');
const app = express();
// ここを追加
app.get('/', (req, res) => {
res.render('index');
});
app.listen('5000');
コードを追加したらviewsというフォルダを手動で新規作成して中にファイルでindex.ejsを作成します。
- node_modules
- package.json
- package-lock.json
- server.js
- views
- index.ejs
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h1>test</h1>
</body>
</html>
ターミナルでnpm run startと実行していれば次回からは同じコマンドは実行しなくても大丈夫です。
以下のようになってしまっている方は消している可能性が高いので再度「npm run start」と実行しておいてください。
それではブラウザでhttp://localhost:5000というURLを打って画面を表示させてみましょう。
上図のように表示できていれば問題ありません、テキストが画面に出ているのがわかります。
index.ejsというのはHTMLのように画面に表示するものを作れるファイルです。
HTMLとJavaScriptがわかっていれば扱えるものですので初めての人も大丈夫です。
続いて変数に入れたものを画面に表示させてみます。
const express = require('express');
const mongoose = require('mongoose');
const nodemon = require('nodemon');
const app = express();
app.get('/', (req, res) => {
// ここを変更
res.render('index', { text: "テスト" });
});
app.listen('5000');
変数名は自由に決めることができて今回はtextという名前の変数に文字列でテストを格納しました。
変数の中身を画面に表示する際にはindex.ejsにて<%=%>という特別なタグの中で変数を書くことになります。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h1>test</h1>
// ここを追加
<h1><%= text %></h1>
</body>
</html>
画面をリロードすると先ほどのテキストに加えて変数に入れていた文字も表示されました。
通常のJavaScriptと違ってバックエンドで作成しているので画面に表示する際には特殊なタグを使用します。
これらをテンプレートタグなどと言ってRubyやPHPでも<?php ?>のような特殊なタグが用意されています。
続いては配列、オブジェクトのような複数のデータを繰り返し処理で取り出して表示してみます。
データについては通常DBやAPIから取ってくるのですが、今回は簡易的にserver.jsに手書きで作って使用します。
// モジュールのエクスポート、インポート
const express = require('express');
const mongoose = require('mongoose');
const nodemon = require('nodemon');
const app = express();
app.set('view engine', 'ejs');
app.get('/', (req, res) => {
// ここを追加
const data = [
{
title: 'タイトル',
desc: '初投稿です。',
},
{
title: '2回目',
desc: '2回目の投稿です。',
},
{
title: '3回目',
desc: '3回目の投稿です。',
},
];
// ここを変更
res.render('index', { text: data });
});
app.listen('5000');
配列dataにはオブジェクトが3つ格納されており、1個のオブジェクトはブログ記事だと思ってください。
まず配列dataをres.renderの変数textに代入しておきます。
続いてindex.ejsの中でforEachを使います。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h1>test</h1>
// ここを変更
<% text.forEach((article) => { %>
<div>
<%= article.title %>
</div>
<div>
<%= article.description %>
</div>
<% }) %>
</body>
</html>
forEachのような処理を書くときはテンプレートタグで<%=%>ではなく<%%>として書くことになっています。
さらに関数のように複数行にまたがるときは1行ごとにテンプレートタグを閉じるルールになっていますので上記のような書き方をしています。
画面をリロードするとテキストが複数になっていて、こちらはserver.jsで作っていた配列dataの中身であることがわかります。
なんとなくバックエンドで作ったものを画面に表示することが理解してもらえればと思います。
ちなみに画面の表示もexpressを使っていない場合は以下のような書き方になります。
const http = require('http');
const fs = require('fs');
const server = http.createServer((req, res) => {
fs.readFile('./views/index.html', (err, data) => {
if (err) {
console.log(err);
res.end();
} else {
res.write(data);
res.end();
}
});
});
server.listen(5000, 'localhost', () => {
console.log('ポート5000!');
});
httpモジュールのcreateServerの引数でファイルの読み込みを書くことになります。
ファイルの読み込みは別のモジュールでfsというものがあり、fsモジュールのreadFileメソッドでindex.htmlを読み込むような内容を書きます。
またブラウザの設定はlistenメソッドの第一引数にポート番号、第二引数にドメイン名、第三引数にブラウザ表示の際に必要な処理を書きます。
特にlistenメソッドについてはexpressの場合だとポート番号のみを引数に指定すれば良いのですが、引数が3つ指定しないといけないのがexpressを使わない場合の書き方ですね。
少しずつexpressを使う場合とそうでない場合の違いがわかってきたかと思います。
他にもexpressの便利な点としてはルーティング設定があります。
先ほどまではindex.ejsと言う1ページだけでしたが、他にもページがあったりリダイレクトや404ページの表示条件など本来はもう少し複雑なページ構成になるはずです。
例えばトップページ(index.html)、アバウトページ(about.html)、404ページ(404.html)があるとした場合のルーティングは以下のように書きます。
const express = require('express');
const nodemon = require('nodemon');
const app = express();
app.listen(3000);
app.get('/', (req, res) => {
res.sendFile('./views/index.html', {
root: __dirname,
});
});
app.get('/about', (req, res) => {
// res.send('<p>about</p>');
res.sendFile('./views/about.html', {
root: __dirname,
});
});
app.use((req, res) => {
res.sendFile('./views/404.html', {
root: __dirname,
});
});
先ほどと同じようにgetメソッドを使って第一引数にパス、第二引数に読み込むファイルを指定します。
ファイルの読み込みの切り替えについてはsendFileと言うメソッドがあり、第一引数にファイルのパス、第二引数にルートの場所を指定します。
第二引数には{root: __dirname}と書いておくことでドメイン名が変わっても第一引数の相対パスを認識できるようになっています。
URLをユーザーが手入力したときにありがちな存在しないページにアクセスした場合には404.htmlを使って404ページを表示させたいのですが、他のページで使ったgetメソッドではなくuseメソッドというものを使います。
useメソッドを使うことで全てのパスを考慮できますので、index.htmlとabout.htmlの読み込みの下に書いておくことで「/と/about以外のパス全て」という意味で404ページを使うことができるようになります。
全ての間違いを404ページにしたくなくて、文字の1文字違いはリダイレクトさせたい時には以下のようにgetメソッドのパターンを増やすと実現できます。
const express = require('express');
const nodemon = require('nodemon');
const app = express();
app.listen(3000);
app.get('/', (req, res) => {
res.sendFile('./views/index.html', {
root: __dirname,
});
});
app.get('/about', (req, res) => {
// res.send('<p>about</p>');
res.sendFile('./views/about.html', {
root: __dirname,
});
});
// ここを追加
app.get('/aboutt', (req, res) => {
res.redirect('/about');
});
app.use((req, res) => {
res.sendFile('./views/404.html', {
root: __dirname,
});
});
いずれにしても404ページの表示は一番下に書くことがポイントです。
app.useは全てのパスを指定できる特別なメソッドなのでリダイレクトさせたいパス名があるのであれば、404ページの表示よりも上部分に書きます。
ちなみに一連のルーティングをexpressを使わない場合は以下のように書くことになります。
const http = require('http');
const fs = require('fs');
const server = http.createServer((req, res) => {
res.setHeader('Content-Type', 'text/html');
let path;
switch (req.url) {
case '/':
path = './views/index.html';
res.statusCode = 200;
break;
case '/about':
path = './views/about.html';
res.statusCode = 200;
break;
// リダイレクトさせたいページ
case '/aboutt':
res.setHeader('Location', '/about');
res.statusCode = 301;
res.end();
break;
// 404ページ
default:
path = './views/404.html';
res.statusCode = 404;
break;
}
fs.readFile(path, (err, data) => {
if (err) {
console.log(err);
res.end();
} else {
res.end(data);
}
});
});
server.listen(5000, 'localhost', () => {
console.log('ポート5000!');
});
getメソッドがありませんのでswitch文を使った条件分岐を作ることになります。
またルーティングや404ページ、リダイレクトにはステータスコードという通信の種類を指定することになっていて、expressのgetメソッドであればステータコードの指定は自動でされるので不要です。
expressを使うことでわかりやすいコードを書くことができるわけですね。
expressを使わないときに登場したメソッドについては別の記事で解説しているので気になる方は以下より確認してみてください。
Node.jsにおけるモジュール、エクスポート、インポートの基本操作
簡単なWebサイトを例にお話しましたが何回かインポートという言葉が登場しました。
JavaScriptでは外部ファイル、ライブラリからコードを拝借することをモジュールと言い、モジュールを使用するにはエクスポートとインポートという作業が必要になります。
Node.jsに限らずReactなどのモダンJSでも必要になる考え方なので基本操作を紹介します。
例えば以下のファイルがあったとします。
const studentsData = [
{
id: '0001',
name: 'tanaka',
age: 20,
},
{
id: '0002',
name: 'yamada',
age: 21,
},
{
id: '0003',
name: 'nakamura',
age: 20
},
];
const arr = [1, 2, 3, 4, 5];
配列がデータとして用意されていて、こちらの配列を別のJSファイルで使用したい場合にはまずエクスポートという文法が必要です。
例えば定数studentsDataであれば以下のように書きます。
const studentsData = [
{
id: '0001',
name: 'tanaka',
age: 20,
},
{
id: '0002',
name: 'yamada',
age: 21,
},
{
id: '0003',
name: 'nakamura',
age: 20
},
];
const arr = [1, 2, 3, 4, 5];
// ここを追加
module.exports = studentsData;
module.exportsと書いて=で挟んだデータは他のJSファイルに取り込むことが可能になります。
取り込む側のファイルを用意して、以下のようにインポート文を書いて取り込みます。
const students = require('./modules_students');
console.log(students);
// 以下が表示される
// [{id: '0001',name: 'tanaka',age: 20,},{id: '0002',name: 'yamada',age: 21,},{id: '0003',name: 'nakamura',age: 20},]
requireというメソッドはmodule.exportsされているデータをファイルパスを指定することで取得できます。
インポートしたデータを定数studentsに代入すれば、そのままデータを自由に使用できます。
またインポートしたデータを書き換えても元のデータは書きかわりませんの安心してください。
しかし注意点としてはエクスポートしたファイル側で以下のように何かの関数やメソッドが実行された場合にはインポートした時点のその関数やメソッドが発動します。
const studentsData = [
{
id: '0001',
name: 'tanaka',
age: 20,
},
{
id: '0002',
name: 'yamada',
age: 21,
},
{
id: '0003',
name: 'nakamura',
age: 20
},
];
const arr = [1, 2, 3, 4, 5];
// ここを追加
console.log("test")
module.exports = studentsData;
const students = require('./modules_students');
console.log(students);
// 以下が表示される
// test
// [{id: '0001',name: 'tanaka',age: 20,},{id: '0002',name: 'yamada',age: 21,},{id: '0003',name: 'nakamura',age: 20},]
エクスポートしたファイルとインポートしたファイルそれぞれにconsole.log()がありますので2つのログが出力されるわけです。
一般的にはエクスポートする側では関数やメソッドは定数に格納しておくだけで、実行まではしないようにしておくことが多いです。
ちなみに2つのデータをエクスポートするときにはオブジェクト形式にします。
const studentsData = [
{
id: '0001',
name: 'tanaka',
age: 20,
},
{
id: '0002',
name: 'yamada',
age: 21,
},
{
id: '0003',
name: 'nakamura',
age: 20
},
];
const arr = [1, 2, 3, 4, 5];
// ここを変更
module.exports = {
studentsData: studentsData,
arr: arr,
};
通常のオブジェクト形式と全く同じでキーと値を指定します。
キーは自由に決めることができますが、今回は値の名前と同じにしました。
2つのデータをインポートしてみましょう。
// ここを変更
const data = require('./modules_students');
// ここを変更
console.log(data.students);
console.log(data.arr);
// 以下が表示される
// [{id: '0001',name: 'tanaka',age: 20,},{id: '0002',name: 'yamada',age: 21,},{id: '0003',name: 'nakamura',age: 20},]
// [1,2,3,4,5]
インポートした側もオブジェクトで受け取るのでキー名を指定すれば各自のデータが参照できます。
ちなみに分割代入で書いておくと少し短くことができます。
// ここを変更
const { studentsData, arr } = require('./modules_students');
// ここを変更
console.log(students);
console.log(arr);
// 以下が表示される
// [{id: '0001',name: 'tanaka',age: 20,},{id: '0002',name: 'yamada',age: 21,},{id: '0003',name: 'nakamura',age: 20},]
// [1,2,3,4,5]
データ名.キー名と「.」で繋げた書き方より分割代入でキー名のみを指定する方が簡単ですよね。
またエクスポートする側もキーと値が同じ名前なら値を省略して以下のように書くことが可能です。
const studentsData = [
{
id: '0001',
name: 'tanaka',
age: 20,
},
{
id: '0002',
name: 'yamada',
age: 21,
},
{
id: '0003',
name: 'nakamura',
age: 20
},
];
const arr = [1, 2, 3, 4, 5];
// ここを変更
module.exports = {studentsData, arr};
ここまで2つのJSファイルを用意してモジュールを体験していましたが、ライブラリについてはエクスポートはすでにされているので必要なタイミングでインポートだけすれば使用できるようにできています。
例えばOSというライブラリがあるのですが以下のように、いきなりインポートして使用できます。
const { studentsData, arr } = require('./modules_students');
// ここを追加
const pc = require('os');
// ここを変更
console.log(pc.platform()); // Windowsならwin,Macならdarwinと表示される
console.log(pc.homedir()); // ホームディレクトリが表示される
試してもらえれば何か出力されたはずです。
module.exportsと書かないといけないのは自分で作ったデータやJSファイルのみで、すでにあるライブラリでは必要ありません。
nodeMailerを使ってメール送信をやってみる
続いてバックエンドならではの処理としてメールの送信をやってみたいと思います。
メール送信というとPHPのイメージが強いかもしれませんがJavaScriptでもNode.jsを使えばメールを送信することができます。
今回は初心者が簡単にメール送信を実装できるnodeMailerというライブラリを使います。
まずはターミナルで以下のコマンドを実行してnodeMailerをインストールしておきます。
npm i nodemailer
nodeMailerでテキストのメールを送る
ファイルについては前章までのとは変えたいので新しく作りましょう。
本記事ではapp.jsという名前にしてnodeMailerをインポートしておきます。
const nodeMailer = require('nodemailer');
続いてメール本文を定数htmlとして作成しておきます。
const nodeMailer = require('nodemailer');
// ここを追加
const html = `
<h1>こんにちは</h1>
<p>こちらはテストメールです。</p>
<img src="cid:unique@gmail.com" width="400">
`;
続いて送信元の設定をしていきます、今回はGmailを使っているものとします。
const nodeMailer = require('nodemailer');
const html = `
<h1>こんにちは</h1>
<p>こちらはテストメールです。</p>
<img src="cid:unique@gmail.com" width="400">
`;
// ここを追加
async function mailFn() {
const transport = nodeMailer.createTransport({
host: 'smtp.gmail.com',
port: 465,
secure: true,
auth: {
user: '自分のGmailアドレス',
pass: 'SMTPアプリパスワード',
},
});
}
mailFn().catch((error) => console.log(error));
定数transportにはnodeMailerのcreateTransportという特別なメソッドで送信元の設定をします。
userプロパティには送信する人のGmailアドレスを文字列で書きます。
passプロパティについてはGoogleのアプリパスワードを文字列で書きます。
Googleの右上の自分のアイコンから「アカウント管理」をクリックします。
続いて左のサイドメニューからセキュリティをクリックします。
ヘッダーにある検索バーに「アプリパスワード」と検索して予測変換に表示されたものをクリックします。
そのまま画面が切り替わる場合もありますが、以下のように再度ログインを求められることもあります。
その場合はログインパスワードを入れると画面が切り替わります。
アプリパスワードでは今回のような外部のライブラリ、APIと連携させるための特別なパスワードを発行することができます。
ログインパスワードとは違うものになりますので注意しましょう。
まず名前を決めます、本記事では「nodemailer」としました。
名前を入力して作成ボタンをクリックするとパスワードが自動生成されてポップアップとして表示されます。
こちらは表示できるのは1回だけなのでメモにコピーしておいてください。
「完了」というボタンをクリックすると設定が終了します。
メモしたパスワードをコードのpassプロパティに貼り付けましょう。
const nodeMailer = require('nodemailer');
const html = `
<h1>こんにちは</h1>
<p>こちらはテストメールです。</p>
<img src="cid:unique@gmail.com" width="400">
`;
async function mailFn() {
const transport = nodeMailer.createTransport({
host: 'smtp.gmail.com',
port: 465,
secure: true,
auth: {
user: 'lorem.co.ltd@gmail.com',
pass: 'hmxzdcppnxragkpu',
},
});
}
mailFn().catch((error) => console.log(error));
あとは送信先の設定をします。
同じく関数mailFnの中で書いていきます。
// node -v
// npm init --y
// npm i nodemailer
// 設定→Googleの設定、Googleアカウントの管理→セキュリティ→2段階認証→アプリパスワード
const nodeMailer = require('nodemailer');
const html = `
<h1>こんにちは</h1>
<p>こちらはテストメールです。</p>
<img src="cid:unique@gmail.com" width="400">
`;
async function mailFn() {
const transport = nodeMailer.createTransport({
host: 'smtp.gmail.com',
port: 465,
secure: true,
auth: {
user: '自分のGmailアドレス',
pass: 'SMTPアプリパスワード',
},
});
// ここを追加
const info = await transport.sendMail({
from: 'CodeTips<自分のGmailアドレス>',
to: '送信先のアドレス',
subject: 'テストです。',
html: html,
});
}
mailFn().catch((error) => console.log(error));
先ほどの定数transportにsendMailというメソッドでメールの送信内容を設定しています。
fromには自分のアドレス、toには送信先のアドレス、subjectには件名を入れました。
htmlプロパティは本文ですが先ほど定数htmlとして用意していましたのでhtmlを書きます。
送信先のアドレスは何でも大丈夫です、送信元と同じでも、アドレスを2個お持ちの方は使っていないアドレスを書いても良いです。
プログラムの実行をターミナルからやってみます。
node app.js
そうするとtoプロパティに書いたアドレスにメールが届いているはずです。
nodeMailerで画像を添付して送信する
続いてテキストだけでなく画像を添付してみましょう。
画像は何でも大丈夫なのでパソコンの中で用意しておきます。
- node_modules
- package.json
- package-lock.json
- app.js
- images
- 画像ファイル
先ほどのコードに加筆する形で書いていきます。
sendMailの中のプロパティでattachmentsというものがあり画像などの添付ファイルを配列で指定できます。
// node -v
// npm init --y
// npm i nodemailer
// 設定→Googleの設定、Googleアカウントの管理→セキュリティ→2段階認証→アプリパスワード
const nodeMailer = require('nodemailer');
const html = `
<h1>こんにちは</h1>
<p>こちらはテストメールです。</p>
<img src="cid:unique@gmail.com" width="400">
`;
async function mailFn() {
const transport = nodeMailer.createTransport({
host: 'smtp.gmail.com',
port: 465,
secure: true,
auth: {
user: '自分のGmailアドレス',
pass: 'SMTPアプリパスワード',
},
});
const info = await transport.sendMail({
from: 'CodeTips<自分のGmailアドレス>',
to: '送信先のアドレス',
subject: 'テストです。',
html: html,
// ここを追加
attachments: [
{
filename: 'csv',
path: './images/file_icon_text_csv.png',
cid: 'unique@gmail.com',
},
{
filename: 'jpg',
path: './images/file_icon_text_jpg.png',
cid: 'unique@gmail.com',
},
{
filename: 'txt',
path: './images/file_icon_text_txt.png',
cid: 'unique@gmail.com',
},
],
});
}
mailFn().catch((error) => console.log(error));
配列の中でファイル1個をオブジェクトにして格納するようにします。
filenameはファイル名でpathはファイルのパスを指定します、uidは識別番号ですが今回はunique@gmail.comとしておきましょう。
画像が複数あるときは上記コードのようにオブジェクトを増やしてくイメージです。
再度コマンドを叩いてメールを送信してみます。
node app.js
添付ファイル付きのメールアドレスが届いていますね。
今回は画像にしましたがpdfやcsvでも実行方法は同じ流れです。
nodeMailerで複数人にメールを送信する
最後に同じメールを複数人に送ってみましょう。
こちらはsendMail関数の引数の中でtoオブジェクトに修正を加えます。
事前にアドレスを配列として用意しておき、toプロパティに配列として指定します。
// node -v
// npm init --y
// npm i nodemailer
// 設定→Googleの設定、Googleアカウントの管理→セキュリティ→2段階認証→アプリパスワード
const nodeMailer = require('nodemailer');
const html = `
<h1>こんにちは</h1>
<p>こちらはテストメールです。</p>
<img src="cid:unique@gmail.com" width="400">
`;
async function mailFn() {
const transport = nodeMailer.createTransport({
host: 'smtp.gmail.com',
port: 465,
secure: true,
auth: {
user: '自分のGmailアドレス',
pass: 'SMTPアプリパスワード',
},
});
// ここを追加
const emails = ['送信先1', '送信先2'];
const info = await transport.sendMail({
from: 'CodeTips<自分のGmailアドレス>',
// ここを修正
to: mails,
subject: 'テストです。',
html: html,
attachments: [
{
filename: 'csv',
path: './images/file_icon_text_csv.png',
cid: 'unique@gmail.com',
},
{
filename: 'jpg',
path: './images/file_icon_text_jpg.png',
cid: 'unique@gmail.com',
},
{
filename: 'txt',
path: './images/file_icon_text_txt.png',
cid: 'unique@gmail.com',
},
],
});
}
mailFn().catch((error) => console.log(error));
送信内容は先ほどと同じテキストと添付画像でやってみます。
複数人に送る時もコマンドは1回実行すればOKです。
node app.js
本記事ではGmailとYohooメールのアドレスを指定して、両方とも送信することができました。
画像もダウンロードしてパソコンの中で使用することができます。
普通のJavaScriptと書き方や途中過程が違うので最初は慣れないですが少しずつ覚えていきましょう。
Node.jsを使ってバックエンドを書くとフロントとバックエンドが1つの言語で統一することができます。
初学者のうちはいろんな言語が使えませんし、会社でも少人数でやっているチームは使用言語にバラツキがあるとプロジェクトが組めなかったりします。
そのためバックエンドにNode.jsを採用することが割とありますので興味がある方は勉強していきましょう。