我有一个错误。我正在使用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选项,但到目前为止还没有取得多大成功。这也让它很难在本地工作,但当我部署它时,它就不工作了。
有什么想法吗?
我也遇到过同样的问题,需要一些挖掘,但解决方案非常简单。
解决方案
您无法使用云功能中端口25上的出站连接。
所以我把端口改为465,并使用了安全连接,它确实有效。
我(随机(在Tips&技巧文档页面。
PS:同样的限制也适用于计算引擎(请参阅文档(。
您应该使用Promises来管理云函数的生命周期,该函数执行一个返回promise的异步操作(即sendMail()
方法(。有关更多详细信息,请参阅此文档。
因此,通过使用sendMail()
方法返回的promise,而不是回调,它应该可以工作。
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.js8(我猜情况并非如此,因为自2020年2月15日起不再允许部署Node.js 8功能(,请阅读以下内容:
如果你在云功能中使用Node.js版本8,请注意你需要在";Blaze";定价计划。事实上;Spark";计划;只允许对谷歌拥有的服务的出站网络请求";。看见https://firebase.google.com/pricing/(将鼠标悬停在"云功能"标题后面的问号上(
由于您的SMTP服务器不是谷歌拥有的服务,您需要切换到";Blaze";计划
- 需要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);