9.0 KiB
9.0 KiB
Custom Recipients Implementation
Overview
This feature allows campaigns to target any email address (custom recipients) instead of or in addition to elected representatives from the Represent API.
Implementation Summary
✅ Backend (Complete)
1. Database Schema (scripts/build-nocodb.sh)
-
custom_recipients table with fields:
id- Primary keycampaign_id- Links to campaigns tablecampaign_slug- Campaign identifierrecipient_name- Full name of recipientrecipient_email- Email addressrecipient_title- Job title/position (optional)recipient_organization- Organization name (optional)notes- Internal notes (optional)is_active- Boolean flag
-
campaigns table updated:
- Added
allow_custom_recipientsboolean field (default: false)
- Added
2. Backend Controller (app/controllers/customRecipients.js)
Full CRUD operations:
getRecipientsByCampaign(req, res)- Fetch all recipients for a campaigncreateRecipient(req, res)- Add single recipient with validationbulkCreateRecipients(req, res)- Import multiple recipients from CSVupdateRecipient(req, res)- Update recipient detailsdeleteRecipient(req, res)- Delete single recipientdeleteAllRecipients(req, res)- Clear all recipients for a campaign
3. NocoDB Service (app/services/nocodb.js)
getCustomRecipients(campaignId)- Query by campaign IDgetCustomRecipientsBySlug(campaignSlug)- Query by slugcreateCustomRecipient(recipientData)- Create with field mappingupdateCustomRecipient(recipientId, updateData)- Partial updatesdeleteCustomRecipient(recipientId)- Single deletiondeleteCustomRecipientsByCampaign(campaignId)- Bulk deletion
4. API Routes (app/routes/api.js)
All routes protected with requireNonTemp authentication:
GET /api/campaigns/:slug/custom-recipients- List all recipientsPOST /api/campaigns/:slug/custom-recipients- Create single recipientPOST /api/campaigns/:slug/custom-recipients/bulk- Bulk importPUT /api/campaigns/:slug/custom-recipients/:id- Update recipientDELETE /api/campaigns/:slug/custom-recipients/:id- Delete recipientDELETE /api/campaigns/:slug/custom-recipients- Delete all recipients
5. Campaign Controller Updates (app/controllers/campaigns.js)
- Added
allow_custom_recipientsfield to all campaign CRUD operations - Field normalization in 5+ locations for consistent API responses
✅ Frontend (Complete)
1. JavaScript Module (app/public/js/custom-recipients.js)
Comprehensive module with:
- CRUD Operations: Add, edit, delete recipients
- Bulk Import: CSV file upload or paste with parsing
- Validation: Email format validation
- UI Management: Dynamic recipient list display with cards
- Error Handling: User-friendly error messages
- XSS Protection: HTML escaping for security
Key methods:
CustomRecipients.init(campaignSlug) // Initialize module
CustomRecipients.loadRecipients(slug) // Load from API
CustomRecipients.displayRecipients() // Render list
// Plus handleAddRecipient, handleEditRecipient, handleDeleteRecipient, etc.
2. Admin Panel Integration (app/public/admin.html + app/public/js/admin.js)
- Create Form: Checkbox to enable custom recipients
- Edit Form:
- Checkbox with show/hide toggle
- Add recipient form (5 fields: name, email, title, organization, notes)
- Bulk CSV import button with modal
- Recipients list with edit/delete actions
- Clear all button
- JavaScript Integration:
toggleCustomRecipientsSection()- Show/hide based on checkboxsetupCustomRecipientsHandlers()- Event listeners for checkbox- Auto-load recipients when editing campaign with feature enabled
- Form data includes
allow_custom_recipientsin create/update
3. Bulk Import Modal (app/public/admin.html)
Complete modal with:
- CSV format instructions
- File upload input
- Paste textarea for direct CSV input
- Import results display with success/failure details
- CSV format:
recipient_name,recipient_email,recipient_title,recipient_organization,notes
4. CSS Styling (app/public/admin.html)
.recipient-card- Card layout with hover effects.recipient-info- Name, email, metadata display.recipient-actions- Edit/delete icon buttons with hover colors.bulk-import-help- Modal styling- Responsive grid layout
Usage
For Administrators:
-
Create Campaign:
- Check "Allow Custom Recipients" during creation
- An info section will appear explaining that recipients can be added after campaign is created
- Complete the campaign creation
-
Edit Campaign:
- Navigate to the Edit tab and select your campaign
- Check "Allow Custom Recipients" to enable the feature
- The custom recipients management section will appear below the checkbox
-
Add Single Recipient:
- Fill in name (required) and email (required)
- Optionally add title, organization, notes
- Click "Add Recipient"
-
Bulk Import:
- Click "Bulk Import (CSV)" button
- Upload CSV file or paste CSV data
- CSV format:
recipient_name,recipient_email,recipient_title,recipient_organization,notes - First row can be header (will be skipped if contains "recipient_name")
- Results show success/failure for each row
-
Edit Recipient:
- Click edit icon on recipient card
- Form populates with current data
- Make changes and click "Update Recipient"
- Or click "Cancel" to revert
-
Delete Recipients:
- Single: Click delete icon on card
- All: Click "Clear All" button
API Examples:
# Create recipient
curl -X POST /api/campaigns/my-campaign/custom-recipients \
-H "Content-Type: application/json" \
-d '{
"recipient_name": "Jane Doe",
"recipient_email": "jane@example.com",
"recipient_title": "CEO",
"recipient_organization": "Tech Corp"
}'
# Bulk import
curl -X POST /api/campaigns/my-campaign/custom-recipients/bulk \
-H "Content-Type: application/json" \
-d '{
"recipients": [
{"recipient_name": "John Smith", "recipient_email": "john@example.com"},
{"recipient_name": "Jane Doe", "recipient_email": "jane@example.com"}
]
}'
# Get all recipients
curl /api/campaigns/my-campaign/custom-recipients
# Update recipient
curl -X PUT /api/campaigns/my-campaign/custom-recipients/123 \
-H "Content-Type: application/json" \
-d '{"recipient_title": "CTO"}'
# Delete recipient
curl -X DELETE /api/campaigns/my-campaign/custom-recipients/123
# Delete all recipients
curl -X DELETE /api/campaigns/my-campaign/custom-recipients
Security Features
- Authentication: All API routes require non-temporary user session
- Validation: Email format validation on client and server
- XSS Protection: HTML escaping in display
- Campaign Check: Verifies campaign exists and feature is enabled
- Input Sanitization: express-validator on API endpoints
Next Steps (TODO)
- Dashboard Integration: Add same UI to
dashboard.htmlfor regular users - Campaign Display: Update
campaign.jsto show custom recipients alongside elected officials - Email Composer: Ensure custom recipients work in email sending flow
- Testing: Comprehensive end-to-end testing
- Documentation: Update main README and files-explainer
Files Modified/Created
Backend:
- ✅
scripts/build-nocodb.sh- Database schema - ✅
app/controllers/customRecipients.js- NEW FILE (282 lines) - ✅
app/services/nocodb.js- Service methods - ✅
app/routes/api.js- API endpoints - ✅
app/controllers/campaigns.js- Field updates
Frontend:
- ✅
app/public/js/custom-recipients.js- NEW FILE (538 lines) - ✅
app/public/js/admin.js- Integration code - ✅
app/public/admin.html- UI components and forms
Documentation:
- ✅
CUSTOM_RECIPIENTS_IMPLEMENTATION.md- This file
Testing Checklist
- Database table creation (run build-nocodb.sh)
- Create campaign with custom recipients enabled
- Add single recipient via form
- Edit recipient information
- Delete single recipient
- Bulk import via CSV file
- Bulk import via paste
- Clear all recipients
- Toggle checkbox on/off
- Verify API authentication
- Test with campaign where feature is disabled
- Check recipient display on campaign page
- Test email sending to custom recipients
Known Limitations
- Custom recipients can only be added AFTER campaign is created (not during creation)
- Dashboard UI not yet implemented (admin panel only)
- Campaign display page doesn't show custom recipients yet
- CSV import uses simple comma splitting (doesn't handle quoted commas)
- No duplicate email detection
Future Enhancements
- Duplicate email detection/prevention
- Import validation preview before saving
- Export recipients to CSV
- Recipient groups/categories
- Import from external sources (Google Contacts, etc.)
- Recipient engagement tracking
- Custom fields for recipients
- Merge tags in email templates using recipient data