#Nodemailer integration

1 messages · Page 1 of 1 (latest)

onyx notch
#

I'm having trouble integrating nodemailer, because nodemailer relies heavily on node, and importing it's functions into actions (even with 'use node') triggers issues with "missing node"

unreal totemBOT
#

Hi @onyx notch. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:

#

Nodemailer needs to run in Convex’s Node.js runtime, and there are a couple of common pitfalls that match what you’re seeing.

From the docs and Discord threads, here’s what is supported and how to structure it:

  1. Put Nodemailer in a dedicated Node action file

    • Create a file in convex/ that contains only actions and starts with:

      "use node";
      
      import { action } from "./_generated/server";
      import nodemailer from "nodemailer";
      
      export const sendEmail = action({
        args: {
          // your args here
        },
        handler: async (ctx, args) => {
          // use nodemailer here
        },
      });
      
    • Files with "use node" are bundled for the Node.js runtime and are the only place you can safely use Node‑specific libraries like Nodemailer. [Actions runtime; Node runtime]

  2. Do not import Node files from non‑Node files

    • Any file without "use node" must not import from a file with "use node". That will drag Node‑only imports into the Convex runtime and cause “missing node” / node:fs / node:async_hooks style errors. [Node runtime; ESLint rule]

    • Instead, call the Node action via ctx.runAction from a normal action / httpAction:

      // convex/http.ts (no "use node")
      import { httpAction } from "./_generated/server";
      import { internal } from "./_generated/api";
#

export const sendEmailHttp = httpAction(async (ctx, request) => {
// parse body, etc.
await ctx.runAction(internal.mail.sendEmail, { /* args */ });
return new Response(null, { status: 204 });
});
```

 HTTP actions run in the Convex runtime but **can call actions** (including Node actions). [[HTTP limits](<https://docs.convex.dev/functions/http-actions#limits>)]
  1. If you see bundling errors about Node APIs even in a "use node" file

    • That usually means some code that imports Nodemailer (or a helper that imports it) is still being pulled into a non‑Node file (e.g. shared utils.ts imported from both sides). Make sure:
      • All Nodemailer imports live only in "use node" files.
      • Any helper that touches Nodemailer also has "use node" and is not imported from Convex‑runtime files. [Node runtime]
  2. External packages (optional)

    • If Nodemailer’s dependencies cause bundling issues (dynamic imports, large size), you can mark it as an external package so it’s not bundled and is loaded at runtime in Node:

      {
        "node": {
          "externalPackages": ["nodemailer"]
        }
      }
      

      This only applies to Node actions. [External packages]

If you can share the exact error text and how your files are laid out (which file has "use node", where Nodemailer is imported, and where it’s called), I can map it directly to one of these patterns and point to the specific fix.

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: