Пример #1
0
 def test_as_message_attachments(self):
     msg_in = Message()
     msg_in["From"] = "*****@*****.**"
     msg_in["Message-ID"] = "<msg>"
     msg_in.attach(MIMEText("Dummy message"))
     msg_in.attach(MIMEText("<html><body>Dummy message</body></html>", _subtype="html"))
     add_to_list("*****@*****.**", msg_in)
     email = Email.objects.get(message_id="msg")
     msg = email.as_message()
     self.assertEqual(msg["From"], "dummy at example.com")
     self.assertEqual(msg["Message-ID"], "<msg>")
     self.assertTrue(msg.is_multipart())
     payload = msg.get_payload()
     self.assertEqual(len(payload), 2)
     self.assertEqual(
         payload[0].get_payload(decode=True).strip(), "Dummy message")
     # The filename extension detection from content type is a bit random
     # (depends on the PYTHON_HASHSEED), make sure we get the right one
     # here for testing.
     expected_ext = guess_all_extensions("text/html", strict=False)[0]
     self.assertEqual(payload[1].get_content_type(), "text/html")
     self.assertEqual(payload[1]["Content-Disposition"],
         'attachment; filename="attachment%s"' % expected_ext)
     self.assertEqual(
         payload[1].get_payload(decode=True),
         "<html><body>Dummy message</body></html>")
Пример #2
0
    def as_string(self, boundary=None):
        """Return the entire formatted message as a string.

        :param boundary: The boundary to use between MIME parts, if applicable.
            Used for tests.
        """
        if not self._parts:
            msgobj = Message()
            if self._body is not None:
                body, encoding = self.string_with_encoding(self._body)
                msgobj.set_payload(body, encoding)
        else:
            msgobj = MIMEMultipart()

            if boundary is not None:
                msgobj.set_boundary(boundary)

            for body, filename, mime_subtype in self._parts:
                body, encoding = self.string_with_encoding(body)
                payload = MIMEText(body, mime_subtype, encoding)

                if filename is not None:
                    content_type = payload['Content-Type']
                    content_type += '; name="%s"' % filename
                    payload.replace_header('Content-Type', content_type)

                payload['Content-Disposition'] = 'inline'
                msgobj.attach(payload)

        # sort headers here to ease testing
        for header, value in sorted(self._headers.items()):
            msgobj[header] = value

        return msgobj.as_string()
Пример #3
0
 def test_as_message_attachments(self):
     msg_in = Message()
     msg_in["From"] = "*****@*****.**"
     msg_in["Message-ID"] = "<msg>"
     msg_in.attach(MIMEText("Dummy message"))
     msg_in.attach(MIMEText("<html><body>Dummy message</body></html>",
                            _subtype="html"))
     add_to_list("*****@*****.**", msg_in)
     email = Email.objects.get(message_id="msg")
     msg = email.as_message()
     self.assertEqual(msg["From"], "dummy at example.com")
     self.assertEqual(msg["Message-ID"], "<msg>")
     self.assertTrue(msg.is_multipart())
     payload = msg.get_payload()
     self.assertEqual(len(payload), 2)
     self.assertEqual(
         payload[0].get_payload(decode=True).strip(), "Dummy message")
     # The filename extension detection from content type is a bit random
     # (depends on the PYTHON_HASHSEED), make sure we get the right one
     # here for testing.
     expected_ext = guess_all_extensions("text/html", strict=False)[0]
     self.assertEqual(payload[1].get_content_type(), "text/html")
     self.assertEqual(
         payload[1]["Content-Disposition"],
         'attachment; filename="attachment%s"' % expected_ext)
     self.assertEqual(
         payload[1].get_payload(decode=True),
         "<html><body>Dummy message</body></html>")
    def _construct_multipart_request(self, request):
        """
        :type request: office365.runtime.http.request_options.RequestOptions
        """
        request.method = HttpMethod.Post
        boundary = create_boundary("PageBoundary", True)
        request.set_header(
            "Content-Type",
            "multipart/form-data; boundary={0}".format(boundary))

        main_message = Message()
        main_message.add_header(
            "Content-Type",
            "multipart/form-data; boundary={0}".format(boundary))
        main_message.set_boundary(boundary)

        c_type, enc = get_mime_type(self._presentation.name)
        presentation_message = Message()
        presentation_message.add_header("Content-Type", c_type)
        presentation_message.add_header("Content-Disposition",
                                        "form-data; name=\"Presentation\"")
        presentation_message.set_payload(self._presentation.read())
        main_message.attach(presentation_message)

        for name, file in self._files.items():
            file_message = Message()
            c_type, enc = get_mime_type(file.name)
            file_message.add_header("Content-Type", c_type)
            file_message.add_header("Content-Disposition",
                                    "form-data; name=\"{0}\"".format(name))
            file_content = file.read()
            file_message.set_payload(file_content)
            main_message.attach(file_message)

        request.data = _message_to_payload(main_message)
Пример #5
0
    def _rehydrate(self, msg):
        new = EmailMessage()
        settings = utils.get_settings()

        if msg.is_multipart():
            for header, value in msg.items():
                new[header] = value
            for part in msg.get_payload():
                new.attach(
                    self._rehydrate(part)
                )
        elif settings['attachment_interpolation_header'] in msg.keys():
            try:
                attachment = MessageAttachment.objects.get(
                    pk=msg[settings['attachment_interpolation_header']]
                )
                for header, value in attachment.items():
                    new[header] = value
                encoding = new['Content-Transfer-Encoding']
                if encoding and encoding.lower() == 'quoted-printable':
                    # Cannot use `email.encoders.encode_quopri due to
                    # bug 14360: http://bugs.python.org/issue14360
                    output = six.BytesIO()
                    encode_quopri(
                        six.BytesIO(
                            attachment.document.read()
                        ),
                        output,
                        quotetabs=True,
                        header=False,
                    )
                    new.set_payload(
                        output.getvalue().decode().replace(' ', '=20')
                    )
                    del new['Content-Transfer-Encoding']
                    new['Content-Transfer-Encoding'] = 'quoted-printable'
                else:
                    new.set_payload(
                        attachment.document.read()
                    )
                    del new['Content-Transfer-Encoding']
                    encode_base64(new)
            except MessageAttachment.DoesNotExist:
                new[settings['altered_message_header']] = (
                    'Missing; Attachment %s not found' % (
                        msg[settings['attachment_interpolation_header']]
                    )
                )
                new.set_payload('')
        else:
            for header, value in msg.items():
                new[header] = value
            new.set_payload(
                msg.get_payload()
            )
        return new
Пример #6
0
    def _get_dehydrated_message(self, msg, record):
        new = EmailMessage()
        if msg.is_multipart():
            for header, value in msg.items():
                new[header] = value
            for part in msg.get_payload():
                new.attach(self._get_dehydrated_message(part, record))
        elif (STRIP_UNALLOWED_MIMETYPES
              and not msg.get_content_type() in ALLOWED_MIMETYPES):
            for header, value in msg.items():
                new[header] = value
            # Delete header, otherwise when attempting to  deserialize the
            # payload, it will be expecting a body for this.
            del new['Content-Transfer-Encoding']
            new[ALTERED_MESSAGE_HEADER] = (
                'Stripped; Content type %s not allowed' %
                (msg.get_content_type()))
            new.set_payload('')
        elif msg.get_content_type() not in TEXT_STORED_MIMETYPES:
            filename = msg.get_filename()
            if not filename:
                extension = mimetypes.guess_extension(msg.get_content_type())
            else:
                _, extension = os.path.splitext(filename)
            if not extension:
                extension = '.bin'

            attachment = MessageAttachment()

            attachment.document.save(
                uuid.uuid4().hex + extension,
                ContentFile(
                    six.BytesIO(msg.get_payload(decode=True)).getvalue()))
            attachment.message = record
            for key, value in msg.items():
                attachment[key] = value
            attachment.save()

            placeholder = EmailMessage()
            placeholder[ATTACHMENT_INTERPOLATION_HEADER] = str(attachment.pk)
            new = placeholder
        else:
            content_charset = msg.get_content_charset()
            if not content_charset:
                content_charset = 'ascii'
            try:
                # Make sure that the payload can be properly decoded in the
                # defined charset, if it can't, let's mash some things
                # inside the payload :-\
                msg.get_payload(decode=True).decode(content_charset)
            except UnicodeDecodeError:
                msg.set_payload(
                    msg.get_payload(decode=True).decode(
                        content_charset, 'ignore'))
            new = msg
        return new
Пример #7
0
    def _get_dehydrated_message(self, msg, record):
        new = EmailMessage()
        if msg.is_multipart():
            for header, value in msg.items():
                new[header] = value
            for part in msg.get_payload():
                new.attach(
                    self._get_dehydrated_message(part, record)
                )
        elif (
            STRIP_UNALLOWED_MIMETYPES
            and not msg.get_content_type() in ALLOWED_MIMETYPES
        ):
            for header, value in msg.items():
                new[header] = value
            # Delete header, otherwise when attempting to  deserialize the
            # payload, it will be expecting a body for this.
            del new['Content-Transfer-Encoding']
            new[ALTERED_MESSAGE_HEADER] = (
                'Stripped; Content type %s not allowed' % (
                    msg.get_content_type()
                )
            )
            new.set_payload('')
        elif msg.get_content_type() not in TEXT_STORED_MIMETYPES:
            filename = msg.get_filename()
            if not filename:
                extension = mimetypes.guess_extension(msg.get_content_type())
            else:
                _, extension = os.path.splitext(filename)
            if not extension:
                extension = '.bin'

            attachment = MessageAttachment()

            attachment.document.save(
                uuid.uuid4().hex + extension,
                ContentFile(
                    six.BytesIO(
                        msg.get_payload(decode=True)
                    ).getvalue()
                )
            )
            attachment.message = record
            for key, value in msg.items():
                attachment[key] = value
            attachment.save()

            placeholder = EmailMessage()
            placeholder[ATTACHMENT_INTERPOLATION_HEADER] = str(attachment.pk)
            new = placeholder
        else:
            new = msg
        return new
Пример #8
0
    def _get_dehydrated_message(self, msg, record):
        new = EmailMessage()
        if msg.is_multipart():
            for header, value in msg.items():
                new[header] = value
            for part in msg.get_payload():
                new.attach(
                    self._get_dehydrated_message(part, record)
                )
        elif (
            STRIP_UNALLOWED_MIMETYPES
            and not msg.get_content_type() in ALLOWED_MIMETYPES
        ):
            for header, value in msg.items():
                new[header] = value
            # Delete header, otherwise when attempting to  deserialize the
            # payload, it will be expecting a body for this.
            del new['Content-Transfer-Encoding']
            new[ALTERED_MESSAGE_HEADER] = (
                'Stripped; Content type %s not allowed' % (
                    msg.get_content_type()
                )
            )
            new.set_payload('')
        elif msg.get_content_type() not in TEXT_STORED_MIMETYPES:
            filename = msg.get_filename()
            extension = '.bin'
            if not filename:
                extension = mimetypes.guess_extension(msg.get_content_type())
            else:
                _, extension = os.path.splitext(filename)

            attachment = MessageAttachment()
            
            attachment.document.save(
                uuid.uuid4().hex + extension,
                ContentFile(six.BytesIO(msg.get_payload(decode=True)).getvalue())
            )
            attachment.message = record
            for key, value in msg.items():
                attachment[key] = value
            attachment.save()

            placeholder = EmailMessage()
            placeholder[ATTACHMENT_INTERPOLATION_HEADER] = str(attachment.pk)
            new = placeholder
        else:
            for header, value in msg.items():
                new[header] = value
            new.set_payload(
                msg.get_payload()
            )
        return new
Пример #9
0
 def _prepare_payload(self):
     """Serializes a batch request body."""
     main_message = Message()
     main_message.add_header("Content-Type", "multipart/mixed")
     main_message.set_boundary(self._current_boundary)
     for _ in self.context.get_next_query():
         part_message = Message()
         part_message.add_header("Content-Type", "application/http")
         part_message.add_header("Content-Transfer-Encoding", "binary")
         request = self.context.build_request()
         part_message.set_payload(self._serialize_request(request))
         main_message.attach(part_message)
     return main_message.as_bytes()
Пример #10
0
    def prepare_multipart_body(self):
        # type: () -> None
        """Will prepare the body of this request according to the multipart information.

        This call assumes the on_request policies have been applied already in their
        correct context (sync/async)

        Does nothing if "set_multipart_mixed" was never called.
        """
        if not self.multipart_mixed_info:
            return

        requests = self.multipart_mixed_info[0]  # type: List[HttpRequest]
        boundary = self.multipart_mixed_info[2]  # type: Optional[str]

        # Update the main request with the body
        main_message = Message()
        main_message.add_header("Content-Type", "multipart/mixed")
        if boundary:
            main_message.set_boundary(boundary)
        for i, req in enumerate(requests):
            part_message = Message()
            part_message.add_header("Content-Type", "application/http")
            part_message.add_header("Content-Transfer-Encoding", "binary")
            part_message.add_header("Content-ID", str(i))
            part_message.set_payload(req.serialize())
            main_message.attach(part_message)

        try:
            from email.policy import HTTP

            full_message = main_message.as_bytes(policy=HTTP)
            eol = b"\r\n"
        except ImportError:  # Python 2.7
            # Right now we decide to not support Python 2.7 on serialization, since
            # it doesn't serialize a valid HTTP request (and our main scenario Storage refuses it)
            raise NotImplementedError(
                "Multipart request are not supported on Python 2.7"
            )
            # full_message = main_message.as_string()
            # eol = b'\n'
        _, _, body = full_message.split(eol, 2)
        self.set_bytes_body(body)
        self.headers["Content-Type"] = (
            "multipart/mixed; boundary=" + main_message.get_boundary()
        )
Пример #11
0
def emsg(kv):
    from email.message import Message
    from email.generator import Generator
    from StringIO import StringIO

    m = Message()
    m['Content-type'] = 'multipart/formdata'
    for k,v in kv.items():
        p = Message()
        p.add_header('Content-Disposition', 'form-data', name=k)
        p.set_payload(v)
        m.attach(p)
#print m.as_string()
    fp = StringIO()
    g = Generator(fp)
    g.flatten(m)
    return fp.getvalue()
Пример #12
0
def make_mdn(sender, recipient, orig_message_id, subject, disposition_type):
    domain = sender.partition('@')[2]

    msg = Message()
    msg['MIME-Version'] = '1.0'
    msg['Content-Type'] = 'multipart/report; report-type=disposition-notification'
    msg['From'] = '<%s>' % sender
    msg['To'] = '<%s>' % recipient
    msg['Date'] = email.utils.formatdate().replace('-0000','+0000 (UTC)')
    msg_id = '<%d.%s@%s>' % (time.time(), str(random.getrandbits(64)), domain)
    msg['Message-ID'] =  msg_id
    if (disposition_type == 'processed'):
        msg['Subject'] = 'Processed: %s' % subject
    else:
        msg['Subject'] = 'Delivered: %s' % subject

    txt = Message()
    #txt['Content-Type'] = 'text/plain;charset=us-ascii'
    #txt['Content-Transfer-Encoding'] = '7bit'
    if (disposition_type == 'processed'):
        txt.set_payload('Your message was successfully processed.')
    else:
        txt.set_payload('Your message was successfully delivered.')
    msg.attach(txt)

    dn = Message()
    dn['Content-Type'] = 'message/disposition-notification'
    #dn['Content-Transfer-Encoding'] = '7bit'
    if (disposition_type == 'processed'):
        dn.set_payload(NOTIFICATION_PROCESSED % (domain,sender,orig_message_id))
    else:
        dn.set_payload(NOTIFICATION_DISPATCHED % (domain,sender,orig_message_id))
    msg.attach(dn)
    msg_string = msg.as_string()
    msg_string = msg_string.replace('\r\n', '\n')
    msg_string = msg_string.replace('\n\n\n', '\n\n')
    msg_string = msg_string.replace('\n', '\r\n')
    msg_string = msg_string + '\r\n'

    return msg_id, msg_string
    def _prepare_payload(self):
        """Serializes a batch request body."""

        for qry in self.context.get_next_query():
            request = self.context.build_request()
            if isinstance(qry, ReadEntityQuery):
                self._get_requests.append(request)
                self._get_queries.append(qry)
            else:
                self._change_requests.append(request)

        main_message = Message()
        main_message.add_header("Content-Type", "multipart/mixed")
        main_message.set_boundary(self._current_boundary)

        if len(self._change_requests) > 0:
            change_set_message = Message()
            change_set_boundary = _create_boundary("changeset_", True)
            change_set_message.add_header("Content-Type", "multipart/mixed")
            change_set_message.set_boundary(change_set_boundary)

            for request in self._change_requests:
                part_message = self._serialize_request(request)
                change_set_message.attach(part_message)
            main_message.attach(change_set_message)

        for request in self._get_requests:
            part_message = self._serialize_request(request)
            main_message.attach(part_message)

        return main_message
Пример #14
0
    def _prepare_payload(self):
        """
        Serializes a batch request body.
        """
        main_message = Message()
        main_message.add_header("Content-Type", "multipart/mixed")
        main_message.set_boundary(self.current_query.current_boundary)

        if self.current_query.has_change_sets:
            change_set_message = Message()
            change_set_boundary = create_boundary("changeset_", True)
            change_set_message.add_header("Content-Type", "multipart/mixed")
            change_set_message.set_boundary(change_set_boundary)

            for qry in self.current_query.change_sets:
                request = qry.build_request()
                message = self._serialize_request(request)
                change_set_message.attach(message)
            main_message.attach(change_set_message)

        for qry in self.current_query.get_queries:
            request = qry.build_request()
            message = self._serialize_request(request)
            main_message.attach(message)

        return message_as_bytes_or_string(main_message)
Пример #15
0
 def _filter_message_body(self, message):
     if not message.is_multipart() or not STRIP_UNALLOWED_MIMETYPES:
         return message
     stripped_content = {}
     new = EmailMessage()
     for header, value in message.items():
         new[header] = value
     for part in message.walk():
         content_type = part.get_content_type()
         print content_type
         if not content_type in ALLOWED_MIMETYPES:
             if content_type not in stripped_content:
                 stripped_content[content_type] = 0
             stripped_content[content_type] = (
                 stripped_content[content_type] + 1
             )
             continue
         new.attach(part)
     new[ALTERED_MESSAGE_HEADER] = 'Stripped ' + ', '.join(
         ['%s*%s' % (key, value) for key, value in stripped_content.items()]
     )
     return new
Пример #16
0
def make_mdn(sender, recipient, orig_message_id, subject):
    domain = sender.partition('@')[2]

    msg = Message()
    msg['MIME-Version'] = '1.0'
    msg['content-type'] = 'multipart/report; report-type=disposition-notification'
    msg['From'] = '<%s>' % sender
    msg['To'] = '<%s>' % recipient
    msg['Date'] = email.utils.formatdate()
    msg_id = '<%d.%s@%s>' % (time.time(), str(random.getrandbits(64)), domain)
    msg['Message-ID'] = msg_id
    msg['Subject'] = 'Processed: %s' % subject

    txt = Message()
    txt.set_payload('Your message was successfully processed.')
    msg.attach(txt)

    dn = Message()
    dn['Content-Type'] = 'message/disposition-notification'
    dn['Content-Transfer-Encoding'] = '7bit'
    dn.set_payload(NOTIFICATION % (sender, orig_message_id))
    msg.attach(dn)

    return msg_id, msg.as_string()
Пример #17
0
def make_mdn(sender, recipient, orig_message_id, subject):
    domain = sender.partition('@')[2]

    msg = Message()
    msg['MIME-Version'] = '1.0'
    msg['content-type'] = 'multipart/report; report-type=disposition-notification'
    msg['From'] = '<%s>' % sender
    msg['To'] = '<%s>' % recipient
    msg['Date'] = email.utils.formatdate()
    msg_id = '<%d.%s@%s>' % (time.time(), str(random.getrandbits(64)), domain)
    msg['Message-ID'] =  msg_id
    msg['Subject'] = 'Processed: %s' % subject

    txt = Message()
    txt.set_payload('Your message was successfully processed.')
    msg.attach(txt)

    dn = Message()
    dn['Content-Type'] = 'message/disposition-notification'
    dn['Content-Transfer-Encoding'] = '7bit'
    dn.set_payload(NOTIFICATION % (sender,orig_message_id))
    msg.attach(dn)

    return msg_id, msg.as_string()
Пример #18
0
    def _get_dehydrated_message(self, msg, record):
        new = EmailMessage()
        if msg.is_multipart():
            for header, value in msg.items():
                new[header] = value
            for part in msg.get_payload():
                new.attach(
                    self._get_dehydrated_message(part, record)
                )
        elif (
            STRIP_UNALLOWED_MIMETYPES
            and not msg.get_content_type() in ALLOWED_MIMETYPES
        ):
            for header, value in msg.items():
                new[header] = value
            # Delete header, otherwise when attempting to  deserialize the
            # payload, it will be expecting a body for this.
            del new['Content-Transfer-Encoding']
            new[ALTERED_MESSAGE_HEADER] = (
                'Stripped; Content type %s not allowed' % (
                    msg.get_content_type()
                )
            )
            new.set_payload('')
        elif msg.get_content_type() not in TEXT_STORED_MIMETYPES:
            filename = msg.get_filename()
            if not filename:
                extension = mimetypes.guess_extension(msg.get_content_type())
            else:
                _, extension = os.path.splitext(filename)
            if not extension:
                extension = '.bin'

            attachment = MessageAttachment()

            attachment.document.save(
                uuid.uuid4().hex + extension,
                ContentFile(
                    six.BytesIO(
                        msg.get_payload(decode=True)
                    ).getvalue()
                )
            )
            attachment.message = record
            for key, value in msg.items():
                attachment[key] = value
            attachment.save()

            placeholder = EmailMessage()
            placeholder[ATTACHMENT_INTERPOLATION_HEADER] = str(attachment.pk)
            new = placeholder
        else:
            content_charset = msg.get_content_charset()
            if not content_charset:
                content_charset = 'ascii'
            try:
                # Make sure that the payload can be properly decoded in the
                # defined charset, if it can't, let's mash some things
                # inside the payload :-\
                msg.get_payload(decode=True).decode(content_charset)
            except LookupError:
                logger.warning(
                    "Unknown encoding %s; interpreting as ASCII!",
                    content_charset
                )
                msg.set_payload(
                    msg.get_payload(decode=True).decode(
                        'ascii',
                        'ignore'
                    )
                )
            except ValueError:
                logger.warning(
                    "Decoding error encountered; interpreting as ASCII!",
                    content_charset
                )
                msg.set_payload(
                    msg.get_payload(decode=True).decode(
                        content_charset,
                        'ignore'
                    )
                )
            new = msg
        return new
Пример #19
0
# E-Mail versenden

from email.message import Message

msg = Message()
log = open(LogOutputFile, "r")

# Error Log Datei auslesen
Text = ""
for line in log:
    Text += line

log.close()

# EMail erzeuegen
msg.attach(LogErrorFile)  # toDo
msg.set_payload(Text)
msg["Subject"] = MailSubject
msg["From"] = MailFrom
msg["To"] = MailTo

# EMail verschicken
server = smtplib.SMTP('localhost')
server.sendmail(MailFrom, MailTo, msg.as_string())
server.quit()

# Alle Dateien loeschen
os.remove(OUITmpDatei)
os.remove(LogOutputFile)
os.remove(LogErrorFile)
Пример #20
0
    if mimeencoding or (mimetype is None): 
        mimetype = 'application/octet-stream' 
    maintype, subtype = mimetype.split('/') 
    if maintype == 'text': 
        retval = MIMEText(fd.read(), _subtype=subtype) 
    else: 
        retval = MIMEBase(maintype, subtype) 
        retval.set_payload(fd.read()) 
        encoders.encode_base64(retval) 
    retval.add_header('Content-Disposition', 'attachment', 
        filename = filename) 
    fd.close() 
    return retval 
 
#attaches attachements, and finishes message
msg.attach(body) 
for filename in sys.argv[1:]: 
    msg.attach(attachment(filename)) 

file1.write(msg)
file1.close()

#uses SMTP to send the object to the server.
#parses command line args
if len(sys.argv) < 4:
    print "usage: %s server fromaddr toaddr [toaddr...]" % sys.argv[0]
    sys.exit(2)
server, fromaddr, toaddrs = sys.argv[1], sys.argv[2], sys.argv[3:]
#opens up the created file
message = file1.open('message.txt', 'r')
Пример #21
0
class GPGEmail(SimpleEmail):
    """Třída pro vytvoření a odeslaní jednoduchého kryptovaného mailu."""
    def __init__(self,
                 to,
                 from_,
                 subject,
                 content,
                 key,
                 html=False,
                 smtp='localhost',
                 charset='UTF-8'):
        """Inicializuj instanci.

          to -- adresa příjemce (zatím podporujeme jen jednoho příjemce)
          from_ -- adresa odesílatele
          subject -- předmět zprávy (může obsahovat buď řetězec nebo unicode
          content -- vlastní obsah zprávy
          key -- veřejný klíč, kterým má být zpráva zakryptována
          html -- příznak, zda obsah je html
          smtp -- adresa odesílacího serveru
          charset -- v případě, že content není v unicode, je zde uveden charset pro content
        """
        super(GPGEmail, self).__init__(to,
                                       from_,
                                       subject,
                                       content,
                                       html=html,
                                       smtp=smtp,
                                       charset=charset)
        self.key = key

    def _create_message(self):
        """Return basic instance of Message."""
        self.msg = Message()

    def _gpg_encrypt_content(self):
        import tempfile
        import gnupg
        try:
            # Work around gnupg > 2.1.19/Python gnupg module version incompatibility.
            gnupg._parsers.Verify.TRUST_LEVELS[
                "ENCRYPTION_COMPLIANCE_MODE"] = 23
        except:
            pass
        keyring = tempfile.mkstemp()[1]
        options = ('--no-secmem-warning', '--always-trust',
                   '--no-default-keyring', '--keyring=%s' % keyring)
        gpg = gnupg.GPG(options=options)
        import_result = gpg.import_keys(self.key)
        fingerprints = import_result.fingerprints
        content = self.get_content_text(self.content,
                                        html=self.html,
                                        charset=self.charset)
        encryption_result = gpg.encrypt(str(content), fingerprints[0])
        if not encryption_result.ok:
            raise pytis.util.ProgramError(encryption_result.stderr)
        # BUG: There is no `keyring' defined here so the following
        # statement is effectively void:
        try:
            os.remove(keyring)
        except Exception:
            pass
        return str(encryption_result)

    def create_headers(self):
        super(GPGEmail, self).create_headers()
        self.msg["Mime-version"] = "1.0"
        self.msg["Content-type"] = "Multipart/encrypted"
        self.msg["Content-transfer-encoding"] = "8bit"
        self.msg.preamble = "This is an OpenPGP/MIME encrypted message (RFC 2440 and 3156)"

    def create_content(self):
        # Part 1
        firstSubMsg = email.message.Message()
        firstSubMsg["Content-Type"] = "application/pgp-encrypted"
        firstSubMsg["Content-Description"] = "PGP/MIME version identification"
        firstSubMsg.set_payload("Version: 1\n")
        # Part 2
        if self.html:
            filename = 'content.html.pgp'
        else:
            filename = 'content.txt.pgp'
        encrypted = self._gpg_encrypt_content()
        secondSubMsg = email.message.Message()
        secondSubMsg.add_header("Content-Type",
                                "application/octet-stream",
                                name=filename)
        secondSubMsg.add_header("Content-Description",
                                "OpenPGP encrypted message")
        secondSubMsg.add_header("Content-Disposition",
                                "attachment",
                                filename=filename)
        secondSubMsg.set_payload(encrypted)
        # Přidání částí do main
        self.msg.attach(firstSubMsg)
        self.msg.attach(secondSubMsg)
Пример #22
0
    def _get_dehydrated_message(self, msg, record):
        new = EmailMessage()
        if msg.is_multipart():
            for header, value in msg.items():
                new[header] = value
            for part in msg.get_payload():
                new.attach(
                    self._get_dehydrated_message(part, record)
                )
        elif (
            STRIP_UNALLOWED_MIMETYPES
            and not msg.get_content_type() in ALLOWED_MIMETYPES
        ):
            for header, value in msg.items():
                new[header] = value
            # Delete header, otherwise when attempting to  deserialize the
            # payload, it will be expecting a body for this.
            del new['Content-Transfer-Encoding']
            new[ALTERED_MESSAGE_HEADER] = (
                'Stripped; Content type %s not allowed' % (
                    msg.get_content_type()
                )
            )
            new.set_payload('')
        elif msg.get_content_type() not in TEXT_STORED_MIMETYPES:
            filename = msg.get_filename()
            if not filename:
                extension = mimetypes.guess_extension(msg.get_content_type())
            else:
                _, extension = os.path.splitext(filename)
            if not extension:
                extension = '.bin'

            attachment = MessageAttachment()

            # this will save on hd and in db
            # attachment.document.save(
                # uuid.uuid4().hex + extension,
                # ContentFile(
                    # six.BytesIO(
                        # msg.get_payload(decode=True)
                    # ).getvalue()
                # )
            # )
            
            # save only on hd
            attach = open(os.path.join(settings.BASE_DIR, 'apps', 'cores', 'incoming', 'django_mailbox', self.name, 'attachments', uuid.uuid4().hex + extension), 'wb')
            attach.write(six.BytesIO(msg.get_payload(decode=True)).getvalue())
            attach.close()
            
            attachment.message = record
            for key, value in msg.items():
                attachment[key] = value
            #attachment.save()

            placeholder = EmailMessage()
            placeholder[ATTACHMENT_INTERPOLATION_HEADER] = str(attachment.pk)
            new = placeholder
        else:
            content_charset = msg.get_content_charset()
            if not content_charset:
                content_charset = 'ascii'
            try:
                # Make sure that the payload can be properly decoded in the
                # defined charset, if it can't, let's mash some things
                # inside the payload :-\
                msg.get_payload(decode=True).decode(content_charset)
            except UnicodeDecodeError:
                msg.set_payload(
                    msg.get_payload(decode=True).decode(
                        content_charset,
                        'ignore'
                    )
                )
            new = msg
        return new
Пример #23
0
	def build_mail (self) -> str:
		"""Build the multipart mail and return it as a string"""
		(headers, charset) = self.__finalize_header ()
		root = Message ()
		for header in headers:
			(name, value) = header.split (':', 1)
			root[name] = value.strip ()
		msgs = []
		parts = []
		if len (self.content) == 1:
			if not self.attachments:
				parts.append ((root, self.content[0]))
			else:
				msg = Message ()
				msgs.append (msg)
				root.attach (msg)
				parts.append ((msg, self.content[0]))
		else:
			if self.content:
				if self.attachments:
					parent = Message ()
					msgs.append (parent)
					root.attach (parent)
				else:
					parent = root
				parent.set_type ('multipart/alternative')
				for content in self.content:
					msg = Message ()
					msgs.append (msg)
					parts.append ((msg, content))
					if content.related:
						base_message = Message ()
						msgs.append (base_message)
						base_message.set_type ('multipart/related')
						base_message.attach (msg)
						for related in content.related:
							r = Message ()
							msgs.append (r)
							parts.append ((r, related))
							base_message.attach (r)
						parent.attach (base_message)
					else:
						parent.attach (msg)
		for (msg, content) in parts:
			content.set_message (msg, charset)
		if self.attachments:
			root.set_type ('multipart/related')
			for attachment in self.attachments:
				at = Message ()
				msgs.append (at)
				root.attach (at)
				attachment.set_message (at, None)
		for msg in msgs:
			del msg['MIME-Version']
		return self.sign (root.as_string (False) + '\n')
class StartMessage:
    def __init__(self, fromAdd, toAdd, subject, body):
        self.msg = Message()
        self.msg.set_payload(body)
        self["Subject"] = subject
        self.setFrom(fromAdd)
        self.setTo(toAdd)
        self.hasAttachments = False

    def setFrom(self, fromAdd):
        if not fromAdd or not type(fromAdd) == type(""):
            raise Exception("a message must have one and only one sender")
        self["From"] = fromAdd

    def setTo(self, to):
        if not to:
            raise Exception("a message must have at least one recipient")
        self._addresses(to, "To")
        self.to = to

    def setCc(self, cc):
        self._addresses(cc, "Cc")

    def addAttachment(self, attachment, filename, mimetype=None):
        if not mimetype:
            mimetype = mimetypes.guess_type(filename)[0]
        if not mimetype:
            raise Exception("could not determine MIME type for ", filename)
        if "/" in mimetype:
            major, minor = mimetype.split("/")
        else:
            major = mimetype
            minor = None
        if not self.hasAttachments:
            body = self.msg.set_payload()
            newMsg = MIMEMultipart()
            newMsg.attach(MIMEText(body))

            for header, value in self.msg.items():
                newMsg[header] = value

            self.msg = newMsg
            self.hasAttachments = True
        subMessage = MIMENonMultipart(major, minor, name=filename)
        subMessage.set_payload(attachment)

        if major == "text":
            encoder = Encoders.encode_quopri
        else:
            encoder = Encoders.encode_base64
        encoder(subMessage)
        self.msg.attach(subMessage)

    def _addresses(self, addresses, key):
        if hasattr(addresses, "__iter__"):
            addresses = ''.join(addresses)
        self[key] = addresses

    def __getitem__(self, key):
        return self.msg[key]

    def __setitem__(self, key, value):
        self.msg[key] = value

    def __getattr__(self, key):
        return getattr(self.msg, key)

    def __str__(self):
        return self.msg.as_string()
Пример #25
0
    def emailException(self, htmlErrMsg):
        """Email the exception.

        Send the exception via mail, either as an attachment,
        or as the body of the mail.
        """
        message = Message()

        # Construct the message headers
        headers = self.setting('ErrorEmailHeaders').copy()
        headers['Date'] = formatdate()
        headers['Mime-Version'] = '1.0'
        headers['Subject'] = '{} {}: {}'.format(
            headers.get('Subject', '[Webware Error]'),
            *sys.exc_info()[:2])
        for header, value in headers.items():
            if isinstance(value, (list, tuple)):
                value = ','.join(value)
            message.add_header(header, value)

        # Construct the message body
        if self.setting('EmailErrorReportAsAttachment'):
            # start off with a text/plain part
            text = self._emailBody.format(path=self.servletPathname(),
                                          ascTime=asclocaltime(self._time),
                                          time=self._time)
            message.set_type('multipart/mixed')
            part = Message()
            part.set_type('text/plain')
            body = StringIO()
            body.write(text)
            traceback.print_exc(file=body)
            part.set_payload(body.getvalue())
            body.close()
            message.attach(part)
            part = Message()
            # now add htmlErrMsg
            part.add_header('Content-Transfer-Encoding', '7bit')
            part.add_header('Content-Description',
                            'HTML version of Webware error message')
            part.add_header('Content-Disposition',
                            'attachment',
                            filename='WebwareErrorMsg.html')
            part.set_type('text/html')
            part.set_payload(htmlErrMsg)
            message.attach(part)
        else:
            message.set_type('text/html')
            message.set_payload(htmlErrMsg, 'us-ascii')

        # Send the message
        server = self.setting('ErrorEmailServer')
        # This setting can be: server, server:port, server:port:user:password
        # or server:port:user:password:popserver:popport for "smtp after pop".
        parts = server.split(':', 5)
        server = port = user = passwd = None
        popserver = popssl = popport = None
        try:
            # fetch individual parts until we get an IndexError
            server = parts[0]
            try:
                port = int(parts[1])
            except ValueError:
                pass
            user = parts[2]
            passwd = parts[3]
            popserver = parts[4]
            try:
                popport = int(parts[5])
            except ValueError:
                popport = None
            if parts[6].lower() == 'ssl':
                popssl = True
        except IndexError:
            pass
        if user and passwd and popserver:
            # SMTP after POP
            if popssl is None and popport == 995:
                popssl = True
            popssl = poplib.POP3_SSL if popssl else poplib.POP3
            if popport:
                popserver = popssl(popserver, popport)
            else:
                popserver = popssl(popserver)
            popserver.set_debuglevel(0)
            popserver.user(user)
            popserver.pass_(passwd)
            try:
                popserver.quit()
            except Exception:
                pass
        if port:
            server = smtplib.SMTP(server, port)
        else:
            server = smtplib.SMTP(server)
        try:
            server.set_debuglevel(0)
            if user and passwd and not popserver:
                # SMTP-AUTH
                server.ehlo()
                if server.has_extn('starttls'):
                    server.starttls()
                    server.ehlo()
                server.login(user, passwd)
            body = message.as_string()
            server.sendmail(headers['From'], headers['To'], body)
        finally:
            try:
                server.quit()
            except Exception:
                pass
Пример #26
0
def encrypt_mail(inmail, recipients, contingencydir, gpghomedir=None):
    parser = Parser()
    if hasattr(inmail, "read"):
        orig = parser.parse(inmail)
    else:
        orig = parser.parsestr(inmail)
    contingencydir = os.path.expanduser(contingencydir)
    if gpghomedir:
        gpghomedir = os.path.expanduser(gpghomedir)
    if isinstance(recipients, str):
        recipients = [recipients]

    # minimal message with data to be encrypted
    new = Message()

    keep_headers = ("Content-Type", "Transfer-Encoding", "Content-Disposition")
    for h in keep_headers:
        if h in orig:
            new[h] = orig[h]

    if orig.is_multipart():
        for p in orig.get_payload():
            new.attach(p)
    else:
        new.set_payload(orig.get_payload())

    if recipients:
        gpg_command = ["gpg"]
        if gpghomedir:
            gpg_command.extend(["--homedir", gpghomedir])
        gpg_command.extend(["--batch", "--quiet", "--no-secmem-warning",
                            "--no-tty",
                            "--trust-model", "always",
                            "--armor", "--output", "-", "--encrypt"])

        for r in recipients:
            gpg_command.append("-r")
            gpg_command.append(r)

        popen = subprocess.Popen(gpg_command,
                                 stdin=subprocess.PIPE,
                                 stdout=subprocess.PIPE,
                                 stderr=subprocess.PIPE)

        encrypted, errors = popen.communicate(input=str(new))
        status = popen.returncode
    else:
        status = "invalid"
        errors = "No recipients set"

    if status == 0 and "-----BEGIN PGP MESSAGE-----" in encrypted:
        new_outer = MIMEMultipart("encrypted",
                                  protocol="application/pgp-encrypted")
        new_outer["Transfer-Encoding"] = "7bit"
        new_outer.preamble = "OpenPGP/MIME encrypted message, see "\
            "http://tools.ietf.org/html/rfc3156"

        gpg_attachment = MIMEApplication("Version: 1\n",
                                         _subtype="pgp-encrypted",
                                         _encoder=encode_7or8bit)
        gpg_attachment["Content-Disposition"] = "inline"
        new_outer.attach(gpg_attachment)

        gpg_message = MIMEApplication(encrypted,
                                      _subtype="octet-stream",
                                      _encoder=encode_7or8bit)
        gpg_message["Content-Disposition"] = "inline"
        new_outer.attach(gpg_message)
    else:
        now = datetime.datetime.now()
        ofilename = "encryptmail-" + str(now) + "-unencrypted.eml"
        localcopy = os.path.join(contingencydir, ofilename)
        try:
            fd = os.open(localcopy, os.O_WRONLY | os.O_CREAT, 0600)
            out = os.fdopen(fd, "wb")
            out.write(str(orig))
            out.close()
        except:
            log.error("Storing unencrypted message", exc_info=True)
            try:
                with tempfile.NamedTemporaryFile(
                        prefix="encryptmail-",
                        suffix="-unencrypted.eml") as out:
                    out.write(str(orig))
                    localcopy = out.name
            except:
                log.error("Storing unencrypted message in tempdir",
                          exc_info=True)
                localcopy = "nowhere (too many exceptions)"

        message = """{sep}
gpg encryption failed with exit status {status}

{errors}

A local copy of the e-mail was stored at {localcopy}
{sep}""".format(status=status, errors=errors,
                localcopy=localcopy, sep="=" * 80)
        new_outer = MIMEText(message)

    new_outer = copy_headers(orig, new_outer)
    return new_outer.as_string()
Пример #27
0
class SmartMessage:
    """A simplified interface to Python's library for creating email
    messages, with and without MIME attachments."""
    def __init__(self, fromAddr, toAddrs, subject, body):
        """Start off on the assumption that the message will be a simple RFC
        2822 message with no MIME."""
        self.msg = Message()
        self.msg.set_payload(body)
        self['Subject'] = subject
        self.setFrom(fromAddr)
        self.setTo(toAddrs)
        self.hasAttachments = False

    def setFrom(self, fromAddr):
        "Sets the address of the sender of the message."
        if not fromAddr or not type(fromAddr) == type(''):
            raise Exception('A message must have one and only one sender.')
        self['From'] = fromAddr

    def setTo(self, to):
        "Sets the address or addresses that will receive this message."
        if not to:
            raise Exception('A message must have at least one recipient.')
        self._addresses(to, 'To')
        #Also store the addresses as a list, for the benefit of future
        #code that will actually send this message.
        self.to = to

    def setCc(self, cc):
        """Sets the address or addresses that should receive this message,
        even though it's not addressed directly to them ("carbon-copy")."""
        self._addresses(cc, 'Cc')

    def addAttachment(self, attachment, filename, mimetype=None):
        "Attaches the given file to this message."
        #Figure out the major and minor MIME type of this attachment,
        #given its filename.
        if not mimetype:
            mimetype = mimetypes.guess_type(filename)[0]
        if not mimetype:
            raise Exception("Couldn't determine MIME type for ", filename)
        if '/' in mimetype:
            major, minor = mimetype.split('/')
        else:
            major = mimetype
            minor = None
        #The message was constructed under the assumption that it was
        #a single-part message. Now that we know there's to be at
        #least one attachment, we need to change it into a multi-part
        #message, with the first part being the body of the message.
        if not self.hasAttachments:
            body = self.msg.get_payload()
            newMsg = MIMEMultipart()
            newMsg.attach(MIMEText(body))
            #Copy over the old headers to the new object.
            for header, value in self.msg.items():
                newMsg[header] = value
            self.msg = newMsg
            self.hasAttachments = True
        subMessage = MIMENonMultipart(major, minor, name=filename)
        subMessage.set_payload(attachment)
        #Encode text attachments as quoted-printable, and all other
        #types as base64.
        if major == 'text':
            encoder = Encoders.encode_quopri
        else:
            encoder = Encoders.encode_base64
        encoder(subMessage)
        #Link the MIME message part with its parent message.
        self.msg.attach(subMessage)

    def _addresses(self, addresses, key):
        """Sets the given header to a string representation of the given
        list of addresses."""
        if hasattr(addresses, '__iter__'):
            addresses = ', '.join(addresses)
        self[key] = addresses

    #A few methods to let scripts treat this object more or less like
    #a Message or MultipartMessage, by delegating to the real Message
    #or MultipartMessage this object holds.
    def __getitem__(self, key):
        "Return a header of the underlying message."
        return self.msg[key]

    def __setitem__(self, key, value):
        "Set a header of the underlying message."
        self.msg[key] = value

    def __getattr__(self, key):
        return getattr(self.msg, key)

    def __str__(self):
        "Returns a string representation of this message."
        return self.msg.as_string()
Пример #28
0
class SmartMessage:
    """A simplified interface to Python's library for creating email
    messages, with and without MIME attachments."""

    def __init__(self, fromAddr, toAddrs, subject, body):
        """Start off on the assumption that the message will be a simple RFC
        2822 message with no MIME."""
        self.msg = Message()
        self.msg.set_payload(body)
        self["Subject"] = subject
        self.setFrom(fromAddr)
        self.setTo(toAddrs)
        self.hasAttachments = False

    def setFrom(self, fromAddr):
        "Sets the address of the sender of the message."
        if not fromAddr or not type(fromAddr) == type(""):
            raise Exception("A message must have one and only one sender.")
        self["From"] = fromAddr

    def setTo(self, to):
        "Sets the address or addresses that will receive this message."
        if not to:
            raise Exception("A message must have at least one recipient.")
        self._addresses(to, "To")
        # Also store the addresses as a list, for the benefit of future
        # code that will actually send this message.
        self.to = to

    def setCc(self, cc):
        """Sets the address or addresses that should receive this message,
        even though it's not addressed directly to them ("carbon-copy")."""
        self._addresses(cc, "Cc")

    def addAttachment(self, attachment, filename, mimetype=None):
        "Attaches the given file to this message."
        # Figure out the major and minor MIME type of this attachment,
        # given its filename.
        if not mimetype:
            mimetype = mimetypes.guess_type(filename)[0]
        if not mimetype:
            raise Exception("Couldn't determine MIME type for ", filename)
        if "/" in mimetype:
            major, minor = mimetype.split("/")
        else:
            major = mimetype
            minor = None
        # The message was constructed under the assumption that it was
        # a single-part message. Now that we know there's to be at
        # least one attachment, we need to change it into a multi-part
        # message, with the first part being the body of the message.
        if not self.hasAttachments:
            body = self.msg.get_payload()
            newMsg = MIMEMultipart()
            newMsg.attach(MIMEText(body))
            # Copy over the old headers to the new object.
            for header, value in self.msg.items():
                newMsg[header] = value
            self.msg = newMsg
            self.hasAttachments = True
        subMessage = MIMENonMultipart(major, minor, name=filename)
        subMessage.set_payload(attachment)
        # Encode text attachments as quoted-printable, and all other
        # types as base64.
        if major == "text":
            encoder = Encoders.encode_quopri
        else:
            encoder = Encoders.encode_base64
        encoder(subMessage)
        # Link the MIME message part with its parent message.
        self.msg.attach(subMessage)

    def _addresses(self, addresses, key):
        """Sets the given header to a string representation of the given
        list of addresses."""
        if hasattr(addresses, "__iter__"):
            addresses = ", ".join(addresses)
        self[key] = addresses

    # A few methods to let scripts treat this object more or less like
    # a Message or MultipartMessage, by delegating to the real Message
    # or MultipartMessage this object holds.
    def __getitem__(self, key):
        "Return a header of the underlying message."
        return self.msg[key]

    def __setitem__(self, key, value):
        "Set a header of the underlying message."
        self.msg[key] = value

    def __getattr__(self, key):
        return getattr(self.msg, key)

    def __str__(self):
        "Returns a string representation of this message."
        return self.msg.as_string()
Пример #29
0
    def prepare_multipart_body(self, content_index=0):
        # type: (int) -> int
        """Will prepare the body of this request according to the multipart information.

        This call assumes the on_request policies have been applied already in their
        correct context (sync/async)

        Does nothing if "set_multipart_mixed" was never called.

        :param int content_index: The current index of parts within the batch message.
        :returns: The updated index after all parts in this request have been added.
        :rtype: int
        """
        if not self.multipart_mixed_info:
            return 0

        requests = self.multipart_mixed_info[0]  # type: List[HttpRequest]
        boundary = self.multipart_mixed_info[2]  # type: Optional[str]

        # Update the main request with the body
        main_message = Message()
        main_message.add_header("Content-Type", "multipart/mixed")
        if boundary:
            main_message.set_boundary(boundary)

        for req in requests:
            part_message = Message()
            if req.multipart_mixed_info:
                content_index = req.prepare_multipart_body(
                    content_index=content_index)
                part_message.add_header("Content-Type",
                                        req.headers['Content-Type'])
                payload = req.serialize()
                # We need to remove the ~HTTP/1.1 prefix along with the added content-length
                payload = payload[payload.index(b'--'):]
            else:
                part_message.add_header("Content-Type", "application/http")
                part_message.add_header("Content-Transfer-Encoding", "binary")
                part_message.add_header("Content-ID", str(content_index))
                payload = req.serialize()
                content_index += 1
            part_message.set_payload(payload)
            main_message.attach(part_message)

        try:
            from email.policy import HTTP

            full_message = main_message.as_bytes(policy=HTTP)
            eol = b"\r\n"
        except ImportError:  # Python 2.7
            # Right now we decide to not support Python 2.7 on serialization, since
            # it doesn't serialize a valid HTTP request (and our main scenario Storage refuses it)
            raise NotImplementedError(
                "Multipart request are not supported on Python 2.7")
            # full_message = main_message.as_string()
            # eol = b'\n'
        _, _, body = full_message.split(eol, 2)
        self.set_bytes_body(body)
        self.headers["Content-Type"] = ("multipart/mixed; boundary=" +
                                        main_message.get_boundary())
        return content_index
Пример #30
0
# E-Mail versenden
    
from email.message import Message

msg = Message()
log = open(LogOutputFile, "r")

# Error Log Datei auslesen
Text = ""
for line in log:
    Text += line

log.close()

# EMail erzeuegen
msg.attach(LogErrorFile) # toDo
msg.set_payload(Text) 
msg["Subject"] = MailSubject 
msg["From"] = MailFrom
msg["To"] = MailTo

# EMail verschicken
server = smtplib.SMTP('localhost')
server.sendmail(MailFrom, MailTo, msg.as_string())
server.quit()


# Alle Dateien loeschen
os.remove(OUITmpDatei)
os.remove(LogOutputFile)
os.remove(LogErrorFile)
Пример #31
0
    def _get_dehydrated_message(self, msg, record):
        settings = utils.get_settings()

        new = EmailMessage()
        if msg.is_multipart():
            for header, value in msg.items():
                new[header] = value
            for part in msg.get_payload():
                new.attach(
                    self._get_dehydrated_message(part, record)
                )
        elif (
            settings['strip_unallowed_mimetypes']
            and not msg.get_content_type() in settings['allowed_mimetypes']
        ):
            for header, value in msg.items():
                new[header] = value
            # Delete header, otherwise when attempting to  deserialize the
            # payload, it will be expecting a body for this.
            del new['Content-Transfer-Encoding']
            new[settings['altered_message_header']] = (
                'Stripped; Content type %s not allowed' % (
                    msg.get_content_type()
                )
            )
            new.set_payload('')
        elif (
            (
                msg.get_content_type() not in settings['text_stored_mimetypes']
            ) or
            ('attachment' in msg.get('Content-Disposition', ''))
        ):
            filename = None
            raw_filename = msg.get_filename()
            if raw_filename:
                filename = utils.convert_header_to_unicode(raw_filename)
            if not filename:
                extension = mimetypes.guess_extension(msg.get_content_type())
            else:
                _, extension = os.path.splitext(filename)
            if not extension:
                extension = '.bin'

            attachment = MessageAttachment()

            attachment.document.save(
                uuid.uuid4().hex + extension,
                ContentFile(
                    six.BytesIO(
                        msg.get_payload(decode=True)
                    ).getvalue()
                )
            )
            attachment.message = record
            for key, value in msg.items():
                attachment[key] = value
            attachment.save()

            placeholder = EmailMessage()
            placeholder[
                settings['attachment_interpolation_header']
            ] = str(attachment.pk)
            new = placeholder
        else:
            content_charset = msg.get_content_charset()
            if not content_charset:
                content_charset = 'ascii'
            try:
                # Make sure that the payload can be properly decoded in the
                # defined charset, if it can't, let's mash some things
                # inside the payload :-\
                msg.get_payload(decode=True).decode(content_charset)
            except LookupError:
                logger.warning(
                    "Unknown encoding %s; interpreting as ASCII!",
                    content_charset
                )
                msg.set_payload(
                    msg.get_payload(decode=True).decode(
                        'ascii',
                        'ignore'
                    )
                )
            except ValueError:
                logger.warning(
                    "Decoding error encountered; interpreting %s as ASCII!",
                    content_charset
                )
                msg.set_payload(
                    msg.get_payload(decode=True).decode(
                        'ascii',
                        'ignore'
                    )
                )
            new = msg
        return new
Пример #32
0
def request_cached(url, type, msg=None, *,
        method="GET", headers=(), cleanup, **kw):
    if msg is None:
        msg = url
    print(method, msg, end=" ", flush=True, file=sys.stderr)
    
    path = url.split("/")
    dir = os.path.join(*path[:-1])
    suffix = hashlib.md5(url.encode()).digest()[:6]
    suffix = urlsafe_b64encode(suffix).decode("ascii")
    if path[-1]:
        suffix = path[-1] + os.extsep + suffix
    suffix += os.extsep
    metadata = os.path.join(dir, suffix + "mime")
    try:
        metadata = open(metadata, "rb")
    except FileNotFoundError:
        os.makedirs(dir, exist_ok=True)
        with open(metadata, "xb") as metadata:
            response = http_request(url, (type,),
                method=method,
                headers=headers + (
                    ("Accept-Encoding", "gzip, x-gzip"),
                ),
            **kw)
            cleanup.enter_context(response)
            print(response.status, response.reason, flush=True,
                file=sys.stderr)
            
            header = response.info()
            for field in header_list(header, "Connection"):
                del header[field]
            for field in (
                "Close", "Connection", "Content-Length", "Keep-Alive",
                "Proxy-Authenticate", "Proxy-Authorization",
                "Public",
                "Transfer-Encoding", "TE", "Trailer",
                "Upgrade",
            ):
                del header[field]
            
            [type, value] = header.get_params()[0]
            suffix += {
                'text/html': 'html', 'text/javascript': 'js',
                'application/json': 'json',
            }[type]
            for encoding in header_list(header, "Content-Encoding"):
                if encoding.lower() in {"gzip", "x-gzip"}:
                    suffix += os.extsep + "gz"
                    break
            cache = open(os.path.join(dir, suffix), "xb")
            cleanup.enter_context(cache)
            msg = Message()
            msg.add_header("Content-Type",
                "message/external-body; access-type=local-file",
                name=suffix)
            msg.attach(header)
            metadata = email.generator.BytesGenerator(metadata,
                mangle_from_=False, maxheaderlen=0)
            metadata.flatten(msg)
        return (header, TeeReader(response, cache.write))
    with metadata:
        msg = email.message_from_binary_file(metadata)
    cache = os.path.join(dir, msg.get_param("name"))
    [msg] = msg.get_payload()
    response = cleanup.enter_context(open(cache, "rb"))
    print("(cached)", flush=True, file=sys.stderr)
    return (msg, response)
Пример #33
0
    def _get_dehydrated_message(self, msg: RawMessage,
                                record: Message) -> Message:
        """
        We want to hand truncated messages so we split this method into several and change part with attachments.
        """
        new = RawMessage()
        if msg.is_multipart():
            for header, value in msg.items():
                new[header] = value
            for part in msg.get_payload():
                new.attach(self._get_dehydrated_message(part, record))
            return new

        if (mailbox_settings['strip_unallowed_mimetypes']
                and msg.get_content_type()
                not in mailbox_settings['allowed_mimetypes']):
            return self._get_dehydrated_as_stripped(msg, record)

        if ((msg.get_content_type()
             not in mailbox_settings['text_stored_mimetypes'])
                or ('attachment' in msg.get('Content-Disposition', ''))):
            return self._get_dehydrated_attachment(msg, record)

        content_charset = msg.get_content_charset()
        if not content_charset:
            content_charset = 'ascii'

        raw_payload = msg.get_payload()
        if raw_payload and raw_payload.splitlines(
        )[-1] == '----- Message truncated -----':
            raw_lines = raw_payload.splitlines()[:-1]
            truncated_payload = ''.join(raw_lines)
            truncated_payload = truncated_payload[:-(len(truncated_payload) %
                                                     4)]
            msg.set_payload(truncated_payload)

        try:
            # Make sure that the payload can be properly decoded in the
            # defined charset, if it can't, let's mash some things
            # inside the payload :-\

            msg.get_payload(decode=True).decode(content_charset)
        except LookupError:
            import codecs
            try:
                payload = codecs.decode(msg.get_payload(decode=True),
                                        content_charset, 'replace')
            except LookupError:
                import webencodings
                try:
                    payload = webencodings.decode(msg.get_payload(decode=True),
                                                  content_charset,
                                                  'replace')[0]
                except LookupError:
                    logger.warning(
                        "Unknown encoding %s; interpreting as ASCII!",
                        content_charset)
                    payload = msg.get_payload(decode=True).decode(
                        'ascii', 'ignore')
            msg.set_payload(payload)
        except ValueError:
            logger.warning(
                "Decoding error encountered; interpreting %s as ASCII!",
                content_charset)
            msg.set_payload(
                msg.get_payload(decode=True).decode('ascii', 'ignore'))
        return msg
Пример #34
0
    def emailException(self, htmlErrMsg):
        """Email the exception.

        Send the exception via mail, either as an attachment,
        or as the body of the mail.

        """
        message = Message()

        # Construct the message headers
        headers = self.setting('ErrorEmailHeaders').copy()
        headers['Date'] = formatdate()
        headers['Mime-Version'] = '1.0'
        headers['Subject'] = headers.get('Subject',
            '[WebKit Error]') + ' %s: %s' % sys.exc_info()[:2]
        for h, v in headers.items():
            if isinstance(v, (list, tuple)):
                v = ','.join(v)
            message.add_header(h, v)

        # Construct the message body
        if self.setting('EmailErrorReportAsAttachment'):
            # start off with a text/plain part
            text = ('WebKit caught an exception while processing'
                ' a request for "%s" at %s (timestamp: %s).'
                ' The plain text traceback from Python is printed below and'
                ' the full HTML error report from WebKit is attached.\n\n'
                    % (self.servletPathname(),
                        asclocaltime(self._time), self._time))
            message.set_type('multipart/mixed')
            part = Message()
            part.set_type('text/plain')
            body = StringIO()
            body.write(text)
            traceback.print_exc(file=body)
            part.set_payload(body.getvalue())
            body.close()
            message.attach(part)
            part = Message()
            # now add htmlErrMsg
            part.add_header('Content-Transfer-Encoding', '7bit')
            part.add_header('Content-Description',
                'HTML version of WebKit error message')
            part.add_header('Content-Disposition',
                'attachment', filename='WebKitErrorMsg.html')
            part.set_type('text/html')
            part.set_payload(htmlErrMsg)
            message.attach(part)
        else:
            message.set_type('text/html')
            message.set_payload(htmlErrMsg, 'us-ascii')

        # Send the message
        server = self.setting('ErrorEmailServer')
        # This setting can be: server, server:port, server:port:user:password
        # or server:port:user:password:popserver:popport for "smtp after pop".
        parts = server.split(':', 5)
        server = port = user = passwd = None
        popserver = popssl = popport = None
        try:
            server = parts[0]
            try:
                port = int(parts[1])
            except ValueError:
                pass
            user = parts[2]
            passwd = parts[3]
            popserver = parts[4]
            try:
                popport = int(parts[5])
            except ValueError:
                popport = None
            if parts[6].lower() == 'ssl':
                popssl = True
        except IndexError:
            pass
        if user and passwd and popserver:
            # SMTP after POP
            if popssl is None and popport == 995:
                popssl = True
            popssl = popssl and poplib.POP3_SSL or poplib.POP3
            if popport:
                popserver = popssl(popserver, popport)
            else:
                popserver = popssl(popserver)
            popserver.set_debuglevel(0)
            popserver.user(user)
            popserver.pass_(passwd)
            try:
                popserver.quit()
            except Exception:
                pass
        if port:
            server = smtplib.SMTP(server, port)
        else:
            server = smtplib.SMTP(server)
        try:
            server.set_debuglevel(0)
            if user and passwd and not popserver:
                # SMTP-AUTH
                server.ehlo()
                if server.has_extn('starttls'):
                    server.starttls()
                    server.ehlo()
                server.login(user, passwd)
            body = message.as_string()
            server.sendmail(headers['From'], headers['To'], body)
        finally:
            try:
                server.quit()
            except Exception:
                pass