我目前正在构建一个 flutter 应用程序,允许用户请求与其他人会面。当一个用户请求另一用户时,被请求的用户应该收到一封电子邮件,说明他们收到了请求。创建新请求时,一个新文档会附加到集合中
meeting_requests.
使用 Google Cloud 功能,我能够使用 Nodemailer 编写以下代码,以便在创建请求时发送电子邮件:
const transporter = nodemailer.createTransport({
service: "gmail",
auth: {
user: <MY EMAIL HERE>
pass: <MY APPS PASSWORD HERE>,
},
});
exports.sendMeetingNotification = functions.firestore
.document("meeting_requests/{docId}")
.onCreate(async (snap, context) => {
const data = snap.data();
const receiverId = data.receiverId;
console.log("Fetching user data for receiverId:", receiverId);
try {
const userDoc = await admin.firestore().collection(
"users").doc(receiverId).get();
if (!userDoc.exists) {
console.log("No user found with the given receiverId:", receiverId);
return;
}
const email = userDoc.data().email;
console.log("Found user with email:", email);
const mailOptions = {
from: "\"ConnectEd\" [email protected]",
to: email,
subject: "New Meeting Request from Teacher",
html: `
<div style="background-color: #f9f7cf; padding: 20px;
font-family: Arial, sans-serif; color: #333;">
<div style="text-align: center; margin-bottom: 20px;">
<img src="https://your-logo-url.com/logo.png" alt="ConnectEd Logo" style="width: 100px; height: auto;" />
</div>
<div style="background-color: #fff;
padding: 20px; border-radius: 8px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);">
<h2 style="color: #2c3e50;
">New Meeting Request from ${data.senderName}</h2>
<p style="font-size: 16px; line-height: 1.6;">
<strong>Note from teacher:</strong> ${data.note}
</p>
<p style="font-size: 16px; line-height: 1.6;">
Please click the link below to view the request:
</p>
<div style="text-align: center; margin: 20px 0;">
<a href="yourapp://app/openRequest?requestId=${context.params.docId}" style="background-color: #f39c12; color: #fff; padding: 10px 20px; text-decoration: none; border-radius: 5px; font-size: 16px;">View Request</a>
</div>
</div>
<div style="text-align: center;
margin-top: 20px; font-size: 12px; color: #999;">
<p>© 2024 ConnectEd. All rights reserved.</p>
<p>If you did not request this email, please ignore it.</p>
</div>
</div>
`,
};
console.log("Sending email to:", email);
await transporter.sendMail(mailOptions);
console.log("Email sent successfully to:", email);
} catch (error) {
console.error("Error sending email notification:", error);
}
});
但是,当我运行它时,没有发送电子邮件,并且出现以下日志错误:
2024-09-07T14:37:34.038106Z ? sendMeetingNotification: Error sending email notification: Error: 7 PERMISSION_DENIED: Missing or insufficient permissions.
2024-09-07T14:37:34.038127Z ? sendMeetingNotification: at callErrorFromStatus (/workspace/node_modules/@grpc/grpc-js/build/src/call.js:31:19)
2024-09-07T14:37:34.038251Z ? sendMeetingNotification: code: 7,
2024-09-07T14:37:34.038256Z ? sendMeetingNotification: details: 'Missing or insufficient permissions.',
s.',
2024-09-07T14:37:34.038261Z ? sendMeetingNotification: metadata: Metadata {
2024-09-07T14:37:34.038266Z ? sendMeetingNotification: internalRepr: Map(1) { 'x-debug-tracking-id' => [Array] },
d' => [Array] },
2024-09-07T14:37:34.038270Z ? sendMeetingNotification: options: {}
2024-09-07T14:37:34.038274Z ? sendMeetingNotification: }
2024-09-07T14:37:34.038274Z ? sendMeetingNotification: }
2024-09-07T14:37:34.038279Z ? sendMeetingNotification: }
2024-09-07T14:37:34.039269068Z D sendMeetingNotification: Function execution took 54 ms, finished with status: 'ok'
我是新手,所以真的不明白发生了什么。
我尝试更改 Firebase 权限,将此 Gmail 帐户添加到我的云权限中,但没有任何效果。奇怪的是,昨天它工作得很好,今天却不行了,这让我很困惑。
感谢您的帮助!
在发送电子邮件之前将 firestore 逻辑包装到 try/catch 中,因为这不是 nodemailer 的错误。该错误意味着用于您的 gcp 函数的服务帐户没有权限从 firestore 查询数据。
在 gcp console iam 服务中检查服务帐户的权限。