def notify(self, request=None): import process.views ctx = { "visitor": self.audit_author, "person": self.person, "process": self._process, "process_url": build_absolute_uri(self._process.get_absolute_url(), request), "emeritus_url": process.views.Emeritus.get_nonauth_url(self.person, request), "cancel_url": build_absolute_uri(reverse("process_cancel", args=[self._process.pk]), request), "deadline": self._process.hide_until, "text": self.text, } from django.template.loader import render_to_string body = render_to_string("mia/mia_ping_email.txt", ctx).strip() mia_addr = "mia-{}@qa.debian.org".format(self.person.uid) from process.email import build_django_message msg = build_django_message( from_email=("Debian MIA team", "*****@*****.**"), to=[self.person.email], cc=[self._process.archive_email], bcc=[mia_addr, "*****@*****.**"], subject="WAT: Are you still active in Debian? ({})".format(self.person.uid), headers={ "X-MIA-Summary": "out, wat; WAT by nm.d.o", }, body=body) msg.send()
def notify(self, request=None): import process.views ctx = { "visitor": self.audit_author, "person": self.process.person, "process": self.process, "process_url": build_absolute_uri(self.process.get_absolute_url(), request), "emeritus_url": process.views.Emeritus.get_nonauth_url(self.process.person, request), "cancel_url": build_absolute_uri(reverse("process_cancel", args=[self.process.pk]), request), "deadline": self.process.hide_until, "text": self.text, } from django.template.loader import render_to_string body = render_to_string("mia/mia_remove_email.txt", ctx).strip() mia_addr = "mia-{}@qa.debian.org".format(self.process.person.uid) from process.email import build_django_message msg = build_django_message( from_email=("Debian MIA team", "*****@*****.**"), to=["*****@*****.**"], cc=[self.process.person.email, self.process.archive_email], bcc=[mia_addr, "*****@*****.**"], subject="Debian Project member MIA: {} ({})".format( self.process.person.fullname, self.process.person.uid ), headers={ "X-MIA-Summary": "out; public removal pre-announcement", }, body=body) msg.send()
def get_nonauth_url(cls, person, request=None): from django.utils.http import urlencode if person.uid is None: raise RuntimeError("cannot generate an Emeritus url for a user without uid") url = reverse("process_emeritus") + "?" + cls.make_token(person.uid) if not request: return url return build_absolute_uri(url, request)
def notify_new_dd(process, request=None): """ Render a notification email template to let [email protected] know of new DDs, then send the resulting email. """ if request is None: url = "https://{}{}".format(Site.objects.get_current().domain, process.get_absolute_url()) else: url = build_absolute_uri(process.get_absolute_url(), request) body = """Hello, {process.person.fullname} <{process.person.uid}> has just become a {status}. The nm.debian.org page for this process is at {url} Debian New Member Front Desk """ body = body.format(process=process, status=const.ALL_STATUS_DESCS[process.applying_for], url=url) msg = build_django_message( from_email=("nm.debian.org", "*****@*****.**"), to=["*****@*****.**"], subject="New {}: {} <{}>".format( const.ALL_STATUS_DESCS[process.applying_for], process.person.fullname, process.person.uid), body=body) msg.send() log.debug("sent mail from %s to %s cc %s bcc %s subject %s", msg.from_email, ", ".join(msg.to), ", ".join(msg.cc), ", ".join(msg.bcc), msg.subject)
def notify(self, request=None): process = self.process url = build_absolute_uri(process.get_absolute_url(), request) body = """{op.statement} {op.audit_author.fullname} (via nm.debian.org) """ body += "-- \n" body += "{url}\n" body = body.format(op=self, url=url) cc = [process.person, process.archive_email] if self.is_public: subject = "{}: new public log entry".format(process.person.fullname) else: subject = "{}: new private log entry".format(process.person.fullname) msg = build_django_message( self.audit_author, to="*****@*****.**", cc=cc, bcc=["mia-{}@qa.debian.org".format(process.person.uid)], subject=subject, headers={ # See /srv/qa.debian.org/mia/README "X-MIA-Summary": "in, ok; still active via nm.d.o", }, body=body) msg.send()
def notify(self, request=None): process = self._statement.requirement.process url = build_absolute_uri(process.get_absolute_url(), request) body = """{statement.statement} {statement.uploaded_by.fullname} (via nm.debian.org) For details and to comment, visit {url} """ body += "-- \n" # Note the trailing space body += "{url}\n" body = body.format(statement=self._statement, url=url) mia_address = "mia-{}@qa.debian.org".format(process.person.uid) cc = [process.archive_email] bcc = [] if self.silent: to = mia_address else: to = "*****@*****.**" cc.append(process.person) bcc.append(mia_address) msg = build_django_message( self._statement.uploaded_by, to=to, cc=cc, bcc=bcc, subject="Retiring from the Project", headers={"X-MIA-Summary": "in, retired; emeritus via nm.d.o"}, # See /srv/qa.debian.org/mia/README body=body) msg.send()
def notify_new_statement(statement, request=None, cc_nm=True, notify_ml="newmaint", mia=None): """ Render a notification email template for a newly uploaded statement, then send the resulting email. """ process = statement.requirement.process if request is None: url = "https://{}{}".format(Site.objects.get_current().domain, process.get_absolute_url()) else: url = build_absolute_uri(process.get_absolute_url(), request) body = """{statement.statement} {statement.uploaded_by.fullname} (via nm.debian.org) For details and to comment, visit {url} """ body += "-- \n" body += "{url}\n" body = body.format(statement=statement, url=url) cc = [process.person, process.archive_email] if cc_nm: cc.append("*****@*****.**") headers = {} if mia is not None: headers["X-MIA-Summary"] = mia cc.append("mia-{}@qa.debian.org".format(process.person.uid)) msg = build_django_message( statement.uploaded_by, to="debian-{}@lists.debian.org".format(notify_ml), cc=cc, subject="{}: {}".format(process.person.fullname, statement.requirement.type_desc), headers=headers, body=body) msg.send() log.debug("sent mail from %s to %s cc %s bcc %s subject %s", msg.from_email, ", ".join(msg.to), ", ".join(msg.cc), ", ".join(msg.bcc), msg.subject)
def notify_am_assigned(assignment, request=None): """ Render a notification email template for an AM assignment, then send the resulting email. """ process = assignment.process if request is None: url = "https://{}{}".format(Site.objects.get_current().domain, process.get_absolute_url()) else: url = build_absolute_uri(process.get_absolute_url(), request) body = """Hello, {process.person.fullname} meet {am.person.fullname}, your new application manager. {am.person.fullname} meet {process.person.fullname}, your new applicant. The next step is usually one of these: - the application manager sends an email to the applicant starting a conversation; - the application manager has no time and goes to {url}/am_ok to undo the assignment. The nm.debian.org page for this process is at {url} I hope you have a good time, and if you need anything please mail [email protected]. {assignment.assigned_by.fullname} for Front Desk """ body = body.format(process=process, am=assignment.am.person, assignment=assignment, url=url) msg = build_django_message( assignment.assigned_by, to=[process.person, assignment.am.person], cc=process.archive_email, subject="New Member process, {}".format( const.ALL_STATUS_DESCS[process.applying_for]), body=body) msg.send() log.debug("sent mail from %s to %s cc %s bcc %s subject %s", msg.from_email, ", ".join(msg.to), ", ".join(msg.cc), ", ".join(msg.bcc), msg.subject)
def ping_process(pinger, process, message=None, request=None): """ Render a notification email template for pinging a stuck process, then send the resulting email. """ if request is None: url = "https://{}{}".format(Site.objects.get_current().domain, process.get_absolute_url()) else: url = build_absolute_uri(process.get_absolute_url(), request) format_args = { "process": process, "pinger": pinger, "url": url, } body = [ """Hello, the process at {url} looks stuck. """.format(**format_args) ] if message: body.append(message) body.append(""" If you need help with anything, please mail [email protected]. {pinger.fullname} for Front Desk """.format(**format_args)) to = [process.person] assignment = process.current_am_assignment if assignment: to.append(assignment.am.person) msg = build_django_message(pinger, to=to, cc=[process.archive_email, "*****@*****.**"], subject="NM process stuck?", body="".join(body)) msg.send() log.debug("sent mail from %s to %s cc %s bcc %s subject %s", msg.from_email, ", ".join(msg.to), ", ".join(msg.cc), ", ".join(msg.bcc), msg.subject)
def notify_new_process(process, request=None): """ Render a notification email template for a newly uploaded statement, then send the resulting email. """ if request is None: url = "https://{}{}".format(Site.objects.get_current().domain, process.get_absolute_url()) else: url = build_absolute_uri(process.get_absolute_url(), request) body = """Hello, you have just started a new process to become {applying_for}. The nm.debian.org page for managing this process is at {url} That page lists several requirements that need to be fulfilled for this process to complete. Some of those you can provide yourself: look at the page for a list and some explanation. I hope you have a smooth process, and if you need anything please mail [email protected]. Yours, the nm.debian.org housekeeping robot """ body = body.format( applying_for=const.ALL_STATUS_DESCS[process.applying_for], process=process, url=url) msg = build_django_message( from_email=("nm.debian.org", "*****@*****.**"), to=process.person, cc=process.archive_email, subject="New Member process, {}".format( const.ALL_STATUS_DESCS[process.applying_for]), body=body) msg.send() log.debug("sent mail from %s to %s cc %s bcc %s subject %s", msg.from_email, ", ".join(msg.to), ", ".join(msg.cc), ", ".join(msg.bcc), msg.subject)
def notify_new_log_entry(entry, request=None, mia=None): """ Render a notification email template for a newly uploaded process log entry, then send the resulting email. """ process = entry.process url = build_absolute_uri(process.get_absolute_url(), request) body = """{entry.logtext} {entry.changed_by.fullname} (via nm.debian.org) """ body += "-- \n" body += "{url}\n" body = body.format(entry=entry, url=url) if entry.is_public: cc = [process.person, process.archive_email] subject = "{}: new public log entry".format(process.person.fullname) else: cc = [] subject = "{}: new private log entry".format(process.person.fullname) headers = {} if mia is not None: headers["X-MIA-Summary"] = mia cc.append("mia-{}@qa.debian.org".format(process.person.uid)) msg = build_django_message(entry.changed_by, to="*****@*****.**", cc=cc, subject=subject, headers=headers, body=body) msg.send() log.debug("sent mail from %s to %s cc %s bcc %s subject %s", msg.from_email, ", ".join(msg.to), ", ".join(msg.cc), ", ".join(msg.bcc), msg.subject)
def make_rt_ticket_text(request, visitor, process): retiring = process.applying_for in (const.STATUS_EMERITUS_DD, const.STATUS_REMOVED_DD) ctx = { "visitor": visitor, "person": process.person, "process": process, "retiring": retiring, } ## Build request text req = [] if process.person.status == const.STATUS_DC: if process.applying_for == const.STATUS_DC_GA: req.append("Please create a porter account for {person.fullname} (sponsored by {sponsors}).") elif process.person.status == const.STATUS_DC_GA: pass elif process.person.status == const.STATUS_DM: if process.applying_for == const.STATUS_DM_GA: req.append("Please create a porter account for {person.fullname} (currently a DM).") elif process.person.status == const.STATUS_DM_GA: pass elif process.person.status == const.STATUS_DD_NU: pass elif process.person.status == const.STATUS_EMERITUS_DD: pass elif process.person.status == const.STATUS_REMOVED_DD: pass only_guest_account = only_needs_guest_account(process) if retiring: req.append("Please make {person.fullname} (currently '{status}') a '{applying_for}'.") elif not only_guest_account: req.append("Please make {person.fullname} (currently '{status}') a '{applying_for}' (advocated by {sponsors}).") if not only_guest_account: if process.person.status == const.STATUS_DC: req.append("Key {person.fpr} should be added to the '{applying_for}' keyring.") else: req.append("Key {person.fpr} should be moved from the '{status}' to the '{applying_for}' keyring.") if retiring: req.append("Please also disable the {person.uid} LDAP account.") elif process.person.status not in (const.STATUS_DC, const.STATUS_DM): req.append("Note that {person.fullname} already has an account in LDAP.") sponsors = set() try: adv_req = process.requirements.get(type="advocate") except pmodels.Requirement.DoesNotExist: adv_req = None if adv_req is not None: for st in adv_req.statements.all(): sponsors.add(st.uploaded_by.lookup_key) sponsors = ", ".join(sorted(sponsors)) format_args = { "person": process.person, "process": process, "status": const.ALL_STATUS_DESCS[process.person.status], "applying_for": const.ALL_STATUS_DESCS[process.applying_for], "sponsors": sponsors, } import textwrap wrapper = textwrap.TextWrapper(width=75) wrapped = [] for paragraph in req: for line in wrapper.wrap(paragraph.format(**format_args)): wrapped.append(line) wrapped.append("") ctx["request"] = "\n".join(wrapped) # Format the declarations of intent wrapper = textwrap.TextWrapper(width=75, initial_indent=" ", subsequent_indent=" ") wrapped = [] intents_from = set() for intent in pmodels.Statement.objects.filter(requirement__process=process, requirement__type="intent"): intents_from.add(intent.uploaded_by) for paragraph in intent.statement_clean.splitlines(): for line in wrapper.wrap(paragraph): wrapped.append(line) wrapped.append("") ctx["intents"] = "\n".join(wrapped) ctx["intents_from"] = ", ".join(x.uid for x in sorted(intents_from)) ctx["process_url"] = build_absolute_uri(process.get_absolute_url(), request) from django.template.loader import render_to_string return render_to_string("process/rt_ticket.txt", ctx).strip()