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

11,295

Solution 1

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)

}

Solution 2

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',
    },
  });
Share:
11,295

Related videos on Youtube

douglasrcjames
Author by

douglasrcjames

San Jose State computer engineering graduate working on bringing 21st century tech support to the masses.

Updated on June 04, 2022

Comments

  • douglasrcjames
    douglasrcjames almost 2 years

    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

    • Doug Stevenson
      Doug Stevenson over 3 years
      Your code needs to return a promise that resolves when all the async work is compelte. Otherwise, you can expect strange behavior like this. Be sure to review the documentation. firebase.google.com/docs/functions/terminate-functions
    • douglasrcjames
      douglasrcjames over 3 years
      @DougStevenson that makes sense, so if I understand correctly, simply adding the return at the end of some cases, such as return console.error(error) and those console.logs/errors inside transporter.sendMail might fix this weird error? Or do I ned to build a full Promise?
    • Doug Stevenson
      Doug Stevenson over 3 years
      You will have to use the nodemailer API documentation to figure out how it works with promises and use them correctly. I've never used it.
    • douglasrcjames
      douglasrcjames over 3 years
      @DougStevenson I’ll take a look and report back
  • douglasrcjames
    douglasrcjames over 3 years
    Thanks for the clarification on this. Looks like Firebase Functions are temporarily having issues, so I will report back when they fix it!