Menu

BLOG ベアメールブログ

Node.js・Nodemailerでメールを送信する方法

このシリーズでは、色々なプログラムでメールを送る方法を紹介しています。 今回は第4回として、Node.jsでNodemailerを使ってメールを送る方法を紹介します。

環境情報

本記事では、メールサーバとは別のサーバでプログラムを実行します。
メールサーバに接続可能でプログラムが実行できる環境であれば、クライアントPCやメールサーバと同一環境でも問題ありません。

プログラムを実行可能なサーバやクライアントPC

実行環境のOSは「AlmaLinux 8.10」を使用しています。

# cat /etc/redhat-release
AlmaLinux release 8.10 (Cerulean Leopard)

メールサーバ

OSは「AlmaLinux 8.9」、SMTPサーバとして「postfix 3.5.8」を使用しています。

# cat /etc/redhat-release
AlmaLinux release 8.9 (Midnight Oncilla)

# postconf | grep mail_version
mail_version = 3.5.8
milter_macro_v = $mail_name $mail_version

プログラムの実行環境とメールサーバ間は587ポートで接続し、SMTP AUTHで認証します。

シンプルですが今回の構成を図にするとこんな感じです。

今回の構成図。クライアントPCから、587番ポートでメールサーバに接続する

Node.js・Nodemailerでメールを送る

JavaScriptの実行環境はいくつかありますが、本記事では最もメジャーだと思われるNode.jsで、Nodemailerというモジュールを使用してメールを送信する仕組みを作ります。

Nodemailerは、Node.js環境でメールを送信するための無料ライブラリで、SMTPサーバーやメール送信サービスと簡単に連携できます。設定はシンプルで、認証や添付ファイルの送信、HTMLメールの作成など多くの機能を備えています。特に、コード内で手軽にメール送信を実装できるため、開発者にとって扱いやすいのではないでしょうか。

必要となるのは以下の4つです。

  • Node.js             (JavaScript実行環境)
  • npm                 (Node.jpのパッケージマネージャー)
  • nodemailer       (SMTP接続ライブラリ)
  • uuid                  (uuid生成ライブラリ)

「nodemailer」と「uuid」はnpmでのインストールが必要です。

では、実際にJavaScriptでプログラムを作っていきましょう。 今回もSMTP接続するための設定ファイルと、メールを送るプログラムを分けて作成します。

SMTP設定ファイルの作成

まずはSMTPの接続情報や、エンベロープFrom、ヘッダFromなどを指定するための設定ファイルを作成します。ここではファイル名を「smtp_conf.js」とします。

# vi smtp_conf.js

※ここから
-------
module.exports = {
    host: 'SERVER_HOST_NAME',         // SMTPサーバのホスト名
    port: 587,                        // SMTPポート番号
    secure: false,                    // TLSの仕様有無。使用する場合はTrue
    auth: {
        user: 'SMTP_USERNAME',        // SMTPユーザ名
        pass: 'SMTP_PASSWORD',        // SMTPパスワード
    },
    fromEmail: 'HEADER_FROM_ADD',     // ヘッダーFromメールアドレス
    fromName: 'YOUR_NAME',            // ヘッダーFROM表示名
    envelopeFrom: 'ENVELOPE_FROM_ADD' // エンベロープFromアドレス
};
-------
※ここまで

メール送信プログラムの作成

続いて、メールを送るプログラムを作成します。ファイル名は「send_mail.js」としています。

# vi send_mail.js

※ここから
-------
const nodemailer = require('nodemailer');
const { v4: uuidv4 } = require('uuid');
const config = require('./smtp_config');

async function sendEmail(to, subject, message) {
    // Nodemailerのトランスポートを設定
    let transporter = nodemailer.createTransport({
        host: config.host,
        port: config.port,
        secure: config.secure, 
        auth: {
            user: config.auth.user,
            pass: config.auth.pass
        }
    });

    // メールオプションを設定
    let mailOptions = {
        from: `"${config.fromName}" <${config.fromEmail}>`, // 送信元の設定
        to: to,
        subject: subject,
        text: message,
        headers: {
            'Message-ID': `<${uuidv4()}@${config.host}>`, 
            'X-Sender': config.envelopeFrom 
        },
        envelope: {
            from: config.envelopeFrom, 
            to: to
        }
    };

    try {
        let info = await transporter.sendMail(mailOptions);
        console.log(`Message sent: ${info.messageId}`);
    } catch (error) {
        console.error(`Error occurred: ${error.message}`);
    }
}

if (process.argv.length !== 5) {
    console.log("Usage: node send_mail.js   ");
    process.exit(1);
}

const to = process.argv[2];
const subject = process.argv[3];
const message = process.argv[4];

sendEmail(to, subject, message);

-------
※ここまで

保存すれば準備完了です!

実行

それでは実行してみましょう。引数として「Toアドレス」、「件名」、「メール本文」を使用します。
コマンドの実行例は下記の通りです。

# node send_mail.js "<TO_ADDRESS>" "Test Mail from JavaScript" "JavaScript"

送信に成功すると下記のメッセージが出ます。

Message sent to <TO_ADDRESS>: <MESSAGE_ID@YOUR_DOMAIN>

ではメールボックスを確認してみます。

テストメールのメールヘッダのスクリーンショット

無事に届いていました!

注意事項

今回作成したプログラムではSMTP接続に失敗した場合でもリトライされません。
また、エラー処理も最低限となっておりますので、実際に業務やサービスとして使用される場合は、SMTP接続に失敗した場合のリトライ処理、プログラムの再実行処理、エラー処理やログの生成などのカスタマイズが必要になります。

応用編

応用編として、現在の天気予報を取得し、取得した結果をメールで送る簡単なプログラムを作ってみたいと思います。 メールを送る部分は先ほど作ったsend_mail.jsをそのまま使い、天気の取得には無料で使える「Open-Meteo」の天気予報APIを使用させていただきます。

【参考】
Open-Meteo:https://open-meteo.com/

では、さっそくプログラムを作っていきます。

天気予報を取得するプログラムは「weather_mail.js」という名前で作成します。同じにする必要はないので任意の名前で作成して下さい。

事前準備

JavaScriptでHTTPリクエストを行う必要がありますので、事前にaxiosライブラリをインストールします。

npm install axios

weather_mail.js

const axios = require("axios");
const { sendEmail } = require("./send_mail");

// Open-Meteo APIのURL
const WEATHER_API_URL = "https://api.open-meteo.com/v1/forecast";

// 位置情報(緯度と経度)
// 東京の緯度・経度を指定
const LAT = 35.6895; 
const LON = 139.6917; 

async function sendWeatherEmail(toEmail) {
  try {
    // Open-Meteo APIから天気予報を取得
    const response = await axios.get(WEATHER_API_URL, {
      params: {
        latitude: LAT,
        longitude: LON,
        current_weather: true,
        hourly: "temperature_2m,precipitation,wind_speed_10m",
        timezone: "Asia/Tokyo",
      },
    });

    // APIレスポンスが正常かどうかを確認
    if (response.status !== 200) {
      console.log("APIからの応答が不正です:", response.status);
      return;
    }

    const data = response.data;

    // 現在の天気情報を取得
    const currentWeather = data.current_weather;
    // 温度
    const temperature = currentWeather.temperature;
    // 降水量
    const precipitation = data.hourly.precipitation[0];
    // 風速
    const windSpeed = data.hourly.wind_speed_10m[0];

    // メールの件名と本文
    const emailSubject = "現在の天気予報(東京)";
    const emailText = `
      東京の現在の天気予報:
      - 温度: ${temperature}°C
      - 降水量: ${precipitation}mm
      - 風速: ${windSpeed}km/h
    `;

    // sendEmailに必要な引数を渡して実行
    await sendEmail(toEmail, emailSubject, emailText);
    console.log("天気予報メールを送信しました。");
  } catch (error) {
    console.error("エラーが発生しました:", error.message);
    // エラーの詳細を確認
    if (error.response) {
      console.log("APIエラーレスポンス:", error.response.data);
    }
  }
}

// コマンドライン引数からメールアドレスを取得して実行
const args = process.argv.slice(2);
const toEmail = args[0];
sendWeatherEmail(toEmail);

実行

send_mail.jsを実行する時は、「送信先メールアドレス」、「メールタイトル」、「メール本文」の3つが必要でしたが、「メールタイトル」、「メール本文」については「weather_mail.js」の中で記載しています。
そのため、「weather_mail.js」の実行には「送信先メールアドレス」を引数として指定する必要があります。

node weather_mail.js <送信先メールアドレス>

下記のように出力されれば送信成功です。

Message sent: 
天気予報メールを送信しました。

メールボックスを見てみると、こんな感じのメールが届いているはずです。

テストメールの文面のスクリーンショット

「Open-Meteo」では緯度・経度を指定する必要があり、今回のプログラムでは「東京」の緯度・経度をプログラムの中に記載しています。

様々なパラメータを指定することで取得できる情報が増えますので、「Open-Meteo」の公式ドキュメントを一読することをお勧めします。

パラメータが複雑で分かりにくいと思われる方には、必要なパラメータにチェック入れるだけでAPI用のURLを自動生成してくれる便利ツールが用意されています。

【参考】
公式ドキュメント:https://open-meteo.com/en/docs
公式エディタ:https://open-meteo.com/en/docs#api_form

まとめ

今回はメールを送る簡単なプログラムをNode.jsで作成しました。

本来、JavaScriptは動きのあるWebコンテンツを作成するためのクライアントサイドスクリプト言語です。そのため、本来であればGoogle ChromeやFirefox、Edge等のWebブラウザでしか動かすことができませんが、Node.jsを使うことでJavaScriptをサーバサイドで動かすための実行環境が構築できます。

Node.jsを使えばフロントエンドとバックエンドを一つの言語で作成できるため、別々の言語を習得するよりも学習コストを低く抑えることが可能です。用途も幅広く、Webサーバやスマホアプリ、IoTなど様々な分野で使用されています。公式ドキュメントや技術ブログなどの情報が豊富なので、困ったことがあったとしても調査がしやすいため、初心者にも練達のプログラマにも使いやすいプログラミング言語であるといえます。

本記事で作成したプログラムはメールを自動化するための最初の小さな一歩ですが、自動化する技術は様々な場面で役に立つ技術ですので、この一歩が皆様の一助になれば幸いです。