Search code examples
node.jsemailnetlifymailjet

Set up a Mailjet lambda on Netlify


I'm trying to send an email through an Netlify Lambda, the lambda works smoothly without the Mailjet integration and I've tried the Mailjet integration in a node test script

const { MJ_USER, MJ_PASSWORD } = process.env;
const mailjet = require('node-mailjet').connect(MJ_USER, MJ_PASSWORD)

exports.handler = async (event, context) => {

  if (event.httpMethod !== "POST") {
    return { statusCode: 405, body: "Method Not Allowed" };
  }

  const data = JSON.parse(event.body)

  const msg = { "Messages":[
          {
            "From": {
              "Email": "sender@gmail.com",
              "Name": "Paul"
            },
            "To": [
              {
                "Email": "receiver@gmail.com",
                "Name": "Emma"
              }
            ],
            "TemplateID": 511035,
            "TemplateLanguage": true,
            "Subject": "Test mail",
            "Variables": {
                            "input":  "Test"
                        }
          }
    ]}

  mailjet.post("send", {'version': 'v3.1'}).request(msg)
         .then((result) => {
           return{ statusCode: 200, body: result.body}
         }).catch((err) => {
          return err 
         })

}

Resulting in

{"errorMessage":"i is not a function","errorType":"TypeError","stackTrace":["n (/var/task/hello.js:1:220)","/var/task/hello.js:1:1019","Object.<anonymous> (/var/task/hello.js:1:1030)","Module._compile (module.js:652:30)","Object.Module._extensions..js (module.js:663:10)","Module.load (module.js:565:32)","tryModuleLoad (module.js:505:12)","Function.Module._load (module.js:497:3)","Module.require (module.js:596:17)"]}

The module doesn't appear to load properly but I cannot find a workaround

Update :

I've found more log in Netlify :

2:27:00 PM: Critical dependency: require function is used in a way in which dependencies cannot be statically extracted
2:27:00 PM:  @ /opt/build/repo/node_modules/formidable/lib/index.js
2:27:00 PM:  @ /opt/build/repo/node_modules/superagent/lib/node/index.js
2:27:00 PM:  @ /opt/build/repo/node_modules/node-mailjet/mailjet-client.js
2:27:00 PM:  @ /opt/build/repo/node_modules/node-mailjet/index.js
2:27:00 PM:  @ ./hello.js

Solution

  • The root cause of the error comes from the formidable module dependency in the superagent and is caused by the babel transpile using webpack in netlify functions.

    Specifically, the issue can be tracked here

    if (global.GENTLY) require = GENTLY.hijack(require);
    

    Transpiled code:

    var require;if (global.GENTLY) require = GENTLY.hijack(!(function webpackMissingModule() { var e = new Error("Cannot find module \".\""); e.code = 'MODULE_NOT_FOUND'; throw e; }()));
    

    Hence:

    • Critical dependency warning during build
    • Error in response Cannot find module.

    Solution:

    Using the temporary fix in the issue we will add a global setting for global.GENTLY so webpack will set the value to false and not pay attention to the rest of the line. This line was confirmed it was for testing purposes only.

    Create a file to hold the extra webpack config settings called webpack.config.js and put in the root of the project.

    webpack.config.js

    var webpack = require('webpack')
    
    module.exports = {
      plugins: [
        new webpack.DefinePlugin({ "global.GENTLY": false })
      ]
    }
    

    Now change the build command for the functions to include the config as additional settings for webpack.

    Old Command

    netlify-lambda build <folder>
    

    New Command

    netlify-lambda build <folder> -c webpack.config.js
    

    If all goes well, you should not have the warning or runtime failure on the module.

    NOTE: The command netlify-lambda is the Netlify Lambda CLI tool used to help bundle your functions for netlify deploy. If you are not using the CLI, then you would solve this by adding the plugin to your webpack config.