diff --git a/backend/campaigns/views.py b/backend/campaigns/views.py index 2a11bf0..7eadc69 100644 --- a/backend/campaigns/views.py +++ b/backend/campaigns/views.py @@ -714,25 +714,35 @@ def _build_fallback_content(self, request): from django.http import HttpResponse from django.middleware.csrf import get_token +from django.utils.html import escape from leads.models import Lead from .utils import verify_unsubscribe_token -def _unsubscribe_page(title, message, extra_html=''): +def _unsubscribe_page(title, message, extra_html='', logo_url=''): + safe_title = escape(title or "") + safe_message = escape(message or "") + safe_logo_url = escape(logo_url or "") + + logo_html = ( + f'Organization Logo' + if safe_logo_url else '' + ) + return ( '' '' '' '' '' - f'{title} | LeadOrbit' + f'{safe_title} | LeadOrbit' '' '' - f'

{title}

{message}

{extra_html}
' + f'
{logo_html}

{safe_title}

{safe_message}

{extra_html}
' '' ) @@ -749,6 +759,20 @@ def unsubscribe_view(request, lead_id, token): try: lead = Lead.objects.get(id=lead_id) + + organization = lead.organization + + custom_title = ( + organization.unsubscribe_title + or "Confirm unsubscribe" + ) + + custom_message = ( + organization.unsubscribe_message + or "Please confirm that you want to unsubscribe from future emails sent through LeadOrbit." + ) + + logo_url = organization.brand_logo_url or "" except Lead.DoesNotExist: return HttpResponse( "Lead not found", @@ -764,20 +788,23 @@ def unsubscribe_view(request, lead_id, token): '' ) html = _unsubscribe_page( - 'Confirm unsubscribe', - 'Please confirm that you want to unsubscribe from future emails sent through LeadOrbit.', + custom_title, + custom_message, form, + logo_url ) + return HttpResponse(html, content_type='text/html') lead.global_unsubscribe = True lead.save(update_fields=["global_unsubscribe"]) html = _unsubscribe_page( - 'Unsubscribed', - 'You have been unsubscribed from all future emails sent through LeadOrbit.', - '

If you received this link by mistake, no further action is needed.

', - ) + 'Unsubscribed', + 'You have been unsubscribed from all future emails sent through LeadOrbit.', + '

If you received this link by mistake, no further action is needed.

', + logo_url, +) return HttpResponse(html, content_type='text/html') diff --git a/backend/tenants/migrations/0003_organization_brand_logo_url_and_more.py b/backend/tenants/migrations/0003_organization_brand_logo_url_and_more.py new file mode 100644 index 0000000..d5d87ca --- /dev/null +++ b/backend/tenants/migrations/0003_organization_brand_logo_url_and_more.py @@ -0,0 +1,28 @@ +# Generated by Django 5.0.14 on 2026-06-22 05:33 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('tenants', '0002_organization_enable_ai_personalization_and_more'), + ] + + operations = [ + migrations.AddField( + model_name='organization', + name='brand_logo_url', + field=models.URLField(blank=True, null=True), + ), + migrations.AddField( + model_name='organization', + name='unsubscribe_message', + field=models.TextField(blank=True, null=True), + ), + migrations.AddField( + model_name='organization', + name='unsubscribe_title', + field=models.CharField(blank=True, max_length=255, null=True), + ), + ] diff --git a/backend/tenants/models.py b/backend/tenants/models.py index bb58b37..e13fef4 100644 --- a/backend/tenants/models.py +++ b/backend/tenants/models.py @@ -9,7 +9,22 @@ class Organization(models.Model): created_at = models.DateTimeField(auto_now_add=True) gemini_api_key = models.CharField(max_length=255, blank=True, null=True) enable_ai_personalization = models.BooleanField(default=True) + + unsubscribe_title = models.CharField( + max_length=255, + blank=True, + null=True + ) + unsubscribe_message = models.TextField( + blank=True, + null=True + ) + + brand_logo_url = models.URLField( + blank=True, + null=True + ) def __str__(self): return self.name