442
442
def getSubscribedAddresses(self):
443
443
"""See `IMailingList`."""
444
store = Store.of(self)
445
# In order to handle the case where the preferred email address is
446
# used (i.e. where MailingListSubscription.email_address is NULL), we
447
# need to UNION, those using a specific address and those using the
451
Join(Person, Person.id == EmailAddress.personID),
452
Join(Account, Account.id == Person.accountID),
453
Join(TeamParticipation, TeamParticipation.personID == Person.id),
455
MailingListSubscription,
456
MailingListSubscription.personID == Person.id),
459
MailingList.id == MailingListSubscription.mailing_listID),
461
preferred = store.using(*tables).find(
463
And(MailingListSubscription.mailing_list == self,
464
TeamParticipation.team == self.team,
465
MailingList.status != MailingListStatus.INACTIVE,
466
MailingListSubscription.email_addressID == None,
467
EmailAddress.status == EmailAddressStatus.PREFERRED,
468
Account.status == AccountStatus.ACTIVE))
469
explicit = store.using(*tables).find(
471
And(MailingListSubscription.mailing_list == self,
472
TeamParticipation.team == self.team,
473
MailingList.status != MailingListStatus.INACTIVE,
474
EmailAddress.id == MailingListSubscription.email_addressID,
475
Account.status == AccountStatus.ACTIVE))
476
# Union the two queries together to give us the complete list of email
477
# addresses allowed to post. Note that while we're retrieving both
478
# the EmailAddress and Person records, this method is defined as only
479
# returning EmailAddresses. The reason why we include the Person in
480
# the query is because the consumer of this method will access
481
# email_address.person.displayname, so the prejoin to Person is
482
# critical to acceptable performance. Indeed, without the prejoin, we
483
# were getting tons of timeout OOPSes. See bug 259440.
484
for email_address in preferred.union(explicit):
445
address for (name, address) in
446
getUtility(IMailingListSet).getSubscribedAddresses(
447
[self.team.name]).get(self.team.name, [])]
487
449
def getSenderAddresses(self):
488
450
"""See `IMailingList`."""
489
store = Store.of(self)
490
# First, we need to find all the members of the team this mailing list
491
# is associated with. Find all of their validated and preferred email
492
# addresses of those team members. Every one of those email addresses
493
# are allowed to post to the mailing list.
496
Join(Account, Account.id == Person.accountID),
497
Join(EmailAddress, EmailAddress.personID == Person.id),
498
Join(TeamParticipation, TeamParticipation.personID == Person.id),
499
Join(MailingList, MailingList.teamID == TeamParticipation.teamID),
501
team_members = store.using(*tables).find(
503
And(TeamParticipation.team == self.team,
504
MailingList.status != MailingListStatus.INACTIVE,
505
Person.teamowner == None,
506
EmailAddress.status.is_in(EMAIL_ADDRESS_STATUSES),
507
Account.status == AccountStatus.ACTIVE,
509
# Second, find all of the email addresses for all of the people who
510
# have been explicitly approved for posting to this mailing list.
511
# This occurs as part of first post moderation, but since they've
512
# already been approved for this list, we don't need to wait for three
516
Join(Account, Account.id == Person.accountID),
517
Join(EmailAddress, EmailAddress.personID == Person.id),
518
Join(MessageApproval, MessageApproval.posted_byID == Person.id),
520
approved_posters = store.using(*tables).find(
522
And(MessageApproval.mailing_list == self,
523
MessageApproval.status.is_in(MESSAGE_APPROVAL_STATUSES),
524
EmailAddress.status.is_in(EMAIL_ADDRESS_STATUSES),
525
Account.status == AccountStatus.ACTIVE,
527
# Union the two queries together to give us the complete list of email
528
# addresses allowed to post. Note that while we're retrieving both
529
# the EmailAddress and Person records, this method is defined as only
530
# returning EmailAddresses. The reason why we include the Person in
531
# the query is because the consumer of this method will access
532
# email_address.person.displayname, so the prejoin to Person is
533
# critical to acceptable performance. Indeed, without the prejoin, we
534
# were getting tons of timeout OOPSes. See bug 259440.
535
return team_members.union(approved_posters)
452
address for (name, address) in
453
getUtility(IMailingListSet).getSenderAddresses(
454
[self.team.name]).get(self.team.name, [])]
537
456
def holdMessage(self, message):
538
457
"""See `IMailingList`."""