You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Node.js中拼接AWS数据生成的message并传递给SendEmail函数

解决AWS IAM组和用户信息拼接及邮件发送的异步问题

你的代码核心问题在于异步操作的顺序控制——iam.listGroups和iam.getGroup都是异步回调式的API,当前代码不仅没有调用SendEmail函数,就算调用了,也会在所有组的用户信息还没完成拼接时就执行,最终得到不完整的message。

下面是重构后的完整解决方案,使用async/await(Node.js 8.10+支持,Lambda默认环境已兼容)来清晰控制异步流程,确保所有信息拼接完成后再发送邮件:

const aws = require('aws-sdk');
const ses = new aws.SES({ region: 'us-east-1' });
const iam = new aws.IAM({ apiVersion: '2010-05-08' });

// 将IAM listGroups方法包装为Promise,方便使用await
const listIamGroups = () => {
  return new Promise((resolve, reject) => {
    iam.listGroups({}, (err, data) => {
      if (err) reject(err);
      else resolve(data.Groups);
    });
  });
};

// 将IAM getGroup方法包装为Promise,按组名获取用户
const getGroupUsers = (groupName) => {
  return new Promise((resolve, reject) => {
    iam.getGroup({ GroupName: groupName }, (err, data) => {
      if (err) reject(err);
      else resolve(data.Users);
    });
  });
};

// 邮件发送函数(补充了SES实际发送的示例逻辑)
const sendEmail = async (messageContent) => {
  console.log('===SENDING EMAIL HERE using message variable===');
  
  // 配置SES发送参数(请替换为你的发件人、收件人信息)
  const sesParams = {
    Destination: {
      ToAddresses: ['your-recipient@example.com']
    },
    Message: {
      Body: {
        Html: {
          Charset: 'UTF-8',
          Data: messageContent // 拼接好的HTML格式内容
        }
      },
      Subject: {
        Charset: 'UTF-8',
        Data: 'AWS IAM Groups & Users Report'
      }
    },
    Source: 'your-sender@example.com' // 需要在SES中验证该邮箱
  };

  try {
    await ses.sendEmail(sesParams).promise();
    console.log('Email sent successfully!');
  } catch (emailErr) {
    console.error('Failed to send email:', emailErr);
    throw emailErr; // 抛出错误让上层处理
  }
};

exports.handler = async (event, context) => {
  console.log("Incoming event: ", event);
  let message = "";

  try {
    // 第一步:获取所有IAM组
    const allGroups = await listIamGroups();
    
    // 第二步:遍历每个组,获取用户并拼接内容
    for (const group of allGroups) {
      // 添加组名(用加粗标签增强邮件可读性)
      message += `<h3>${group.GroupName}</h3>`;
      
      // 获取当前组下的所有用户
      const groupUsers = await getGroupUsers(group.GroupName);
      
      // 拼接用户信息
      if (groupUsers.length === 0) {
        message += "<p>No users assigned to this group</p><hr/>";
      } else {
        message += "<ul>";
        for (const user of groupUsers) {
          // 处理PasswordLastUsed可能为undefined的情况
          const lastUsed = user.PasswordLastUsed 
            ? user.PasswordLastUsed.toLocaleString() 
            : "Never";
          message += `<li>${user.UserName} - Password Last Used: ${lastUsed}</li>`;
        }
        message += "</ul><hr/>";
      }
    }

    // 第三步:所有内容拼接完成后,发送邮件
    await sendEmail(message);
    console.log('IAM report generated and email sent successfully');
  } catch (err) {
    console.error('Process failed:', err);
    // 这里可以添加错误处理逻辑,比如发送告警邮件
  }
};

关键改进点说明:

  • 异步流程控制:用Promise包装AWS SDK的回调式API,结合async/await让异步代码像同步代码一样顺序执行,确保先获取所有组,再逐个获取每个组的用户,最后才发送邮件。
  • 避免竞态条件:原来的代码中多个异步回调同时修改message变量,可能导致内容混乱;现在顺序执行每个组的用户查询,不会出现并发修改问题。
  • 邮件内容优化:用HTML标签(<h3>、<ul>、<hr/>)让邮件内容结构更清晰,同时处理PasswordLastUsed为空的边界情况。
  • 错误处理:用try/catch包裹整个流程,捕获从IAM查询到邮件发送的所有错误,便于调试和异常处理。

原来代码的核心问题回顾:

  1. 未等待所有iam.getGroup异步调用完成就尝试使用message(甚至没调用SendEmail);
  2. 多个异步回调并发修改同一个message变量,可能导致内容错乱;
  3. 回调嵌套导致代码可读性和可维护性差。

内容的提问来源于stack exchange,提问作者David

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 09:59:44