diff rhodecode/lib/rcmail/message.py @ 2031:82a88013a3fd

merge 1.3 into stable
author Marcin Kuzminski <marcin@python-works.com>
date Sun, 26 Feb 2012 17:25:09 +0200
parents 69e95ad5b6f0
children d95ef6587bca
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rhodecode/lib/rcmail/message.py	Sun Feb 26 17:25:09 2012 +0200
@@ -0,0 +1,182 @@
+from rhodecode.lib.rcmail.response import MailResponse
+
+from rhodecode.lib.rcmail.exceptions import BadHeaders
+from rhodecode.lib.rcmail.exceptions import InvalidMessage
+
+class Attachment(object):
+    """
+    Encapsulates file attachment information.
+
+    :param filename: filename of attachment
+    :param content_type: file mimetype
+    :param data: the raw file data, either as string or file obj
+    :param disposition: content-disposition (if any)
+    """
+
+    def __init__(self,
+                 filename=None,
+                 content_type=None,
+                 data=None,
+                 disposition=None):
+
+        self.filename = filename
+        self.content_type = content_type
+        self.disposition = disposition or 'attachment'
+        self._data = data
+
+    @property
+    def data(self):
+        if isinstance(self._data, basestring):
+            return self._data
+        self._data = self._data.read()
+        return self._data
+
+
+class Message(object):
+    """
+    Encapsulates an email message.
+
+    :param subject: email subject header
+    :param recipients: list of email addresses
+    :param body: plain text message
+    :param html: HTML message
+    :param sender: email sender address
+    :param cc: CC list
+    :param bcc: BCC list
+    :param extra_headers: dict of extra email headers
+    :param attachments: list of Attachment instances
+    :param recipients_separator: alternative separator for any of
+        'From', 'To', 'Delivered-To', 'Cc', 'Bcc' fields
+    """
+
+    def __init__(self,
+                 subject=None,
+                 recipients=None,
+                 body=None,
+                 html=None,
+                 sender=None,
+                 cc=None,
+                 bcc=None,
+                 extra_headers=None,
+                 attachments=None,
+                 recipients_separator="; "):
+
+        self.subject = subject or ''
+        self.sender = sender
+        self.body = body
+        self.html = html
+
+        self.recipients = recipients or []
+        self.attachments = attachments or []
+        self.cc = cc or []
+        self.bcc = bcc or []
+        self.extra_headers = extra_headers or {}
+
+        self.recipients_separator = recipients_separator
+
+    @property
+    def send_to(self):
+        return set(self.recipients) | set(self.bcc or ()) | set(self.cc or ())
+
+    def to_message(self):
+        """
+        Returns raw email.Message instance.Validates message first.
+        """
+
+        self.validate()
+
+        return self.get_response().to_message()
+
+    def get_response(self):
+        """
+        Creates a Lamson MailResponse instance
+        """
+
+        response = MailResponse(Subject=self.subject,
+                                To=self.recipients,
+                                From=self.sender,
+                                Body=self.body,
+                                Html=self.html,
+                                separator=self.recipients_separator)
+
+        if self.cc:
+            response.base['Cc'] = self.cc
+
+        for attachment in self.attachments:
+
+            response.attach(attachment.filename,
+                            attachment.content_type,
+                            attachment.data,
+                            attachment.disposition)
+
+        response.update(self.extra_headers)
+
+        return response
+
+    def is_bad_headers(self):
+        """
+        Checks for bad headers i.e. newlines in subject, sender or recipients.
+        """
+
+        headers = [self.subject, self.sender]
+        headers += list(self.send_to)
+        headers += self.extra_headers.values()
+
+        for val in headers:
+            for c in '\r\n':
+                if c in val:
+                    return True
+        return False
+
+    def validate(self):
+        """
+        Checks if message is valid and raises appropriate exception.
+        """
+
+        if not self.recipients:
+            raise InvalidMessage, "No recipients have been added"
+
+        if not self.body and not self.html:
+            raise InvalidMessage, "No body has been set"
+
+        if not self.sender:
+            raise InvalidMessage, "No sender address has been set"
+
+        if self.is_bad_headers():
+            raise BadHeaders
+
+    def add_recipient(self, recipient):
+        """
+        Adds another recipient to the message.
+
+        :param recipient: email address of recipient.
+        """
+
+        self.recipients.append(recipient)
+
+    def add_cc(self, recipient):
+        """
+        Adds an email address to the CC list.
+
+        :param recipient: email address of recipient.
+        """
+
+        self.cc.append(recipient)
+
+    def add_bcc(self, recipient):
+        """
+        Adds an email address to the BCC list.
+
+        :param recipient: email address of recipient.
+        """
+
+        self.bcc.append(recipient)
+
+    def attach(self, attachment):
+        """
+        Adds an attachment to the message.
+
+        :param attachment: an **Attachment** instance.
+        """
+
+        self.attachments.append(attachment)