Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
Discussion options

Describe the Bug

Regardless of whether I use .env, .env.local, or .env.development.local, I am unable to utilize any environment variables in my email template when using email dev.

I've tried with both a regular environment variable and a "public" one (i.e., prefixed with NEXT_PUBLIC_). In both cases, the value of the variable when accessing via the template was undefined.

As a workaround, I was able to manually copy the file to the .react-email folder before running email dev. When doing this, I was able to access the variables as expected.

Which package is affected (leave empty if unsure)

No response

Link to the code that reproduces this issue

https://gist.github.com/dmarcucci/2401aaf65e83daa76ed0c75476df7abc

To Reproduce

  1. Add an environment variable to your .env file (either .env, .env.local, or .env.development.local).
  2. Create an email template where the aforementioned environment variable is referenced in some way (e.g., in a <Text> element).
  3. Run email dev and navigate to the applicable email template in the app UI to preview the rendered template.

Expected Behavior

The value of the environment variable (as set in the applicable environment variables file) should be visible.

What's your node version? (if relevant)

No response

You must be logged in to vote

Replies: 21 comments · 1 reply

Comment options

can confirm the workaround works.

moving .env from root folder into .react-email

You must be logged in to vote
0 replies
Comment options

I investigated a bit and I think I understand why this happens.
Since react-email package is the one that runs the app, the process.env reads from the .react-email directory, hence why your workaround works.
I've also logged the directory with process.cwd() and I can confirm that is indeed what happens, even logging it through the files inside the emails folder.

I've been trying to wrap my head around on how to fix this issue, and there's an easy solution which is to use the dotenv library and then use the .config to set the path to the parent folder, which is hacky and non intuitive.

The other option is to think of a way for the react-email package to point to the .env of the parent, somehow.

Let me know what would be best and I can get to work on a PR to fix this issue.

You must be logged in to vote
0 replies
Comment options

Not sure who your reply is addressed to, but I don't have a preference at this point since I'm now running a script before running locally in order to set up some ngrok stuff and my workaround is simply baked into that script. But I imagine any solution where the root environment variable files would just work would suffice.

You must be logged in to vote
0 replies
Comment options

In package.json

"email:dev": "cp .env .react-email/ && email dev"

Updated for react-email 2.0:

"email:dev": "cp .env ./node_modules/react-email/ && email dev"

Updated for react-email 3.0, thanks to #668 (comment)

"email:dev": "cp .env ./node_modules/react-email/dist/preview && email dev"
You must be logged in to vote
1 reply
@austin-dudzik
Comment options

If using react-email 4.1.0, which migrated the preview server to a separate package, you can use this instead:

"email:dev": "cp .env ./node_modules/@react-email/preview-server && email dev"
Comment options

It's not a "workaround" it's just a hack for email dev, what about email export? It doesn't create .react-email folder.

You must be logged in to vote
0 replies
Comment options

Created a patch to solve the problem for both dev and export (for 1.9.5):

diff --git a/node_modules/react-email/dist/source/commands/dev.js b/node_modules/react-email/dist/source/commands/dev.js
index c0f050a..6e63dd9 100644
--- a/node_modules/react-email/dist/source/commands/dev.js
+++ b/node_modules/react-email/dist/source/commands/dev.js
@@ -8,16 +8,20 @@ const utils_1 = require("../utils");
 const fs_1 = __importDefault(require("fs"));
 const shelljs_1 = __importDefault(require("shelljs"));
 const run_server_1 = require("../utils/run-server");
+const _env = require("dotenv").config();
+const _env_file = Object.entries(_env.parsed).map(([k, v]) => `${k}="${v}"`).join("\n") + "\n";
 const dev = async ({ dir, port, skipInstall }) => {
     try {
         if (!fs_1.default.existsSync(dir)) {
             throw new Error(`Missing ${dir} folder`);
         }
         if (fs_1.default.existsSync(utils_1.REACT_EMAIL_ROOT)) {
+            fs_1.default.writeFileSync(utils_1.REACT_EMAIL_ROOT + "/.env", _env_file);
             await (0, run_server_1.setupServer)('dev', dir, port, skipInstall);
             return;
         }
         await (0, utils_1.downloadClient)();
+        fs_1.default.writeFileSync(utils_1.REACT_EMAIL_ROOT + "/.env", _env_file);
         await (0, run_server_1.setupServer)('dev', dir, port, skipInstall);
     }
     catch (error) {
diff --git a/node_modules/react-email/dist/source/commands/export.js b/node_modules/react-email/dist/source/commands/export.js
index e3b8200..5e99456 100644
--- a/node_modules/react-email/dist/source/commands/export.js
+++ b/node_modules/react-email/dist/source/commands/export.js
@@ -39,6 +39,8 @@ const path_1 = __importDefault(require("path"));
 const shelljs_1 = __importDefault(require("shelljs"));
 const fs_2 = __importDefault(require("fs"));
 const close_ora_on_sigint_1 = require("../utils/close-ora-on-sigint");
+const _process_env = {};
+require('dotenv').config({ processEnv: _process_env });
 /*
   This first builds all the templates using esbuild and then puts the output in the `.js`
   files. Then these `.js` files are imported dynamically and rendered to `.html` files
@@ -48,12 +50,17 @@ const exportTemplates = async (outDir, srcDir, options) => {
     const spinner = (0, ora_1.default)('Preparing files...\n').start();
     (0, close_ora_on_sigint_1.closeOraOnSIGNIT)(spinner);
     const allTemplates = glob_1.glob.sync((0, normalize_path_1.default)(path_1.default.join(srcDir, '*.{tsx,jsx}')));
+    const define = {};
+    for (const k in _process_env) {
+        define[`process.env.${k}`] = JSON.stringify(_process_env[k]);
+    }
     esbuild_1.default.buildSync({
         bundle: true,
         entryPoints: allTemplates,
         platform: 'node',
         write: true,
         outdir: outDir,
+        define,
     });
     spinner.succeed();
     const allBuiltTemplates = glob_1.glob.sync((0, normalize_path_1.default)(`${outDir}/*.js

Place the patch into patches/react-email+1.9.5.patch in your project.
Make sure that dotenv package is installed.
Apply the patch using the marvelous patch-package npm module.

You must be logged in to vote
0 replies
Comment options

Would also love this to be fixed 🙏 I'm using React Email in a project when I've set up T3 Env and I can't even start the dev server due to the missing env variables:

❌ Invalid environment variables: {
  ...
}
You must be logged in to vote
0 replies
Comment options

Would also love this to be fixed 🙏 I'm using React Email in a project when I've set up T3 Env and I can't even start the dev server due to the missing env variables:

❌ Invalid environment variables: {
  ...
}

Is this from using t3-env within the /emails files?

Just use process.env in those files and follow this to copy the .env file to the generated react-email previewer:
#668 (comment)

You must be logged in to vote
0 replies
Comment options

Copying the environment variables to ./node_modules/react-email/ doesn't seem to work with "react-email": "3.0.1". Any idea on how to handle it now?

You must be logged in to vote
0 replies
Comment options

it seems to work if you copy the .env file to ./node_modules/react-email/dist/preview/. I wonder if there's a better way to do it.

You must be logged in to vote
0 replies
Comment options

How can we access environment variables for "email export"?

You must be logged in to vote
0 replies
Comment options

How can we access environment variables for "email export"?

Terminal:
TEST_ENV_VAR=asdef email export

In tsx template:
console.log(process.env.TEST_ENV_VAR);

asdef

Works fine

You must be logged in to vote
0 replies
Comment options

For Windows users, the solution with cp doesn't work since it's not a recognized command. Use the Windows copy command instead:
"email:dev": "copy .env.local .\\node_modules\\react-email\\dist\\preview\\ && email dev -p 3001 --dir src/components/emails"
Make sure to use backslashes for paths and note that I'm copying from .env.local (which is my Next.js environment file) to the React Email preview directory.
Thanks to everyone in this thread, especially @LavransBjerkestrand and @viczam 🫶

You must be logged in to vote
0 replies
Comment options

How can we access environment variables for "email export"?

Terminal: TEST_ENV_VAR=asdef email export

In tsx template: console.log(process.env.TEST_ENV_VAR);

asdef

Works fine

would be cool if you could show how it works for u. for me it just works for the preview but not for the "email export" script. it stays undefined

You must be logged in to vote
0 replies
Comment options

"import "dotenv/config"; "

inside of my ParentComponent of each template. so it must be imported one by one for each template.

might be a special case for me and doesnt work for u since im using it inside of a node service.

You must be logged in to vote
0 replies

This comment has been minimized.

Comment options

Hello everyone 👋,

I'm looking for feedback on this issue: #{2074} (process.env not recognized in React Email). If you have any ideas or time to help, please let me know!

Thanks in advance 🙏.

you did not understand github. Dont open a second issue with exactly the same issue. Specially not with "i solved it" its not an issue if you solved it.

You must be logged in to vote
0 replies
Comment options

Here's what worked for me :

🔧 What I did

1. I installed dotenv:

npm install dotenv

2. I set the environment variable in the .env file

// .env
NEXT_PUBLIC_VERCEL_ENV=development

3. In test.tsx file, I used dotenv/config to load the environment variables

import "dotenv/config";

import { Html } from '@react-email/html'
import { Text } from '@react-email/text'
import { Section } from '@react-email/section'
import * as React from 'react'

const publicVercelEnv = `${process.env.NEXT_PUBLIC_VERCEL_ENV}`

export default function Email() {
    return (
        <Html>
            <Section style={{ backgroundColor: '#ffffff', margin: '0 auto' }}>
                <Text>
                    {publicVercelEnv}
                </Text>
            </Section>
        </Html>
    )
}
You must be logged in to vote
0 replies
Comment options

Here's what worked for me :

🔧 What I did

1. I installed dotenv:

npm install dotenv

2. I set the environment variable in the .env file

// .env
NEXT_PUBLIC_VERCEL_ENV=development

3. In test.tsx file, I used dotenv/config to load the environment variables

import "dotenv/config";

import { Html } from '@react-email/html'
import { Text } from '@react-email/text'
import { Section } from '@react-email/section'
import * as React from 'react'

const publicVercelEnv = ${process.env.NEXT_PUBLIC_VERCEL_ENV}

export default function Email() {
return (

<Section style={{ backgroundColor: '#ffffff', margin: '0 auto' }}>

{publicVercelEnv}



)
}

this is not optimal. you have to do it for each email individually.

You must be logged in to vote
0 replies
Comment options

Here's what worked for me :

🔧 What I did

1. I installed dotenv:

npm install dotenv

2. I set the environment variable in the .env file

// .env
NEXT_PUBLIC_VERCEL_ENV=development

3. In test.tsx file, I used dotenv/config to load the environment variables

import "dotenv/config";
import { Html } from '@react-email/html'
import { Text } from '@react-email/text'
import { Section } from '@react-email/section'
import * as React from 'react'
const publicVercelEnv = ${process.env.NEXT_PUBLIC_VERCEL_ENV}
export default function Email() {
return (

{publicVercelEnv}

)
}

this is not optimal. you have to do it for each email individually.

were only users ourself, those are workarounds. A workaround is never optimal. Use dotenv in the Parent of each template, that is the current workaround until someone with knowledge of the project fixes it.

You must be logged in to vote
0 replies
Comment options

Converting this to a discussion, since this isn't a bug, it's more of a feature request. Let's keep this discussion to the level of thinking of an API for users to load their env files in, which is a completely valid use case.

You must be logged in to vote
0 replies
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Category
💡
Ideas
Labels
Package: react-email This is the CLI we generally use as just `email` on the temrinal.
Converted from issue

This discussion was converted from issue #668 on July 14, 2025 17:13.

Morty Proxy This is a proxified and sanitized view of the page, visit original site.