Example #1
0
def plaintext_to_message(old_message, plaintext):
    '''
        Create a new Message with only the plain text.

        >>> # Test extreme cases
        >>> plaintext_to_message(None, None) == None
        True
     '''
    new_message = None

    try:
        if old_message and plaintext:
            parser = Parser()
            plain_message = parser.parsestr(plaintext)
            payloads = plain_message.get_payload()
            if isinstance(payloads, list):
                new_message = MIMEMultipart(old_message.get_content_subtype(),
                                            old_message.get_boundary())
            else:
                new_message = MIMEText(plain_message.get_payload())

            # save all the headers
            for key, value in old_message.items():
                new_message.add_header(key, value)

            if type(payloads) == list:
                for payload in payloads:
                    new_message.attach(payload)

            # add the content type and encoding from the plain text
            for key, value in plain_message.items():
                if key.lower() == mime_constants.CONTENT_TYPE_KEYWORD.lower():
                    new_message.__delitem__(key)
                    new_message.add_header(key, value)

                elif key.lower(
                ) == mime_constants.CONTENT_XFER_ENCODING_KEYWORD.lower():
                    new_message.__delitem__(key)
                    new_message.add_header(key, value)

            if type(new_message) == Message and DEBUGGING:
                log_message('new message:\n{}'.format(new_message.as_string()))

    except IOError as io_exception:
        record_exception(message=io_exception)
    except MessageException as message_exception:
        record_exception(message=message_exception)

    return new_message
Example #2
0
def plaintext_to_message(old_message, plaintext):
    '''
        Create a new Message with only the plain text.

        >>> # Test extreme cases
        >>> plaintext_to_message(None, None) == None
        True
     '''
    new_message = None

    try:
        if old_message and plaintext:
            parser = Parser()
            plain_message = parser.parsestr(plaintext)
            payloads = plain_message.get_payload()
            if isinstance(payloads, list):
                new_message = MIMEMultipart(old_message.get_content_subtype(), old_message.get_boundary())
            else:
                new_message = MIMEText(plain_message.get_payload())

            # save all the headers
            for key, value in old_message.items():
                new_message.add_header(key, value)

            if type(payloads) == list:
                for payload in payloads:
                    new_message.attach(payload)

            # add the content type and encoding from the plain text
            for key, value in plain_message.items():
                if key.lower() == mime_constants.CONTENT_TYPE_KEYWORD.lower():
                    new_message.__delitem__(key)
                    new_message.add_header(key, value)

                elif key.lower() == mime_constants.CONTENT_XFER_ENCODING_KEYWORD.lower():
                    new_message.__delitem__(key)
                    new_message.add_header(key, value)

            if type(new_message) == Message and DEBUGGING:
                log_message('new message:\n{}'.format(new_message.as_string()))

    except IOError as io_exception:
        record_exception(message=io_exception)
    except MessageException as message_exception:
        record_exception(message=message_exception)

    return new_message
def main(sender,gmail_password,recipients,subject,body,is_reminder):
    email_sent = dbcreate()

    msgID= email.utils.make_msgid()

    outer = MIMEMultipart()
    outer.add_header('Subject',subject)
    outer.add_header('From',sender)

    outer.add_header('Message-ID',msgID)

    # Send the email
    try:
        with smtplib.SMTP('smtp.gmail.com', 587) as s:
            s.ehlo()
            s.starttls()
            s.ehlo()
            s.login(sender, gmail_password)
            for recipient in recipients:
                outer.add_header('To',recipient)
                outer.attach(MIMEText(body, "html"))
                composed = outer.as_string()

                s.sendmail(sender, recipient, composed)
                outer.__delitem__('To')

            s.close()

        print("Reminder mail sent!")

        email_sent.insert_one(
            {
                'to':recipients,
                'from':sender,
                'subject':outer['Subject'],
                'MessageID':str(outer['Message-ID']),
                'DateTime':datetime.datetime.now(),
                'time':time.time(),
                'message':body,
                'is_reminder':is_reminder
            }
        )

    except:
        print("Unable to send the email. Error: ", sys.exc_info()[0])
        raise
Example #4
0
class Message(object):
    """
        Wrapper around email.Message class simplifying creation of simple email
        message objects.

        Allows most basic email messages types (including text, html &
        attachments) to be created simply from constructor. More complex
        messages should be created using the email.mime classes directly

        Class wraps the email.Message class and delegates item/attr lookups
        to the wrapped class (allows the object to be treated as a MIMEBase
        instance even though it doesnt inherit from this)

        Basic usage:

        >>> msg = Message('Test Message',to='*****@*****.**',text="Hello",html="<b>Hello</b>",attachments=['img.jpg'])

    """
    def __init__(self,
                 subject,
                 to,
                 cc=None,
                 bcc=None,
                 text=None,
                 html=None,
                 attachments=None,
                 sender=None,
                 reply_to=None):
        """
            Create message object

            subject         : Subject field
            to              : To recipients (as string - eg. "A <*****@*****.**>, B <*****@*****.**>")
            cc              : Cc recipients (same format as to)
            bcc             : Bcc recipients (same format as to)
            text            : Plain text body
            html            : HTML body ('text' will be included as alternative)
            attachments     : List of attachments - if the item is a subclass of MIMEBase
                              this is inserted directly, otherwise it is assumed to be
                              a filename and a MIME attachment craeted guessing the
                              content-type (for detailed control of the attachment
                              parameters create these separately)
            sender          : Value for the 'From' header (e.g. Foo Barr <*****@*****.**>).
                              If specified, 'Reply-To' header is also set to this address.
            reply_to        : Value for the 'Reply-To' header.

        """
        if not html and not attachments:
            # Simple plain text email
            self.root = MIMEText(text, 'plain', self._charset(text))
        else:
            # Multipart message
            self.root = MIMEMultipart()
            if html:
                # Add html & plain text alernative parts
                alt = MIMEMultipart('alternative')
                alt.attach(MIMEText(text, 'plain', self._charset(text)))
                alt.attach(MIMEText(html, 'html', self._charset(html)))
                self.root.attach(alt)
            else:
                # Just add plain text part
                txt = MIMEText(text, 'plain', self._charset(text))
                self.root.attach(txt)
            # Add attachments
            for a in attachments or []:
                self.root.attach(self._attachment(a))
        # Set headers
        self.root['To'] = to
        if cc: self.root['Cc'] = cc
        if bcc: self.root['Bcc'] = bcc

        if sender:
            self.root['From'] = sender

            if not reply_to:
                # If 'Reply-To' is not provided, set it to the 'From' value
                self.root['Reply-To'] = sender

        if reply_to:
            self.root['Reply-To'] = reply_to

        self.root['Subject'] = subject

    def _charset(self, s):
        """
            Guess charset - assume ascii for text and force utf-8 for unicode
            (email.mime classes take care of encoding)
        """
        return 'utf-8' if isinstance(s, unicode_type) else 'us-ascii'

    def _attachment(self, a):
        """
            Create MIME attachment
        """
        if isinstance(a, MIMEBase):
            # Already MIME object - return
            return a
        else:
            # Assume filename - guess mime-type from extension and return MIME object
            main, sub = (guess_type(a)[0]
                         or 'application/octet-stream').split('/', 1)
            attachment = MIMEBase(main, sub)
            with open(a, 'rb') as f:
                attachment.set_payload(f.read())
            if sys.version_info[0] == 2:
                # Try to handle non-ascii filenames
                attachment.add_header('Content-Disposition',
                                      'attachment',
                                      filename=unicode(
                                          os.path.basename(a),
                                          sys.getfilesystemencoding()))
            else:
                attachment.add_header('Content-Disposition',
                                      'attachment',
                                      filename=os.path.basename(a))
            encode_base64(attachment)
            return attachment

    # Delegate to root MIME object (allows object to be treated as MIMEBase)

    def __getitem__(self, key):
        return self.root.__getitem__(key)

    def __setitem__(self, key, value):
        self.root.__setitem__(key, value)

    def __delitem__(self, key):
        return self.root.__delitem__(key)

    def __getattr__(self, attr):
        if attr != 'root':
            return getattr(self.root, attr)
Example #5
0
class Message(object):
    """
        Wrapper around email.Message class simplifying creation of simple email
        message objects.

        Allows most basic email messages types (including text, html &
        attachments) to be created simply from constructor. More complex
        messages should be created using the email.mime classes directly

        Class wraps the email.Message class and delegates item/attr lookups
        to the wrapped class (allows the object to be treated as a MIMEBase
        instance even though it doesnt inherit from this)

        Basic usage:

        >>> msg = Message('Test Message',to='*****@*****.**',text="Hello",html="<b>Hello</b>",attachments=['img.jpg'])

    """

    def __init__(self,subject,to,cc=None,bcc=None,text=None,html=None,
                 attachments=None, sender=None, reply_to=None):
        """
            Create message object

            subject         : Subject field
            to              : To recipients (as string - eg. "A <*****@*****.**>, B <*****@*****.**>")
            cc              : Cc recipients (same format as to)
            bcc             : Bcc recipients (same format as to)
            text            : Plain text body
            html            : HTML body ('text' will be included as alternative)
            attachments     : List of attachments - if the item is a subclass of MIMEBase
                              this is inserted directly, otherwise it is assumed to be
                              a filename and a MIME attachment craeted guessing the
                              content-type (for detailed control of the attachment
                              parameters create these separately)
            sender          : Value for the 'From' header (e.g. Foo Barr <*****@*****.**>).
                              If specified, 'Reply-To' header is also set to this address.
            reply_to        : Value for the 'Reply-To' header.

        """
        if not html and not attachments:
            # Simple plain text email
            self.root = MIMEText(text,'plain',self._charset(text))
        else:
            # Multipart message
            self.root = MIMEMultipart()
            if html:
                # Add html & plain text alernative parts
                alt = MIMEMultipart('alternative')
                alt.attach(MIMEText(text,'plain',self._charset(text)))
                alt.attach(MIMEText(html,'html',self._charset(html)))
                self.root.attach(alt)
            else:
                # Just add plain text part
                txt = MIMEText(text,'plain',self._charset(text))
                self.root.attach(txt)
            # Add attachments
            for a in attachments or []:
                self.root.attach(self._attachment(a))
        # Set headers
        self.root['To'] = to
        if cc: self.root['Cc'] = cc
        if bcc: self.root['Bcc'] = bcc

        if sender:
            self.root['From'] = sender

            if not reply_to:
                # If 'Reply-To' is not provided, set it to the 'From' value
                self.root['Reply-To'] = sender

        if reply_to:
            self.root['Reply-To'] = reply_to

        self.root['Subject'] = subject

    def _charset(self,s):
        """
            Guess charset - assume ascii for text and force utf-8 for unicode
            (email.mime classes take care of encoding)
        """
        return 'utf-8' if isinstance(s,unicode_type) else 'us-ascii'

    def _attachment(self,a):
        """
            Create MIME attachment
        """
        if isinstance(a,MIMEBase):
            # Already MIME object - return
            return a
        else:
            # Assume filename - guess mime-type from extension and return MIME object
            main,sub = (guess_type(a)[0] or 'application/octet-stream').split('/',1)
            attachment = MIMEBase(main,sub)
            with open(a,'rb') as f:
                attachment.set_payload(f.read())
            attachment.add_header('Content-Disposition','attachment',filename=os.path.basename(a))
            encode_base64(attachment)
            return attachment

    # Delegate to root MIME object (allows object to be treated as MIMEBase)

    def __getitem__(self,key):
        return self.root.__getitem__(key)

    def __setitem__(self,key,value):
        self.root.__setitem__(key,value)

    def __delitem__(self,key):
        return self.root.__delitem__(key)

    def __getattr__(self,attr):
        if attr != 'root':
            return getattr(self.root,attr)
def main(sender, gmail_password, recipients, subject, body, is_reminder, resub,
         reminder_mails, reminder_numbers, remsg, remsms, remdatetime,
         timestamp, attachments):

    data = []  #To build reminder dictionary for each email recipient

    for i in recipients:
        d = {
            'id': i,
            'resub': resub,
            'remsg': remsg,
            'remmails': reminder_mails,
            'remnumbers': reminder_numbers,
            'remsms': remsms,
            'remdatetime': remdatetime,
            'timestamp': timestamp
        }
        data.append(d)

    #Checking whether DB present or not. If not create it.
    email_sent = dbcreate()

    #Generating a MesaageID locally so that we can store it and use it in future to track replies
    #Most of the current day email systems add 'In-Reply' parameter to header of reply email
    #'In-Reply' consists of MessageID of original mail for which reply mail is sent
    msgid = email.utils.make_msgid()

    #Our email can contain attachments too so creating MIMEMultipart() object
    outer = MIMEMultipart()

    #User add_header() method to add header values

    outer.add_header('Subject', subject)  #Adding subject to header
    outer.add_header('From', sender)  #Adding from to header
    outer.add_header('Message-ID', msgid)  #Adding msgid to header

    #If you want to send customised emails rather than plain text then HTML programmed mails must be used
    #The recieving email system will parse the email as HTML lines. So you could use HTML tags like <b></b> to make text bold,etc.
    #Here we are attaching the Text part to our Multipart object
    outer.attach(MIMEText(body, "html"))

    #Attaching attachments to Multipart object
    for file in attachments:
        try:
            with open(file, 'rb') as fp:
                #Since attachment is not restricted to any file type
                #We are using Main Content type: application and Sub Content type: octet-stream for the part
                msg = MIMEBase('application', "octet-stream")

                #Ataaching the attachment file to the part
                msg.set_payload(fp.read())
            #Files must be transferred in ASCII coding so the attachment is encoded using base scheme
            encoders.encode_base64(msg)

            # 'Content-Disposition' can have two values viz.
            # 1. 'inline' :  This tells the email reader to open the file within the email as part of web page
            # 2. 'attachment': This tells the email reader to download the file locally and that to when user clicks on it
            msg.add_header('Content-Disposition',
                           'attachment',
                           filename=os.path.basename(file))

            #Here we are attaching the attachment part to our Multipart object
            outer.attach(msg)
        except:
            print("Unable to open one of the attachments. Error: ",
                  sys.exc_info()[0])
            raise

    try:
        with smtplib.SMTP('smtp.gmail.com', 587) as s:
            #ehlo() method identifies our system with Email Server
            s.ehlo()

            #starttls() shifts our connection to TLS mode for secure connection
            s.starttls()

            #As per smtplib documentation we need to again identify our system after using starttls
            s.ehlo()

            #login() method to login to the account
            s.login(sender, gmail_password)

            #Adding 'BCC' header doesn't work
            #So we loop over receipents and sendmail to each individual
            for recipient in recipients:

                #Adding 'To' header
                outer.add_header('To', recipient)

                #Converting our whole mail to a single string to send mail
                composed = outer.as_string()

                #Using sendmail() method to send mail
                #Arguments paased are sender(i.e. From) , recipient(i.e. To) , composed(i.e. The mail contents)
                s.sendmail(sender, recipient, composed)

                #We need to just delete current 'To' header so that we could reuse the smae Mulitpart mail object for other recipients
                outer.__delitem__('To')

            #Close smtp connection
            s.close()
        print("Email sent!")

        #Insering the data into Database
        email_sent.insert_one({
            'to': recipients,
            'from': sender,
            'subject': outer['Subject'],
            'MessageID': msgid,
            'DateTime': datetime.datetime.now(),
            'time': time.time(),
            'attachments': attachments,
            'message': body,
            'reminder': data,
            'reminder_mails': reminder_mails,
            'reminder_numbers': reminder_numbers,
            'is_reminder': is_reminder
        })

    except:
        print("Unable to send the email. Error: ", sys.exc_info()[0])

        raise  #raise keyword without exception mentioned reraises the last exception so you know what went wrong