You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
109 lines
3.3 KiB
109 lines
3.3 KiB
2 years ago
|
# Copyright (C) 2021 Max Erenberg
|
||
|
# This file is adapted from GNU Mailman. The original copyright notice
|
||
|
# is preserved below.
|
||
|
#
|
||
|
# Copyright (C) 2008-2019 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/>.
|
||
|
|
||
|
"""
|
||
|
A simple archiver which copies each message into a folder for the current
|
||
|
month.
|
||
|
"""
|
||
|
|
||
|
from contextlib import suppress
|
||
|
import datetime
|
||
|
from datetime import timedelta
|
||
|
from email.utils import parsedate
|
||
|
import gzip
|
||
|
import logging
|
||
|
import os
|
||
|
import time
|
||
|
|
||
|
from flufl.lock import Lock, TimeOutError
|
||
|
from mailbox import Maildir
|
||
|
from mailman.config import config
|
||
|
from mailman.interfaces.archiver import IArchiver
|
||
|
from public import public
|
||
|
from zope.interface import implementer
|
||
|
|
||
|
|
||
|
log = logging.getLogger('mailman.error')
|
||
|
|
||
|
|
||
|
@public
|
||
|
@implementer(IArchiver)
|
||
|
class MonthlyArchiver:
|
||
|
"""
|
||
|
A simple archiver which copies each message into a folder for the
|
||
|
current month. It is adapted from the `Prototype` archiver.
|
||
|
"""
|
||
|
|
||
|
name = 'monthly_archiver'
|
||
|
is_enabled = False
|
||
|
|
||
|
@staticmethod
|
||
|
def list_url(mlist):
|
||
|
"""See `IArchiver`."""
|
||
|
# This archiver is not web-accessible, therefore no URL is returned.
|
||
|
return None
|
||
|
|
||
|
@staticmethod
|
||
|
def permalink(mlist, msg):
|
||
|
"""See `IArchiver`."""
|
||
|
# This archiver is not web-accessible, therefore no URL is returned.
|
||
|
return None
|
||
|
|
||
|
@staticmethod
|
||
|
def archive_message(mlist, message):
|
||
|
"""See `IArchiver`.
|
||
|
|
||
|
This archiver saves messages into a folder for the current year and
|
||
|
month, e.g. '2021-April'.
|
||
|
|
||
|
:type mlist: mailman.model.listmanager.ListManager
|
||
|
:type message: mailman.email.message.Message
|
||
|
"""
|
||
|
message_id = message.get('message-id')
|
||
|
date_secs = parsedate(message.get('date'))
|
||
|
if date_secs is not None:
|
||
|
date = time.localtime(time.mktime(date_secs))
|
||
|
else:
|
||
|
log.warning('Could not extract date from message %s, using '
|
||
|
'local time instead' % message_id)
|
||
|
date = time.localtime()
|
||
|
year_and_month = time.strftime('%Y-%B', date)
|
||
|
|
||
|
archive_dir = os.path.join(
|
||
|
config.ARCHIVE_DIR,
|
||
|
MonthlyArchiver.name,
|
||
|
mlist.fqdn_listname,
|
||
|
year_and_month
|
||
|
)
|
||
|
with suppress(FileExistsError):
|
||
|
os.makedirs(archive_dir, 0o775)
|
||
|
|
||
|
# Just use the current timestamp as the file name
|
||
|
filename = str(round(time.time(), 3)) + '.mail.gz'
|
||
|
dst = os.path.join(archive_dir, filename)
|
||
|
log.info('MonthlyArchiver archived message %s to %s' %
|
||
|
(message_id, dst))
|
||
|
# gzip the file to try to save some disk space
|
||
|
with gzip.open(dst, 'wb') as fo:
|
||
|
fo.write(message.as_bytes())
|
||
|
|
||
|
return None
|