[英]Nodemailer Custom SMTP not working on Firebase Functions
我有一個錯誤。 我正在使用 nodemailer 從我的 Firebase 應用程序發送電子郵件。
這是我的代碼的樣子:
const functions = require('firebase-functions');
const admin = require("firebase-admin");
const nodemailer = require('nodemailer');
admin.initializeApp();
//THESE SETTINGS WORK ON LOCAL AND LIVE. BUT I DONT WANT TO USE THEM
// const transporter = nodemailer.createTransport({
// service: 'gmail',
// auth: {
// user: 'GMAIL HERE',
// pass: 'GMAIL PW HERE'
// },
// })
//THESE SETTINGS WORK ON LOCAL, BUT NOT ON LIVE.
const transporter = nodemailer.createTransport({
host: "smtp.mycompanyname.com",
port: 25,
secureConnection: false, // TLS requires secureConnection to be false
logger: true,
debug: true,
secure: false,
requireTLS: true,
auth: {
user: "USERNAME HERE",
pass: "PASSWORD HERE"
},
tls: { rejectUnauthorized: false }
})
exports.sendConfirmationEmail = functions.https.onCall((data, context) => {
var email_adress = data.data.email;
var email = {
from: 'E-Mail Adress Goes Here',
to: email_adress,
subject: 'BlaBlaBla',
text: 'BlaBlaBla',
html: 'BlaBlaBla'
};
// Function to send e-mail to the user
transporter.sendMail(email, function(err, info) {
if (err) {
console.log(err);
return { success: false };
} else {
return { success: true }
}
});
})
現在。 如果我使用 GMail 設置。 一切正常。 它發送電子郵件。 但是,我的公司有一個自己的 SMTP 服務器。 SMTP 適用於 Firebase 身份驗證電子郵件。 它正在成功發送這些電子郵件。
當我將上述配置粘貼到本地環境中時,SMTP 服務器也可以工作。 但是,當我在 Firebase Cloud 函數中運行它時,它給了我以下錯誤:
10:24:43.479 AM
sendConfirmationEmail
[2020-09-25 08:24:43] DEBUG [Cq6p67HnXLA] Closing connection to the server using "destroy"
10:24:43.479 AM
sendConfirmationEmail
[2020-09-25 08:24:43] ERROR Send Error: Connection timeout
10:24:44.673 AM
sendConfirmationEmail
{ Error: Connection timeout
10:24:44.673 AM
sendConfirmationEmail
at SMTPConnection._formatError (/workspace/node_modules/nodemailer/lib/smtp-connection/index.js:784:19)
10:24:44.674 AM
sendConfirmationEmail
at SMTPConnection._onError (/workspace/node_modules/nodemailer/lib/smtp-connection/index.js:770:20)
10:24:44.674 AM
sendConfirmationEmail
at Timeout._connectionTimeout.setTimeout (/workspace/node_modules/nodemailer/lib/smtp-connection/index.js:235:22)
我嘗試使用不同的 nodemailer 選項,但到目前為止還沒有取得多大成功。 這也使得它在本地工作變得困難,但是當我部署它時卻沒有。
有任何想法嗎?
我遇到了完全相同的問題,需要進行一些挖掘,但解決方案非常簡單。
您不能在 Cloud Function 中的端口 25上使用出站連接。
所以我將端口更改為 465 並使用安全連接,它確實有效。
我在Tips & Tricks文檔頁面(隨機)發現了這個。
PS:同樣的限制適用於 Compute Engine(請參閱文檔)。
您應該使用 Promises 來管理 Cloud Functions 的生命周期,它執行一個異步操作並返回一個 promise(即sendMail()
方法)。 有關更多詳細信息,請參閱此 文檔。
因此,通過使用sendMail()
方法返回的承諾而不是回調,它應該可以工作,如下所示。
exports.sendConfirmationEmail = functions.https.onCall((data, context) => {
var email_adress = data.data.email;
var email = {
from: 'E-Mail Adress Goes Here',
to: email_adress,
subject: 'BlaBlaBla',
text: 'BlaBlaBla',
html: 'BlaBlaBla'
};
return transporter.sendMail(email).then(() => { // Note the return here
return { success: false };
}).catch(error => {
console.log(error);
// !! Here, return an instance of functions.https.HttpsError.
// See the doc: https://firebase.google.com/docs/functions/callable#handle_errors
});
});
注意:如果您使用的不是Node.js 10 或 12,而是 Node.js 8(我猜不是這種情況,因為自 2020 年 2 月 15 日起不再允許部署 Node.js 8 功能。),請閱讀以下內容:
如果您在 Cloud Function 中使用 Node.js 版本 8,請注意您需要使用“Blaze”定價計划。 事實上,免費的“Spark”計划“只允許對谷歌擁有的服務的出站網絡請求”。 請參閱https://firebase.google.com/pricing/ (將鼠標懸停在“雲函數”標題后面的問號上)
由於您的 SMTP 服務器不是 Google 擁有的服務,因此您需要切換到“Blaze”計划。
25
不起作用Node.js 12
確實有效tls: { rejectUnauthorized: false }
是使其工作必不可少的下面的工作( TypeScript
)代碼,用例是一個聯系表單。
import * as functions from 'firebase-functions';
import * as nodemailer from 'nodemailer';
import * as Mail from 'nodemailer/lib/mailer';
import { DocumentSnapshot } from 'firebase-functions/lib/providers/firestore';
import { EventContext } from 'firebase-functions';
async function onCreateSendEmail(
snap: DocumentSnapshot,
_context: EventContext
) {
try {
const contactFormData = snap.data();
console.log('Submitted contact form: ', contactFormData);
console.log('context: ', _context);
// The non-null assertion signs (!) might be not required, if your IDE/TypeScript settings aren't strict.
const mailTransport: Mail = nodemailer.createTransport({
host: 'mail.yourdomain.com', // Or however your SMTP provides defines it.
port: 587, // Most probably that's your port number.
auth: {
user: 'yourmail@domain.com', // It could happen that your SMTP provides in user authentication requires full name of mail account. For example 'yourmail' would be not correct, 'yourmail@domain.com' would.
pass: 'YOUR_MAIL_PASSWORD',
},
tls: {
rejectUnauthorized: false, //! ESSENTIAL! Fixes ERROR "Hostname/IP doesn't match certificate's altnames".
},
});
const mailOptions = {
from: `${contactFormData!.formControlName} <${
contactFormData!.formControlEmail
}>`,
to: 'yourmail@domain.com',
subject: `Contact Form`,
html: `
<p>Message from a contact form has been send.</p>
<h3>Message content:</h3>
<ul>
<li>Name: ${contactFormData!.formControlName}</li>
<li>E-mail: ${contactFormData!.formControlEmail}</li>
...
</ul>
`,
};
await mailTransport.sendMail(mailOptions);
} catch (err) {
console.error(err);
}
}
exports.contactFormFunction = functions.firestore
.document('mails/{formControlEmail}'
)
.onCreate(onCreateSendEmail);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.