# Rejection reasons emailed to submitter with resubmission instructions

- **Pattern:** `ab-001084` (`directory-submissions-moderation.moderation.rejection-email-instructions`)
- **Severity:** high
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-001084
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-001084)

## Why it matters

A rejected submission that generates no notification leaves the submitter with no recourse: they do not know the listing was rejected, why it failed, or how to fix it. This silently degrades the directory's submission funnel — legitimate businesses give up and post elsewhere. It also creates GDPR Art. 17 exposure if a user later requests deletion of data that was never communicated to them as rejected. The submitter's time and data were consumed with zero return.

## Severity rationale

High because silent rejections destroy submitter trust, suppress resubmission of valid listings, and leave users unable to exercise data rights they don't know are triggered.

## Remediation

Trigger a rejection email with reason and next steps as part of the moderation action. Tie it to the same API route that logs the action:

```ts
// app/api/admin/listings/[id]/moderate/route.ts
if (action === 'reject') {
  await sendEmail({
    to: listing.contact_email,
    subject: `Your listing "${listing.title}" was not approved`,
    html: `
      <p><strong>Reason:</strong> ${reason}</p>
      <p>To resubmit with corrections, visit:
         <a href="${BASE_URL}/listings/resubmit?id=${listing.id}">Resubmit listing</a>.
      </p>
      <p>Questions? Reply to this email or contact support@yourdomain.com.</p>
    `
  })
}
```

Require `reason` to be non-empty when action is `reject` — enforce this at the API route level so moderators cannot submit a rejection without providing text.

## Detection

- **ID:** `rejection-email-instructions`
- **Severity:** `high`
- **What to look for:** When a listing is rejected, check if an email is sent to the submitter. The email should include: (1) the rejection reason, (2) clear guidance on what needs to be fixed (if applicable), (3) a link to resubmit or contact support. Look for email templates triggered on rejection.
- **Pass criteria:** Enumerate all relevant code paths. When a listing is rejected, the submitter receives an email with the rejection reason and next steps (e.g., "Please clarify operating hours and resubmit"). with at least 1 verified instance.
- **Fail criteria:** No rejection email is sent, or the email lacks a reason or resubmission instructions.
- **Skip (N/A) when:** The project has no moderation feature.
- **Detail on fail:** `"Listings are rejected but submitters receive no notification. They don't know why or how to fix it."` or `"Rejection email sent but with no reason, just 'Rejected'."`
- **Remediation:** Send rejection emails with guidance:

  ```ts
  // app/api/admin/listings/[id]/moderate/route.ts
  const listing = await db.listings.findUnique({ where: { id: listingId } })

  if (action === 'reject') {
    await sendEmail({
      to: listing.contact_email,
      subject: 'Your listing submission was not approved',
      html: `
        <p>Your listing submission for "${listing.title}" was not approved.</p>
        <p><strong>Reason:</strong> ${reason}</p>
        <p><strong>Next Steps:</strong></p>
        <ul>
          <li>Review the feedback above</li>
          <li>Make the requested changes to your listing information</li>
          <li><a href="https://yourdomain.com/listings/resubmit?id=${listing.id}">Resubmit your listing</a></li>
        </ul>
        <p>If you have questions, <a href="mailto:support@yourdomain.com">contact our support team</a>.</p>
      `
    })
  }
  ```

## External references

- gdpr Art. 17

Taxons: user-experience

HTML version: https://auditbuffet.com/patterns/ab-001084
