iT邦幫忙

2026 iThome 鐵人賽

DAY 20
0
IT Operation

從前後端踏上 AWS 雲端架構勇者之路系列 第 20 篇

SES 郵件服務(下):用 Node.js 寄一封信給自己

  • 分享至 

  • xImage
  •  

前一篇收到 AWS 的驗證信,信箱也變成 Verified 了。不過那封是 AWS 寄給我們的,還不是自己的程式寄的哦

今天就把這一段補上:用自己電腦上的 Node.js,寄一封信給自己

先看我們今天要接哪一段:本機程式請 SES 寄信,再到信箱確認結果~

本機 Node.js 以 IAM 權限呼叫 SES;MessageId 與實際收信是兩個確認點

給程式一個只負責寄信的身分

用有管理 IAM 權限的帳號,進 IAM → Policies → Create policy → JSON,建立 SesPracticeSendToSelf。下面所有 you@example.com 都換成自己的已驗證信箱,YOUR_ACCOUNT_ID 換成自己的 AWS 帳號 ID:

{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Action": "ses:SendEmail",
    "Resource": "arn:aws:ses:ap-northeast-1:YOUR_ACCOUNT_ID:identity/you@example.com",
    "Condition": {
      "StringEquals": { "ses:FromAddress": "you@example.com" },
      "ForAllValues:StringEquals": {
        "ses:Recipients": ["you@example.com"]
      }
    }
  }]
}

這份設定的 Allow 是允許,Action 限定能做 SendEmail,Resource 指向這個寄件身分;Condition 再把寄收件人限在自己的信箱。這樣程式就只拿到本次練習需要的寄信權限,也附上(SES 寄信權限範例)

接著到 IAM → Users → Create user,名稱填 ses-practice-sender,不要勾 Console access。Permissions 選直接附加剛剛那份政策

進這個 User 的 Security credentials → Access keys → Create access key,用途選 Local code,閱讀提示後建立。把這次的 Access key ID 和 Secret access key 保存好,Secret 只會在建立時顯示

這是本機練習用的長期金鑰,等下測完就停用

用 Node.js 寫一個寄信範例

先在自己的電腦確認 node -v 顯示 v24 開頭、npm -v 有版本號。還沒安裝的人,先完成 Node.js 安裝,再開一個新的終端機

mkdir ses-practice
cd ses-practice
npm init -y
npm install @aws-sdk/client-ses

接下來用 VS Code 開啟這個 ses-practice 資料夾。在裡面新增名為 .env 的文字檔,填入這次的設定。Key 是 IAM 建立的那一組

AWS_REGION=ap-northeast-1
AWS_ACCESS_KEY_ID=填本次的KeyID
AWS_SECRET_ACCESS_KEY=填本次的Secret
SES_FROM_EMAIL=填自己的已驗證信箱
SES_TO_EMAIL=填同一個信箱

這五個欄位可以分成三組看:用誰的身分、找哪個區域的 SES、從誰寄給誰

本機設定分成 AWS 身分、寄信區域與寄收件人三組,交給 Node.js 程式使用

同一層再新增 .gitignore,內容放下面兩行。第一行避免密碼檔進 Git,第二行排除之後能用 npm 重裝的套件:

.env
node_modules/

新增 send-email.cjs:

const { randomUUID } = require('node:crypto');
const { SESClient, SendEmailCommand } = require('@aws-sdk/client-ses');

async function main() {
  const names = ['AWS_REGION', 'AWS_ACCESS_KEY_ID',
    'AWS_SECRET_ACCESS_KEY', 'SES_FROM_EMAIL', 'SES_TO_EMAIL'];
  for (const name of names) {
    if (!process.env[name]?.trim()) throw new Error(`請填 ${name}`);
  }
  const env = process.env;
  if (env.SES_FROM_EMAIL !== env.SES_TO_EMAIL) {
    throw new Error('這次先寄給自己,From 與 To 請填同一個信箱');
  }
  const client = new SESClient({
    region: env.AWS_REGION,
    credentials: {
      accessKeyId: env.AWS_ACCESS_KEY_ID,
      secretAccessKey: env.AWS_SECRET_ACCESS_KEY,
    },
    maxAttempts: 1,
  });
  const subject = `Node.js 寄信測試 ${randomUUID().slice(0, 8)}`;
  const result = await client.send(new SendEmailCommand({
    Source: env.SES_FROM_EMAIL,
    Destination: { ToAddresses: [env.SES_TO_EMAIL] },
    Message: {
      Subject: { Data: subject, Charset: 'UTF-8' },
      Body: { Text: {
        Data: `這封信是本機 Node.js 寄的。\n時間:${new Date().toISOString()}`,
        Charset: 'UTF-8',
      } },
    },
  }));
  console.log('SES 已接受寄送請求,請到信箱確認。');
  console.log('主旨:', subject);
  console.log('MessageId:', result.MessageId);
}
main().catch(error => {
  console.error(error.name, error.message);
  process.exitCode = 1;
});

AWS SDK 是讓程式呼叫 AWS 服務的套件。這裡的 SESClient 負責使用指定區域與身分連到 SES,SendEmailCommand 裡面就是寄件人、收件人和信件內容。完整欄位可以對照 AWS 的 JavaScript 範例

現在資料夾裡應有 send-email.cjs、.env、.gitignore、package.json、package-lock.json,以及安裝出來的 node_modules。程式會依序讀設定、準備信件、送給 SES,最後印出這次的寄送編號

回到剛才的終端機,確認還在 ses-practice 資料夾,再執行一次:

node --env-file=.env send-email.cjs

--env-file 會讓 Node.js 讀取 .env。程式拿到這些值後,才知道用誰的身分、從哪個區域寄信。每執行一次,就會真的送出一次寄信請求

終端機成功了,信呢?

程式跑完後,終端機會印出主旨和 MessageId

用 Gmail 地址練習,還可能遇到來源警示。原因是我們能驗證自己的 Gmail,卻不能替 gmail.com 設定 DNS 與寄件認證。正式網站要換成自己管理的網域,處理 DKIM、DMARC 這類讓收件方查證寄件來源、決定驗證失敗時怎麼處理的設定

如果程式直接出錯,可以先從這幾個地方查:

畫面或錯誤 先看哪裡
AccessDenied 這把 Key 的 User,有沒有附加寄信政策?寄收件人是否符合條件?
Email address is not verified 程式與 Identity 是否同一個 Region?Sandbox 收件人有驗證嗎?
金鑰無效 ID/Secret 是否同一組?Key 是否已停用?
有 MessageId,沒找到信 核對主旨尾碼、垃圾郵件、退信與 suppression,先別重寄

記得測完把 Key 收起來 XD

確認收到後,回 IAM → Users → ses-practice-sender → Security credentials,找到這次的 Key,選 Deactivate,確認是 Inactive。確定不再使用,再刪除這把 Key 與本機 .env;專用 User 和 Policy 也可以一併清除,這樣才安全

希望以上小範例,有讓你對 SES 服務有更加深入的瞭解,我們下篇見勒 :D


上一篇
SES 郵件服務(上):先讓 AWS 認得寄件信箱
下一篇
Docker Image 是什麼?把程式打包後,再交給主機執行
系列文
從前後端踏上 AWS 雲端架構勇者之路 共 22 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言