datatracker/ietf/bin/generate-draft-aliases
Henrik Levkowetz a2318d9f2c Backported patches from production
- Legacy-Id: 17370
2020-02-28 20:46:20 +00:00

179 lines
6.5 KiB
Python
Executable file

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# -*- Python -*-
#
# $Id: generate-draft-aliases $
#
# Author: Markus Stenberg <markus.stenberg@iki.fi>
#
"""
This script requires that the proper virtual python environment has been
invoked before start.
This code dumps Django model InternetDraft's contents as postfix email
aliases.
<no suffix> (same as -authors)
.authors (list of authors)
.chairs (WG chairs)
.notify (notify emails(?))
.ad (sponsoring AD)
.all (all of the above)
TODO:
- results somewhat inconsistent with the results from the old tool;
should examine why (ask me for diff tool if interested in fixing it)
"""
# boilerplate (from various other ietf/bin scripts)
import io, os, sys, re
filename = os.path.abspath(__file__)
basedir = os.path.abspath(os.path.join(os.path.dirname(__file__), "../.."))
sys.path = [ basedir ] + sys.path
os.environ["DJANGO_SETTINGS_MODULE"] = "ietf.settings"
import django
django.setup()
from django.conf import settings
from ietf.doc.models import Document
from ietf.group.utils import get_group_role_emails, get_group_ad_emails
from ietf.utils.aliases import dump_sublist
from email.utils import parseaddr
from ietf.utils.mail import formataddr
def get_draft_ad_emails(draft):
" Get AD email for the given draft, if any. "
# If working group document, return current WG ADs
wg = draft.group
if wg and wg.acronym != 'none' and wg.parent and wg.parent.acronym != 'none':
ad_emails = get_group_ad_emails(wg)
if draft.ad:
if draft.ad.email_address() not in ad_emails:
ad_emails.add(draft.ad.email_address())
return ad_emails
# If not, return explicit AD set (whether up to date or not)
ad = draft.ad
#return [ad and ad.user and ad.user.email]
return [ad and ad.email_address()]
def get_draft_shepherd_email(draft):
return [ draft.shepherd.email_address() ] if draft.shepherd else []
def get_draft_authors_emails(draft):
" Get list of authors for the given draft."
# This feels 'correct'; however, it creates fairly large delta
return [author.email.email_address() for author in draft.documentauthor_set.all() if author.email and author.email.email_address()]
# This gives fairly small delta compared to current state,
# however, it seems to be wrong (doesn't check for emails being
# active etc).
#return [email.address for email in draft.authors.all()]
def get_draft_notify_emails(draft):
" Get list of email addresses to notify for the given draft."
n = draft.notify
if not n:
return []
l = []
ad_email_alias_regex = "^%s\.ad@(%s|%s)$" % (draft.name, settings.DRAFT_ALIAS_DOMAIN, settings.TOOLS_SERVER)
all_email_alias_regex = "^%s\.all@(%s|%s)$" % (draft.name, settings.DRAFT_ALIAS_DOMAIN, settings.TOOLS_SERVER)
author_email_alias_regex = "^%s@(%s|%s)$" % (draft.name, settings.DRAFT_ALIAS_DOMAIN, settings.TOOLS_SERVER)
notify_email_alias_regex = "^%s\.notify@(%s|%s)$" % (draft.name, settings.DRAFT_ALIAS_DOMAIN, settings.TOOLS_SERVER)
shepherd_email_alias_regex = "^%s\.shepherd@(%s|%s)$" % (draft.name, settings.DRAFT_ALIAS_DOMAIN, settings.TOOLS_SERVER)
for e in n.split(','):
# If one of the directly expandable aliases are listed in the notify
# list, we expand it
e = e.strip()
if re.search(ad_email_alias_regex, e):
l.extend(get_draft_ad_emails(draft))
elif re.search(author_email_alias_regex, e):
l.extend(get_draft_authors_emails(draft))
elif re.search(shepherd_email_alias_regex, e):
l.extend(get_draft_shepherd_email(draft))
elif re.search(all_email_alias_regex, e):
l.extend(get_draft_ad_emails(draft))
l.extend(get_draft_authors_emails(draft))
l.extend(get_draft_shepherd_email(draft))
elif re.search(notify_email_alias_regex, e):
pass
else:
e = formataddr(parseaddr(e))
l.append(e)
# Alternative: if we don't want to do expansion, just this would be
# perhaps better (MTA can do expansion too):
# l = n.split(',')
return l
if __name__ == '__main__':
import datetime
import time
# Year ago?
show_since = datetime.datetime.now() - datetime.timedelta(2*365)
# 10 years ago?
#show_since = datetime.datetime.now() - datetime.timedelta(10 * 365)
date = time.strftime("%Y-%m-%d_%H:%M:%S")
signature = '# Generated by %s at %s\n' % (filename, date)
afile = io.open(settings.DRAFT_ALIASES_PATH, "w")
vfile = io.open(settings.DRAFT_VIRTUAL_PATH, "w")
afile.write(signature)
vfile.write(signature)
vfile.write("%s anything\n" % settings.DRAFT_VIRTUAL_DOMAIN)
drafts = Document.objects.filter(name__startswith='draft-')
# Drafts with active status
active_drafts = drafts.filter(states__slug='active')
# Drafts that expired within year
inactive_recent_drafts = drafts.exclude(states__slug='active').filter(expires__gte=show_since)
interesting_drafts = active_drafts | inactive_recent_drafts
alias_domains = ['ietf.org', ]
for draft in interesting_drafts.distinct().iterator():
# Omit RFCs, we care only about drafts
if draft.docalias.filter(name__startswith='rfc'):
if (datetime.datetime.now() - draft.latest_event(type='published_rfc').time) > datetime.timedelta(days= 365 * 3 ):
continue
alias = draft.name
all = []
def handle_sublist(afile, vfile, alias, emails):
all.extend( dump_sublist(afile, vfile, alias, alias_domains, settings.DRAFT_VIRTUAL_DOMAIN, emails) )
#.authors (/and no suffix) = authors
# First, do no suffix case
handle_sublist(afile, vfile, alias, get_draft_authors_emails(draft))
handle_sublist(afile, vfile, alias+'.authors', get_draft_authors_emails(draft))
# .chairs = group chairs
if draft.group:
handle_sublist(afile, vfile, alias+'.chairs', get_group_role_emails(draft.group, ['chair', 'secr']))
# .ad = sponsoring AD / WG AD (WG document)
handle_sublist(afile, vfile, alias+'.ad', get_draft_ad_emails(draft))
# .notify = notify email list from the Document
handle_sublist(afile, vfile, alias+'.notify', get_draft_notify_emails(draft))
# .shepherd = shepherd email from the Document
handle_sublist(afile, vfile, alias+'.shepherd', get_draft_shepherd_email(draft))
# .all = everything on 'all' (expanded aliases)
handle_sublist(afile, vfile, alias+'.all', all)
afile.close()
vfile.close()