Email AutoReply
Table of Contents
- ✨ About This Template
- Beginner Tutorial
- How it works
- Features
- Prerequisites
- Quick Start
- Step 1 — Configure your environment
- Step 2 — Accounts configuration
- Step 3 — Run locally or in CI
- GitHub Actions & Secrets
- Folder layout
- Troubleshooting
- Reference
- Contributing
- License
✨ 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 .envOpen
.envin 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
MAILUSERand the App Password forMAILPASS
5. Create your accounts.json
Copy
data/accounts.example.jsontodata/accounts.json:cp data/accounts.example.json data/accounts.jsonEdit
data/accounts.jsonto 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:
- Go to your Google Account Security page.
- Under "Signing in to Google", select App Passwords.
- Sign in again if prompted.
- Under "Select app", choose Other (Custom name) and enter a name (e.g.,
EmailAutoReply).- Click Generate.
- Copy the 16-character password and use it as
MAILPASSin your.envfile.
[!WARNING] Never share your App Password. Treat it like your real password.
How to get a Groq API Key
- Go to the Groq Developer Portal.
- Sign in or create a free account.
- Click Create API Key and give it a name (e.g.,
email-autoreply). - Copy the generated key and paste it as
GROQ_API_KEYin your.envfile.
[!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
.envfile 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 repliesemail: string or regex (prefix withregex:)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.jsonas 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) withruntime. 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.
- Checkout repository
- Setup Node.js & pnpm
- Restore
lastIdfrom thelastidtag - Prepare accounts config from secret
- Install & build (the build job also publishes a
runtimetag) - Process new emails in action mode
- **Publish updated
lastIdas alastidtag`
When you use this template or fork the repo, the
build.ymlworkflow will automatically run on the first push tomaster(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 > Actionsin 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_JSONwith the minified content of yourdata/accounts.json.
[{"name":"Support","email":"[email protected]","prompt":"You are the support team. Be helpful, concise and polite."}]
[!WARNING] Never commit secrets or
.envfiles.
Folder layout
src/— TypeScript sourcedata/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
- Reads
data/lastId(from file or tag) - Fetches only mails with UID >
lastId - Processes and replies to each
- Updates
data/lastIdwith 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