NPM scripts and CLI for sending text and HTML emails using Gmail SMTP with Google OAuth2.
- Requirements
- Quickstart
- Installation
- Usage
- Alternate Usage
- Code Samples
- Available Scripts
- Docker Scripts
- Building the Windows Executable File
👉 Click to expand the list of requirements
- Windows 11/Linux OS
- NodeJS LTS v22 or higher
Recommended: node: 22.14.0 npm: 10.9.2 - Gmail Account
- Gmail email/password
- Optional:
- Google Cloud Platform project configured with OAuth2 settings and credentials
- Read on the Google Gmail, SMTP and OAuth2 Setup sections for more information
(Installed via npm)
- googleapis
v164.1.0 - nodemailer
v7.0.10 - typescript
v5.9.3- Compile-time error checker - vite-node
v3.2.4- Runs TS files in development mode - vitest
v4.0.4- Runs tests - commander
v14.0.2- CLI library - sanitize-html
v2.17.0- Sanitizes WYSIWYG HTML input
-
Create a
.envfile in the/appdirectory, replacing the contents of the.env.examplefile with actual values.- See Installation # 4 for more information about these environment variables.
-
Install dependencies.
npm install
-
Transpile to JavaScript.
npm run transpile
-
Send a text email using the CLI, eg. using Bash:
npm run send-email -- text \ -s "You are Invited" \ -c "Birthday party in December" \ -r a@gmail.com,b@gmail.com,c@gmail.com
💡 TIP: Use
send-email:devto work on development mode without needing to run"npm run transpile" -
Send a styled HTML email using the CLI, eg. using Bash:
npm run send-email -- html \ -s "Reading Materials" \ -c "Lorem ipsum dolor sit amet" "this is paragraph 1" "this is paragraph 2" \ -r test@gmail.com,one@gmail.com,two@gmail.com
💡 TIP: No transpilation needed with
"send-email:dev" -
Send WYSIWYG HTML content using the CLI, eg. using Bash:
(Adjust@/utils/config/sanitizeHtml.tsto allow more styles.)npm run send-email -- html \ -s "WYSIWYG Email" \ -w "<div style='width:100px; height:100px; border:5px solid blue; border-radius: 3px; padding: 8px; text-align: center; background-color: azure;'><h3>Hello, World</h3></div>" \ -r "tester@gmail.com"
💡 TIP: Development mode via
"send-email:dev"skips transpilation
-
Clone the repository.
git clone https://github.com/weaponsforge/send-email.git -
Install dependencies.
npm install -
Configure OAuth2. Get a refresh token from the Google OAuth 2 Playground.
- Read on Using the OAuth 2.0 Playground for more information about generating a refresh token using the Google OAuth Playground.
- INFO: This is an older note, some steps may vary in 2025)
-
Set up the environment variables. Create a
.envfile inside the /app directory with reference to the.env.examplefile.Variable Name Description GOOGLE_USER_EMAIL Your google email that you've configured for Gmail SMTP and Google OAuth2 GOOGLE_CLIENT_ID Google Developer Project ID associated with your email GOOGLE_CLIENT_SECRET Client secret for the Google Developer Project CLIENT_ID GOOGLE_REDIRECT_URI Allowed Google API redirect URI. Its value is https://developers.google.com/oauthplaygroundby default.GOOGLE_REFRESH_TOKEN The initial (or any) refresh token obtained from OAuthPlayground. - Read on Using the OAuth 2.0 Playground for more information about generating a refresh token using the Google OAuth Playground.
(INFO: This is an older note, some steps may vary this 2025)
-
Run a non-test TypeScript file inside the /app/src directory from the project's "root directory". For example:
cd app npx vite-node src/utils/sample.ts -
Run compiled JavaScript code from the TypeScript files. For example:
cd app npm run transpile node dist/utils/sample.js -
See the Available Scripts section for more information.
-
Build the image (Run only once)
docker compose build --no-cache
-
Run the container (Run only once)
docker compose up
-
Run an NPM script using Docker compose
Ensure the Docker container is running (see Run the container)docker exec -it weaponsforge-sendemail-dev <AVAILABLE_SCRIPT_OR_DOCKER_SCRIPT>
-
Run an NPM script using only Docker
Ensure the Docker container is running (see Run the container)docker run -it -v ${pwd}/app:/opt/app -v /opt/app/node_modules --rm weaponsforge/sendemail:dev <AVAILABLE_SCRIPT_OR_DOCKER_SCRIPT>
-
Run a non-test TS file using Vite
(requires Run an NPM script using Docker compose)docker exec -it weaponsforge-sendemail-dev npx vite-node /opt/app/src/<PATH_TO_TS_FILE>.ts
-
See the Available Scripts and Docker Scripts sections for more information.
app/src/demo/sendEmail.ts
import { send } from '@/lib/index.js'
const main = async () => {
await send({
recipient: 'tester@gmail.com',
subject: 'Test Message',
content: 'How are you?'
})
}
main()app/src/demo/sendHtml.ts
import { send } from '@/lib/index.js'
import { buildHtml } from '@/lib/index.js'
const emails = ['tester@gmail.com', 'admin@gmail.com']
const main = async () => {
// Build the HTML email content
const emailContent = await buildHtml({
content: ['Lorem ipsum dolor sit amet...', 'paragraph #2', 'paragraph #3'],
recipients: emails,
sender: process.env.GOOGLE_USER_EMAIL
})
// Send the email
await send({
subject: 'Welcome Aboard!',
content: emailContent,
recipients: emails,
isHtml: true
})
}
main()These scripts, compatible with running in Node and Docker, run various TypeScript scripts and tests.
👉 Click to expand the list of available scripts
Runs vitest in watch mode, watching file changes and errors to files linked with *.test.ts files.
Watches file changes in .ts files using the tsc --watch option.
Builds JavaScript, .d.ts declaration files, and map files from the TypeScript source files in the /src directory.
Runs type-checking without generating the JavaScript or declaration files from the TypeScript files in the /src and __tests__ directories.
Lints TypeScript source codes.
Fixes lint errors in TypeScript files.
- Runs test scripts defined in
*.test.tsfiles with coverage. - Generates a vitest test report into the /html directory.
- Run
npm run report:viewto preview the generated report.
- Runs test scripts defined in
*.test.tsfiles with coverage. - Spawns a local report-like website showing each test's real-time status and coverage using vitest-ui
- This script is similar to the vitest
npm run devscript that watches for changes in the*.test.tsfiles but displays the result logs and coverage details in the local website rather than the command line.
NOTE: This script requires running
npm testfirst to generate a test report into the /html directory
- Spins up a local web server accessible at
http://localhost:4174/ - Serves the website contents of a test report from the /html directory
Copies the EJS email template into the /dist/templates directory.
This script runs automatically after "npm run transpile", copying the "/app/src/templates/email.ejs" to the "/dist/templates" directory.
Sends text and HTML emails using the command line interface (CLI) with transpiled JavaScript.
💡 IMPORTANT:
- This script requires running the
"npm run transpile"script before usage.- If you want to run these without transpiling, append a
:devafter the NPM script:"npm run send-email:dev"
-
To view the list of available commands:
npm run send-email helpUsage: send-email [options] [command] CLI for sending an email using Gmail SMTP and Google OAuth2 Options: -V, --version output the version number -h, --help display help for command Commands: text [options] Send raw text email to one or multiple recipient/s html [options] Send paragraphs of text or WYSIWYG content as styled HTML email to one or multiple recipient/s. help [command] display help for command -
Append a double dash
--to pass arguments to the CLI commands eg., (using Bash)npm run send-email -- text \ -s "You are Invited" \ -c "Birthday party in December" \ -r a@gmail.com,b@gmail.com,c@gmail.com
-
View available options for the send-email text [options] command.
# Usage options for the send "text" email command npm run send-email help text
Usage: send-email text [options] Send raw text email to one or multiple recipient/s Options: -s, --subject <title> email subject or title enclosed in double-quotes -c, --content <text> email text content enclosed in double-quotes -e, --env <path> path to .env file (optional) -r, --recipients <emails> comma-separated list of email addresses -h, --help display help for command -
View available options for the send-email html [options] command.
# Usage options for the send "html" email command npm run send-email help html
Usage: send-email html [options] Send paragraphs of text or WYSIWYG content as styled HTML email to one or multiple recipient/s. Options: -s, --subject <title> email subject or title enclosed in double-quotes -r, --recipients <emails> comma-separated list of email addresses -c, --content <text...> whitespace-delimited of text/paragraphs enclosed in double-quotes -w, --wysiwyg [html] optional HTML tags that form a WYSIWYG content enclosed in double-quotes -e, --env <path> path to .env file (optional) -h, --help display help for command
- Sends an email using the command line interface (CLI) in development mode using TypeScript.
- Append a double dash
--to pass arguments to the CLI commands. - Usage: view the
"npm run send-email"script for more information. They share similar usage.-
💡 NOTE: Append
:devin the script eg.,npm run send-email:dev
-
These scripts allow optional Docker-related processes, such as enabling file watching in Docker containers running in Windows WSL2 and others.
Tip
Scripts with a ":win" suffix indicate compatibility for Windows Docker running in WSL2.
👉 Click to expand the list of available scripts
Run the Docker containers first using options A or B.
A. Using Docker compose
docker compose build
docker compose upUse the template:
docker exec -it weaponsforge-sendemail-dev <AVAILABLE_DOCKER_SCRIPT>B. Using Only Docker (PowerShell)
docker run -it -v ${pwd}/app:/opt/app -v /opt/app/node_modules --rm weaponsforge/sendemail:dev <AVAILABLE_DOCKER_SCRIPT>
- Runs the
"/src/utils/sample/sample.ts"script in containers with debugging enabled in VSCode by default. - Replace the
"/src/utils/sample/sample.ts"file path in the package.json file's"docker:debug"script with a target TypeScript file for debugging. - Map port
9229to enable debugging VSCode while running in Docker (PowerShell).- (A. Using Docker compose):
docker exec -it weaponsforge-sendemail-dev npm run docker:debug - (B. Using Only Docker (PowerShell))
docker run -it -v ${pwd}/app:/opt/app -v /opt/app/node_modules -p 9229:9229 --rm weaponsforge/sendemail:dev npm run docker:debug
- (A. Using Docker compose):
- Launch the VSCode debugger using the following configuration:
{ "version": "0.2.0", "configurations": [ { "type": "node", "request": "attach", "name": "Attach to Docker", "address": "localhost", "port": 9229, "restart": true, "skipFiles": ["<node_internals>/**"], "localRoot": "${workspaceFolder}/app", "remoteRoot": "/opt/app" } ] }
- Docker command counterpart of the
npm run test:uiscript, compatible with containers running in Linux OS. - Runs test scripts defined in
*.test.tsfiles in watch mode with coverage from a container. - Spawns a local report-like website showing each test's real-time status and coverage using vitest-ui accessible at
http://localhost:51204/__vitest__/.
NOTE: This script requires running
npm testfirst to generate a test report into the /html directory
- Docker command counterpart of the
npm run report:viewscript. - Spins up a local web server accessible at
http://localhost:4174/ - Serves the website contents of a test report from the host's /html directory
Watches file changes in .ts files using the tsc --watch option with dynamicPriorityPolling in Docker containers running in Windows WSL2.
- Sets and exports the environment variables:
CHOKIDAR_USEPOLLING=1andCHOKIDAR_INTERVAL=1000 - Runs
vitestin watch mode inside Docker containers running in Windows WSL2, watching file changes and errors to files linked with*.test.tsfiles.
- Sets and exports the environment variables:
CHOKIDAR_USEPOLLING=1andCHOKIDAR_INTERVAL=1000 - Runs test scripts defined in
*.test.tsfiles in watch mode with coverage inside Docker containers running in Windows WSL2. - Spawns a local report-like website showing each test's real-time status and coverage using vitest-ui accessible at
http://localhost:51204/__vitest__/.
This project packages the CLI app into a Windows (.exe) Node Single Executable Application (SEA) file into "/app/build/sendemail.exe" using esbuild and postject.
Using Node
Run the Bash script using GitBash when working in a Windows OS.
chmod u+x ./app/scripts/build-sea-win.sh
./app/scripts/build-sea-win.shUsing Docker
This steps needs to have the Docker container up and running first ("docker compose up").
docker exec -it weaponsforge-sendemail-dev sh ./scripts/build-sea-win.sh- Refer to Available Scripts - C. CLI for CLI argument syntax. When running the executable directly, invoke it without npm (no
"--"needed), for example:sendemail text -s "You are Invited" -c "Birthday party" -r a@gmail.com,b@gmail.com
@weaponsforge
20250323