summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--port_me/bumpdigests.py74
-rw-r--r--src/mailman/app/digests.py7
-rw-r--r--src/mailman/commands/cli_digests.py42
-rw-r--r--src/mailman/commands/tests/test_digests.py89
4 files changed, 110 insertions, 102 deletions
diff --git a/port_me/bumpdigests.py b/port_me/bumpdigests.py
deleted file mode 100644
index f30772ca8..000000000
--- a/port_me/bumpdigests.py
+++ /dev/null
@@ -1,74 +0,0 @@
-# Copyright (C) 1998-2015 by the Free Software Foundation, Inc.
-#
-# This file is part of GNU Mailman.
-#
-# GNU Mailman is free software: you can redistribute it and/or modify it under
-# the terms of the GNU General Public License as published by the Free
-# Software Foundation, either version 3 of the License, or (at your option)
-# any later version.
-#
-# GNU Mailman is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
-# more details.
-#
-# You should have received a copy of the GNU General Public License along with
-# GNU Mailman. If not, see <http://www.gnu.org/licenses/>.
-
-import sys
-import optparse
-
-from mailman import errors
-from mailman import MailList
-from mailman.configuration import config
-from mailman.core.i18n import _
-from mailman.version import MAILMAN_VERSION
-
-# Work around known problems with some RedHat cron daemons
-import signal
-signal.signal(signal.SIGCHLD, signal.SIG_DFL)
-
-
-
-def parseargs():
- parser = optparse.OptionParser(version=MAILMAN_VERSION,
- usage=_("""\
-%prog [options] [listname ...]
-
-Increment the digest volume number and reset the digest number to one. All
-the lists named on the command line are bumped. If no list names are given,
-all lists are bumped."""))
- parser.add_option('-C', '--config',
- help=_('Alternative configuration file to use'))
- opts, args = parser.parse_args()
- return opts, args, parser
-
-
-
-def main():
- opts, args, parser = parseargs()
- config.load(opts.config)
-
- listnames = set(args or config.list_manager.names)
- if not listnames:
- print(_('Nothing to do.'))
- sys.exit(0)
-
- for listname in listnames:
- try:
- # Be sure the list is locked
- mlist = MailList.MailList(listname)
- except errors.MMListError:
- parser.print_help()
- print(_('No such list: $listname'), file=sys.stderr)
- sys.exit(1)
- try:
- mlist.bump_digest_volume()
- finally:
- mlist.Save()
- mlist.Unlock()
-
-
-
-if __name__ == '__main__':
- main()
diff --git a/src/mailman/app/digests.py b/src/mailman/app/digests.py
index b66a4c54c..2190fdf98 100644
--- a/src/mailman/app/digests.py
+++ b/src/mailman/app/digests.py
@@ -28,9 +28,7 @@ import os
from mailman.config import config
from mailman.email.message import Message
from mailman.interfaces.digests import DigestFrequency
-from mailman.interfaces.listmanager import IListManager
from mailman.utilities.datetime import now as right_now
-from zope.component import getUtility
@@ -95,7 +93,10 @@ def maybe_send_digest_now(mlist, force=False):
# us exactly how big the resulting MIME and rfc1153 digest will
# actually be, but it's the most easily available metric to decide
# whether the size threshold has been reached.
- size = os.path.getsize(mailbox_path)
+ try:
+ size = os.path.getsize(mailbox_path)
+ except FileNotFoundError:
+ size = 0
if (size >= mlist.digest_size_threshold * 1024.0 or
(force and size > 0)):
# Send the digest. Because we don't want to hold up this process
diff --git a/src/mailman/commands/cli_digests.py b/src/mailman/commands/cli_digests.py
index 9af91f1c3..7d3de92b9 100644
--- a/src/mailman/commands/cli_digests.py
+++ b/src/mailman/commands/cli_digests.py
@@ -24,7 +24,8 @@ __all__ = [
import sys
-from mailman.app.digests import maybe_send_digest_now
+from mailman.app.digests import (
+ bump_digest_number_and_volume, maybe_send_digest_now)
from mailman.core.i18n import _
from mailman.interfaces.command import ICLISubCommand
from mailman.interfaces.listmanager import IListManager
@@ -59,33 +60,28 @@ class Digests:
default=False, action='store_true',
help=_("""Increment the digest volume number and reset the digest
number to one. If given with --send, the volume number is
- incremented after any current digests are sent."""))
+ incremented before any current digests are sent."""))
def process(self, args):
"""See `ICLISubCommand`."""
list_manager = getUtility(IListManager)
- if args.send:
- if not args.lists:
- # Send the digests for every list.
- for mlist in list_manager.mailing_lists:
- maybe_send_digest_now(mlist, force=True)
- return
- for list_spec in args.lists:
+ if args.lists:
+ lists = []
+ for spec in args.lists:
# We'll accept list-ids or fqdn list names.
- if '@' in list_spec:
- mlist = list_manager.get(list_spec)
+ if '@' in spec:
+ mlist = list_manager.get(spec)
else:
- mlist = list_manager.get_by_list_id(list_spec)
+ mlist = list_manager.get_by_list_id(spec)
if mlist is None:
- print(_('No such list found: $list_spec'), file=sys.stderr)
- continue
- maybe_send_digest_now(mlist, force=True)
- if args.bump:
- if not args.lists:
- mlists = list(list_manager.mailing_lists)
- else:
- # We'll accept list-ids or fqdn list names.
- if '@' in list_spec:
- mlist = list_manager.get(list_spec)
+ print(_('No such list found: $spec'), file=sys.stderr)
else:
- mlist = list_manager.get_by_list_id(list_spec)
+ lists.append(mlist)
+ else:
+ lists = list(list_manager.mailing_lists)
+ if args.bump:
+ for mlist in lists:
+ bump_digest_number_and_volume(mlist)
+ if args.send:
+ for mlist in lists:
+ maybe_send_digest_now(mlist, force=True)
diff --git a/src/mailman/commands/tests/test_digests.py b/src/mailman/commands/tests/test_digests.py
index 2640580af..607949f6e 100644
--- a/src/mailman/commands/tests/test_digests.py
+++ b/src/mailman/commands/tests/test_digests.py
@@ -18,6 +18,7 @@
"""Test the send-digests subcommand."""
__all__ = [
+ 'TestBumpVolume',
'TestSendDigests',
]
@@ -25,16 +26,19 @@ __all__ = [
import os
import unittest
+from datetime import timedelta
from io import StringIO
from mailman.app.lifecycle import create_list
from mailman.commands.cli_digests import Digests
from mailman.config import config
+from mailman.interfaces.digests import DigestFrequency
from mailman.interfaces.member import DeliveryMode
from mailman.runners.digest import DigestRunner
from mailman.testing.helpers import (
get_queue_messages, make_testable_runner,
specialized_message_from_string as mfs, subscribe)
from mailman.testing.layers import ConfigLayer
+from mailman.utilities.datetime import now as right_now
from unittest.mock import patch
@@ -48,8 +52,6 @@ class FakeArgs:
class TestSendDigests(unittest.TestCase):
- """Test the send-digests subcommand."""
-
layer = ConfigLayer
def setUp(self):
@@ -361,3 +363,86 @@ Subject: message 3
digest_contents = str(bee)
self.assertIn('Subject: message 3', digest_contents)
self.assertIn('Subject: message 4', digest_contents)
+
+ def test_send_no_digest_ready(self):
+ # If no messages have been sent through the mailing list, no digest
+ # can be sent.
+ mailbox_path = os.path.join(self._mlist.data_path, 'digest.mmdf')
+ self.assertFalse(os.path.exists(mailbox_path))
+ args = FakeArgs()
+ args.send = True
+ args.lists.append('ant.example.com')
+ self._command.process(args)
+ self._runner.run()
+ items = get_queue_messages('virgin')
+ self.assertEqual(len(items), 0)
+
+ def test_bump_after_send(self):
+ self._mlist.digest_volume_frequency = DigestFrequency.monthly
+ self._mlist.volume = 7
+ self._mlist.next_digest_number = 4
+ self._mlist.digest_last_sent_at = right_now() + timedelta(
+ days=-32)
+ msg = mfs("""\
+To: ant@example.com
+From: anne@example.com
+Subject: message 1
+
+""")
+ self._handler.process(self._mlist, msg, {})
+ args = FakeArgs()
+ args.bump = True
+ args.send = True
+ args.lists.append('ant.example.com')
+ self._command.process(args)
+ self._runner.run()
+ # The volume is 8 and the digest number is 2 because a digest was sent
+ # after the volume/number was bumped.
+ self.assertEqual(self._mlist.volume, 8)
+ self.assertEqual(self._mlist.next_digest_number, 2)
+ self.assertEqual(self._mlist.digest_last_sent_at, right_now())
+ items = get_queue_messages('virgin')
+ self.assertEqual(len(items), 1)
+ self.assertEqual(items[0].msg['subject'], 'Ant Digest, Vol 8, Issue 1')
+
+
+
+class TestBumpVolume(unittest.TestCase):
+ layer = ConfigLayer
+
+ def setUp(self):
+ self._mlist = create_list('ant@example.com')
+ self._mlist.digest_volume_frequency = DigestFrequency.monthly
+ self._mlist.volume = 7
+ self._mlist.next_digest_number = 4
+ self.right_now = right_now()
+ self._command = Digests()
+
+ def test_bump_one_list(self):
+ self._mlist.digest_last_sent_at = self.right_now + timedelta(
+ days=-32)
+ args = FakeArgs()
+ args.bump = True
+ args.lists.append('ant.example.com')
+ self._command.process(args)
+ self.assertEqual(self._mlist.volume, 8)
+ self.assertEqual(self._mlist.next_digest_number, 1)
+ self.assertEqual(self._mlist.digest_last_sent_at, self.right_now)
+
+ def test_bump_two_lists(self):
+ self._mlist.digest_last_sent_at = self.right_now + timedelta(
+ days=-32)
+ # Create the second list.
+ bee = create_list('bee@example.com')
+ bee.digest_volume_frequency = DigestFrequency.monthly
+ bee.volume = 7
+ bee.next_digest_number = 4
+ bee.digest_last_sent_at = self.right_now + timedelta(
+ days=-32)
+ args = FakeArgs()
+ args.bump = True
+ args.lists.extend(('ant.example.com', 'bee.example.com'))
+ self._command.process(args)
+ self.assertEqual(self._mlist.volume, 8)
+ self.assertEqual(self._mlist.next_digest_number, 1)
+ self.assertEqual(self._mlist.digest_last_sent_at, self.right_now)