我正在尝试将秘密访问密钥转换为 SMTP 凭据。我按照 https://docs.aws.amazon.com/ses/latest/dg/smtp-credentials.html 中的说明进行操作,并从 https://gist.github.com/damusix/c12400ee0ccb7e56351619ae2b19a303 获取实现。但是,当我尝试发送电子邮件时,nodemailer 会抛出错误:
Error: Invalid login: 535 Authentication Credentials Invalid
。我错过了什么?
const region = "eu-central-1";
const date = "11111111";
const service = "ses";
const terminal = "aws4_request";
const message = "SendRawEmail";
const versionInBytes = [0x04];
function sign(key, msg: string) {
return crypto
.createHmac("sha256", Buffer.from(key.map((a) => a.charCodeAt(0))))
.update(utf8.encode(msg))
.digest("latin1")
.split("");
}
export const generateSmtpPassword = (key: string) => {
let signature = sign(utf8.encode("AWS4" + key).split(""), date);
signature = sign(signature, region);
signature = sign(signature, service);
signature = sign(signature, terminal);
signature = sign(signature, message);
const signatureAndVersion = versionInBytes.slice(); //copy of array
signature.forEach((a) => signatureAndVersion.push(a.charCodeAt(0)));
const smtpPassword = Buffer.from(signatureAndVersion).toString("base64");
return smtpPassword;
};
const id = generateId("project");
const iam = await getIAM();
const { User } = await iam.createUser({
UserName: `project.${id}`,
});
if (!User?.UserName) throw new Error("Failed to create IAM user");
await iam.attachUserPolicy({
UserName: User.UserName,
PolicyArn: "arn:aws:iam::aws:policy/AmazonSESFullAccess",
});
const { AccessKey } = await iam.createAccessKey({
UserName: User.UserName,
});
if (!AccessKey?.AccessKeyId || !AccessKey?.SecretAccessKey)
throw new Error("AccessKeyId or SecretAccessKey is missing");
const smtpPassword = generateSmtpPassword(AccessKey.SecretAccessKey);
console.log(AccessKey);
//{
// UserName: 'project.wLhJPIEKdSX3QIEB',
// AccessKeyId: 'AKIA34AMCYCZNSLPIOGL',
// Status: 'Active',
// SecretAccessKey: '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',
// CreateDate: 2024-10-25T08:41:51.000Z
//}
console.log(smtpPassword);
// BJFVirrONXceMVwlLwSiGPYw2NG1BCRmSlcslY5lg+SC
const transport = createTransport({
host: "email-smtp.eu-central-1.amazonaws.com",
port: 587,
secure: false,
auth: {
user: AccessKey.AccessKeyId,
pass: smtpPassword,
},
});
await transport.sendMail({
subject: ...,
to: "***", // Verified address
text: ...,
from: "***", // Verified address
});
首先我使用这个实现进行转换:https://gist.github.com/jesusgoku/533ba67ea218608c5a74a6d341d75189。但它不起作用的原因是 AWS 需要在其系统中传播用户(根据 ChatGPT)。所以我在发送电子邮件之前添加了延迟(大约 10 秒)。
await new Promise((resolve) => setTimeout(resolve, 10000))