GitHub avatar

Fox's Blog

← Back to projects

Email AutoReply

Stars Forks Issues Last Commit

Typing SVG

Table of Contents


✨ About This Template

Email AutoReply is a modern, AI-powered email autoresponder for IMAP mailboxes. It is designed as a template you can:

  • Fork on GitHub and use as-is
  • Clone and adapt for your own needs
  • Copy files or integrate logic into an existing Node.js project

[!TIP] You do not have to fork this repo to use it! You can clone, download, or copy-paste the code into your own project structure.

This template is suitable for:

  • Personal automation (Gmail, Outlook, etc.)
  • Teams and shared mailboxes
  • CI/CD workflows (GitHub Actions)
  • Self-hosted or cloud deployments

Beginner Tutorial

This section is for users new to Node.js, email automation, or GitHub Actions. Follow these steps for a smooth first experience.

1. Install Node.js and pnpm

  • Download and install Node.js LTS (choose the LTS version).
  • Install pnpm (recommended for this project):
npm install -g pnpm

2. Clone the repository

git clone https://github.com/your-username/email-autoreply.git
cd email-autoreply

3. Install dependencies

pnpm install

4. Configure your environment

  • Copy the example environment file:

    cp .env.example .env
    
  • Open .env in a text editor and fill in your email credentials and API keys.

Gmail Setup Tips

[!TIP] For Gmail, you need to:

  • Enable IMAP in your Gmail settings (see how)
  • Create an App Password if you have 2FA enabled
  • Use your Gmail address for MAILUSER and the App Password for MAILPASS

5. Create your accounts.json

  • Copy data/accounts.example.json to data/accounts.json:

    cp data/accounts.example.json data/accounts.json
    
  • Edit data/accounts.json to set your own names, emails, and prompts.

6. Run the app

pnpm run start

If everything is set up correctly, the app will connect to your mailbox and start processing emails.

7. Common beginner issues


⚠️ Important: Conversation Memory in GitHub Actions

[!WARNING] When running in GitHub Actions (CI) mode, conversation memory is not persistent between runs. This means the app cannot remember previous exchanges with the same sender across different runs, as the memory is not stored in a shared or durable location. For best results and true conversation context, run the app in a persistent environment (e.g., a server or VM) where the data/ folder is preserved.

Problem Solution
Error: Login failed Double-check your email and password. For Gmail, use an App Password.
IMAP not enabled Enable IMAP in your email provider's settings.
Cannot find module Run pnpm install again to ensure all dependencies are installed.
accounts.json not found Make sure you copied and edited data/accounts.json.

[!NOTE] If you get stuck, check the Troubleshooting section below or open an issue on GitHub.


How it works

Incoming email
    │
    ▼
[IMAP fetcher] ──► [AI Reply Generator] ──► [SMTP Sender]
    │
    └─► [Conversation Memory]

In action mode (for CI/CD):

┌─────────────┐
│  lastId     │
└─────┬───────┘
      │
      ▼
[Batch fetch new mails]
      │
      ▼
[Process & reply]
      │
      ▼
[Update lastId]

Features

  • Monitors a mailbox (All Mail) across localized IMAP servers
  • Extracts sender, recipients, and message content (text/html)
  • Per-account AI prompts stored in data/accounts.json
  • Conversation memory for context-aware replies
  • Optional manual-forward trigger for human review
  • Pluggable SMTP transport (Nodemailer)
  • CI/CD ready: GitHub Actions workflow for batch processing
  • Secure: All secrets via GitHub Secrets or .env (never committed)

Prerequisites

  • Node.js (20+ recommended)
  • pnpm or npm
  • IMAP/SMTP credentials (e.g., Gmail, Outlook, etc.)
  • Groq API key (for AI replies)
  • (For CI) GitHub account and repository

[!NOTE] For Gmail, you may need an App Password and to enable IMAP in your account settings.

How to create a Google App Password

If you use Gmail and have 2-Step Verification enabled, you must create an App Password for this app:

  1. Go to your Google Account Security page.
  2. Under "Signing in to Google", select App Passwords.
  3. Sign in again if prompted.
  4. Under "Select app", choose Other (Custom name) and enter a name (e.g., EmailAutoReply).
  5. Click Generate.
  6. Copy the 16-character password and use it as MAILPASS in your .env file.

[!WARNING] Never share your App Password. Treat it like your real password.

How to get a Groq API Key

  1. Go to the Groq Developer Portal.
  2. Sign in or create a free account.
  3. Click Create API Key and give it a name (e.g., email-autoreply).
  4. Copy the generated key and paste it as GROQ_API_KEY in your .env file.

[!WARNING] Keep your Groq API key secret. Never share it or commit it to a public repository.


Quick Start

# Install dependencies
pnpm install

# Build the project
pnpm build

# Run in development (reloads on change)
pnpm run dev

# Run the compiled app
pnpm run start

# Run in batch mode (for CI or one-shot processing)
pnpm run start -- --action

Step 1 — Configure your environment

Copy the example environment file and set your credentials:

cp .env.example .env

Edit .env with your IMAP/SMTP and AI provider credentials:

# Main configuration (.env)
# By default, all values are set for Gmail.

# --- Gmail (default IMAP/SMTP) ---
[email protected]
MAILPASS=your_app_password

# --- Groq API (for AI) ---
GROQ_API_KEY=sk-your-groq-key

# --- SMTP (Nodemailer) ---
NODEMAILER_HOST=smtp.gmail.com
NODEMAILER_PORT=587
NODEMAILER_SECURE=false

# --- IMAP ---
IMAP_HOST=imap.gmail.com
IMAP_PORT=993
IMAP_TLS=true

# --- Optional ---
[email protected]

[!WARNING] Never commit your .env file or secrets to the repository. Use GitHub Secrets for CI/CD.


Step 2 — Accounts configuration

Define per-account prompts in data/accounts.json. Each entry should contain:

  • name: display name for replies
  • email: string or regex (prefix with regex:)
  • prompt: system prompt for the AI

Example:

[
  {
    "name": "Support",
    "email": "[email protected]",
    "prompt": "You are the support team. Be helpful, concise and polite.\nAlways ask for the user's OS and version when relevant."
  },
  {
    "name": "Sales",
    "email": "regex:^sales@.*$",
    "prompt": "You handle sales inquiries. Answer in the customer's language, be professional, and propose a clear next step."
  }
]

[!TIP] Use data/accounts.example.json as a template. Never commit secrets.


Step 3 — Run locally or in CI

  • Development: pnpm run dev (auto-reloads)
  • Production: pnpm run start
  • Batch/CI mode: pnpm run start -- --action

In --action mode, the app does not open an IMAP listener. It fetches only new mails (UID > data/lastId), processes them, and updates data/lastId. On first run, it initializes lastId to the latest UID (no old mails processed).


GitHub Actions & Secrets

⚡ Precompiled runtime

The build workflow automatically tags the latest compiled output (dist + node_modules) with runtime. The cron workflow checks out this tag instead of rebuilding from scratch, cutting run time from about 20 s to 10 s. Tags don’t pollute the branch list and are overwritten on each build.

This template includes a ready-to-use GitHub Actions workflow (.github/workflows/cron.yml) for automated batch processing. State is stored in a lightweight lastid tag (not a branch), and the runtime code lives in a runtime tag, ensuring the branch list remains clean.

Workflow overview

The repository includes two actions: a standard build job and a cron processor. The build job not only lints and compiles the source, but also creates/updates a runtime tag containing the compiled output and node_modules so that the cron workflow can run in about 10 seconds instead of ~20.

  1. Checkout repository
  2. Setup Node.js & pnpm
  3. Restore lastId from the lastid tag
  4. Prepare accounts config from secret
  5. Install & build (the build job also publishes a runtime tag)
  6. Process new emails in action mode
  7. **Publish updated lastId as a lastid tag`

When you use this template or fork the repo, the build.yml workflow will automatically run on the first push to master (you can also trigger it manually via Actions → Build → Run workflow). That initial run generates the runtime snapshot (as a tag) with compiled code + dependencies; the cron job then consumes that tag, shaving roughly half the execution time.

[!NOTE] The workflow is idempotent: it never processes the same email twice. On first run, no old emails are processed.

Using GitHub Secrets

  • Go to Settings > Secrets and variables > Actions in your GitHub repo.
  • Add secrets: MAILUSER, MAILPASS, GROQ_API_KEY, IMAP_HOST, IMAP_PORT, IMAP_TLS, NODEMAILER_HOST, NODEMAILER_PORT, NODEMAILER_SECURE, MANUAL_REPLYER, etc.
  • For account config, add ACCOUNTS_JSON with the minified content of your data/accounts.json.
[{"name":"Support","email":"[email protected]","prompt":"You are the support team. Be helpful, concise and polite."}]

[!WARNING] Never commit secrets or .env files.


Folder layout

  • src/ — TypeScript source
  • data/accounts.json — per-account prompts (never committed)
  • .env — credentials and keys (never committed)

Troubleshooting

Symptom Likely cause Fix
IMAP access fails Wrong credentials or IMAP not enabled Check MAILUSER/MAILPASS and IMAP settings
No new mails processed lastId not initialized or no new mails Check data/lastId and mailbox
App crashes in CI Missing or invalid secrets Check GitHub Secrets and workflow logs
Mailbox selection fails Localized server or folder name App auto-discovers All Mail folder

[!NOTE] For more help, open an issue or PR.


Reference

How batch mode works
  1. Reads data/lastId (from file or tag)
  2. Fetches only mails with UID > lastId
  3. Processes and replies to each
  4. Updates data/lastId with the latest UID

This ensures no mail is processed twice, and the state is preserved across runs (even in CI/CD).

How to extend
  • Add new AI providers by extending src/services/AIService/ReplyService.ts
  • Add new mail providers by extending src/services/MailService/ImapService.ts
  • Customize prompts per account in data/accounts.json

Contributing

Contributions welcome! Open issues or PRs. Keep changes small and add tests where possible.


License

MIT