An open API service indexing awesome lists of open source software.

https://github.com/weaponsforge/send-email

NPM CLI and library for sending text and HTML emails using Gmail SMTP with Google OAuth2
https://github.com/weaponsforge/send-email

cli email gmail-oauth2 hacktoberfest nodejs nodejs-cli oauth2 send-email

Last synced: 11 days ago
JSON representation

NPM CLI and library for sending text and HTML emails using Gmail SMTP with Google OAuth2

Awesome Lists containing this project

README

          

## @weaponsforge/sendemail

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](#๏ธ-building-the-windows-executable-file) are available for download in the latest [Releases](https://github.com/weaponsforge/send-email/releases) download page.
>
> - **Docker image**

> A Docker image is available at https://hub.docker.com/r/weaponsforge/sendemail

### Table of Contents

- [Requirements](#-requirements)
- [Quickstart](#-quickstart)
- [Installation](#%EF%B8%8F-installation)
- [Usage](#-usage)
- [Alternate Usage](#alternate-usage)
- [Code Samples](#-code-samples)
- [Available Scripts](#-available-scripts)
- [Docker Scripts](#-docker-scripts)
- [Building the Windows Executable File](#๏ธ-building-the-windows-executable-file)
- [Usage with GitHub Actions](#-usage-with-github-actions)

## ๐Ÿ“‹ Requirements

๐Ÿ‘‰ Click to expand the list of requirements

1. Windows 11/Linux OS
2. NodeJS LTS v24.11.0 or higher
```text
Recommended:
node: 24.11.0
npm: 11.6.1
```
3. Gmail Account
- Google Cloud Platform project configured with [OAuth2](https://developers.google.com/workspace/guides/configure-oauth-consent) settings and [credentials](https://developers.google.com/workspace/guides/manage-credentials)
- Read on the Google [Gmail](https://developers.google.com/gmail/api/guides), [SMTP and OAuth2 Setup](https://github.com/weaponsforge/email-sender?tab=readme-ov-file#using-the-oauth-20-playground) sections for more information

### Core Libraries/Frameworks

(Installed via npm)

1. [googleapis](https://www.npmjs.com/package/googleapis) `v171.4.0` - Manages Gmail token access
2. [nodemailer](https://www.npmjs.com/package/nodemailer) `v8.0.1` - Sends emails using various transport options
3. [typescript](https://www.npmjs.com/package/typescript) `v5.9.3` - Compile-time error checker
4. [tsx](https://www.npmjs.com/package/tsx) `v4.21.0` - Runs TS files in development mode
5. [vitest](https://www.npmjs.com/package/vitest) `v4.0.18` - Runs tests
6. [commander](https://www.npmjs.com/package/commander) `v14.0.3` - CLI library
7. [sanitize-html](https://www.npmjs.com/package/sanitize-html) `v2.17.1` - Sanitizes WYSIWYG HTML input
8. [zod](https://www.npmjs.com/package/zod) `v3.24.2` - Run-time input validation
9. [ejs](https://www.npmjs.com/package/ejs) `v4.0.1` - Composes HTML with dynamic text content


## Contributing

We welcome contributions! Please see [CONTRIBUTING.md](/CONTRIBUTING.md) and the [CODING STYLE](/docs/CODING_STYLE.md) for guidelines.

## ๐Ÿ†• Quickstart

1. Create a `.env` file in the `/app` directory, replacing the contents of the `.env.example` file with actual values.
- See **Installation # 4** for more information about these environment variables.
2. Install dependencies.
```bash
cd app
npm install
```
3. Transpile to JavaScript.
```bash
npm run transpile
```
4. Send a **text email** using the CLI, eg. using Bash:
```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:dev` to work on development mode without needing to run `"npm run transpile"`

5. Send a **styled HTML email** using the CLI, eg. using Bash:
```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"`

6. Send **WYSIWYG** HTML content using the CLI, eg. using Bash:

_(Adjust `@/utils/config/sanitizeHtml.ts` to allow more styles.)_

```bash
npm run sendemail -- html \
-s "WYSIWYG Email" \
-w "

Hello, World

" \
-r "tester@gmail.com"
```

> ๐Ÿ’ก **TIP:** Development mode via `"sendemail:dev"` skips transpilation

## ๐Ÿ› ๏ธ Installation

1. Clone the repository.

`git clone https://github.com/weaponsforge/send-email.git`

2. Install dependencies.

`npm install`

3. Configure **OAuth2**. Get a refresh token from the Google [OAuth 2 Playground](https://developers.google.com/oauthplayground).
- Read on [Using the OAuth 2.0 Playground](https://github.com/weaponsforge/email-sender?tab=readme-ov-file#using-the-oauth-20-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)_

4. Set up the environment variables. Create a `.env` file inside the **/app** directory with reference to the `.env.example` file.


๐Ÿ‘‰ 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/oauthplayground` by default. |
| GOOGLE_REFRESH_TOKEN | The initial (or any) refresh token obtained from the [OAuthPlayground](https://developers.google.com/oauthplayground).


  • Read on [Using the OAuth 2.0 Playground](https://github.com/weaponsforge/email-sender?tab=readme-ov-file#using-the-oauth-20-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)_

|

## ๐Ÿš€ Usage

### Using Node

1. Run a non-test TypeScript file inside the **/app/src** directory from the project's _**"root directory"**_. For example:

```bash
cd app
npx tsx src/utils/sample.ts
```

2. Run compiled JavaScript code from the TypeScript files. For example:

```bash
cd app
npm run transpile
node dist/utils/sample.js
```

3. See the [Available Scripts](#-available-scripts) section for more information.

## โšกAlternate Usage

### Using Docker

- **Build the image** (Run only once)
```bash
docker compose build --no-cache
```

- **Run the container** (Run only once)
```bash
docker compose up
```

- **Run an NPM script using Docker compose**

Ensure the Docker container is running (see **Run the container**)
```bash
docker exec -it weaponsforge-sendemail-dev
```

- **Run an NPM script using only Docker**

Ensure the Docker container is running (see **Run the container**)
```bash
docker run -it -v ${pwd}/app:/opt/app -v /opt/app/node_modules --rm weaponsforge/sendemail:dev
```

- **Run a non-test TS file using TypeScript Execute (tsx)**

(requires **Run an NPM script using Docker compose**)
```bash
docker exec -it weaponsforge-sendemail-dev npx tsx /opt/app/src/.ts
```

- See the [Available Scripts](#-available-scripts) and [Docker Scripts](#-docker-scripts) sections for more information.

## ๐Ÿงพ Code Samples

### Send a Text-format Email

**app/src/demo/sendEmail.ts**
```typescript
import { send } from '@/lib/index.js'

const main = async () => {
await send({
recipient: 'tester@gmail.com',
subject: 'Test Message',
content: 'How are you?'
})
}

main()
```

### Send an HTML-format Email

**app/src/demo/sendHtml.ts**
```typescript
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()
```


## ๐Ÿ“œ Available Scripts

These scripts, compatible with running in Node and Docker, run various TypeScript scripts and tests.

๐Ÿ‘‰ Click to expand the list of available scripts

### A. Running the Codes โš™๏ธโžก๏ธ

### `npm run dev`

Runs `vitest` in watch mode, watching file changes and errors to files linked with `*.test.ts` files.

### `npm run watch`

Watches file changes in `.ts` files using the `tsc --watch` option.

### `npm run transpile`

Builds JavaScript, `.d.ts` declaration files, and map files from the TypeScript source files in the `/src` directory.

### `npm run transpile:noemit`

Runs type-checking without generating the JavaScript or declaration files from the TypeScript files in the `/src` and `__tests__` directories.

### B. Testing ๐Ÿšฆโœ…

### `npm run lint`
Lints TypeScript source codes.

### `npm run lint:fix`
Fixes lint errors in TypeScript files.

### `npm test`
- Runs test scripts defined in `*.test.ts` files with coverage.
- Generates a vitest test report into the **/html** directory.
- Run `npm run report:view` to preview the generated report.

### `npm run test:ui`

- Runs test scripts defined in `*.test.ts` files 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 dev`** script that watches for changes in the `*.test.ts` files but displays the result logs and coverage details in the local website rather than the command line.

### `npm run report:view`

> **NOTE:** This script requires running `npm test` first 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

### `npm run copy:files`

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.

### `npm run info`

Logs the installed Node.js and npm version, environment platform, architecture and V8 version.

### C. CLI ๐Ÿ’ป

### `npm start`

Shorthand for `"npm run sendemail"`

### `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 `:dev` after the NPM script: `"npm run sendemail:dev"`

#### CLI Usage

- To view the list of available commands: `npm run sendemail help`
```text
Usage: 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)
```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.
```bash
# Usage options for the send "text" email command
npm run sendemail help text
```

```text
Usage: sendemail text [options]

Send raw text email to one or multiple recipient/s

Options:
-s, --subject email subject or title enclosed in double-quotes
-c, --content email text content enclosed in double-quotes
-e, --env [path] path to .env file (optional)
-r, --recipients comma-separated list of email addresses
-h, --help display help for command
```

- View available options for the **sendemail html [options]** command.
```bash
# Usage options for the send "html" email command
npm run sendemail help html
```

```text
Usage: sendemail html [options]

Send paragraphs of text or WYSIWYG content as styled
HTML email to one or multiple recipient/s.

Options:
-s, --subject email subject or title enclosed in double-quotes
-r, --recipients comma-separated list of email addresses
-c, --content 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
```

### `npm run sendemail:dev`

- 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 `:dev` in the script eg., `npm run sendemail:dev`


## ๐Ÿ“ฆ Docker Scripts

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

### Docker run command

Run the Docker containers first using options A or B.

**A. Using Docker compose**

```bash
docker compose build
docker compose up
```

Use the template:

```bash
docker exec -it weaponsforge-sendemail-dev
```

**B. Using Only Docker (PowerShell)**

`docker run -it -v ${pwd}/app:/opt/app -v /opt/app/node_modules --rm weaponsforge/sendemail:dev `

### Scripts

### `npm run docker:debug`

1. Runs the `"/src/utils/sample/sample.ts"` script in containers with debugging enabled in VSCode by default.
2. 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.
3. Map port **`9229`** to 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`
4. Launch the VSCode debugger using the following configuration:
```json
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "attach",
"name": "Attach to Docker",
"address": "localhost",
"port": 9229,
"restart": true,
"skipFiles": ["/**"],
"localRoot": "${workspaceFolder}/app",
"remoteRoot": "/opt/app"
}
]
}
```

### `npm run docker:test:ui`

- Docker command counterpart of theย `npm run test:ui`ย script, compatible with containers running inย **Linux**ย OS.
- Runs test scripts defined in `*.test.ts` files 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__/`.

### `npm run docker:report:view`

> **NOTE:** This script requires running `npm test` first to generate a test report into the **/html** directory

- Docker command counterpart of the `npm run report:view` script.
- 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

### `npm run docker:watch:win`

Watches file changes in `.ts` files using the `tsc --watch` option with `dynamicPriorityPolling` in Docker containers running in Windows WSL2.

### `npm run docker:dev:win`

- Sets and exports the environment variables: `CHOKIDAR_USEPOLLING=1` and `CHOKIDAR_INTERVAL=1000`
- Runs `vitest` in watch mode inside Docker containers running in Windows WSL2, watching file changes and errors to files linked with `*.test.ts` files.

### `npm run docker:test:ui:win`

- Sets and exports the environment variables: `CHOKIDAR_USEPOLLING=1` and `CHOKIDAR_INTERVAL=1000`
- Runs test scripts defined in `*.test.ts` files 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__/`.


## ๐Ÿ—๏ธ Building the Windows Executable File

This project packages the CLI app into a **Windows (.exe)** Node Single Executable Application [(SEA)](https://nodejs.org/api/single-executable-applications.html) file into `"/app/build/sendemail.exe"` using esbuild and postject.

**Using Node**

Run the Bash script using GitBash when working in a Windows OS.

```bash
chmod u+x ./app/scripts/build-sea-win.sh
./app/scripts/build-sea-win.sh
```

**Using Docker**

These steps need to have the Docker container up and running first (`"docker compose up"`).

```bash
docker exec -it weaponsforge-sendemail-dev sh ./scripts/build-sea-win.sh
```

### Using the Executable File

- Refer to [Available Scripts - C. CLI](#-available-scripts) for CLI argument syntax. When running the executable directly, invoke it without npm (no `"--"` needed), for example:
```bash
sendemail text -s "You are Invited" -c "Birthday party" -r a@gmail.com,b@gmail.com
```


## ๐Ÿš€ Usage with GitHub Actions

### Deployment to Docker Hub

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 Secrets and Variables

#### GitHub Secrets

| GitHub Secret Name | Description |
| --- | --- |
| DOCKERHUB_USERNAME | Docker Hub username |
| DOCKERHUB_TOKEN | Deploy token for the Docker Hub account |

#### GitHub Variables

| GitHub Variable Name | Description |
| --- | --- |
| DOCKERHUB_USERNAME | Docker Hub username |


## References

- Gmail API [[1]](https://developers.google.com/gmail/api/guides) [[2]](https://github.com/googleapis/google-api-nodejs-client)
- Gmail Quickstart [[3]](https://developers.google.com/gmail/api/quickstart/js)
- AMP for Gmail [[4]](https://developers.google.com/gmail/ampemail)
- Google Workspace Guide [[5]](https://developers.google.com/workspace/guides/get-started)

@weaponsforge

20250323