contacts: Update unsubscribe to work through browser GET interface
Also add field to mark unsubscribes as actioned.
This commit is contained in:
		
							parent
							
								
									c377b329e2
								
							
						
					
					
						commit
						de861fe14d
					
				
					 4 changed files with 40 additions and 2 deletions
				
			
		|  | @ -6,4 +6,5 @@ from .models import Unsubscription | |||
| @admin.register(Unsubscription) | ||||
| class UnsubscriptionAdmin(admin.ModelAdmin): | ||||
|     list_display = ['created', 'email', 'mailout'] | ||||
|     list_filter = ['mailout', 'actioned'] | ||||
|     search_fields = ['email', 'mailout'] | ||||
|  |  | |||
|  | @ -0,0 +1,18 @@ | |||
| # Generated by Django 5.1.2 on 2024-12-10 18:34 | ||||
| 
 | ||||
| from django.db import migrations, models | ||||
| 
 | ||||
| 
 | ||||
| class Migration(migrations.Migration): | ||||
| 
 | ||||
|     dependencies = [ | ||||
|         ('contacts', '0002_unsubscription_mailout'), | ||||
|     ] | ||||
| 
 | ||||
|     operations = [ | ||||
|         migrations.AddField( | ||||
|             model_name='unsubscription', | ||||
|             name='actioned', | ||||
|             field=models.DateField(blank=True, null=True), | ||||
|         ), | ||||
|     ] | ||||
|  | @ -5,6 +5,13 @@ class Unsubscription(models.Model): | |||
|     created = models.DateTimeField(auto_now_add=True, blank=True) | ||||
|     email = models.EmailField() | ||||
|     mailout = models.SlugField() | ||||
|     actioned = models.DateField(null=True, blank=True) | ||||
| 
 | ||||
|     class Meta: | ||||
|         ordering = ['created'] | ||||
| 
 | ||||
|     def __str__(self): | ||||
|         if self.mailout: | ||||
|             return f'{self.email} ({self.mailout})' | ||||
|         else: | ||||
|             return self.email | ||||
|  |  | |||
|  | @ -27,15 +27,27 @@ def unsubscribe(request): | |||
| 
 | ||||
|     Interfaces like Gmail will then provide a user interface to unsubscribe | ||||
|     which will hit this endpoint. | ||||
| 
 | ||||
|     Our understanding is that Gmail will submit the form with and HTTP POST request, but | ||||
|     with GET-style URL parameters. Hence this feature has been built to work both with | ||||
|     GET and POST-style data as well as GET and POST methods, just in case. Test it like | ||||
|     this: | ||||
| 
 | ||||
|     curl -X POST -d 'email=foo@bar.com&mailout=jan2024-new' https://sfconservancy.org/contacts/unsubscribe/ | ||||
|     curl -X POST 'https://sfconservancy.org/contacts/unsubscribe/?email=foo@bar.com&mailout=jan2024-new' | ||||
| 
 | ||||
|     Or visit in a browser: | ||||
| 
 | ||||
|     https://sfconservancy.org/contacts/unsubscribe/?email=foo@bar.com&mailout=jan2024-new | ||||
|     """ | ||||
|     if request.method == 'POST': | ||||
|         logger.debug('Unsubscribe GET: %s', request.GET) | ||||
|         logger.debug('Unsubscribe POST: %s', request.POST) | ||||
|         form = UnsubscribeForm(request.GET) | ||||
|         form = UnsubscribeForm(request.GET.dict() | request.POST.dict()) | ||||
|         if form.is_valid(): | ||||
|             form.save() | ||||
|             logger.info('Unsubscribed %s', form.cleaned_data['email']) | ||||
|             return render(request, 'contacts/unsubscribe_success.html') | ||||
|     else: | ||||
|         form = UnsubscribeForm() | ||||
|         form = UnsubscribeForm(request.GET.dict() | request.POST.dict()) | ||||
|     return render(request, 'contacts/unsubscribe.html', {'form': form}) | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue