Skip to content

Conversation

@Bosun-Josh121
Copy link
Contributor

@Bosun-Josh121 Bosun-Josh121 commented Jan 31, 2026

Feat: Personalized Weekly Email Digest & Subscription System

Closes #101

Summary

This PR implements a robust Weekly Email Digest system. It introduces a background worker that runs on a configurable weekly schedule (default: Friday at 09:00 UTC) to aggregate new activity, Audit Reports, Vulnerabilities and Forum Thread, then sends personalized email summaries to users.

The system is designed to be "spam-free," sending emails only when relevant content exists for the entities a user explicitly follows.

Changes

1. Database & Models

  • Enhanced SubscriptionModel:
    • Added ProtocolId and CategoryId Foreign Keys to support specific content filtering.
    • Added UserId Foreign Key linked to the Login table (mapped to LoginId).
    • Updated Email to be nullable to support registered users via UserId while keeping guest support possible.
  • Updated UserProfileModel:
    • Added ReceiveWeeklyDigest (bool, default true) for opt-out management.
    • Added LastDigestSentAt (DateTime) to track send history and prevent duplicate emails.
  • Migration: Added migration file to apply schema changes and indexes.

2. Core Services

  • DigestService (New Business Logic):
    • Aggregation: Queries new content (Reports, Vulns, Threads) created in the last 7 days.
    • Personalization: Filters content based on the user's active subscriptions (Protocol vs. Category).
    • Resilience: Implemented per-user error isolation (one failed email does not stop the batch) and "Double-Send" prevention using LastDigestSentAt.
    • Unsubscribe: Generates valid unsubscribe links using the configurable FrontendUrl.
  • DigestHostedService (Background Worker):
    • Implements IHostedService to run indefinitely.
    • Calculates delay until the next configured run time (e.g., next Friday at 9 AM).
    • Handles retries and error logging.
  • IEmailService: Introduced interface for email abstraction (with ConsoleEmailService implementation for dev/logging).

3. Dependency Injection (Startup.cs)

  • Registered new services in ConfigureServices:
    • services.AddSingleton<IEmailService, ConsoleEmailService>();
    • services.AddScoped<IDigestService, DigestService>();
    • services.AddHostedService<DigestHostedService>();

4. Configuration (appsettings.json)

  • Added support for dynamic scheduling and frontend linking:
    "DigestDayOfWeek": "Friday",
    "DigestHourUtc": 9,
    "FrontendUrl": "[https://portal.soroban.com](https://portal.soroban.com)"

5. Testing

  • DigestServiceTests: Added a comprehensive test suite covering 6 scenarios:
    • Personalization: Verifies users see only what they follow.
    • Timing: Verifies LastDigestSentAt prevents double-sending.
    • Consent: Verifies ReceiveWeeklyDigest = false is respected.
    • Noise: Verifies unrelated content is excluded.
    • Resilience: Verifies the loop continues after a single user failure.
    • Formatting: Verifies HTML structure adapts to partial content.

@Bosun-Josh121 Bosun-Josh121 marked this pull request as draft January 31, 2026 13:01
@Bosun-Josh121 Bosun-Josh121 marked this pull request as ready for review January 31, 2026 13:58
@0xGeorgii 0xGeorgii requested a review from Copilot February 1, 2026 01:15
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR implements an automated weekly email digest system that sends users a summary of platform activity every Friday at 09:00 UTC. Users can opt-in or opt-out of receiving these digests through their profile settings.

Changes:

  • Added database fields to track user digest preferences and last send timestamp
  • Created a digest service to aggregate weekly content (reports, vulnerabilities, forum threads) and generate HTML emails
  • Implemented a background hosted service for scheduling and executing the weekly digest job

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
UserProfileModel.cs Added ReceiveWeeklyDigest and LastDigestSentAt fields to track user preferences and prevent duplicate sends
DigestService.cs Implements content aggregation logic and HTML email generation for weekly digests
DigestHostedService.cs Background service that schedules and triggers digest processing every Friday at 09:00 UTC
IEmailService.cs Email service abstraction with console-based implementation for development
Startup.cs Registers new services and background worker in dependency injection container
20260205100000_AddWeeklyDigestFields.cs Database migration to add digest-related columns to user_profiles table

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@Bosun-Josh121
Copy link
Contributor Author

@0xGeorgii this is updated as well

@0xGeorgii
Copy link
Contributor

@Bosun-Josh121
Copy link
Contributor Author

@Bosun-Josh121, please use the existing Model: https://github.com/Inferara/soroban-security-portal/blob/main/Backend/SorobanSecurityPortalApi/Models/DbModels/SubscriptionModel.cs

Yeah but the model needs to be updated to be able to track subscription for personalized feeds. Should I do that?

@0xGeorgii
Copy link
Contributor

yes, please, better to update existing models if they are semantically fit with new functionality than introduce new models

@Bosun-Josh121
Copy link
Contributor Author

yes, please, better to update existing models if they are semantically fit with new functionality than introduce new models

@0xGeorgii I didn't introduce any new model though, I only updated the UserProfileModel to allow to opt in for the feeds

@0xGeorgii
Copy link
Contributor

@Bosun-Josh121, yes, I see, but it seems the subscription model is more suitable for this feature. Do you agree?

@Bosun-Josh121
Copy link
Contributor Author

@Bosun-Josh121, yes, I see, but it seems the subscription model is more suitable for this feature. Do you agree?

Yes it is. I'll update it shortly

@Bosun-Josh121
Copy link
Contributor Author

@0xGeorgii updated

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Create Weekly Email Digest of Followed Content

2 participants