首页 > 解决方案 > Nodemailer 在本地工作,但不在 lambda

问题描述

当我在本地而不是 lambda 上运行时,Nodemailer 正在发送电子邮件。令人惊讶的是,对于我来说,与此类似的问题的解决方案都没有。其中一个问题还建议使 nodemailer 中的 sendEmail 函数异步并等待它,因为它不会像在本地那样等待它在 AWS 上完成执行。

下面是我的具有邮件逻辑的代码(请参阅我用标签 [1] 和 [2] 注释的行):

import * as nodemailer from 'nodemailer';
import SMTPTransport = require('nodemailer/lib/smtp-transport');
import * as Tracer from 'tracer';
import {Transport} from 'common-models/transport';
import {MailObject} from 'common-models/mailObject';

import * as Mail from 'nodemailer';
import EmailTemplates = require('swig-email-templates');



export class MailHelper {
    private logLevel = process.env.TRACER_LEVEL || 'debug';
    private smtpOptions: SMTPTransport.Options;
    private transporter: nodemailer.Transporter;
    private templates: EmailTemplates;
    private logger: Tracer.Tracer.Logger = Tracer.colorConsole({
        level: this.logLevel
    });


    constructor(transport: Transport) {
        this.smtpOptions = {
                host: transport.host,
                port: transport.port,
                secure: transport.secure,
                tls: transport.tls,
                auth: {
                    user: transport.auth.user,
                    pass: transport.auth.password
                }
            }
        }

    connect(): Promise < boolean > {
        console.log(`Inside connect`);
        return new Promise < boolean > (async (resolve, reject) => {
            try {
                this.transporter = await nodemailer.createTransport(this.smtpOptions)
                resolve(true);
            } catch (error) {
                this.logger.fatal(error);
                reject(error);
            }
        })
    }

    async sendMail(body: MailObject): Promise < string > { //<-----[1] made this asynchronous

        console.log(`[bodymail][value]: ${JSON.stringify(body)}`)
        const senderAddress: Mail.Address = {
            address: body.from.emailAddress,
            name: body.from.name ? body.from.name : ''
        }


        const recipientAddress: Mail.Address = {
            address: body.to.emailAddress,
            name: body.to.name ? body.to.name : ''
        }

        const mailOptions: Mail.Options = {
            from: senderAddress,
            to: recipientAddress,
            subject: body.subject,
            text: body.text ? body.text : undefined,
            html: body.html ? body.html : undefined,
            amp: body.html ? body.html : undefined
        }
        console.log(`[mail options][value]: ${JSON.stringify(mailOptions)}`)

        return new Promise<any> (async(resolve, reject) => {
            if (!this.transporter) {
                this.logger.warn(`Transporter not intitialized. Use connect method`);
                reject(`Transporter not initialized. Use connect method`);
            }
            console.log(`Inside the promise of sendMail`);
                 this.transporter.sendMail(mailOptions).then(async value => { //<--- [2] also using then to await for the result
                    console.log(`[sentMail][value]: ${JSON.stringify(value)}`);
                resolve(value);
            }).catch(error => {
                this.logger.fatal(error);
                reject(error);
            })
        })
    }

    public sendMailFromHTML(body: MailObject): Promise < string > {
        return new Promise < string > (async (resolve, reject) => {
            console.log(`Inside the promise of sendMailFromHTML`);
            this.sendMail(body).then((value: string) => {
                resolve(value);
            }).catch(error => {
                reject(error);
            })
        })
    }

    public sendMailFromTemplate(body: MailObject, values: {}): Promise < string > {
        this.templates = new EmailTemplates();

        return new Promise < string > ((resolve, reject) => {
            console.log(`Inside promise of sendMailFromTemplate`);
            this.templates.render(body.template ? body.template : '', values, (err, html, text, subject) => {
                if (err) {
                    this.logger.error(err);
                    reject(err);
                } else {
                    body.subject = subject ? subject : body.subject;
                    body.html = html;
                    body.text = text;
                    this.sendMail(body).then((value: string) => {
                        resolve(value);
                    }).catch(error => {
                        reject(error);
                    });
                }
            });
        });
    }
}

标签: javascriptnode.jslambdanodemailer

解决方案


尝试改变:

this.transporter = await nodemailer.createTransport(this.smtpOptions)

至:

this.transporter = nodemailer.createTransport(this.smtpOptions)

这解决了我在 Vercel 上托管的项目的 SMTP 问题。行为相似,我无法从生产环境发送电子邮件,但我的本地环境没有问题。


推荐阅读