Repository: dotkom/onlineweb4

Issue:
Changing primary email address should change email address used for list subscriptions
## What kind of an issue is this?

- Bug report


## What is the expected behaviour?

If I change my primary email address I expect the mailing list services to be updated with my new address, whilst removing my old address.

## What is the current behaviour?

The old address is not removed and the new address is not added.


## How do you reproduce this problem? 

* (Add a new email to an account) (_Only required if there is no alternative email added to the account already_)
* Set the new email address as the primary
* _Notice that the action happens immediately_
    * (Vs. unsubscribing / subscribing to a list, which queries the mailing list service to add/remove addresses.)
* Verify that the old primary address is still on the list
* Verify that the new primary address is absent from the list

## Other information

The settings page tells the user that the primary address is the one used for mailing lists:

> **Adressen som er markert som primær brukes til alle våre e-postlister**, gjenoppretning av passord og andre varsler som sendes fra oss.

The [`set_primary`](https://github.com/dotkom/onlineweb4/blob/v4.24.28/apps/profiles/views.py#L326) function does not handle subscribing/unsubscribing to a list. (Neither does the [`Email model`](https://github.com/dotkom/onlineweb4/blob/v4.24.28/apps/authentication/models.py#L278) nor any signals attached to it.)



Discussion:
Additional information: 

Because this sync has not worked since the fall of 2016, any person who tries to unsubscribe with an "invalid" email address should be informed about this change (look out for error codes from the Google API saying that this email address is not found), and prompt the user to either

* unsubscribe directly through the email, or
* switch back to the original email address as primary, unsubscribe from list, change back to current

Furthermore, this could also make it so that people who subscribed to the list with one address, changed their primary address (thought they) unsubscribed, then changed back, can experience an error where the API responds that this address is already on the list. (If that is the case, we should just silently update the checkbox state/database state and tell the user it succeeded.)
Hacky fix: unsubscribing, changing primary, then resubscribing programmatically :smiling_imp: 

Resolving patch:
diff --git a/apps/authentication/signals.py b/apps/authentication/signals.py
--- a/apps/authentication/signals.py
+++ b/apps/authentication/signals.py
@@ -5,17 +5,20 @@
 from django.conf import settings
 from django.contrib.auth import get_user_model
 from django.contrib.auth.models import Group
-from django.db.models.signals import m2m_changed, post_save, pre_delete
+from django.db.models.signals import m2m_changed, post_save, pre_delete, pre_save
 from django.dispatch import receiver
 
-from apps.authentication.models import GroupMember, OnlineGroup
+from apps.authentication.models import Email, GroupMember, OnlineGroup
 from apps.authentication.tasks import SynchronizeGroups
 from apps.gsuite.mail_syncer.main import update_g_suite_group, update_g_suite_user
+from apps.gsuite.mail_syncer.tasks import update_mailing_list
 
 User = get_user_model()
 logger = logging.getLogger("syncer.%s" % __name__)
 sync_uuid = uuid.uuid1()
 
+MAILING_LIST_USER_FIELDS_TO_LIST_NAME = settings.MAILING_LIST_USER_FIELDS_TO_LIST_NAME
+
 
 def run_group_syncer(user):
     """
@@ -103,3 +106,25 @@ def remove_online_group_members_from_django_group(
     user: User = instance.user
     if user in group.user_set.all():
         group.user_set.remove(user)
+
+
+@receiver(pre_save, sender=Email)
+def re_subscribe_primary_email_to_lists(sender, instance: Email, **kwargs):
+    user: User = instance.user
+    jobmail = MAILING_LIST_USER_FIELDS_TO_LIST_NAME.get("jobmail")
+    infomail = MAILING_LIST_USER_FIELDS_TO_LIST_NAME.get("infomail")
+    if instance.pk:
+        stored_instance: Email = Email.objects.get(pk=instance.pk)
+
+        # Handle case when the instance is changed to primary
+        if instance.primary and not stored_instance.primary:
+            if user.jobmail:
+                update_mailing_list.delay(jobmail, email=instance.email, added=True)
+            if user.infomail:
+                update_mailing_list.delay(infomail, email=instance.email, added=True)
+        # Handle case when the instance is changed from primary
+        elif not instance.primary and stored_instance.primary:
+            if user.jobmail:
+                update_mailing_list.delay(jobmail, email=instance.email, added=False)
+            if user.infomail:
+                update_mailing_list.delay(infomail, email=instance.email, added=False)
diff --git a/apps/gsuite/mail_syncer/signals.py b/apps/gsuite/mail_syncer/signals.py
--- a/apps/gsuite/mail_syncer/signals.py
+++ b/apps/gsuite/mail_syncer/signals.py
@@ -1,5 +1,6 @@
 import logging
 
+from django.conf import settings
 from django.contrib.auth import get_user_model
 from django.db.models.signals import pre_save
 from django.dispatch import receiver
@@ -8,7 +9,7 @@
 
 User = get_user_model()
 
-MAILING_LIST_USER_FIELDS_TO_LIST_NAME = {"infomail": "info", "jobmail": "oppdrag"}
+MAILING_LIST_USER_FIELDS_TO_LIST_NAME = settings.MAILING_LIST_USER_FIELDS_TO_LIST_NAME
 
 logger = logging.getLogger(__name__)
 
diff --git a/onlineweb4/settings/gsuite.py b/onlineweb4/settings/gsuite.py
--- a/onlineweb4/settings/gsuite.py
+++ b/onlineweb4/settings/gsuite.py
@@ -53,3 +53,8 @@
         'techtalks' : 'techtalks'
     }
 }
+
+MAILING_LIST_USER_FIELDS_TO_LIST_NAME = {
+    'infomail': 'info',
+    'jobmail': 'oppdrag',
+}


Test patch: