We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Missing chair email aliases for research area groups
### Describe the issue

There are two Research Area Groups in the datatracker, anrw and irtfopen. These groups have a chair listed, but the email expansions at https://datatracker.ietf.org/group/irtfopen/email/ appear to be missing the chairs alias (irtfopen-chair@ietf.org) and email sent to that address bounces. Similarly, presumably, for anrw.



### Code of Conduct

- [X] I agree to follow the [IETF's Code of Conduct](https://github.com/ietf-tools/.github/blob/main/CODE_OF_CONDUCT.md)

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `ietf/group/management/commands/generate_group_aliases.py`
Content:
```
1 # Copyright The IETF Trust 2012-2021, All Rights Reserved
2 # -*- coding: utf-8 -*-
3 
4 # This was written as a script by Markus Stenberg <markus.stenberg@iki.fi>.
5 # It was turned into a management command by Russ Housley <housley@vigisec.com>.
6 
7 import datetime
8 import io
9 import os
10 import shutil
11 import stat
12 import time
13 
14 from tempfile import mkstemp
15     
16 from django.conf import settings
17 from django.core.management.base import BaseCommand
18 from django.utils import timezone
19 
20 import debug                            # pyflakes:ignore
21 
22 from ietf.group.models import Group
23 from ietf.group.utils import get_group_ad_emails, get_group_role_emails, get_child_group_role_emails
24 from ietf.name.models import GroupTypeName
25 from ietf.utils.aliases import dump_sublist
26 
27 DEFAULT_YEARS = 5
28 ACTIVE_STATES=['active', 'bof', 'proposed']
29 GROUP_TYPES=['wg', 'rg', 'dir', 'team', 'review', 'program', 'rfcedtyp']
30 NO_AD_GROUP_TYPES=['rg', 'team', 'program', 'rfcedtyp']
31 IETF_DOMAIN=['ietf.org', ]
32 IRTF_DOMAIN=['irtf.org', ]
33 IAB_DOMAIN=['iab.org', ]
34 
35 class Command(BaseCommand):
36     help = ('Generate the group-aliases and group-virtual files for Internet-Draft '
37             'mail aliases, placing them in the file configured in '
38             'settings.GROUP_ALIASES_PATH and settings.GROUP_VIRTUAL_PATH, '
39             'respectively.  The generation includes aliases for groups that '
40             'have seen activity in the last %s years.' % (DEFAULT_YEARS))
41 
42     def handle(self, *args, **options):
43         show_since = timezone.now() - datetime.timedelta(DEFAULT_YEARS*365)
44 
45         date = time.strftime("%Y-%m-%d_%H:%M:%S")
46         signature = '# Generated by %s at %s\n' % (os.path.abspath(__file__), date)
47 
48         ahandle, aname = mkstemp()
49         os.close(ahandle)
50         afile = io.open(aname,"w")
51 
52         vhandle, vname = mkstemp()
53         os.close(vhandle)
54         vfile = io.open(vname,"w")
55 
56         afile.write(signature)
57         vfile.write(signature)
58         vfile.write("%s anything\n" % settings.GROUP_VIRTUAL_DOMAIN)
59 
60         # Loop through each group type and build -ads and -chairs entries
61         for g in GROUP_TYPES:
62             domains = []
63             domains += IETF_DOMAIN
64             if g == 'rg':
65                 domains += IRTF_DOMAIN
66             if g == 'program':
67                 domains += IAB_DOMAIN
68 
69             entries = Group.objects.filter(type=g).all()
70             active_entries = entries.filter(state__in=ACTIVE_STATES)
71             inactive_recent_entries = entries.exclude(state__in=ACTIVE_STATES).filter(time__gte=show_since)
72             interesting_entries = active_entries | inactive_recent_entries
73 
74             for e in interesting_entries.distinct().iterator():
75                 name = e.acronym
76                 
77                 # Research groups, teams, and programs do not have -ads lists
78                 if not g in NO_AD_GROUP_TYPES:
79                     dump_sublist(afile, vfile, name+'-ads', domains, settings.GROUP_VIRTUAL_DOMAIN, get_group_ad_emails(e))
80                 # All group types have -chairs lists
81                 dump_sublist(afile, vfile, name+'-chairs', domains, settings.GROUP_VIRTUAL_DOMAIN, get_group_role_emails(e, ['chair', 'secr']))
82 
83         # The area lists include every chair in active working groups in the area
84         areas = Group.objects.filter(type='area').all()
85         active_areas = areas.filter(state__in=ACTIVE_STATES)
86         for area in active_areas:
87             name = area.acronym
88             area_ad_emails = get_group_role_emails(area, ['pre-ad', 'ad', 'chair'])
89             dump_sublist(afile, vfile, name+'-ads', IETF_DOMAIN, settings.GROUP_VIRTUAL_DOMAIN, area_ad_emails)
90             dump_sublist(afile, vfile, name+'-chairs', IETF_DOMAIN, settings.GROUP_VIRTUAL_DOMAIN, (get_child_group_role_emails(area, ['chair', 'secr']) | area_ad_emails))
91 
92         # Other groups with chairs that require Internet-Draft submission approval
93         gtypes = GroupTypeName.objects.values_list('slug', flat=True)
94         special_groups = Group.objects.filter(type__features__req_subm_approval=True, acronym__in=gtypes, state='active')
95         for group in special_groups:
96             dump_sublist(afile, vfile, group.acronym+'-chairs', IETF_DOMAIN, settings.GROUP_VIRTUAL_DOMAIN, get_group_role_emails(group, ['chair', 'delegate']))
97 
98         afile.close()
99         vfile.close()
100 
101         os.chmod(aname, stat.S_IWUSR|stat.S_IRUSR|stat.S_IRGRP|stat.S_IROTH) 
102         os.chmod(vname, stat.S_IWUSR|stat.S_IRUSR|stat.S_IRGRP|stat.S_IROTH) 
103 
104         shutil.move(aname, settings.GROUP_ALIASES_PATH)
105         shutil.move(vname, settings.GROUP_VIRTUAL_PATH)
106
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/ietf/group/management/commands/generate_group_aliases.py b/ietf/group/management/commands/generate_group_aliases.py
--- a/ietf/group/management/commands/generate_group_aliases.py
+++ b/ietf/group/management/commands/generate_group_aliases.py
@@ -26,8 +26,8 @@
 
 DEFAULT_YEARS = 5
 ACTIVE_STATES=['active', 'bof', 'proposed']
-GROUP_TYPES=['wg', 'rg', 'dir', 'team', 'review', 'program', 'rfcedtyp']
-NO_AD_GROUP_TYPES=['rg', 'team', 'program', 'rfcedtyp']
+GROUP_TYPES=['wg', 'rg', 'rag', 'dir', 'team', 'review', 'program', 'rfcedtyp']
+NO_AD_GROUP_TYPES=['rg', 'rag', 'team', 'program', 'rfcedtyp']
 IETF_DOMAIN=['ietf.org', ]
 IRTF_DOMAIN=['irtf.org', ]
 IAB_DOMAIN=['iab.org', ]
@@ -61,7 +61,7 @@
         for g in GROUP_TYPES:
             domains = []
             domains += IETF_DOMAIN
-            if g == 'rg':
+            if g in ('rg', 'rag'):
                 domains += IRTF_DOMAIN
             if g == 'program':
                 domains += IAB_DOMAIN

{"golden_diff": "diff --git a/ietf/group/management/commands/generate_group_aliases.py b/ietf/group/management/commands/generate_group_aliases.py\n--- a/ietf/group/management/commands/generate_group_aliases.py\n+++ b/ietf/group/management/commands/generate_group_aliases.py\n@@ -26,8 +26,8 @@\n \n DEFAULT_YEARS = 5\n ACTIVE_STATES=['active', 'bof', 'proposed']\n-GROUP_TYPES=['wg', 'rg', 'dir', 'team', 'review', 'program', 'rfcedtyp']\n-NO_AD_GROUP_TYPES=['rg', 'team', 'program', 'rfcedtyp']\n+GROUP_TYPES=['wg', 'rg', 'rag', 'dir', 'team', 'review', 'program', 'rfcedtyp']\n+NO_AD_GROUP_TYPES=['rg', 'rag', 'team', 'program', 'rfcedtyp']\n IETF_DOMAIN=['ietf.org', ]\n IRTF_DOMAIN=['irtf.org', ]\n IAB_DOMAIN=['iab.org', ]\n@@ -61,7 +61,7 @@\n         for g in GROUP_TYPES:\n             domains = []\n             domains += IETF_DOMAIN\n-            if g == 'rg':\n+            if g in ('rg', 'rag'):\n                 domains += IRTF_DOMAIN\n             if g == 'program':\n                 domains += IAB_DOMAIN\n", "issue": "Missing chair email aliases for research area groups\n### Describe the issue\n\nThere are two Research Area Groups in the datatracker, anrw and irtfopen. These groups have a chair listed, but the email expansions at https://datatracker.ietf.org/group/irtfopen/email/ appear to be missing the chairs alias (irtfopen-chair@ietf.org) and email sent to that address bounces. Similarly, presumably, for anrw.\r\n\r\n\n\n### Code of Conduct\n\n- [X] I agree to follow the [IETF's Code of Conduct](https://github.com/ietf-tools/.github/blob/main/CODE_OF_CONDUCT.md)\n", "before_files": [{"content": "# Copyright The IETF Trust 2012-2021, All Rights Reserved\n# -*- coding: utf-8 -*-\n\n# This was written as a script by Markus Stenberg <markus.stenberg@iki.fi>.\n# It was turned into a management command by Russ Housley <housley@vigisec.com>.\n\nimport datetime\nimport io\nimport os\nimport shutil\nimport stat\nimport time\n\nfrom tempfile import mkstemp\n    \nfrom django.conf import settings\nfrom django.core.management.base import BaseCommand\nfrom django.utils import timezone\n\nimport debug                            # pyflakes:ignore\n\nfrom ietf.group.models import Group\nfrom ietf.group.utils import get_group_ad_emails, get_group_role_emails, get_child_group_role_emails\nfrom ietf.name.models import GroupTypeName\nfrom ietf.utils.aliases import dump_sublist\n\nDEFAULT_YEARS = 5\nACTIVE_STATES=['active', 'bof', 'proposed']\nGROUP_TYPES=['wg', 'rg', 'dir', 'team', 'review', 'program', 'rfcedtyp']\nNO_AD_GROUP_TYPES=['rg', 'team', 'program', 'rfcedtyp']\nIETF_DOMAIN=['ietf.org', ]\nIRTF_DOMAIN=['irtf.org', ]\nIAB_DOMAIN=['iab.org', ]\n\nclass Command(BaseCommand):\n    help = ('Generate the group-aliases and group-virtual files for Internet-Draft '\n            'mail aliases, placing them in the file configured in '\n            'settings.GROUP_ALIASES_PATH and settings.GROUP_VIRTUAL_PATH, '\n            'respectively.  The generation includes aliases for groups that '\n            'have seen activity in the last %s years.' % (DEFAULT_YEARS))\n\n    def handle(self, *args, **options):\n        show_since = timezone.now() - datetime.timedelta(DEFAULT_YEARS*365)\n\n        date = time.strftime(\"%Y-%m-%d_%H:%M:%S\")\n        signature = '# Generated by %s at %s\\n' % (os.path.abspath(__file__), date)\n\n        ahandle, aname = mkstemp()\n        os.close(ahandle)\n        afile = io.open(aname,\"w\")\n\n        vhandle, vname = mkstemp()\n        os.close(vhandle)\n        vfile = io.open(vname,\"w\")\n\n        afile.write(signature)\n        vfile.write(signature)\n        vfile.write(\"%s anything\\n\" % settings.GROUP_VIRTUAL_DOMAIN)\n\n        # Loop through each group type and build -ads and -chairs entries\n        for g in GROUP_TYPES:\n            domains = []\n            domains += IETF_DOMAIN\n            if g == 'rg':\n                domains += IRTF_DOMAIN\n            if g == 'program':\n                domains += IAB_DOMAIN\n\n            entries = Group.objects.filter(type=g).all()\n            active_entries = entries.filter(state__in=ACTIVE_STATES)\n            inactive_recent_entries = entries.exclude(state__in=ACTIVE_STATES).filter(time__gte=show_since)\n            interesting_entries = active_entries | inactive_recent_entries\n\n            for e in interesting_entries.distinct().iterator():\n                name = e.acronym\n                \n                # Research groups, teams, and programs do not have -ads lists\n                if not g in NO_AD_GROUP_TYPES:\n                    dump_sublist(afile, vfile, name+'-ads', domains, settings.GROUP_VIRTUAL_DOMAIN, get_group_ad_emails(e))\n                # All group types have -chairs lists\n                dump_sublist(afile, vfile, name+'-chairs', domains, settings.GROUP_VIRTUAL_DOMAIN, get_group_role_emails(e, ['chair', 'secr']))\n\n        # The area lists include every chair in active working groups in the area\n        areas = Group.objects.filter(type='area').all()\n        active_areas = areas.filter(state__in=ACTIVE_STATES)\n        for area in active_areas:\n            name = area.acronym\n            area_ad_emails = get_group_role_emails(area, ['pre-ad', 'ad', 'chair'])\n            dump_sublist(afile, vfile, name+'-ads', IETF_DOMAIN, settings.GROUP_VIRTUAL_DOMAIN, area_ad_emails)\n            dump_sublist(afile, vfile, name+'-chairs', IETF_DOMAIN, settings.GROUP_VIRTUAL_DOMAIN, (get_child_group_role_emails(area, ['chair', 'secr']) | area_ad_emails))\n\n        # Other groups with chairs that require Internet-Draft submission approval\n        gtypes = GroupTypeName.objects.values_list('slug', flat=True)\n        special_groups = Group.objects.filter(type__features__req_subm_approval=True, acronym__in=gtypes, state='active')\n        for group in special_groups:\n            dump_sublist(afile, vfile, group.acronym+'-chairs', IETF_DOMAIN, settings.GROUP_VIRTUAL_DOMAIN, get_group_role_emails(group, ['chair', 'delegate']))\n\n        afile.close()\n        vfile.close()\n\n        os.chmod(aname, stat.S_IWUSR|stat.S_IRUSR|stat.S_IRGRP|stat.S_IROTH) \n        os.chmod(vname, stat.S_IWUSR|stat.S_IRUSR|stat.S_IRGRP|stat.S_IROTH) \n\n        shutil.move(aname, settings.GROUP_ALIASES_PATH)\n        shutil.move(vname, settings.GROUP_VIRTUAL_PATH)\n", "path": "ietf/group/management/commands/generate_group_aliases.py"}], "after_files": [{"content": "# Copyright The IETF Trust 2012-2021, All Rights Reserved\n# -*- coding: utf-8 -*-\n\n# This was written as a script by Markus Stenberg <markus.stenberg@iki.fi>.\n# It was turned into a management command by Russ Housley <housley@vigisec.com>.\n\nimport datetime\nimport io\nimport os\nimport shutil\nimport stat\nimport time\n\nfrom tempfile import mkstemp\n    \nfrom django.conf import settings\nfrom django.core.management.base import BaseCommand\nfrom django.utils import timezone\n\nimport debug                            # pyflakes:ignore\n\nfrom ietf.group.models import Group\nfrom ietf.group.utils import get_group_ad_emails, get_group_role_emails, get_child_group_role_emails\nfrom ietf.name.models import GroupTypeName\nfrom ietf.utils.aliases import dump_sublist\n\nDEFAULT_YEARS = 5\nACTIVE_STATES=['active', 'bof', 'proposed']\nGROUP_TYPES=['wg', 'rg', 'rag', 'dir', 'team', 'review', 'program', 'rfcedtyp']\nNO_AD_GROUP_TYPES=['rg', 'rag', 'team', 'program', 'rfcedtyp']\nIETF_DOMAIN=['ietf.org', ]\nIRTF_DOMAIN=['irtf.org', ]\nIAB_DOMAIN=['iab.org', ]\n\nclass Command(BaseCommand):\n    help = ('Generate the group-aliases and group-virtual files for Internet-Draft '\n            'mail aliases, placing them in the file configured in '\n            'settings.GROUP_ALIASES_PATH and settings.GROUP_VIRTUAL_PATH, '\n            'respectively.  The generation includes aliases for groups that '\n            'have seen activity in the last %s years.' % (DEFAULT_YEARS))\n\n    def handle(self, *args, **options):\n        show_since = timezone.now() - datetime.timedelta(DEFAULT_YEARS*365)\n\n        date = time.strftime(\"%Y-%m-%d_%H:%M:%S\")\n        signature = '# Generated by %s at %s\\n' % (os.path.abspath(__file__), date)\n\n        ahandle, aname = mkstemp()\n        os.close(ahandle)\n        afile = io.open(aname,\"w\")\n\n        vhandle, vname = mkstemp()\n        os.close(vhandle)\n        vfile = io.open(vname,\"w\")\n\n        afile.write(signature)\n        vfile.write(signature)\n        vfile.write(\"%s anything\\n\" % settings.GROUP_VIRTUAL_DOMAIN)\n\n        # Loop through each group type and build -ads and -chairs entries\n        for g in GROUP_TYPES:\n            domains = []\n            domains += IETF_DOMAIN\n            if g in ('rg', 'rag'):\n                domains += IRTF_DOMAIN\n            if g == 'program':\n                domains += IAB_DOMAIN\n\n            entries = Group.objects.filter(type=g).all()\n            active_entries = entries.filter(state__in=ACTIVE_STATES)\n            inactive_recent_entries = entries.exclude(state__in=ACTIVE_STATES).filter(time__gte=show_since)\n            interesting_entries = active_entries | inactive_recent_entries\n\n            for e in interesting_entries.distinct().iterator():\n                name = e.acronym\n                \n                # Research groups, teams, and programs do not have -ads lists\n                if not g in NO_AD_GROUP_TYPES:\n                    dump_sublist(afile, vfile, name+'-ads', domains, settings.GROUP_VIRTUAL_DOMAIN, get_group_ad_emails(e))\n                # All group types have -chairs lists\n                dump_sublist(afile, vfile, name+'-chairs', domains, settings.GROUP_VIRTUAL_DOMAIN, get_group_role_emails(e, ['chair', 'secr']))\n\n        # The area lists include every chair in active working groups in the area\n        areas = Group.objects.filter(type='area').all()\n        active_areas = areas.filter(state__in=ACTIVE_STATES)\n        for area in active_areas:\n            name = area.acronym\n            area_ad_emails = get_group_role_emails(area, ['pre-ad', 'ad', 'chair'])\n            dump_sublist(afile, vfile, name+'-ads', IETF_DOMAIN, settings.GROUP_VIRTUAL_DOMAIN, area_ad_emails)\n            dump_sublist(afile, vfile, name+'-chairs', IETF_DOMAIN, settings.GROUP_VIRTUAL_DOMAIN, (get_child_group_role_emails(area, ['chair', 'secr']) | area_ad_emails))\n\n        # Other groups with chairs that require Internet-Draft submission approval\n        gtypes = GroupTypeName.objects.values_list('slug', flat=True)\n        special_groups = Group.objects.filter(type__features__req_subm_approval=True, acronym__in=gtypes, state='active')\n        for group in special_groups:\n            dump_sublist(afile, vfile, group.acronym+'-chairs', IETF_DOMAIN, settings.GROUP_VIRTUAL_DOMAIN, get_group_role_emails(group, ['chair', 'delegate']))\n\n        afile.close()\n        vfile.close()\n\n        os.chmod(aname, stat.S_IWUSR|stat.S_IRUSR|stat.S_IRGRP|stat.S_IROTH) \n        os.chmod(vname, stat.S_IWUSR|stat.S_IRUSR|stat.S_IRGRP|stat.S_IROTH) \n\n        shutil.move(aname, settings.GROUP_ALIASES_PATH)\n        shutil.move(vname, settings.GROUP_VIRTUAL_PATH)\n", "path": "ietf/group/management/commands/generate_group_aliases.py"}]}