From 8fd14bfca79dd02cd9ab9abd25a40775914e086b Mon Sep 17 00:00:00 2001 From: Usman Khalid <2200617@gmail.com> Date: Thu, 24 Apr 2014 20:30:31 +0500 Subject: [PATCH] Wraps long lines in bulk email messages. RFC 2822 states that line lengths in emails must be less than 998. Some MTA's add newlines to messages if any line exceeds a certain limit (the exact limit varies). Sendmail goes so far as to add '!\n' after the 990th character in a line. To ensure that bulk mail messages look consistent long lines are wrapped to a conservative length. LMS-1466 --- common/lib/mail_utils.py | 22 ++++++++++++++++++++++ lms/djangoapps/bulk_email/models.py | 13 +++++++------ 2 files changed, 29 insertions(+), 6 deletions(-) create mode 100644 common/lib/mail_utils.py diff --git a/common/lib/mail_utils.py b/common/lib/mail_utils.py new file mode 100644 index 0000000000..35881bd25a --- /dev/null +++ b/common/lib/mail_utils.py @@ -0,0 +1,22 @@ +""" +Utilities related to mailing. +""" + +import textwrap + +MAX_LINE_LENGTH = 900 + + +def wrap_message(message, width=MAX_LINE_LENGTH): + """ + RFC 2822 states that line lengths in emails must be less than 998. Some MTA's add newlines to messages if any line + exceeds a certain limit (the exact limit varies). Sendmail goes so far as to add '!\n' after the 990th character in + a line. To ensure that messages look consistent this helper function wraps long lines to a conservative length. + """ + lines = message.split('\n') + wrapped_lines = [textwrap.fill( + line, width, expand_tabs=False, replace_whitespace=False, drop_whitespace=False, break_on_hyphens=False + ) for line in lines] + wrapped_message = '\n'.join(wrapped_lines) + + return wrapped_message diff --git a/lms/djangoapps/bulk_email/models.py b/lms/djangoapps/bulk_email/models.py index 8ea5ca80a3..9580703ef2 100644 --- a/lms/djangoapps/bulk_email/models.py +++ b/lms/djangoapps/bulk_email/models.py @@ -12,11 +12,12 @@ file and check it in at the same time as your model changes. To do that, """ import logging -from django.db import models, transaction -from django.contrib.auth.models import User -from html_to_text import html_to_text - from django.conf import settings +from django.contrib.auth.models import User +from django.db import models, transaction + +from html_to_text import html_to_text +from mail_utils import wrap_message log = logging.getLogger(__name__) @@ -192,8 +193,8 @@ class CourseEmailTemplate(models.Model): message_body_tag = COURSE_EMAIL_MESSAGE_BODY_TAG.format() result = result.replace(message_body_tag, message_body, 1) - # finally, return the result, without converting to an encoded byte array. - return result + # finally, return the result, after wrapping long lines and without converting to an encoded byte array. + return wrap_message(result) def render_plaintext(self, plaintext, context): """