summaryrefslogtreecommitdiff
path: root/Mailman/Handlers/ToDigest.py
diff options
context:
space:
mode:
Diffstat (limited to 'Mailman/Handlers/ToDigest.py')
-rw-r--r--Mailman/Handlers/ToDigest.py71
1 files changed, 47 insertions, 24 deletions
diff --git a/Mailman/Handlers/ToDigest.py b/Mailman/Handlers/ToDigest.py
index 1fc8928b2..0e4bb94d9 100644
--- a/Mailman/Handlers/ToDigest.py
+++ b/Mailman/Handlers/ToDigest.py
@@ -1,4 +1,4 @@
-# Copyright (C) 1998-2003 by the Free Software Foundation, Inc.
+# Copyright (C) 1998-2005 by the Free Software Foundation, Inc.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
@@ -37,13 +37,15 @@ from email.Generator import Generator
from email.MIMEBase import MIMEBase
from email.MIMEText import MIMEText
from email.MIMEMessage import MIMEMessage
-from email.Utils import getaddresses
+from email.Utils import getaddresses, formatdate
from email.Header import decode_header, make_header, Header
+from email.Charset import Charset
from Mailman import mm_cfg
from Mailman import Utils
from Mailman import Message
from Mailman import i18n
+from Mailman import Errors
from Mailman.Mailbox import Mailbox
from Mailman.MemberAdaptor import ENABLED
from Mailman.Handlers.Decorate import decorate
@@ -86,9 +88,20 @@ def process(mlist, msg, msgdata):
if size / 1024.0 >= mlist.digest_size_threshhold:
# This is a bit of a kludge to get the mbox file moved to the digest
# queue directory.
- mboxfp.seek(0)
- send_digests(mlist, mboxfp)
- os.unlink(mboxfile)
+ try:
+ # Let's close in try - except here because a error in send_digest
+ # can stop regular delivery silently. Unsuccessful digest
+ # delivery should be tried again by cron and the site
+ # administrator will be notified of any error explicitly by the
+ # cron error message.
+ mboxfp.seek(0)
+ send_digests(mlist, mboxfp)
+ os.unlink(mboxfile)
+ except Exception, errmsg:
+ # I know bare except is prohibited in mailman coding but we can't
+ # forcast what new exception can occur here.
+ syslog('error', 'send_digests() failed: %s', errmsg)
+ pass
mboxfp.close()
@@ -136,9 +149,11 @@ def send_digests(mlist, mboxfp):
def send_i18n_digests(mlist, mboxfp):
mbox = Mailbox(mboxfp)
- # Prepare common information
+ # Prepare common information (first lang/charset)
lang = mlist.preferred_language
lcset = Utils.GetCharSet(lang)
+ lcset_out = Charset(lcset).output_charset or lcset
+ # Common Information (contd)
realname = mlist.real_name
volume = mlist.volume
issue = mlist.next_digest_number
@@ -146,6 +161,7 @@ def send_i18n_digests(mlist, mboxfp):
digestsubj = Header(digestid, lcset, header_name='Subject')
# Set things up for the MIME digest. Only headers not added by
# CookHeaders need be added here.
+ # Date/Message-ID should be added here also.
mimemsg = Message.Message()
mimemsg['Content-Type'] = 'multipart/mixed'
mimemsg['MIME-Version'] = '1.0'
@@ -153,6 +169,8 @@ def send_i18n_digests(mlist, mboxfp):
mimemsg['Subject'] = digestsubj
mimemsg['To'] = mlist.GetListEmail()
mimemsg['Reply-To'] = mlist.GetListEmail()
+ mimemsg['Date'] = formatdate(localtime=1)
+ mimemsg['Message-ID'] = Utils.unique_message_id(mlist)
# Set things up for the rfc1153 digest
plainmsg = StringIO()
rfc1153msg = Message.Message()
@@ -160,6 +178,8 @@ def send_i18n_digests(mlist, mboxfp):
rfc1153msg['Subject'] = digestsubj
rfc1153msg['To'] = mlist.GetListEmail()
rfc1153msg['Reply-To'] = mlist.GetListEmail()
+ rfc1153msg['Date'] = formatdate(localtime=1)
+ rfc1153msg['Message-ID'] = Utils.unique_message_id(mlist)
separator70 = '-' * 70
separator30 = '-' * 30
# In the rfc1153 digest, the masthead contains the digest boilerplate plus
@@ -210,18 +230,19 @@ def send_i18n_digests(mlist, mboxfp):
if msg == '':
# It was an unparseable message
msg = mbox.next()
+ continue
msgcount += 1
messages.append(msg)
# Get the Subject header
msgsubj = msg.get('subject', _('(no subject)'))
- subject = oneline(msgsubj, lcset)
+ subject = Utils.oneline(msgsubj, lcset)
# Don't include the redundant subject prefix in the toc
mo = re.match('(re:? *)?(%s)' % re.escape(mlist.subject_prefix),
subject, re.IGNORECASE)
if mo:
subject = subject[:mo.start(2)] + subject[mo.end(2):]
username = ''
- addresses = getaddresses([oneline(msg.get('from', ''), lcset)])
+ addresses = getaddresses([Utils.oneline(msg.get('from', ''), lcset)])
# Take only the first author we find
if isinstance(addresses, ListType) and addresses:
username = addresses[0][0]
@@ -301,15 +322,30 @@ def send_i18n_digests(mlist, mboxfp):
print >> plainmsg, separator30
print >> plainmsg
# Use Mailman.Handlers.Scrubber.process() to get plain text
- msg = scrubber(mlist, msg)
+ try:
+ msg = scrubber(mlist, msg)
+ except Errors.DiscardMessage:
+ print >> plainmsg, _('[Message discarded by content filter]')
+ continue
# Honor the default setting
for h in mm_cfg.PLAIN_DIGEST_KEEP_HEADERS:
if msg[h]:
- uh = Utils.wrap('%s: %s' % (h, oneline(msg[h], lcset)))
+ uh = Utils.wrap('%s: %s' % (h, Utils.oneline(msg[h], lcset)))
uh = '\n\t'.join(uh.split('\n'))
print >> plainmsg, uh
print >> plainmsg
- payload = msg.get_payload(decode=True)
+ payload = msg.get_payload(decode=True)\
+ or msg.as_string().split('\n\n',1)[1]
+ mcset = msg.get_content_charset('')
+ if mcset and mcset <> lcset and mcset <> lcset_out:
+ try:
+ payload = unicode(payload, mcset, 'replace'
+ ).encode(lcset, 'replace')
+ except LookupError:
+ # TK: Message has something unknown charset.
+ # _out means charset in 'outer world'.
+ payload = unicode(payload, lcset_out, 'replace'
+ ).encode(lcset, 'replace')
print >> plainmsg, payload
if not payload.endswith('\n'):
print >> plainmsg
@@ -375,16 +411,3 @@ def send_i18n_digests(mlist, mboxfp):
recips=plainrecips,
listname=mlist.internal_name(),
isdigest=True)
-
-
-
-def oneline(s, cset):
- # Decode header string in one line and convert into specified charset
- try:
- h = make_header(decode_header(s))
- ustr = h.__unicode__()
- oneline = UEMPTYSTRING.join(ustr.splitlines())
- return oneline.encode(cset, 'replace')
- except (LookupError, UnicodeError):
- # possibly charset problem. return with undecoded string in one line.
- return EMPTYSTRING.join(s.splitlines())