Gets rejected? We make it worse.
A mildly sadistic browser extension that watches your Gmail for rejection emails and automatically plays the "fahhhh" sound effect to rub salt in the wound.
Works on Chrome, Edge, Brave, Opera and Firefox.
- Automated Masochism: Instantly detects when you open an email containing typical rejection phrases (e.g., "unfortunately", "not moving forward", "other candidates").
- Custom Sound: Automatically blasts the soul-crushing "fahhhh" sound to ensure everyone in the room knows you failed. It plays every time you open a rejection mail, even one you have already read.
- Settings: Popup lets you arm/disarm the extension, set the volume, and see how many rejections you have survived so far.
- Smart Detection: Normalizes Gmail's curly quotes, dashes and line breaks, expands contractions, ignores quoted history, and only fires on a phrase that is specific enough to be a rejection.
Since this is strictly for personal suffering, it is not in any extension store.
-
Clone the repository:
git clone https://github.com/silky-x0/Rejected.exe.git cd Rejected.exe -
Install dependencies:
npm install
-
Build the extension (pick your browser):
npm run build # Chrome / Edge / Brave / Opera -> dist/ npm run build:firefox # Firefox -> dist-firefox/
-
Load it into your browser:
- Chrome / Edge / Brave / Opera: open
chrome://extensions, enable Developer mode, click "Load unpacked" and select thedist/folder. - Firefox: open
about:debugging#/runtime/this-firefox, click "Load Temporary Add-on…" and selectdist-firefox/manifest.json. Firefox treats host permissions as opt-in, so open the add-on's Permissions tab and allow access to mail.google.com - otherwise the content script never runs.
- Chrome / Edge / Brave / Opera: open
-
Pin it:
- Click the puzzle piece icon in your browser and pin Rejection Sound Alert.
- Click the extension icon to test the sound manually!
- Manifest V3: Built using modern extension standards.
- Two manifests, one codebase: Chrome runs the background script as a service worker (
background.service_worker), Firefox has no extension service workers and needs an event page (background.scripts). The build picks the right manifest for you, so the only difference between the two builds is that one line - plus the browser id that Firefox requires. - Reliable audio: Chrome plays the sound from a hidden offscreen document (
chrome.offscreen), so Chrome's autoplay policy cannot block it. Firefox has no offscreen API, so there the page plays it instead. If playback fails either way, you get a desktop notification instead of silence. - Thread-aware detection: The content script tracks which Gmail thread is on screen, reads every message in it, strips quoted history (so your own replies don't replay an old rejection) and fires once per opened mail.
- Browser-agnostic API: the code talks to
browserwhen it exists (Firefox) and tochromeotherwise (Chromium), always through promises. - Webpack pipeline: Bundles
src/content.ts,src/detection.ts,src/popup.ts,src/offscreen.tsandsrc/bg.tsalongside copied static assets frompublic/.
Rejected.exe/
├── manifest.json # Chrome / Chromium manifest (service worker)
├── manifest.firefox.json # Firefox manifest (background event page)
├── webpack.config.js # Build pipeline configuration
├── public/ # Static assets (MP3s, HTML, icons)
│ ├── popup.html # The UI of the extension popup
│ ├── offscreen.html # Hidden page that owns audio playback (Chrome only)
│ ├── fahhh.mp3 # The sound of failure (re-encoded for Chrome support)
│ └── icons/ # Extension icons (generated by scripts/make-icons.mjs)
├── scripts/
│ ├── make-icons.mjs # Regenerates the PNG icons
│ └── package.mjs # Bundles a build into <target>/rejection-alert.zip
└── src/ # TypeScript source files
├── api.ts # browser/chrome compatibility layer
├── content.ts # Gmail detection script
├── detection.ts # Rejection keyword list and text normalization
├── popup.ts # Popup settings and stats
├── offscreen.ts # Audio playback (Chrome only)
└── bg.ts # Background script (badge, stats, notifications)
| Command | What it does |
|---|---|
npm run build |
Production build for Chrome into dist/ |
npm run build:firefox |
Production build for Firefox into dist-firefox/ |
npm run dev |
Chrome development build with inline source maps |
npm run dev:firefox |
Firefox development build with inline source maps |
npm run watch |
Rebuilds the Chrome build on every change |
npm run typecheck |
Type-checks the TypeScript sources |
npm run icons |
Regenerates public/icons/*.png |
npm run package |
Builds and zips the Chrome build into dist/rejection-alert.zip |
npm run package:firefox |
Builds and zips the Firefox build into dist-firefox/rejection-alert.zip |
Want to add more rejection phrases to trigger the sound?
Open src/detection.ts and modify the keyword lists at the very top:
export const REJECTION_KEYWORDS: string[] = [
"we regret to inform",
"not moving forward",
"we have decided to move forward with other candidates",
/* Add your custom pain here */
];
// Phrases that also appear in non-rejection emails.
// Two of these have to match before the sound plays.
export const WEAK_KEYWORDS: string[] = [
"unfortunately, we",
"our decision",
/* ... */
];Phrases are matched after normalizing the email text: contractions are expanded
(we're → we are), curly apostrophes become straight ones, and line breaks
collapse into spaces. So we're unable to offer you and we are unable to offer you
are the same keyword.
Don't forget to run npm run build again and refresh the extension in your browser!
- No sound? Reload the extension and then refresh the Gmail tab - content scripts are only injected when the page loads. On Firefox, also check that the add-on has been granted access to
mail.google.com. - Still no sound? Open the Gmail tab's devtools console and look for
[Rejected.exe]logs. A💀 Rejection detectedline means the text matched but playback failed; the absence of any log means the phrases did not match. - Sound plays too often? Turn off "Armed" in the popup while you read the sad news in peace.
- Firefox says the manifest is invalid? You probably loaded the Chrome build. Use
dist-firefox/manifest.json.
Everything happens locally in your browser. The extension only requests access to
https://mail.google.com/*, no email content is sent anywhere, and no analytics
or tracking code is included.
ISC License. Enjoy the misery.