# Send to E-Reader Convert web articles to EPUB and email them straight to your e-reader. Works with any device that accepts emailed files — Kindle, PocketBook, or anything else with a similar service. Built with Express 5 + TypeScript. Hosted at [read.atanasov.fi](https://read.atanasov.fi). ## How it works Two ways to send something to your e-reader: **URL → EPUB** 1. You paste an article URL and your e-reader's email address. 2. The server fetches the page, runs Mozilla Readability over it to strip ads/chrome, builds an EPUB, and emails it to the address you gave. 3. The EPUB is deleted from the server immediately after sending. **Upload a file** 1. Drag (or pick) a file — EPUB, PDF, MOBI, anything your device accepts. 2. The server attaches it to an email and sends it to your e-reader as-is, no conversion. 3. The file is deleted from the server immediately after sending. Max size: 25 MB. ## Supported devices Any device that accepts files via email works — the app doesn't restrict by domain. | Device | Email pattern | |---|---| | Amazon Kindle | `*@kindle.com` | | PocketBook | `*@pbsync.com` | | Anything else | whatever address your device gives you | You'll need to add the **sender** address (the Gmail account this app sends from) to your device's approved-senders list — that's a one-time per-device setup. ## Prerequisites - Node.js 20 or newer - An SMTP-capable email provider. Defaults are set up for [Resend](https://resend.com) — sign up (no waitlist), verify your domain, grab an API key. ## Local development ```bash git clone cd send_to_kindle npm install cp .env.example .env # then fill in SMTP_PASSWORD (Resend API key) and MAIL_FROM npm run dev ``` Server listens on `http://localhost:3000` (override with `PORT`). ## Production build ```bash npm run build npm run start ``` ## Environment variables | Variable | Required | Default | Notes | |---|---|---|---| | `SMTP_HOST` | no | `smtp.resend.com` | Any SMTP server works | | `SMTP_PORT` | no | `587` | `587` = STARTTLS (preferred — port 465 is blocked by most VPS providers) | | `SMTP_USER` | yes | — | For Resend, literally the string `resend` | | `SMTP_PASSWORD` | yes | — | For Resend, your API key (`re_…`) | | `MAIL_FROM` | yes | — | Sender address, e.g. `read@atanasov.fi`. Must be from a verified domain on your provider. | | `PORT` | no | `3000` | Listen port | ## Resend setup (quick) 1. Sign up at [resend.com](https://resend.com). 2. Add your domain (e.g. `atanasov.fi`) and add the SPF/DKIM/return-path DNS records they generate. Verification usually completes in a few minutes. 3. Create an API key. 4. In `.env`: ``` SMTP_USER=resend SMTP_PASSWORD=re_xxxxxxxxxxxxxxxxxx MAIL_FROM=send@read.atanasov.fi ``` For a different provider, just point `SMTP_HOST` / `SMTP_PORT` / `SMTP_USER` / `SMTP_PASSWORD` at it — any standard SMTP service works. ## API ### `POST /send-article` Body (JSON): ```json { "url": "https://example.com/article", "readerEmail": "your-device@kindle.com" } ``` Response on success: ```json { "success": true, "message": "Article sent to your e-reader", "title": "Article Title" } ``` ### `POST /send-file` Body (multipart/form-data): - `file` — the binary file (max 25 MB) - `readerEmail` — destination address Response on success: ```json { "success": true, "message": "File sent to your e-reader", "title": "original-filename.epub" } ``` ### Rate limit Both endpoints share a limit of **20 sends per IP per hour**. ## Limitations - Articles must be publicly accessible — no paywalled or login-required pages. - Server-side fetch means JS-heavy SPAs may extract poorly (the page must render meaningful HTML without JavaScript). - Some sites block non-browser user-agents; the app sends a Chrome UA but can still be refused. ## Stack - [Express 5](https://expressjs.com/) — HTTP server - [@mozilla/readability](https://github.com/mozilla/readability) — article extraction - [jsdom](https://github.com/jsdom/jsdom) — DOM for Readability - [@lesjoursfr/html-to-epub](https://github.com/lesjoursfr/html-to-epub) — EPUB generation - [nodemailer](https://nodemailer.com/) — SMTP client - [multer](https://github.com/expressjs/multer) — multipart/form-data upload parsing - [express-rate-limit](https://github.com/express-rate-limit/express-rate-limit) — per-IP rate limiting ## License GPL-3.0-only. See [LICENSE](LICENSE).