NPM library and CLI for sending text and HTML emails using Gmail SMTP with Google OAuth2.
Tip
-
Run via npx (no installation required)
- Requirements: NodeJS LTS v24.11.0 or later
- Run
npx @weaponsforge/sendemail --help
-
Node.js package
A Node.js package is available at https://www.npmjs.com/package/@weaponsforge/sendemail -
Pre-compiled Windows binaries
Pre-compiled Windows binaries are available for download in the latest Releases download page. -
Docker image
A Docker image is available at https://hub.docker.com/r/weaponsforge/sendemail
- Requirements
- Quickstart
- Installation
- Usage
- Alternate Usage
- Code Samples
- Available Scripts
- Docker Scripts
- Building the Windows Executable File
- Usage with GitHub Actions
👉 Click to expand the list of requirements
- Windows 11/Linux OS
- NodeJS LTS v24.11.0 or higher
Recommended: node: 24.11.0 npm: 11.6.1 - Gmail Account
- 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
v171.4.0- Manages Gmail token access - nodemailer
v8.0.1- Sends emails using various transport options - typescript
v5.9.3- Compile-time error checker - tsx
v4.21.0- Runs TS files in development mode - vitest
v4.0.18- Runs tests - commander
v14.0.3- CLI library - sanitize-html
v2.17.1- Sanitizes WYSIWYG HTML input - zod
v3.24.2- Run-time input validation - ejs
v4.0.1- Composes HTML with dynamic text content
We welcome contributions! Please see CONTRIBUTING.md and the CODING STYLE for guidelines.
-
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.
cd app npm install -
Transpile to JavaScript.
npm run transpile
-
Send a text email using the CLI, eg. using Bash:
npm run sendemail -- text \ -s "You are Invited" \ -c "Birthday party in December" \ -r a@gmail.com,b@gmail.com,c@gmail.com
💡 TIP: Use
sendemail: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 sendemail -- 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
"sendemail:dev" -
Send WYSIWYG HTML content using the CLI, eg. using Bash:
(Adjust@/utils/config/sanitizeHtml.tsto allow more styles.)npm run sendemail -- 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
"sendemail: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.👉 Click to view the environment variable definitions
Variable Name Description GOOGLE_USER_EMAIL Your Google email that you've configured for Gmail SMTP and Google OAuth2. GOOGLE_CLIENT_ID Google OAuth2 client ID linked with your Google Cloud Platform project. GOOGLE_CLIENT_SECRET Google OAuth2 client secret associated with the GOOGLE_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 the 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 tsx 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 TypeScript Execute (tsx)
(requires Run an NPM script using Docker compose)docker exec -it weaponsforge-sendemail-dev npx tsx /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 { buildHtml, send } 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.
Logs the installed Node.js and npm version, environment platform, architecture and V8 version.
Shorthand for "npm run sendemail"
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 sendemail:dev"
-
To view the list of available commands:
npm run sendemail helpUsage: sendemail [options] [command] CLI for sending text and HTML emails 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 sendemail -- 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 sendemail text [options] command.
# Usage options for the send "text" email command npm run sendemail help text
Usage: sendemail 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 sendemail html [options] command.
# Usage options for the send "html" email command npm run sendemail help html
Usage: sendemail 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 text/paragraphs enclosed in double-quotes -w, --wysiwyg [html] optional HTML tags that form a WYSIWYG content enclosed in double-quotes, using inline CSS styles -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 sendemail"script for more information. They share similar usage.-
💡 NOTE: Append
:devin the script eg.,npm run sendemail: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
These steps need 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
This repository deploys the latest development Docker image weaponsforge/sendemail to Docker Hub on the creation of new Tags/Releases from the main branch with GitHub Actions. Supply the following GitHub Secrets and Variable to enable deployment to Docker Hub. It requires a Docker Hub account.
The Docker Hub image is available at:
https://hub.docker.com/r/weaponsforge/sendemail
| GitHub Secret Name | Description |
|---|---|
| DOCKERHUB_USERNAME | Docker Hub username |
| DOCKERHUB_TOKEN | Deploy token for the Docker Hub account |
| GitHub Variable Name | Description |
|---|---|
| DOCKERHUB_USERNAME | Docker Hub username |
@weaponsforge
20250323