douglasrcjames
douglasrcjames

Reputation: 1665

"Error: Client network socket disconnected before secure TLS connection was established" on Firebase Function

I am using nodemailer with my Firebase Functions (server-side functions) for my React.js project and am getting the error: Error: Client network socket disconnected before secure TLS connection was established... and causing some emails to not be sent out. This is a big issue for this project, as the client can't be missing emails sent from the system. Why am I getting this error and how might I remedy it?

Firebase Function index.js:

"use strict";
import functions = require('firebase-functions');
import admin = require("firebase-admin");
import nodemailer = require('nodemailer');
import { DocumentSnapshot } from 'firebase-functions/lib/providers/firestore';
import { Change, EventContext } from 'firebase-functions';
import { Status } from './common';

admin.initializeApp(functions.config().firebase);

export const onUserCreated = functions.firestore.document('users/{userId}')
  .onCreate(async (snap: { data: () => any; }) => {
    console.log("Client create heard! Starting inner...")
    const newValue = snap.data();

    try {
        console.log("Started try{}...")

        // Template it
        const htmlEmail = 
        `
        <div>
            <h2>client Sign Up</h2>
        `
        // Config it
        const transporter = nodemailer.createTransport({
            host: "smtp.gmail.com",
            port: 465,
            secure: true,
            auth: {
                user: functions.config().email.user,
                pass: functions.config().email.password
            }
        })
        console.log("transporter = " + transporter)

        // Pack it
        const mailOptions = {
            from: `[email protected]`,
            to: '[email protected]',
            replyTo: `${newValue.email}`,
            subject: `user sign up`,
            text: `A new user sign up with the email of ${newValue.email}.`,
            html: htmlEmail
        }

        // Send it
        transporter.sendMail(mailOptions, (err: any) => {
            if(err) {
                console.error(err);
            } else {
                console.log("Successfully sent mail with sendMail()!");
            }
        })
    } catch (error) {
        console.error(error)
    }
  });

Functions package.json:

{
  "name": "functions",
  "scripts": {
    "lint": "tslint --project tsconfig.json",
    "build": "tsc",
    "serve": "npm run build && firebase emulators:start --only functions",
    "shell": "npm run build && firebase functions:shell",
    "start": "npm run shell",
    "deploy": "firebase deploy --only functions",
    "logs": "firebase functions:log"
  },
  "engines": {
    "node": "10"
  },
  "main": "lib/index.js",
  "dependencies": {
    "@types/nodemailer": "^6.4.0",
    "firebase-admin": "^9.4.1",
    "firebase-functions": "^3.11.0",
    "nodemailer": "^6.4.16"
  },
  "devDependencies": {
    "firebase-functions-test": "^0.2.3",
    "tslint": "^5.12.0",
    "typescript": "^3.8.0"
  },
  "private": true
}

Full error: enter image description here

Upvotes: 4

Views: 26075

Answers (3)

Luis Alberto Pe&#241;a
Luis Alberto Pe&#241;a

Reputation: 136

I just fixed using SMTP Pooled option while creating the transport.

I was expecting same issue but sometimes it send 3, other 6, other 9, now with the pool flag it works perfect and all emails was sent. Hope it helps.

https://nodemailer.com/smtp/pooled/

const transporter = nodemailer.createTransport({ host: 'mail.example.com' port: 587, //2525 pool: true, secureConnection: true, auth: { user: 'xxxxxxxxxxx', pass: 'xxxxxxxxxxx' } });

Upvotes: 0

Anton
Anton

Reputation: 51

In my case the error gone after adding TLS version to nodemailer options:

let transporter = nodemailer.createTransport({
    host: 'smtp-server',
    port: 25,
    tls: {
      ciphers : 'SSLv3',
    },
  });

Upvotes: 5

Methkal Khalawi
Methkal Khalawi

Reputation: 2477

You should return a promise to avoid unexpected Fuctions behaviour like early termination.

Checking Nodemailer API documentation

I can see that transporter.sendMail returns a promise. So just returning this promise should fix your issue:

export const onUserCreated = functions.firestore.document('users/{userId}')
  .onCreate(async (snap: { data: () => any; }) => {

....
return transporter.sendMail(mailOptions)

}

Upvotes: 3

Related Questions