如何解决Nodemailer自定义SMTP在Firebase功能上不起作用
我有一个错误。我正在使用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选项,但到目前为止并没有取得很大的成功。这也使得它很难在本地运行,但是当我部署时却不行。
有什么想法吗?
解决方法
您应该使用Promises来管理Cloud Function的生命周期,该Cloud Function执行一个异步操作并返回一个Promise(即sendMail()
方法)。有关更多详细信息,请参见此doc。
因此,通过如下使用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.js 8(我猜是不) ,因为自2020年2月15日起不再允许部署Node.js 8功能。),请阅读以下内容:
如果您在Cloud Function中使用Node.js版本8,请注意您需要使用“ Blaze”定价计划。实际上,免费的“ Spark”计划“仅允许对Google拥有的服务的出站网络请求”。请参见https://firebase.google.com/pricing/(将鼠标悬停在“云函数”标题之后的问号上)
由于您的SMTP服务器不是Google拥有的服务,因此您需要切换到“ Blaze”计划。
,我遇到了完全相同的问题,这需要花一些时间进行挖掘,但是解决方案非常简单。
解决方案
您无法使用使用云功能中端口25 上的出站连接。
因此,我将端口更改为465,并使用了安全连接,它确实起作用。
我在Tips & Tricks文档页面上(随机)发现了这一点。
PS:相同的限制适用于Compute Engine(请参阅docs)。
,- 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);
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。