diff --git a/src/postorius/static/postorius/js/held_messages.js b/src/postorius/static/postorius/js/held_messages.js index 88e7d03..ceddb63 100644 --- a/src/postorius/static/postorius/js/held_messages.js +++ b/src/postorius/static/postorius/js/held_messages.js @@ -9,7 +9,7 @@ success: function(data) { $('#msg-title').html(data.subject); $('.modal-footer form input[name="msgid"]').attr('value', msgid); - $('#held-stripped-message').html(data.stripped_msg.replace(/\n/g, "
")); + $('#held-stripped-message').html(data.stripped_msg.body.replace(/\n/g, "
")); $('#held-full-message').html(data.msg.replace(/\n/g, "
")); $('#held-messages-modal').modal('show'); }, diff --git a/src/postorius/views/rest.py b/src/postorius/views/rest.py index df9ddda..31ef3ee 100644 --- a/src/postorius/views/rest.py +++ b/src/postorius/views/rest.py @@ -16,46 +16,98 @@ # You should have received a copy of the GNU General Public License along with # Postorius. If not, see . import json +import email +import sys -from email import message_from_string +from email.Header import decode_header +from base64 import b64decode +from email.Parser import Parser as EmailParser +from email.utils import parseaddr +from StringIO import StringIO from django.http import HttpResponse, Http404 - from django.contrib.auth.decorators import login_required from django.utils.translation import gettext as _ + from postorius.auth.decorators import * -def _strip_email(email_text): - """Strip most of the headers from the email for the - held messages view. +# based on https://www.ianlewis.org/en/parsing-email-attachments-python +def parse_attachment(message_part, counter): + content_disposition = message_part.get("Content-Disposition", None) + if content_disposition: + dispositions = content_disposition.strip().split(";") + if bool(content_disposition and dispositions[0].lower() == "attachment"): - Only these headers would be kept: - - To - - From - - Date - - CC - - Subject + file_data = message_part.get_payload(decode=True) + attachment = StringIO(file_data) + attachment.content_type = message_part.get_content_type() + attachment.size = len(file_data) + attachment.name = message_part.get_filename() - If available, show only the text part of the email. + if not attachment.name: + ext = mimetypes.guess_extension(part.get_content_type()) + if not ext: + ext = '.bin' + attachment.name = 'part-%03d%s' % (counter, ext) - TODO: maxking - modify this later to extract text from HTML - to be displayed there. - """ - msg = message_from_string(email_text) + return attachment + return None - content_type = msg.get_content_type() - if content_type == 'multipart/alternative': - for part in msg.walk(): - if part.get_content_type() == 'text/plain': - msg.set_payload(part.as_string()) +def parse(content): + p = EmailParser() + msgobj = p.parsestr(content) + if msgobj['Subject'] is not None: + decodefrag = decode_header(msgobj['Subject']) + subj_fragments = [] + for s , enc in decodefrag: + if enc: + s = unicode(s , enc).encode('utf8','replace') + subj_fragments.append(s) + subject = ''.join(subj_fragments) + else: + subject = None - show_headers = ['To', 'From', 'Date', 'CC', 'Subject'] - for header in msg.keys(): - if header not in show_headers: - del msg[header] + attachments = [] + body = None + html = None + counter = 1 + for part in msgobj.walk(): + attachment = parse_attachment(part, counter) + if attachment: + attachments.append(attachment) + counter += 1 + elif part.get_content_type() == "text/plain": + if body is None: + body = "" + if part.get_content_charset(): + body += unicode( + part.get_payload(decode=True), + part.get_content_charset(), + 'replace' + ).encode('utf8','replace') + else: + body += part.get_payload(decode=True) + elif part.get_content_type() == "text/html": + if html is None: + html = "" + if part.get_content_charset(): + html += unicode( + part.get_payload(decode=True), + part.get_content_charset(), + 'replace' + ).encode('utf8','replace') + else: + html += part.get_payload(decode=True) + return { + 'subject' : subject, + 'body' : body, + 'html' : html, + 'from' : parseaddr(msgobj.get('From'))[1], + 'to' : parseaddr(msgobj.get('To'))[1], + #'attachments': attachments, + } - return msg.as_string() @login_required @list_moderator_required @@ -76,7 +128,7 @@ response_data['moderation_reasons'] = held_message.moderation_reasons response_data['hold_date'] = held_message.hold_date response_data['msg'] = held_message.msg - response_data['stripped_msg'] = _strip_email(held_message.msg) + response_data['stripped_msg'] = parse(held_message.msg) response_data['msgid'] = held_message.request_id response_data['subject'] = held_message.subject