def save_message(self):
        """ Saves changes to a message.
        If the message is a new or saved draft it will call 'save_draft' otherwise
        this will save only properties of a message that are draft-independent such as:
            - is_read
            - category
            - flag
        :return: Success / Failure
        :rtype: bool
        """
        if self.object_id and not self.__is_draft:
            # we are only allowed to save some properties:
            allowed_changes = {self._cc('isRead'), self._cc('categories'), self._cc('flag')}  # allowed changes to be saved by this method
            changes = {tc for tc in self._track_changes if tc in allowed_changes}

            if not changes:
                return True  # there's nothing to update

            url = self.build_url(self._endpoints.get('get_message').format(id=self.object_id))

            data = self.to_api_data(restrict_keys=changes)

            response = self.con.patch(url, data=data)

            if not response:
                return False

            self._track_changes.clear()  # reset the tracked changes as they are all saved
            self.__modified = self.protocol.timezone.localize(dt.datetime.now())

            return True
        else:
            # fallback to save_draft
            return self.save_draft()