Esempio n. 1
0
def get_parts(response):
    """Extract parts from headers.

    Params:
        response: a request object
    Returns:
        an array of content-ids
    """
    head_lines = ""
    for k, v in response.raw.getheaders().items():
        head_lines += str(k) + ":" + str(v) + "\n"
    full = head_lines.encode() + response.content
    parser = email.parser.BytesParser()
    decoded_reply = parser.parsebytes(full)
    parts = {}
    start = decoded_reply.get_param("start").lstrip("<").rstrip(">")
    i = 0
    for part in decoded_reply.get_payload():
        cid = part.get("content-Id", "").lstrip("<").rstrip(">")
        if (not start or start == cid) and "start" not in parts:
            parts["start"] = part.get_payload(decode=True)
        else:
            parts[cid or "Attachment%d" % i] = part.get_payload(decode=True)
        i += 1
    return parts
Esempio n. 2
0
    def load_from_checkpoint(self, checkpoint_data):
        parser = email.parser.BytesParser()
        message = parser.parsebytes(checkpoint_data)

        version = int(message['Version'])
        if version not in self.SUPPORTED_VERSIONS:
            raise storage.UnsupportedFileVersionError()

        if message.get_content_type() != 'application/json':
            raise storage.CorruptedProjectError(
                "Unexpected content type %s" % message.get_content_type())

        serialized_checkpoint = message.get_payload()

        checkpoint = json.loads(serialized_checkpoint, cls=JSONDecoder)

        self.deserialize(checkpoint)
        self.init_references()

        def validate_node(root, parent, node):
            assert node.parent is parent, (node.parent, parent)
            assert node.root is root, (node.root, root)

            for c in node.list_children():
                validate_node(root, node, c)

        validate_node(self, None, self)
Esempio n. 3
0
    def read(self):
        data, entry_type = super().read()

        headers_length = data.index(b'\n\n') + 2

        parser = email.parser.BytesParser()
        message = parser.parsebytes(data[:headers_length])
        content = data[headers_length:]

        if 'Checksum' in message:
            should_checksum = message['Checksum'].split(';')[0]
            checksum_type = message.get_param('type', None, 'Checksum')
            if checksum_type is None:
                raise BadFileFormatError("Checksum type not specified")
            if checksum_type == 'md5':
                have_checksum = hashlib.md5(content).hexdigest()
            else:
                raise BadFileFormatError(
                    "Unsupported checksum type '%s'" % checksum_type)

            if have_checksum != should_checksum:
                logger.error("%r", content)
                raise CorruptedFileError(
                    "Checksum mismatch (%s != %s)"
                    % (have_checksum, should_checksum))

        encoding = message.get_param('charset', 'ascii')

        return content.decode(encoding), message, entry_type
Esempio n. 4
0
    def read(self) -> Tuple[str, email.message.Message, bytes]:
        data, entry_type = self.__file.read()

        headers_length = data.index(b'\n\n') + 2

        parser = email.parser.BytesParser()
        message = parser.parsebytes(data[:headers_length])
        content = data[headers_length:]

        if 'Checksum' in message:
            should_checksum = cast(str, message['Checksum']).split(';')[0]
            checksum_type = cast(str,
                                 message.get_param('type', None, 'Checksum'))
            if checksum_type is None:
                raise BadFileFormatError("Checksum type not specified")
            if checksum_type == 'md5':
                have_checksum = hashlib.md5(content).hexdigest()
            else:
                raise BadFileFormatError("Unsupported checksum type '%s'" %
                                         checksum_type)

            if have_checksum != should_checksum:
                logger.error("%r", content)
                raise CorruptedFileError("Checksum mismatch (%s != %s)" %
                                         (have_checksum, should_checksum))

        encoding = cast(str, message.get_param('charset', 'ascii'))

        return content.decode(encoding), message, entry_type
Esempio n. 5
0
def main():
    # get user login
    user_email = get_login()
    if not user_email:
        exit_with_error("Unauthorized")

    # read stdin and parse to message object
    input_bytes = sys.stdin.buffer.read()
    parser = email.parser.BytesParser()
    try:
        message = parser.parsebytes(input_bytes)
    except MessageError as e:
        exit_with_error("MessageError: %s" % str(e))

    # add a header with the user's email
    message[USER_TRACKING_HEADER] = user_email

    # add a header with the server hostname
    # scripts.mit.edu runs multiple machines and load-balances between them
    message[SCRIPTS_HOSTNAME_HEADER] = platform.node()

    # add date if missing
    if "Date" not in message:
        message["Date"] = email.utils.formatdate()

    if "--debug" in sys.argv:
        # print the email without sending
        print(message.as_string(maxheaderlen=78))
    else:
        # send the email
        send_email(message)
Esempio n. 6
0
 def headers(self):
     if self._content and len(self._content):
         if not self._headers:
             parser = email.parser.BytesParser(policy=email.policy.default)
             msg = parser.parsebytes(self._content, headersonly=True)
             self._headers = msg
         return self._headers
     else:
         return None
Esempio n. 7
0
    def deserialize_command(self, cmd_data):
        parser = email.parser.BytesParser()
        message = parser.parsebytes(cmd_data)

        target_id = message['Target']
        cmd_state = json.loads(message.get_payload(), cls=JSONDecoder)
        cmd = commands.Command.create_from_state(cmd_state)

        return cmd, target_id
Esempio n. 8
0
 def test_mbox_with_8bit_tags(self):
     self.cli_login()
     self.cli_import("0028-tags-need-8bit-encoding.mbox.gz")
     self.cli_logout()
     mbox = self.client.get('/QEMU/[email protected]/mbox')
     parser = email.parser.BytesParser(policy=email.policy.SMTP)
     msg = parser.parsebytes(mbox.content)
     payload = decode_payload(msg)
     self.assertIn('SynICState *synic = get_synic(cs);', payload)
     self.assertIn('Reviewed-by: Philippe Mathieu-Daudé <*****@*****.**>', payload)
Esempio n. 9
0
    def _body(self):
        if not hasattr(self, "_raw_body"):
            status, data = self._client.uid("FETCH", str(self.uid),
                                            "(BODY.PEEK[])")
            if status != "OK":
                raise RuntimeError()

            parser = email.parser.BytesParser(policy=email.policy.default)
            self._raw_body = parser.parsebytes(data[0][1])

        return self._raw_body
Esempio n. 10
0
 def test_mbox_with_8bit_tags(self):
     self.cli_login()
     self.cli_import("0028-tags-need-8bit-encoding.mbox.gz")
     self.cli_logout()
     mbox = self.client.get(
         "/QEMU/[email protected]/mbox")
     parser = email.parser.BytesParser(policy=email.policy.SMTP)
     msg = parser.parsebytes(mbox.content)
     payload = decode_payload(msg)
     self.assertIn("SynICState *synic = get_synic(cs);", payload)
     self.assertIn(
         "Reviewed-by: Philippe Mathieu-Daudé <*****@*****.**>", payload)
Esempio n. 11
0
    def read(self) -> Tuple[FileInfo, bytes]:
        if not os.path.exists(self.path):
            raise NotFoundError()

        with open(self.path, 'rb') as fp:
            magic = fp.read(len(self.MAGIC))
            if magic != self.MAGIC:
                raise BadFileFormatError("Not an noisicaä file")

            # email.parser's headersonly attribute doesn't seem to work the
            # way I would expect it.
            headers = b''
            while headers[-2:] != b'\n\n':
                b = fp.read(1)
                if not b:
                    break
                headers += b

            parser = email.parser.BytesParser()
            message = parser.parsebytes(headers)

            content = fp.read()

            if 'Checksum' in message:
                should_checksum = cast(str, message['Checksum']).split(';')[0]
                checksum_type = cast(
                    str, message.get_param('type', None, 'Checksum'))
                if checksum_type is None:
                    raise BadFileFormatError("Checksum type not specified")
                if checksum_type == 'md5':
                    have_checksum = hashlib.md5(content).hexdigest()
                else:
                    raise BadFileFormatError("Unsupported checksum type '%s'" %
                                             checksum_type)

                if have_checksum != should_checksum:
                    raise CorruptedFileError("Checksum mismatch (%s != %s)" %
                                             (have_checksum, should_checksum))

            file_info = FileInfo()
            file_info.content_type = message.get_content_type()
            file_info.encoding = cast(str,
                                      message.get_param('charset', 'ascii'))
            if 'Version' in message:
                file_info.version = int(cast(str, message['Version']))
            if 'File-Type' in message:
                file_info.filetype = cast(str, message['File-Type'])

            return file_info, content
Esempio n. 12
0
    def from_bytes(cls, data, timestamp=None, flags=None, custom_flags=None):
        if timestamp is None:
            timestamp = time.time()
        if flags is None:
            flags = set()
        else:
            assert isinstance(flags, set)
        if custom_flags is None:
            custom_flags = set()
        else:
            assert isinstance(flags, set)

        parser = cls.msg_parser()
        msg = parser.parsebytes(data)
        return cls(msg, timestamp, flags, custom_flags)
Esempio n. 13
0
    def read(self):
        if not os.path.exists(self.path):
            raise NotFoundError()

        with open(self.path, 'rb') as fp:
            magic = fp.read(len(self.MAGIC))
            if magic != self.MAGIC:
                raise BadFileFormatError("Not an noisicaä file")

            # email.parser's headersonly attribute doesn't seem to work the
            # way I would expect it.
            headers = b''
            while headers[-2:] != b'\n\n':
                b = fp.read(1)
                if not b:
                    break
                headers += b

            parser = email.parser.BytesParser()
            message = parser.parsebytes(headers)

            content = fp.read()

            if 'Checksum' in message:
                should_checksum = message['Checksum'].split(';')[0]
                checksum_type = message.get_param('type', None, 'Checksum')
                if checksum_type is None:
                    raise BadFileFormatError("Checksum type not specified")
                if checksum_type == 'md5':
                    have_checksum = hashlib.md5(content).hexdigest()
                else:
                    raise BadFileFormatError(
                        "Unsupported checksum type '%s'" % checksum_type)

                if have_checksum != should_checksum:
                    raise CorruptedFileError(
                        "Checksum mismatch (%s != %s)"
                        % (have_checksum, should_checksum))

            file_info = FileInfo()
            file_info.content_type = message.get_content_type()
            file_info.encoding = message.get_param('charset', 'ascii')
            if 'Version' in message:
                file_info.version = int(message['Version'])
            if 'File-Type' in message:
                file_info.filetype = message['File-Type']

            return file_info, content
Esempio n. 14
0
def git_am_patch_split(f, encoding=None):
    """Parse a git-am-style patch and split it up into bits.

    :param f: File-like object to parse
    :param encoding: Encoding to use when creating Git objects
    :return: Tuple with commit object, diff contents and git version
    """
    encoding = encoding or getattr(f, "encoding", "ascii")
    contents = f.read()
    if isinstance(contents, bytes) and getattr(email.parser, "BytesParser", None):
        parser = email.parser.BytesParser()
        msg = parser.parsebytes(contents)
    else:
        parser = email.parser.Parser()
        msg = parser.parsestr(contents)
    return parse_patch_message(msg, encoding)
Esempio n. 15
0
def git_am_patch_split(f, encoding=None):
    """Parse a git-am-style patch and split it up into bits.

    :param f: File-like object to parse
    :param encoding: Encoding to use when creating Git objects
    :return: Tuple with commit object, diff contents and git version
    """
    encoding = encoding or getattr(f, "encoding", "ascii")
    contents = f.read()
    if type(contents) is bytes and getattr(email.parser, "BytesParser", None):
        parser = email.parser.BytesParser()
        msg = parser.parsebytes(contents)
    else:
        parser = email.parser.Parser()
        msg = parser.parsestr(contents)
    return parse_patch_message(msg, encoding)
Esempio n. 16
0
def parse_message(data):
    # Parse the email to its constituent parts

    # https://bugs.python.org/issue25545 says
    # > A unicode string has no RFC defintion as an email, so things do not work right...
    # > You do have to conditionalize your 2/3 code to use the bytes parser and generator if you are dealing with 8-bit
    # > messages. There's just no way around that.
    if six.PY2:
        parser = email.feedparser.FeedParser()
        parser.feed(data)
        msg = parser.close()
    else:
        # works the same as BytesFeedParser, and better than non-"Bytes" parsers for some messages
        parser = email.parser.BytesParser()
        msg = parser.parsebytes(data.encode('utf-8'))
    # Extract relevant data
    result = {}
    result['multipart'] = multipart = msg.is_multipart()
    result['headers'] = dict(msg)
    result['message_id'] = _parse_message_id(msg.get('Message-ID'))
    result['in_reply_to'] = _parse_message_id(msg.get('In-Reply-To'))
    result['references'] = _parse_message_id(msg.get('References'))
    if result['message_id'] == []:
        result['message_id'] = h.gen_message_id()
    else:
        result['message_id'] = result['message_id'][0]
    if multipart:
        result['parts'] = []
        for part in msg.walk():
            dpart = dict(headers=dict(part),
                         message_id=result['message_id'],
                         in_reply_to=result['in_reply_to'],
                         references=result['references'],
                         content_type=part.get_content_type(),
                         filename=part.get_filename(None),
                         payload=part.get_payload(decode=True))
            # payload is sometimes already unicode (due to being saved in mongo?)
            if part.get_content_maintype() == 'text':
                dpart['payload'] = six.ensure_text(dpart['payload'])
            result['parts'].append(dpart)
    else:
        result['payload'] = msg.get_payload(decode=True)
        # payload is sometimes already unicode (due to being saved in mongo?)
        if msg.get_content_maintype() == 'text':
            result['payload'] = six.ensure_text(result['payload'])

    return result
Esempio n. 17
0
 def _on_email(num, data):
     parser = email.parser.BytesParser()
     headers_b = data[0][1]
     headers = parser.parsebytes(headers_b, headersonly=True)
     
     if on_email is not None:
         result = on_email(num, data, headers)
         
         if result:
             return
     
     xfr = headers.get('X-Failed-Recipients')
     
     if xfr is not None:
         for xfr_email in filter(None, map(
                 lambda s: s.strip(), xfr.split(','))):
             if on_fail_email is not None:
                 on_fail_email(xfr_email)
Esempio n. 18
0
    def _on_email(num, data):
        parser = email.parser.BytesParser()
        headers_b = data[0][1]
        headers = parser.parsebytes(headers_b, headersonly=True)

        if on_email is not None:
            result = on_email(num, data, headers)

            if result:
                return

        xfr = headers.get('X-Failed-Recipients')

        if xfr is not None:
            for xfr_email in filter(None,
                                    map(lambda s: s.strip(), xfr.split(','))):
                if on_fail_email is not None:
                    on_fail_email(xfr_email)
Esempio n. 19
0
    async def handle_DATA(self, server, session, envelope):
        logger = logging.getLogger('orouboros.localhandler')
        logger.debug(f'Session auth? {session.is_authenticated}')
        logger.debug(f'Message is from {envelope.mail_from!r}')
        logger.debug(f'Message is for {envelope.rcpt_tos!r}')
        valid_recipients = [
            recipient for recipient in envelope.rcpt_tos
            if recipient.rpartition('@')[2] in self.ok_domains
        ]

        # TODO: remove False and -W. Werner, 2018-03-01
        if False and not valid_recipients:
            logger.error(f'No valid recipients in {envelope.rcpt_tos}')
            return '554 Transaction failed'
        else:
            logger.info(f'Sending mail to {valid_recipients}')
            parser = email.parser.BytesParser()
            msg = parser.parsebytes(envelope.original_content)
            self.deliver(msg, valid_recipients)

        return '250 Message accepted for delivery, eh?'
Esempio n. 20
0
def fuzz(parser):
    with open(sys.argv[1], "rb") as fp:
        message = parser.parse(fp)
    message.as_bytes(policy=email.policy.default)
    message.is_multipart()
    message.get_unixfrom()
    keys = message.keys()
    for key in keys:
        message.get(key)
        message.get_all(key)
    message.values()
    message.get_content_type()
    message.get_content_maintype()
    message.get_content_subtype()
    message.get_default_type()
    message.get_filename()
    message.get_boundary()
    message.get_content_charset()
    message.is_attachment()
    message.get_content_disposition()
    for part in message.walk():
        pass


parser = email.parser.BytesParser(policy=email.policy.default)
parser.parsebytes(b"")
afl.init()
fuzz(parser)
os._exit(0)
Esempio n. 21
0
def run_query(mailbox, query, cmd, a_box, boxlst, mail, print_mutex, mqueue, name):
  dqueue = queue.Queue()
  mqueue.put((name.update, 'Running query.'))
  search_query = '('
  for key in query.keys():
    if query[key]:
      if (len(search_query) > 1):
        search_query = search_query+' '
      search_query = search_query+'%s \"%s\"' % (key, query[key])
  search_query = search_query+')'
  if (mailbox != 'ALL'):
    t = email_search(mail, search_query, mailbox, dqueue, print_mutex)
    t.start()
    while(True):
      time.sleep(.5)
      try:
        (result, lst) = dqueue.get(block=False)
      except queue.Empty:
        pass
      else:
        mqueue.put((name.update, 'Query complete.'))
        break

  else:
    i = 0
    box = a_box
    for mailbox in (boxlst):
      if(box == mailbox or mailbox == 'ALL'): continue
      t = email_search(mail, search_query, mailbox, dqueue, print_mutex)
      t.start()
      while(True):
        time.sleep(.5)
        try:
          (result, tmp) = dqueue.get(block=False)
        except queue.Empty:
          pass
        else:
          break
      i += len(tmp)
      if(len(tmp) > 0):
        #mail.copy(a, box)
        t = email_copy(mail, tmp, box, dqueue, print_mutex)
        t.start()
        while(True):
          try:
            result = dqueue.get(block=False)
          except queue.Empty:
            pass
          else:
            break
                       
    mqueue.put((name.update, ('%i Messages found.' % i)))
    return

  #If messages were found ask for what to do, else inform user that not messages matchedthe query
  if(len(lst)==0):
    mqueue.put((name.update, ('No messages that matched query.')))
    return
  
  else:
    
    ans = cmd
    #Delete
    if ans == 'delete':
      mqueue.put((confirm, ((mail.get_name(), '%i Messages found in %s, \ndo you really want to delete these messages?' % (len(lst), mailbox), \
                             delete,  mail, mailbox, lst, print_mutex, mqueue, name))))
      return

    #Move - actually copy and delete
    elif ans == 'move':
      mqueue.put((confirm, ((mail.get_name(), '%i Messages found in %s, \ndo you really want to move these messages?' % (len(lst), mailbox), \
                             move,  mail, mailbox, a_box, lst, print_mutex, dqueue, mqueue, name))))
      return


    #Copy
    elif ans == 'copy':
      mqueue.put((name.update, ('%i Messages found. Copied to %s' % (len(lst), a_box))))
      t = email_copy(mail, lst, a_box, dqueue, print_mutex)
      t.start()
      while(True):
        time.sleep(.5)
        try:
          resukt = dqueue.get(block=False)
        except queue.Empty:
          pass
        else:
          break
      return len(lst)

    #Fetch message
    elif ans == 'fetch':
      #pdb.set_trace()
      mqueue.put((name.update, ('%i Messages found.' % len(lst))))
      log(mail.get_name(), '%i Messages found.' % len(lst))
      for a in lst:
        try:
          #typ, data = mail.fetch(a, '(BODY.PEEK[TEXT])')
          typ, data = mail.fetch(a, '(RFC822)')
          #msg = email.message_from_string(data[0][1])
          
        except Exception as e:
          log (e)
        #log(mail.get_name(), data)
        sdata = str(data[0][1])
        #sdata = sdata[2:]
        #sdata = sdata[:-1]
        #msg = email.message_from_string(str(data[0][1]))
        parser = email.parser.BytesParser()
        #sdata= data[0][1].decode('utf-8')
        msg = parser.parsebytes(data[0][1])
        maintype = msg.get_content_maintype()
        if (maintype == 'multipart'):
          with print_mutex: print('Multipart!!!')
          for part in msg.walk():
            if part.get_content_type() == 'text/plain':
              with print_mutex: print(part.get_payload())
        elif (maintype == 'text'):
          with print_mutex: print('Text!!!')
          with print_mutex: print(msg.get_payload())
    return len(lst)
Esempio n. 22
0
def parse_email(email_string):
    return parser.parsebytes(email_string)
Esempio n. 23
0
 async def handle_DATA(self, server, session, envelope):
     parser = email.parser.BytesParser(policy=email.policy.SMTP)
     message = parser.parsebytes(envelope.content)
     try:
         parsed_message = ParsedMailMessage.from_email_object(message, envelope.mail_from)
     except Exception:
         err_msg = ''.join(traceback.format_exception(*sys.exc_info()))
         self._error_writer('Failed to parse Message:\n{}'.format(err_msg))
         django.core.mail.send_mail(
             'LMTP Handling Error', err_msg, from_email=POSTMASTER_ADDRESS,
             recipient_list=[POSTMASTER_ADDRESS], fail_silently=True)
         return '500 Failed to parse incoming message'
     success_count = 0
     error_messages = []
     internal_problems = []
     for recipient in envelope.rcpt_tos:
         try:
             self._contribution_processor.process_message_for_recipient(parsed_message,
                                                                        recipient)
             success_count += 1
             self._success_writer('Processed recipient {:d}/{:d} ({}) successfully'
                                  .format(success_count, len(envelope.rcpt_tos), recipient))
         except MailProcessingFailure as exc:
             error_messages.append((recipient, str(exc)))
             self._error_writer('Failed to process recipient <{}>: {}'.format(recipient, exc))
         except Exception as exc:
             # unknown internal problems end up here
             internal_problems.append((recipient,
                                       ''.join(traceback.format_exception(*sys.exc_info()))))
             self._error_writer('Internal error while processing recipient <{}>: {}\n{}'
                                .format(recipient, exc, internal_problems[-1][1]))
     if error_messages:
         # The mail was not acceptable for us (e.g. due to permissions). We send a human
         # readable separate response and tell the mail server, that the mail was handled.
         if len(error_messages) > 1:
             # format multiple errors into one string
             error_response_text = '\n\n'.join('= {} =\n\n{}'.format(recipient, error_message)
                                               for recipient, error_message in error_messages)
         else:
             error_response_text = error_messages[0][1]
     else:
         error_response_text = None
     if internal_problems:
         # At least one recipient failed mysteriously.
         problems_text = '\n\n'.join('= {} =\n{}\n'.format(recipient, exc)
                                     for recipient, exc in internal_problems)
         # inform developers
         self._contribution_processor.send_error_mail_response(
             parsed_message, problems_text, recipient=POSTMASTER_ADDRESS, fail_silently=True)
         if success_count > 0:
             # Never reject a message that was at least partly processed. Otherwise a
             # contribution could be published multiple times - which would be quite annoying
             # for the subscribers.
             return '250 Message partially accepted for delivery (ignoring internal errors)'
         else:
             # The mail server should ask us again later. Hopefully the problem is fixed until
             # then.  An error message mail is not yet returned to the sender.
             return '451 Requested action aborted: error in processing'
     elif error_response_text is not None:
         # Try to send an helpful error message mail back to sender.
         # Only return a bounce, if we failed to submit this error message mail.
         try:
             self._contribution_processor.send_error_mail_response(parsed_message,
                                                                   error_response_text,
                                                                   recipient=envelope.mail_from)
             return ('250 The incoming message was at least partly not accepted for '
                     'publication. Instead a separate error mails was returned.')
         except smtplib.SMTPException:
             # emergency bounce in case of mail delivery problems
             return '550 Rejected incoming mail due to errors'
     elif success_count > 0:
         return '250 Message accepted for delivery'
     else:
         self._error_writer('Unexpectedly encountered an empty list of recipients.')
def parse_message_from_bytes(raw_bytes):
    parser = email.parser.BytesParser(policy=email.policy.SMTP)
    return parser.parsebytes(raw_bytes)