Before you begin, ensure you have:
-
Node.js (v22.14.0 or newer) installed on your system ([pnpm][1])
-
pnpm (v10.7.0 as declared) globally available. If not, install via:
npm install -g pnpm
or using the standalone install script from the pnpm docs ([pnpm][1]).
-
Clone the repo
git clone <your-repo-url> mail-service cd mail-service
-
Install dependencies
pnpm install
This will read your
package.jsonandpnpm-lock.yaml, creating a fast, content-addressable package store ([pnpm][2]).
All commands assume you’re in the project root:
| Script | What it does | How to run |
|---|---|---|
| start:smtp | Launches the SMTP server on port 1025 | pnpm run start:smtp |
| start:imap | Launches the IMAP server on port 143 | pnpm run start:imap |
| test:sender | Sends a test email via local SMTP | pnpm run test:sender |
You can also shorten
pnpm run start:smtptopnpm start:smtp—pnpm aliases script names as top-level commands when there’s no naming conflict ([pnpm][3]).
On Linux, binding to ports below 1024 (e.g. IMAP’s default port 143) is restricted to the root user or processes with the CAP_NET_BIND_SERVICE capability ([Stack Overflow][4], [Server Fault][5]). Otherwise, you’ll see:
Error: listen EACCES: permission denied 0.0.0.0:143
-
Run as root
sudo pnpm run start:imap
-
Grant CAP_NET_BIND_SERVICE to Node.js binary (allows non-root binding):
sudo setcap 'cap_net_bind_service=+ep' "$(which node)" pnpm run start:imap
This is minimally invasive—only grants the bind privilege ([Unix & Linux Stack Exchange][6]).
-
Use a non-privileged port (≥ 1025) for pure local testing by editing
src/imap-server.js:net.createServer(handler).listen(8143, …);
and adjust your client accordingly.
mail-service/
├─ node_modules/
├─ src/
│ ├─ email-store.js # Shared in-memory email array
│ ├─ smtp-server.js # SMTP server (port 1025)
│ ├─ imap-server.js # IMAP server (port 143)
│ └─ sender.js # Nodemailer test client
├─ package.json # Scripts & dependencies
└─ pnpm-lock.yaml # Exact dependency tree
{ "name": "mail-service", "version": "1.0.0", "main": "src/smtp-server.js", "scripts": { "start:smtp": "node src/smtp-server.js", "start:imap": "node src/imap-server.js", "test:sender": "node src/sender.js" }, "packageManager": "[email protected]", "dependencies": { "smtp-server": "^3.13.6", "imap-server": "^0.0.1", "mailparser": "^3.7.2", "nodemailer": "^7.0.0" } }