Overview

Distribution lists allow you to create reusable groups of email addresses that can be used across multiple elections. This simplifies bulk email management and ensures consistency when inviting the same groups of voters.

Use Cases

  • Board Members: Create a list of all board members
  • Committee Members: Group committee participants
  • Residents: Maintain lists of residents by building/floor
  • Stakeholders: Group stakeholders for specific elections

Creating Distribution Lists

Via Admin UI

  1. Navigate to Admin → Distribution Lists
  2. Click “Create New List”
  3. Enter:
    • Name: Descriptive name (e.g., “Board Members”)
    • Description: Optional description
  4. Click “Create”

Via API

Endpoint: POST /admin/distribution-lists

Request:

{
  "name": "Board Members",
  "description": "All current board members"
}

Response:

{
  "success": true,
  "list": {
    "id": "list_abc123",
    "name": "Board Members",
    "description": "All current board members",
    "created_at": 1704067200000,
    "updated_at": 1704067200000
  }
}

Managing Emails

Adding Emails

Via Admin UI:

  1. Go to distribution list details page
  2. Enter email addresses (one per line or comma-separated)
  3. Click “Add Emails”

Via API: Endpoint: POST /admin/distribution-lists/:id/emails

Request:

{
  "emails": [
    "voter1@example.com",
    "voter2@example.com",
    "voter3@example.com"
  ]
}

Response:

{
  "success": true,
  "added": 3,
  "emails": [
    { "id": "email_1", "email": "voter1@example.com", "created_at": 1704067200000 },
    { "id": "email_2", "email": "voter2@example.com", "created_at": 1704067200000 },
    { "id": "email_3", "email": "voter3@example.com", "created_at": 1704067200000 }
  ]
}

Note: Duplicate emails in the same list are automatically prevented.

Removing Emails

Via Admin UI:

  1. Go to distribution list details page
  2. Click “Remove” next to the email

Via API: Endpoint: DELETE /admin/distribution-lists/:id/emails/:emailId

Response:

{
  "success": true
}

Using Distribution Lists in Elections

Via Admin UI

When sending invites:

  1. Go to election management page
  2. Scroll to “Send Invites” section
  3. Under “Distribution Lists”, select one or more lists
  4. Optionally add individual emails
  5. Click “Send Invites”

Via API

Endpoint: POST /admin/elections/:id/invite

Request:

{
  "distribution_list_ids": ["list_abc123", "list_def456"],
  "emails": ["additional@example.com"],
  "invite_mode": "batch"
}

Behavior:

  • All emails from selected lists are included
  • Individual emails are added
  • Duplicates are automatically removed (case-insensitive)
  • Works with both individual and batch invite modes

Database Schema

distribution_lists Table

CREATE TABLE distribution_lists (
    id TEXT PRIMARY KEY,           -- UUID
    name TEXT NOT NULL,
    description TEXT,
    created_at INTEGER NOT NULL DEFAULT (unixepoch()),
    updated_at INTEGER NOT NULL DEFAULT (unixepoch())
);

distribution_list_emails Table

CREATE TABLE distribution_list_emails (
    id TEXT PRIMARY KEY,           -- UUID
    list_id TEXT NOT NULL,
    email TEXT NOT NULL,
    created_at INTEGER NOT NULL DEFAULT (unixepoch()),
    FOREIGN KEY (list_id) REFERENCES distribution_lists(id) ON DELETE CASCADE,
    UNIQUE(list_id, email)         -- Prevent duplicates
);

Indexes:

  • idx_distribution_list_emails_list: On list_id (for fast lookups)
  • idx_distribution_list_emails_email: On email (for reverse lookups)

Email Deduplication

Automatic Deduplication

When using distribution lists with individual emails:

  1. All emails are collected (from lists + individual)
  2. Converted to lowercase
  3. Duplicates removed (case-insensitive)
  4. Final list sent

Example:

  • List A: ["user@example.com", "admin@example.com"]
  • List B: ["user@example.com", "voter@example.com"]
  • Individual: ["admin@example.com"]

Result: ["user@example.com", "admin@example.com", "voter@example.com"]

Within Lists

Duplicate emails within the same list are prevented by the UNIQUE(list_id, email) constraint.

List Management

Viewing Lists

Via Admin UI:

  • All Lists: Admin → Distribution Lists
  • List Details: Click on a list name

Via API: Endpoint: GET /admin/distribution-lists

Response:

{
  "lists": [
    {
      "id": "list_abc123",
      "name": "Board Members",
      "description": "All current board members",
      "created_at": 1704067200000,
      "updated_at": 1704067200000,
      "email_count": 5
    }
  ]
}

Updating Lists

Via Admin UI:

  1. Go to distribution list details
  2. Click “Edit”
  3. Update name/description
  4. Click “Save”

Via API: Endpoint: PUT /admin/distribution-lists/:id

Request:

{
  "name": "Updated Name",
  "description": "Updated description"
}

Deleting Lists

Via Admin UI:

  1. Go to distribution list details
  2. Click “Delete”
  3. Confirm deletion

Via API: Endpoint: DELETE /admin/distribution-lists/:id

Response:

{
  "success": true
}

Note: Deleting a list also deletes all associated emails (CASCADE).

Best Practices

Organization

  1. Use Descriptive Names: “Board Members 2024” vs “List 1”
  2. Add Descriptions: Explain the purpose of each list
  3. Keep Updated: Remove inactive members regularly
  4. Group Logically: Organize by role, building, committee, etc.

Maintenance

  1. Regular Review: Periodically review and update lists
  2. Remove Inactive: Remove members who are no longer active
  3. Verify Emails: Ensure email addresses are correct
  4. Document Changes: Keep track of when lists are updated

Usage

  1. Combine Lists: Use multiple lists for complex groups
  2. Add Individuals: Combine lists with individual emails
  3. Test First: Send test invites before bulk sending
  4. Monitor Results: Check invite status after sending

Limitations

Current Limitations

  1. No Nested Lists: Cannot create lists of lists
  2. No Import/Export: Must add emails manually or via API
  3. No Email Validation: System doesn’t validate email format (relies on email service)
  4. No Groups/Roles: Simple email lists only

Future Enhancements

Potential improvements:

  • CSV import/export
  • Nested lists (lists of lists)
  • Email validation
  • Member roles/permissions
  • Bulk operations

API Reference

List Operations

  • GET /admin/distribution-lists - List all lists
  • GET /admin/distribution-lists/:id - Get list details
  • POST /admin/distribution-lists - Create list
  • PUT /admin/distribution-lists/:id - Update list
  • DELETE /admin/distribution-lists/:id - Delete list

Email Operations

  • GET /admin/distribution-lists/:id/emails - List emails in list
  • POST /admin/distribution-lists/:id/emails - Add emails
  • DELETE /admin/distribution-lists/:id/emails/:emailId - Remove email

Election Integration

  • POST /admin/elections/:id/invite - Use lists in invites (via distribution_list_ids)

Troubleshooting

Emails Not Included

Possible causes:

  1. List not selected in invite form
  2. Emails removed from list
  3. Duplicate emails filtered out

Solutions:

  1. Verify list is selected
  2. Check list contents
  3. Review deduplication logic

Duplicate Emails

Scenario: Same email in multiple lists

Behavior: System automatically deduplicates, so each email receives one invite.

Solution: This is expected behavior. If you need separate invites, use individual email mode.

See Also