Skip to content

fix: replace direct mailto with validated in-app outreach flow#4342

Open
mallya-m wants to merge 2 commits into
anurag3407:mainfrom
mallya-m:fix/jobalerts-mailto-validation
Open

fix: replace direct mailto with validated in-app outreach flow#4342
mallya-m wants to merge 2 commits into
anurag3407:mainfrom
mallya-m:fix/jobalerts-mailto-validation

Conversation

@mallya-m

@mallya-m mallya-m commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

User description

Description

Fixes #4254

What changed

  • Replaced the direct mailto: action in JobAlerts.jsx with the existing in-app OutreachPanel flow, keeping users inside the application.
  • Added a fallback "Email recruiter directly" link that is only shown when the recruiter email is valid.
  • Added a confirmation modal before opening the user's mail client.
  • Added frontend/src/utils/email.js with a reusable isValidEmail() helper (regex validation + 254-character length limit).
  • Validated the recruiter email before rendering the fallback link and again before constructing the mailto: URL.
  • Encoded the mail subject with encodeURIComponent to prevent parameter injection.
  • Removed one extra closing brace in Enhance.jsx.

Type of Change

  • Bug fix
  • New feature
  • Documentation update
  • Performance improvement
  • Other (describe)

Related Issue

Fixes #4254

Testing

  • Unit tests pass (no unit tests added for this change)
  • Tested Locally
  • New tests added

Checklist

  • Code follows project style guidelines
  • Self-reviewed my code
  • Added comments where necessary
  • Updated documentation
  • No new warnings generated (except the pre-existing unused motion warning on main)

CodeAnt-AI Description

Keep job outreach inside the app and block invalid email links

What Changed

  • Job alert search results now open the in-app outreach panel instead of sending users straight to their mail app.
  • A recruiter email link still appears as a fallback, but only when the email address looks valid.
  • Opening the mail client now requires confirmation, and the email subject is safely filled in.
  • Invalid recruiter emails no longer trigger a broken mail link, and users see an error instead.

Impact

✅ Fewer broken email links
✅ Safer recruiter outreach
✅ Less accidental mail app launches

💡 Usage Guide

Checking Your Pull Request

Every time you make a pull request, our system automatically looks through it. We check for security issues, mistakes in how you're setting up your infrastructure, and common code problems. We do this to make sure your changes are solid and won't cause any trouble later.

Talking to CodeAnt AI

Got a question or need a hand with something in your pull request? You can easily get in touch with CodeAnt AI right here. Just type the following in a comment on your pull request, and replace "Your question here" with whatever you want to ask:

@codeant-ai ask: Your question here

This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code.

Example

@codeant-ai ask: Can you suggest a safer alternative to storing this secret?

Preserve Org Learnings with CodeAnt

You can record team preferences so CodeAnt AI applies them in future reviews. Reply directly to the specific CodeAnt AI suggestion (in the same thread) and replace "Your feedback here" with your input:

@codeant-ai: Your feedback here

This helps CodeAnt AI learn and adapt to your team's coding style and standards.

Example

@codeant-ai: Do not flag unused imports.

Retrigger review

Ask CodeAnt AI to review the PR again, by typing:

@codeant-ai: review

Check Your Repository Health

To analyze the health of your code repository, visit our dashboard at https://app.codeant.ai. This tool helps you identify potential issues and areas for improvement in your codebase, ensuring your repository maintains high standards of code health.

Summary by CodeRabbit

  • New Features
    • Enhanced job-alert email outreach with an in-app confirmation overlay and a subject preset, before opening your mail client.
    • Added an option to email the recruiter directly that appears only when the recruiter email is valid.
  • Bug Fixes
    • Fixed the enhancement screen’s control flow so actions continue correctly after AI enhancement.
    • Added stricter recruiter email validation to prevent using invalid email addresses.

@codeant-ai

codeant-ai Bot commented Jun 26, 2026

Copy link
Copy Markdown

CodeAnt AI is reviewing your PR.

@vercel

vercel Bot commented Jun 26, 2026

Copy link
Copy Markdown

@mallya-m is attempting to deploy a commit to the Anurag Mishra's projects Team on Vercel.

A member of the Team first needs to authorize it.

@codeant-ai

codeant-ai Bot commented Jun 26, 2026

Copy link
Copy Markdown

Thanks for using CodeAnt! 🎉

We're free for open-source projects. if you're enjoying it, help us grow by sharing.

Share on X ·
Reddit ·
LinkedIn

@coderabbitai

coderabbitai Bot commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 022b9c04-d439-40cf-9546-382803eca06c

📥 Commits

Reviewing files that changed from the base of the PR and between 27622c1 and 2958592.

📒 Files selected for processing (2)
  • frontend/src/pages/JobAlerts.jsx
  • frontend/src/utils/email.js
🚧 Files skipped from review as they are similar to previous changes (1)
  • frontend/src/utils/email.js

📝 Walkthrough

Walkthrough

JobAlerts now validates recruiter emails before offering a mail client fallback, and shows a confirmation overlay before opening a mailto: link. Enhance.jsx also fixes a brace scope issue so later handlers stay inside the component.

Changes

JobAlerts outreach flow

Layer / File(s) Summary
Validation and wiring
frontend/src/utils/email.js, frontend/src/pages/JobAlerts.jsx
Adds isValidEmail and imports it with the Skeleton UI components used by JobAlerts.
Outreach and mailto confirmation
frontend/src/pages/JobAlerts.jsx
Replaces direct mailto: navigation with validation-driven fallback handling, adds the confirmation overlay, and renders the direct mail client action only for valid recruiter emails.

Enhance handler scope fix

Layer / File(s) Summary
Handler scope correction
frontend/src/pages/Enhance.jsx
Adjusts the closing braces around handleEnhanceWithAI so the later handler functions remain inside Enhance.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant JobCard
  participant JobAlerts
  participant MailClient

  User->>JobCard: click Email
  JobCard->>JobAlerts: handleMailtoFallback(job)
  JobAlerts->>JobAlerts: validate recruiterEmail
  JobAlerts->>User: show confirmation overlay or toast error
  User->>JobAlerts: confirm open mail client
  JobAlerts->>MailClient: navigate to encoded mailto URL
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested labels

type:security, type:bug, gssoc:approved

Poem

A bunny peeks at emails bright,
Then checks each hop with careful sight.
A mailto door now asks “Proceed?”
While braces stay where they should be.
🐰✨

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning Email validation and confirmation were added, but the summary does not show the required default routing to the in-app outreach flow from Apply. Make Apply open the existing /outreach flow by default, and keep direct mail as a confirmed fallback only after validation and escaping.
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and accurately summarizes the main change: replacing direct mailto behavior with validated in-app outreach.
Out of Scope Changes check ✅ Passed The Enhance.jsx brace fix and the email validation flow both match the stated objectives, with no unrelated changes evident in the summaries.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@codeant-ai codeant-ai Bot added the size:M This PR changes 30-99 lines, ignoring generated files label Jun 26, 2026
Comment thread frontend/src/pages/JobAlerts.jsx Outdated
>
{searchResults.map((job, index) => (
<JobCard key={job.id || index} job={job} index={index} />
<JobCard key={job.id || index} job={job} index={index} onEmail={setOutreachJob} />

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: setOutreachJob is passed to JobCard but is never declared in this component, so rendering this line throws a runtime ReferenceError. Add local state for outreach selection in JobAlerts and pass its setter. [incorrect variable usage]

Severity Level: Critical 🚨
- ❌ Job Alerts page crashes when visiting `/job-alerts` route.
- ❌ Job search and alerts creation unusable in UI.
Steps of Reproduction ✅
1. Navigate to `/job-alerts`, which renders the `JobAlerts` page via the route in
`frontend/src/App.jsx:320-331` (`<Route path="/job-alerts" ...><JobAlerts /></Route>`).

2. React lazy-loads and executes `JobAlerts` from `frontend/src/pages/JobAlerts.jsx:21`,
which returns JSX including the search results mapping at lines 224-243 of the PR hunk
(tool view lines 224-243, with `<JobCard ... onEmail={setOutreachJob} />` at line 241).

3. At render time, the JSX expression references `setOutreachJob` and `outreachJob` even
though there is no `const [outreachJob, setOutreachJob] = useState(...)` declaration
anywhere in `JobAlerts.jsx` (verified by `rg "setOutreachJob"
frontend/src/pages/JobAlerts.jsx` only matching lines 241 and 274).

4. When React evaluates the JSX tree for `JobAlerts`, the undefined identifiers cause a
runtime `ReferenceError` (e.g., `outreachJob is not defined` / `setOutreachJob is not
defined`), preventing the Job Alerts page from rendering successfully whenever
`/job-alerts` is visited.

Fix in Cursor Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** frontend/src/pages/JobAlerts.jsx
**Line:** 241:241
**Comment:**
	*Incorrect Variable Usage: `setOutreachJob` is passed to `JobCard` but is never declared in this component, so rendering this line throws a runtime `ReferenceError`. Add local state for outreach selection in `JobAlerts` and pass its setter.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

Comment thread frontend/src/pages/JobAlerts.jsx Outdated
Comment on lines +272 to +275
<OutreachPanel
companyName={outreachJob.company}
onClose={() => setOutreachJob(null)}
/>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: OutreachPanel is rendered without being imported or defined anywhere in the codebase, which will crash when this branch renders. Import the correct component module (or add the component) before using it. [import error]

Severity Level: Major ⚠️
- ❌ In-app recruiter outreach panel fails to open.
- ⚠️ Users forced to use email client mailto fallback instead.
Steps of Reproduction ✅
1. In `frontend/src/pages/JobAlerts.jsx`, the JSX at the bottom of the `JobAlerts`
component renders `{outreachJob && ( <OutreachPanel companyName={outreachJob.company}
onClose={() => setOutreachJob(null)} /> )}` (PR hunk lines 271-276; tool view lines 6-17
in the second `Read`).

2. There is no `import OutreachPanel from ...` or other declaration of `OutreachPanel` in
this file (verified by `rg "OutreachPanel" -n frontend/src`, which only returns this usage
in `JobAlerts.jsx`), so `OutreachPanel` is an undefined identifier.

3. Once the missing `outreachJob` state is wired up and set to a non-null job (intended
via the `onEmail={setOutreachJob}` prop on `JobCard` at line 241), React will re-render
`JobAlerts` and evaluate the `{outreachJob && ...}` expression.

4. On that render, JSX will resolve `OutreachPanel` as `undefined` and
`React.createElement` will throw a runtime error like "Element type is invalid: expected a
string or a class/function but got: undefined," breaking the in-app outreach modal when it
is supposed to open.

Fix in Cursor Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** frontend/src/pages/JobAlerts.jsx
**Line:** 272:275
**Comment:**
	*Import Error: `OutreachPanel` is rendered without being imported or defined anywhere in the codebase, which will crash when this branch renders. Import the correct component module (or add the component) before using it.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

@codeant-ai

codeant-ai Bot commented Jun 26, 2026

Copy link
Copy Markdown

CodeAnt AI finished reviewing your PR.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@frontend/src/pages/JobAlerts.jsx`:
- Line 272: `OutreachPanel` is referenced in `JobAlerts.jsx` but has no import,
which will break the page at build/runtime. Update the imports at the top of
`JobAlerts.jsx` to bring in the correct `OutreachPanel` component, or replace
this usage with the intended existing component if the name is wrong. Verify the
symbol matches the rendered JSX usage and that the imported component is
exported from its source module.
- Around line 310-312: The mailto URL in JobAlerts.jsx is still vulnerable
because safeEmail is inserted raw while only the subject is encoded. Update the
email-link construction around the job.recruiterEmail handling to URL-encode the
address portion before concatenating it into the mailto: string, and consider
tightening EMAIL_REGEX or encoding just the local part if full
encodeURIComponent breaks mail clients. Keep the existing subject encoding and
build the final URL only from encoded/validated pieces in the same flow.
- Around line 271-276: `JobAlerts` is missing the state for the outreach flow,
so `outreachJob` and `setOutreachJob` are undefined when the Email action or
`OutreachPanel` is used. Add the missing `useState` hook in the component’s
state block alongside the other `JobAlerts` state variables, and ensure the
`onEmail` handler and `OutreachPanel` both reference that same state pair so the
search tab can open and close the outreach panel safely.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 0315a6c8-3833-4d22-819c-fccb8940b3bd

📥 Commits

Reviewing files that changed from the base of the PR and between 116e9b5 and 27622c1.

📒 Files selected for processing (3)
  • frontend/src/pages/Enhance.jsx
  • frontend/src/pages/JobAlerts.jsx
  • frontend/src/utils/email.js
💤 Files with no reviewable changes (1)
  • frontend/src/pages/Enhance.jsx

Comment thread frontend/src/pages/JobAlerts.jsx Outdated
Comment thread frontend/src/pages/JobAlerts.jsx Outdated
Comment on lines +310 to +312
const safeEmail = job.recruiterEmail.trim();
const safeSubject = encodeURIComponent(`Application for ${job.title || 'this role'}`);
window.location.href = `mailto:${safeEmail}?subject=${safeSubject}`;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Email is not URL-encoded before being placed in the mailto: URL, allowing parameter injection.

The subject is escaped, but safeEmail is interpolated raw. EMAIL_REGEX permits mailto-significant characters in the local part (?, &, =), so a value like foo?cc=victim@example.com passes validation yet injects extra mailto headers/parameters — exactly the query-parameter injection this PR set out to prevent. Encode the address (and split off any local-part edge cases) before building the URL.

🛡️ Encode the address path
-  const safeEmail = job.recruiterEmail.trim();
+  const safeEmail = encodeURIComponent(job.recruiterEmail.trim());
   const safeSubject = encodeURIComponent(`Application for ${job.title || 'this role'}`);
   window.location.href = `mailto:${safeEmail}?subject=${safeSubject}`;

Note: encodeURIComponent will percent-encode @; if that breaks your target mail clients, encode only the local part or tighten EMAIL_REGEX to exclude ?, &, and =.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const safeEmail = job.recruiterEmail.trim();
const safeSubject = encodeURIComponent(`Application for ${job.title || 'this role'}`);
window.location.href = `mailto:${safeEmail}?subject=${safeSubject}`;
const safeEmail = encodeURIComponent(job.recruiterEmail.trim());
const safeSubject = encodeURIComponent(`Application for ${job.title || 'this role'}`);
window.location.href = `mailto:${safeEmail}?subject=${safeSubject}`;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/pages/JobAlerts.jsx` around lines 310 - 312, The mailto URL in
JobAlerts.jsx is still vulnerable because safeEmail is inserted raw while only
the subject is encoded. Update the email-link construction around the
job.recruiterEmail handling to URL-encode the address portion before
concatenating it into the mailto: string, and consider tightening EMAIL_REGEX or
encoding just the local part if full encodeURIComponent breaks mail clients.
Keep the existing subject encoding and build the final URL only from
encoded/validated pieces in the same flow.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
frontend/src/pages/JobAlerts.jsx (1)

287-306: 🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

The fallback mail-client flow became the primary path.

Both email entry points now go straight to handleMailtoFallback(), so users leave the app for their mail client instead of using the existing in-app outreach flow first. That breaks the PR’s stated contract: mailto: should stay a confirmed fallback, not the default email action.

Also applies to: 378-385

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/pages/JobAlerts.jsx` around lines 287 - 306, The mail-client
fallback has replaced the normal outreach path in the email handlers. Update the
JobAlerts flow so the primary email action still uses the existing in-app send
logic, and only route to handleMailtoFallback()/confirmMailtoFallback() when the
fallback is explicitly needed; keep the mailto confirmation as a secondary path
and preserve the current recruiter email validation before opening the client.
♻️ Duplicate comments (1)
frontend/src/pages/JobAlerts.jsx (1)

304-306: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Encode the address before building the mailto: URL.

safeEmail is still inserted raw into the URI. Validation helps, but it does not replace output encoding for a URL sink, so this remains brittle and can reopen header/query injection if the accepted address pattern ever broadens.

🛡️ Suggested change
-  const safeEmail = job.recruiterEmail.trim();
+  const safeEmail = encodeURIComponent(job.recruiterEmail.trim());
   const safeSubject = encodeURIComponent(`Application for ${job.title || 'this role'}`);
   window.location.href = `mailto:${safeEmail}?subject=${safeSubject}`;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/pages/JobAlerts.jsx` around lines 304 - 306, The mailto link in
JobAlerts.jsx still uses the recruiter email as a raw URI component, so the URL
sink needs output encoding even after validation. Update the mailto construction
around the safeEmail and safeSubject logic to encode the address before
concatenating it into window.location.href, using the same link-building flow so
the final URI is safely escaped.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@frontend/src/pages/JobAlerts.jsx`:
- Line 241: The JobCard list key is unstable because it falls back to the array
index, which can cause `showMailtoConfirm` state to be reused for the wrong job
when the list changes. Update the `JobAlerts` render where `JobCard` is created
to use a stable, job-specific key from the job data instead of `index`, and
ensure the chosen identifier is unique and persistent across re-renders. If
`job.id` is not always present, derive the key from another stable unique field
on the job object rather than using the position in the array.

---

Outside diff comments:
In `@frontend/src/pages/JobAlerts.jsx`:
- Around line 287-306: The mail-client fallback has replaced the normal outreach
path in the email handlers. Update the JobAlerts flow so the primary email
action still uses the existing in-app send logic, and only route to
handleMailtoFallback()/confirmMailtoFallback() when the fallback is explicitly
needed; keep the mailto confirmation as a secondary path and preserve the
current recruiter email validation before opening the client.

---

Duplicate comments:
In `@frontend/src/pages/JobAlerts.jsx`:
- Around line 304-306: The mailto link in JobAlerts.jsx still uses the recruiter
email as a raw URI component, so the URL sink needs output encoding even after
validation. Update the mailto construction around the safeEmail and safeSubject
logic to encode the address before concatenating it into window.location.href,
using the same link-building flow so the final URI is safely escaped.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 022b9c04-d439-40cf-9546-382803eca06c

📥 Commits

Reviewing files that changed from the base of the PR and between 27622c1 and 2958592.

📒 Files selected for processing (2)
  • frontend/src/pages/JobAlerts.jsx
  • frontend/src/utils/email.js
🚧 Files skipped from review as they are similar to previous changes (1)
  • frontend/src/utils/email.js

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
frontend/src/pages/JobAlerts.jsx (1)

287-306: 🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

The fallback mail-client flow became the primary path.

Both email entry points now go straight to handleMailtoFallback(), so users leave the app for their mail client instead of using the existing in-app outreach flow first. That breaks the PR’s stated contract: mailto: should stay a confirmed fallback, not the default email action.

Also applies to: 378-385

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/pages/JobAlerts.jsx` around lines 287 - 306, The mail-client
fallback has replaced the normal outreach path in the email handlers. Update the
JobAlerts flow so the primary email action still uses the existing in-app send
logic, and only route to handleMailtoFallback()/confirmMailtoFallback() when the
fallback is explicitly needed; keep the mailto confirmation as a secondary path
and preserve the current recruiter email validation before opening the client.
♻️ Duplicate comments (1)
frontend/src/pages/JobAlerts.jsx (1)

304-306: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Encode the address before building the mailto: URL.

safeEmail is still inserted raw into the URI. Validation helps, but it does not replace output encoding for a URL sink, so this remains brittle and can reopen header/query injection if the accepted address pattern ever broadens.

🛡️ Suggested change
-  const safeEmail = job.recruiterEmail.trim();
+  const safeEmail = encodeURIComponent(job.recruiterEmail.trim());
   const safeSubject = encodeURIComponent(`Application for ${job.title || 'this role'}`);
   window.location.href = `mailto:${safeEmail}?subject=${safeSubject}`;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/pages/JobAlerts.jsx` around lines 304 - 306, The mailto link in
JobAlerts.jsx still uses the recruiter email as a raw URI component, so the URL
sink needs output encoding even after validation. Update the mailto construction
around the safeEmail and safeSubject logic to encode the address before
concatenating it into window.location.href, using the same link-building flow so
the final URI is safely escaped.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@frontend/src/pages/JobAlerts.jsx`:
- Line 241: The JobCard list key is unstable because it falls back to the array
index, which can cause `showMailtoConfirm` state to be reused for the wrong job
when the list changes. Update the `JobAlerts` render where `JobCard` is created
to use a stable, job-specific key from the job data instead of `index`, and
ensure the chosen identifier is unique and persistent across re-renders. If
`job.id` is not always present, derive the key from another stable unique field
on the job object rather than using the position in the array.

---

Outside diff comments:
In `@frontend/src/pages/JobAlerts.jsx`:
- Around line 287-306: The mail-client fallback has replaced the normal outreach
path in the email handlers. Update the JobAlerts flow so the primary email
action still uses the existing in-app send logic, and only route to
handleMailtoFallback()/confirmMailtoFallback() when the fallback is explicitly
needed; keep the mailto confirmation as a secondary path and preserve the
current recruiter email validation before opening the client.

---

Duplicate comments:
In `@frontend/src/pages/JobAlerts.jsx`:
- Around line 304-306: The mailto link in JobAlerts.jsx still uses the recruiter
email as a raw URI component, so the URL sink needs output encoding even after
validation. Update the mailto construction around the safeEmail and safeSubject
logic to encode the address before concatenating it into window.location.href,
using the same link-building flow so the final URI is safely escaped.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 022b9c04-d439-40cf-9546-382803eca06c

📥 Commits

Reviewing files that changed from the base of the PR and between 27622c1 and 2958592.

📒 Files selected for processing (2)
  • frontend/src/pages/JobAlerts.jsx
  • frontend/src/utils/email.js
🚧 Files skipped from review as they are similar to previous changes (1)
  • frontend/src/utils/email.js
🛑 Comments failed to post (1)
frontend/src/pages/JobAlerts.jsx (1)

241-241: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Use a stable key for JobCard.

JobCard now owns showMailtoConfirm state. Falling back to index means React can reuse that modal state for a different job after list changes, so the confirmation can appear on the wrong row.

🔧 Suggested change
- <JobCard key={job.id || index} job={job} index={index} />
+ <JobCard
+   key={job.id ?? `${job.company}:${job.title}:${job.applyLink ?? job.recruiterEmail ?? ''}`}
+   job={job}
+   index={index}
+ />
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

                      <JobCard
                        key={job.id ?? `${job.company}:${job.title}:${job.applyLink ?? job.recruiterEmail ?? ''}`}
                        job={job}
                        index={index}
                      />
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/pages/JobAlerts.jsx` at line 241, The JobCard list key is
unstable because it falls back to the array index, which can cause
`showMailtoConfirm` state to be reused for the wrong job when the list changes.
Update the `JobAlerts` render where `JobCard` is created to use a stable,
job-specific key from the job data instead of `index`, and ensure the chosen
identifier is unique and persistent across re-renders. If `job.id` is not always
present, derive the key from another stable unique field on the job object
rather than using the position in the array.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:M This PR changes 30-99 lines, ignoring generated files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[UX] JobAlerts.jsx mailto: link exposes user email without confirmation

1 participant