def publish(self, message, exchange=None):
        """
        Publish a :class:`fedora_messaging.message.Message` to an `exchange`_ on
        the message broker.

        >>> from fedora_messaging import _session, message
        >>> msg = message.Message(topic='test', body={'test':'message'})
        >>> sess = session.BlockingSession()
        >>> sess.publish(msg)

        Args:
            message (message.Message): The message to publish.
            exchange (str): The name of the AMQP exchange to publish to; defaults
                to :ref:`conf-publish-exchange`

        Raises:
            PublishReturned: If the published message is rejected by the broker.
            ConnectionException: If a connection error occurs while publishing.

        .. _exchange: https://www.rabbitmq.com/tutorials/amqp-concepts.html#exchanges
        """
        message.validate()
        try:
            self._connect_and_publish(exchange, message)
        except (pika_errs.NackError, pika_errs.UnroutableError) as e:
            _log.warning("Message was rejected by the broker (%s)", str(e))
            raise PublishReturned(reason=e)
        except (pika_errs.ConnectionClosed, pika_errs.AMQPChannelError):
            # Because this is a blocking connection (and thus can't heartbeat)
            # we might need to restart the connection.
            _log.info("Resetting connection to %s", self._parameters.host)
            self._connection = self._channel = None
            try:
                self._connect_and_publish(exchange, message)
            except (pika_errs.NackError, pika_errs.UnroutableError) as e:
                _log.warning("Message was rejected by the broker (%s)", str(e))
                raise PublishReturned(reason=e)
            except pika_errs.AMQPError as e:
                _log.error(str(e))
                if self._connection and self._connection.is_open:
                    self._connection.close()
                raise ConnectionException(reason=e)
        except pika_errs.AMQPError as e:
            if self._connection and self._connection.is_open:
                self._connection.close()
            raise ConnectionException(reason=e)