Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 14 additions & 4 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,24 +30,34 @@ jobs:
- name: build mailpress.exe
run: node scripts/build.mjs

- name: zip installer bundle
# Single-file install bundle: unzip, double-click mailpress.exe, done.
shell: pwsh
run: |
Compress-Archive `
-Path dist/mailpress.exe,dist/print-files.ps1,dist/INSTALL.txt `
-DestinationPath dist/mailpress-installer.zip `
-Force

- name: upload artifact
# Includes the zip + the loose files so users can grab either form.
uses: actions/upload-artifact@v4
with:
name: mailpress-windows-x64
path: |
dist/mailpress-installer.zip
dist/mailpress.exe
dist/print-files.ps1
dist/config.example.json
dist/mailpress.ico
dist/INSTALL.txt

- name: release (on tag)
if: startsWith(github.ref, 'refs/tags/v')
uses: softprops/action-gh-release@v2
with:
files: |
dist/mailpress-installer.zip
dist/mailpress.exe
dist/print-files.ps1
dist/config.example.json
dist/mailpress.ico
dist/INSTALL.txt
draft: false
generate_release_notes: true
28 changes: 17 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,23 @@ wired Windows printer. Runs as a Scheduled Task on the office PC.

## Install (the easy way)

1. Download `mailpress.exe`, `print-files.ps1`, and `config.example.json`
from the latest [GitHub Release][releases] (or the artifact of a
`build on windows` workflow run). Put them all in the same folder,
e.g. `C:\mailpress\`.
2. Double-click `mailpress.exe`. The setup wizard runs the first time
there's no config: it lists installed printers, walks you through the
Google OAuth client creation, runs the consent flow in your browser,
picks a polling interval, does a test print, and installs itself as a
Scheduled Task.
3. Done. Send a test email to the office inbox and confirm it prints.
1. Download **`mailpress-installer.zip`** from the latest
[GitHub Release][releases] (or the artifact of a `build on windows`
workflow run if no release is tagged yet).
2. Unzip it on the office PC, e.g. into `C:\mailpress\`. You'll see:
```
mailpress.exe ← double-click this
print-files.ps1 ← PowerShell print helper (must sit next to the exe)
INSTALL.txt ← step-by-step install guide
```
3. Double-click `mailpress.exe`. The setup wizard runs on first launch:
- picks the printer
- walks through the one-time Google OAuth client creation
- runs the consent flow in your browser
- asks how often to check for new mail
- does a test print
- installs itself as a Scheduled Task
4. Done. Send a test email to the office inbox and confirm it prints.

[releases]: https://github.com/turetsky/mailpress/releases

Expand Down Expand Up @@ -129,7 +136,6 @@ lib/
wizard.mjs # first-run interactive setup
test.mjs # post-install test menu (--test)
print-files.ps1 # PowerShell helper: print one or more files
config.example.json # template — copy to config.local.json
assets/
icon.svg # source icon (envelope on slant + speed lines)
icon.ico # multi-size .ico embedded into mailpress.exe
Expand Down
Binary file removed assets/icon-preview-256.png
Binary file not shown.
23 changes: 0 additions & 23 deletions config.example.json

This file was deleted.

10 changes: 0 additions & 10 deletions lib/config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,6 @@ export function configPath() {
return join(installRoot(), "config.local.json");
}

export function examplePath() {
// The example ships beside the source files. When running from a SEA exe,
// it may not be on disk — callers should handle ENOENT.
return join(installRoot(), "config.example.json");
}

export function resolveInRoot(p) {
return resolve(installRoot(), p);
}
Expand Down Expand Up @@ -106,7 +100,3 @@ export function validateConfig(cfg) {
return errors;
}

export function isConfigured() {
const cfg = loadConfig();
return cfg && validateConfig(cfg).length === 0;
}
2 changes: 0 additions & 2 deletions lib/oauth.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -182,5 +182,3 @@ export async function runConsent({ clientId, clientSecret, gmailAddress, port =

return outer;
}

export { SCOPES };
84 changes: 70 additions & 14 deletions scripts/build.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -153,19 +153,74 @@ async function embedIcon() {
}

function copyAssets() {
const assets = ["print-files.ps1", "config.example.json"];
for (const a of assets) {
const src = join(ROOT, a);
if (existsSync(src)) {
copyFileSync(src, join(DIST, a));
} else {
console.warn(`asset missing, skipping: ${a}`);
}
}
// The icon is embedded in the exe; also drop a copy beside it for users
// who want a desktop shortcut with a matching icon.
const ico = join(ROOT, "assets", "icon.ico");
if (existsSync(ico)) copyFileSync(ico, join(DIST, "mailpress.ico"));
// Only files mailpress.exe actually loads at runtime ship next to it.
// print-files.ps1 is invoked by lib/printer.mjs for each print job.
// Icon is already embedded in the exe; config is created by the wizard.
const src = join(ROOT, "print-files.ps1");
if (existsSync(src)) copyFileSync(src, join(DIST, "print-files.ps1"));
else console.warn(`print-files.ps1 missing — printing will fail at runtime`);
}

// Drop a plaintext install guide into the bundle so anyone who unzips it
// has the install steps + command list on paper, without needing internet.
function writeInstallTxt() {
const content = `mailpress - Gmail-to-printer relay
===================================

WHAT'S IN THIS FOLDER

mailpress.exe double-click this to install
print-files.ps1 PowerShell print helper (must stay next to the exe)
INSTALL.txt this file

After the wizard runs, you'll also see these auto-generated files
appear in the same folder:

config.local.json your config (gitignored, contains client secret)
.local-token.json your OAuth refresh token (gitignored)
mailpress.log poll-loop activity
mailpress-setup.log every prompt + response from the wizard


INSTALL (Windows, ~5 minutes including the Google OAuth client step)

1. Copy this entire folder somewhere stable on the office PC.
Recommended: C:\\mailpress\\

2. Double-click mailpress.exe.
The first run launches the setup wizard. The wizard walks you
through:
- picking the printer
- creating a Google Cloud OAuth client (one-time, in your browser)
- signing in as the office Gmail account
- picking how often to check for new mail
- a test print
- installing itself as a Windows Scheduled Task

3. Done. mailpress now polls the office inbox and prints every new
email body + attachments.

The one part not automated: creating the OAuth client in Google Cloud.
Google requires a human in a browser for that. The wizard prints the
exact URLs and what to paste back.


USEFUL COMMANDS (run from a console in this folder)

mailpress poll forever (or run wizard if not configured)
mailpress --test switch printer, test print any file, change
polling interval - safe with task running
mailpress --doctor run health checks and tell you what is broken
mailpress --consent re-do the OAuth consent if the token dies
mailpress --setup re-run the setup wizard
mailpress --uninstall remove the scheduled task
mailpress --help full command list

If anything goes wrong, run "mailpress --doctor" first - it identifies
which subsystem (config, token, Gmail API, printer, scheduled task)
broke and what to do about each.
`;
writeFileSync(join(DIST, "INSTALL.txt"), content);
}

function smokeTest() {
Expand All @@ -189,9 +244,10 @@ async function main() {
inject();
await embedIcon();
copyAssets();
writeInstallTxt();
smokeTest();
console.log(`\nDone. Artifacts in ${DIST}:`);
for (const f of [EXE_NAME, "print-files.ps1", "config.example.json", "mailpress.ico"]) {
for (const f of [EXE_NAME, "print-files.ps1", "INSTALL.txt"]) {
if (existsSync(join(DIST, f))) console.log(` ${f}`);
}
}
Expand Down
Loading