はじめに (対象読者・この記事でわかること)
この記事は、Azure App Service(Linux)上で Node.js アプリを運用しているエンジニアを対象としています。
Gmail の SMTP サーバーを利用してメール送信を実装したものの、「メールが送れない」エラーに直面した方が対象です。
本記事を読むことで、以下のことが理解・実践できるようになります。
- Gmail で必要な「アプリ パスワード」や OAuth2 設定の意味
- Azure App Service の環境変数・ネットワーク制限がメール送信に与える影響
- Nodemailer を用いた正しいコード例とデバッグ手順
背景として、2024 年に Google が「安全性の低いアプリのアクセス」を完全に廃止し、従来の平文認証が使えなくなったことがあります。そのため、既存の実装が突然動かなくなるケースが増えています。この記事では、実際に起きたエラーとその対策を具体的に示します。
前提知識
この記事を読み進める上で、以下の知識があるとスムーズです。
- Node.js と npm の基本的な操作
- Azure ポータルで App Service の設定画面を操作できること
- SMTP(Simple Mail Transfer Protocol)の基礎概念と、TLS/STARTTLS の意味
背景と問題の概要
Azure App Service(Linux)上で動作する Web アプリから Gmail の SMTP (smtp.gmail.com) に対してメール送信を行う際、次のようなエラーが頻出します。
535-5.7.8 Username and Password not accepted. Learn more at
535 5.7.8 https://support.google.com/mail/?p=InvalidCredentials
または
Error: connect ECONNREFUSED 52.95.xxx.xxx:587
主な原因は大きく分けて 3 つあります。
-
Google 側の認証方式変更
従来のユーザー名+パスワード(「安全性の低いアプリ」)が無効化され、アプリ パスワードや OAuth2 が必須となった。 -
Azure App Service のアウトバウンド制限
Azure はポート 25(SMTP の標準ポート)へのアウトバウンドをブロックしていますが、ポート 587/465 は許可されています。TLS 設定が不適切だと接続が遮断されます。 -
環境変数の設定ミス
App Service の「Configuration」画面で設定した環境変数が正しく読み込まれていない、または特殊文字がエスケープされていないケースが多いです。
このような問題を解決するために、以下の手順で設定を見直し、コードを修正します。次のセクションでは、実際の手順とサンプルコードを段階的に示します。
具体的な手順と実装方法
ステップ 1:Gmail 側でアプリ パスワードを取得
- Google アカウントにログインし、Google アカウントのセキュリティページへ移動。
- 「2 段階認証プロセス」を有効化します(未設定の場合はまず設定)。
- 「アプリ パスワード」セクションで「アプリの選択」→「メール」, 「デバイスの選択」→「その他(Custom name)」に「AzureAppService」など分かりやすい名前を入力し、
生成をクリック。 - 表示された 16 桁のパスワードを コピー して、後ほど App Service の環境変数に貼り付けます。
※ OAuth2 を利用したい場合は、Google Cloud Console で「OAuth 同意画面」を作成し、クライアント ID/シークレットを取得したうえで、nodemailer の XOAUTH2 プラグインを使用してください。ここでは手軽さのため、アプリ パスワード方式を採用します。
ステップ 2:Azure App Service に環境変数を設定
- Azure ポータルで対象の App Service を開く。
- 左メニューの 「Configuration」 → 「Application settings」 を選択。
- 以下のキーと取得した値を追加。
| キー名 | 説明 |
|---|---|
GMAIL_USER |
Gmail のメールアドレス (example@gmail.com) |
GMAIL_APP_PASSWORD |
先ほど取得した 16 桁のアプリ パスワード |
SMTP_HOST |
smtp.gmail.com |
SMTP_PORT |
587 (STARTTLS 用) |
SMTP_SECURE |
false (STARTTLS の場合は false) |
- 変更を保存し、「再起動」 ボタンで Web アプリを再起動します。環境変数は Node.js 側で
process.envから取得できます。
ステップ 3:Node.js (Nodemailer) のコード修正
以下は最小構成のサンプルです。package.json で nodemailer をインストールしてください。
Bashnpm install nodemailer
Javascript// mailer.js const nodemailer = require('nodemailer'); // 環境変数から設定を取得 const { GMAIL_USER, GMAIL_APP_PASSWORD, SMTP_HOST = 'smtp.gmail.com', SMTP_PORT = 587, SMTP_SECURE = false } = process.env; // transporter の作成 const transporter = nodemailer.createTransport({ host: SMTP_HOST, port: Number(SMTP_PORT), secure: SMTP_SECURE, // true なら TLS(ポート 465)、false なら STARTTLS(ポート 587) auth: { user: GMAIL_USER, pass: GMAIL_APP_PASSWORD }, tls: { // Gmail が使用する最新の暗号スイートに合わせる rejectUnauthorized: false } }); // テスト送信関数 async function sendTestMail() { try { const info = await transporter.sendMail({ from: `"Azure App Service" <${GMAIL_USER}>`, to: 'receiver@example.com', subject: '【テスト】Azure App Service からのメール送信', text: 'このメールは Azure App Service (Linux) から送信されました。', // html: '<p>HTML 形式でも送信可能です。</p>' }); console.log('Message sent: %s', info.messageId); } catch (err) { console.error('メール送信エラー:', err); // 詳細エラーを Azure のログに出力 console.error('エラーコード:', err.code); console.error('レスポンス:', err.response); } } // 起動時にテストメールを送信(デバッグ用) if (require.main === module) { sendTestMail(); }
ポイント解説
secure: false+port: 587で STARTTLS を使用。Azure では 587 が開放されているため、接続が拒否されることは少ない。tls.rejectUnauthorized: falseは、自己署名証明書等でエラーになる場合の回避策ですが、実運用では可能な限りtrueに戻すことを推奨。- エラーハンドリングで
err.code(例:EAUTH,ECONNECTION)やerr.responseをログに出すと、Azure の「Log stream」や「Application Insights」で原因を追跡しやすくなる。
ステップ 4:デプロイと動作確認
- コードを GitHub などにプッシュし、Azure の デプロイセンター で自動デプロイを設定。
- デプロイ完了後、Azure ポータルの「Log stream」 を開き、アプリ起動時に
sendTestMail()が実行されているか確認。 - 受信側メールボックスにテストメールが届けば成功です。届かない場合は、以下の「ハマった点やエラー解決」セクションを参照してください。
ハマった点やエラー解決
| 発生したエラー | 原因の可能性 | 解決策 |
|---|---|---|
535-5.7.8 Username and Password not accepted |
アプリ パスワードが正しく設定されていない、または 2 段階認証が無効 | Google アカウントの 2FA が有効か確認し、正しいアプリ パスワードを再生成して環境変数に再設定 |
connect ECONNREFUSED 52.xx.xx.xx:587 |
Azure のネットワーク制限か、SMTP_SECURE の設定ミス |
ポート 587 が開放されていることを確認し、secure:false に変更。必要なら tls: {rejectUnauthorized:false} を一時的に有効化 |
self signed certificate in certificate chain |
Gmail の TLS 証明書チェーンが検証できない | tls.rejectUnauthorized: false を一時的に設定し、根本的には最新の Node.js バージョンにアップデート |
| メールは送信成功だが スパムフォルダ に入る | 送信元ドメインが SPF/DKIM で認証されていない | カスタムドメインを使用し、Azure の DNS に SPF/TXT レコードを追加。もしくは SendGrid 等の認証済みサービスへ切り替え |
解決策まとめ
- Google 側で必ずアプリ パスワード(または OAuth2)を取得。
- Azure App Service の環境変数に正しく設定し、再起動。
- Nodemailer の
secureとportをfalse+587に統一し、tlsオプションで一時的にエラー回避。 - ログストリームでエラー出力を確認し、エラーメッセージに応じて対処。
以上で、Azure App Service (Linux) から Gmail へのメール送信が安定して行えるようになります。
まとめ
本記事では、Azure App Service(Linux)上で Gmail の SMTP にメール送信できない典型的な原因と、アプリ パスワード取得 → 環境変数設定 → Nodemailer の正しい構成という三段階の解決フローを解説しました。
- Google の認証変更に伴うアプリ パスワードの必須化
- Azure のアウトバウンド制限とポート設定(587/STARTTLS)への対応
- 環境変数のミス防止とデバッグログの活用
これらを実践すれば、メールが届かないというトラブルを迅速に解消でき、アプリの通知機能やユーザーへのメール配信を安定させられます。次回は OAuth2 による認証や SendGrid との比較といった、さらに高度なメール送信手法についても取り上げる予定です。
参考資料
- Google アカウントのセキュリティ設定 – アプリ パスワード
- Nodemailer 公式ドキュメント – Gmail の使用方法
- Azure App Service のネットワーク制限に関する公式情報
- SMTP over TLS (STARTTLS) の概要
- SendGrid 公式サイト – Azure との連携ガイド
