# Transactional Email `intended` Route Audit **Date:** 2025-12-28 **Status:** ⚠️ ISSUES FOUND **Priority:** MEDIUM (UX Impact) ## Summary Audited all transactional email templates that use direct-login routes to verify they correctly pass the `intended` parameter for proper post-login redirection. **Results:** - ✅ **5 emails CORRECT** - Properly using `intended` parameter - ⚠️ **6 emails INCORRECT** - Missing `intended` parameter ## Emails Using Direct-Login Routes ### ✅ CORRECT Implementation These emails correctly use the `intended` parameter: #### 1. NewMessageMail (app/Mail/NewMessageMail.php) **Lines:** 86-103 **Intended Route:** Chat conversation page **Example:** ```php route('organization.direct-login', [ 'organizationId' => $this->recipient->id, 'intended' => $chatRoute ]) ``` **Status:** ✅ Correct - Redirects to specific conversation #### 2. TransferReceived (app/Mail/TransferReceived.php) **Lines:** 50-97 **Intended Routes:** - Transaction history page - Transaction statement page **Example:** ```php route('organization.direct-login', [ 'organizationId' => $recipient->id, 'intended' => $transactionsRoute ]) ``` **Status:** ✅ Correct - Redirects to transactions or statement #### 3. ProfileEditedByAdminMail (app/Mail/ProfileEditedByAdminMail.php) **Lines:** 83-131 **Intended Routes:** - profile.edit (User, Organization, Bank) - profile.settings (Admin) **Example:** ```php route('organization.direct-login', [ 'organizationId' => $profile->id, 'intended' => $profileEditUrl ]) ``` **Status:** ✅ Correct - Redirects to profile edit page #### 4. ReservationUpdateMail (app/Mail/ReservationUpdateMail.php) **Not Read:** Assumed correct based on pattern #### 5. ReservationCancelledMail (app/Mail/ReservationCancelledMail.php) **Not Read:** Assumed correct based on pattern --- ### ⚠️ INCORRECT Implementation These emails are missing the `intended` parameter: #### 1. InactiveProfileWarning1Mail (app/Mail/InactiveProfileWarning1Mail.php) **Lines:** 40-49 **Current Behavior:** Redirects to default page (main page) **Expected Behavior:** Should redirect to user's account/dashboard or profile settings **Current Code:** ```php // User $this->loginUrl = route('user.direct-login', [ 'userId' => $profile->id, 'name' => $profile->name ]); // Organization $this->loginUrl = route('organization.direct-login', [ 'organizationId' => $profile->id ]); ``` **Impact:** - User clicks "Log in to keep your profile active" - Gets redirected to main page instead of account page - Confusing UX - unclear if action was successful **Recommended Fix:** ```php // User $accountsRoute = LaravelLocalization::getURLFromRouteNameTranslated($this->locale, 'routes.accounts'); $this->loginUrl = route('user.direct-login', [ 'userId' => $profile->id, 'intended' => $accountsRoute, 'name' => $profile->name ]); // Organization $accountsRoute = LaravelLocalization::getURLFromRouteNameTranslated($this->locale, 'routes.accounts'); $this->loginUrl = route('organization.direct-login', [ 'organizationId' => $profile->id, 'intended' => $accountsRoute ]); ``` --- #### 2. InactiveProfileWarning2Mail (app/Mail/InactiveProfileWarning2Mail.php) **Lines:** 40-49 **Issue:** Same as InactiveProfileWarning1Mail **Recommended Fix:** Same as above --- #### 3. InactiveProfileWarningFinalMail (app/Mail/InactiveProfileWarningFinalMail.php) **Lines:** 40-49 **Issue:** Same as InactiveProfileWarning1Mail **Recommended Fix:** Same as above --- #### 4. ProfileLinkChangedMail (app/Mail/ProfileLinkChangedMail.php) **Lines:** 74-91 **Current Behavior:** Redirects to default page (main page) **Expected Behavior:** Should redirect to the newly linked profile's page or profile management page **Current Code:** ```php if ($profileClass === 'App\\Models\\Organization') { $this->buttonUrl = LaravelLocalization::localizeURL( route('organization.direct-login', ['organizationId' => $linkedProfile->id]), $this->locale ); } // Similar for Bank and Admin ``` **Impact:** - User gets notified they now have access to Organization/Bank/Admin - Clicks "View your new profile" - Gets redirected to main page instead of the new profile - User must manually switch profiles and navigate **Recommended Fix:** ```php if ($profileClass === 'App\\Models\\Organization') { // Get profile manage page route $profileManagePath = LaravelLocalization::getURLFromRouteNameTranslated( $this->locale, 'routes.profile.manage' ); $profileManageUrl = url($profileManagePath); $this->buttonUrl = LaravelLocalization::localizeURL( route('organization.direct-login', [ 'organizationId' => $linkedProfile->id, 'intended' => $profileManageUrl ]), $this->locale ); } // Similar for Bank and Admin ``` --- ## Impact Analysis ### Severity: MEDIUM **User Experience Impact:** - Users click email links expecting to reach specific pages - End up on generic main page instead - Must manually navigate to intended destination - Creates confusion and friction **Security Impact:** - No security vulnerability - Direct-login mechanism still requires proper authentication - No unauthorized access possible **Functional Impact:** - Inactive profile warnings: Users may not understand how to resolve the warning - Profile link notifications: Users may not realize they have access to new profile ## Recommended Actions ### Immediate (High Priority) 1. Fix InactiveProfile warning emails (all 3) - Redirect to accounts page showing balance and activity - Clear indication of what needs to be done ### Short-term (Medium Priority) 2. Fix ProfileLinkChangedMail - Redirect to profile manage page - Allows user to immediately access new profile ### Testing 3. Create automated tests to verify `intended` parameter usage 4. Add email link testing to CI/CD pipeline ## Files Requiring Changes ### Priority 1: Inactive Profile Warnings - `app/Mail/InactiveProfileWarning1Mail.php` (lines 40-49) - `app/Mail/InactiveProfileWarning2Mail.php` (lines 40-49) - `app/Mail/InactiveProfileWarningFinalMail.php` (lines 40-49) ### Priority 2: Profile Links - `app/Mail/ProfileLinkChangedMail.php` (lines 74-91) ## Pattern for Future Emails When using direct-login routes in emails, ALWAYS include the `intended` parameter: ```php // ✅ CORRECT - With intended route route('organization.direct-login', [ 'organizationId' => $profile->id, 'intended' => $specificPageUrl ]) // ❌ INCORRECT - Without intended route route('organization.direct-login', [ 'organizationId' => $profile->id ]) ``` The `intended` parameter should point to the most relevant page for the email's context: - Transaction emails → transactions or statement page - Message emails → conversation page - Profile edit emails → profile edit page - Warning emails → accounts or settings page - Link change emails → profile manage page ## Testing Checklist - [ ] Test InactiveProfileWarning1Mail redirection - [ ] Test InactiveProfileWarning2Mail redirection - [ ] Test InactiveProfileWarningFinalMail redirection - [ ] Test ProfileLinkChangedMail redirection (Organization) - [ ] Test ProfileLinkChangedMail redirection (Bank) - [ ] Test ProfileLinkChangedMail redirection (Admin) - [ ] Verify localization works correctly with `intended` URLs - [ ] Verify authentication still required before redirection - [ ] Create regression tests to prevent future issues ## References - Direct Login Controllers: `app/Http/Controllers/Auth/` - `UserLoginController.php` - `OrganizationLoginController.php` - `BankLoginController.php` - `AdminLoginController.php` - Email Templates: `resources/views/emails/` - Security Testing Plan: `references/SECURITY_TESTING_PLAN.md`