Example #1
0
    def send_message(self, header, payload):
        """ Send the message to the partner"""
        logger.info(f'Sending message {self.message_id} from organization "{self.organization}" '
                    f'to partner "{self.partner}".')

        # Set up the http auth if specified in the partner profile
        auth = None
        if self.partner.http_auth:
            auth = (self.partner.http_auth_user, self.partner.http_auth_pass)

        # Send the message to the partner
        try:
            response = requests.post(
                self.partner.target_url, auth=auth, headers=header, data=payload,
                verify=self.partner.https_verify_ssl)
            response.raise_for_status()
        except requests.exceptions.RequestException as e:
            self.status = 'R'
            self.detailed_status = f'Failed to send message, error:\n{traceback.format_exc()}'
            self.save()
            return

        # Process the MDN based on the partner profile settings
        if self.partner.mdn:
            if self.partner.mdn_mode == 'ASYNC':
                self.status = 'P'
            else:
                # Process the synchronous MDN received as response

                # Get the response headers, convert key to lower case
                # for normalization
                mdn_headers = dict(
                    (k.lower().replace('_', '-'), response.headers[k]) for k in response.headers)

                # create the mdn content with message-id and content-type
                # header and response content
                mdn_content = f'message-id: {mdn_headers.get("message-id", self.message_id)}\n'
                mdn_content += f'content-type: {mdn_headers["content-type"]}\n\n'
                mdn_content = mdn_content.encode('utf-8') + response.content

                # Parse the as2 mdn received
                logger.debug(f'Received MDN response for message {self.message_id} '
                             f'with content: {mdn_content}')
                as2mdn = As2Mdn()
                status, detailed_status = as2mdn.parse(mdn_content, lambda x, y: self.as2message)

                # Update the message status and return the response
                if status == 'processed':
                    self.status = 'S'
                    run_post_send(self)
                else:
                    self.status = 'E'
                    self.detailed_status = f'Partner failed to process message: {detailed_status}'
                Mdn.objects.create_from_as2mdn(as2mdn=as2mdn, message=self, status='R')
        else:
            # No MDN requested mark message as success and run command
            self.status = 'S'
            run_post_send(self)

        self.save()
Example #2
0
    def test_run_post_send_triggers_signal(self, message):
        callback = Mock()

        post_send.connect(callback)
        run_post_send(message)
        post_send.disconnect(callback)

        callback.assert_called_once_with(message=message, sender=Message, signal=post_send)
Example #3
0
    def post(self, request, *args, **kwargs):

        # extract the  headers from the http request
        as2headers = ""
        for key in request.META:
            if key.startswith("HTTP") or key.startswith("CONTENT"):
                as2headers += (
                    f'{key.replace("HTTP_", "").replace("_", "-").lower()}: '
                    f"{request.META[key]}\n")

        # build the body along with the headers
        request_body = as2headers.encode() + b"\r\n" + request.body
        logger.debug(
            f'Received an HTTP POST from {request.META["REMOTE_ADDR"]} '
            f"with payload :\n{request_body}")

        # First try to see if this is an MDN
        logger.debug("Check to see if payload is an Asynchronous MDN.")
        as2mdn = As2Mdn()

        # Parse the mdn and get the message status
        status, detailed_status = as2mdn.parse(request_body, self.find_message)

        if not detailed_status == "mdn-not-found":
            message = Message.objects.get(message_id=as2mdn.orig_message_id,
                                          direction="OUT")
            logger.info(
                f"Asynchronous MDN received for AS2 message {as2mdn.message_id} to organization "
                f"{message.organization.as2_name} from partner {message.partner.as2_name}"
            )

            # Update the message status and return the response
            if status == "processed":
                message.status = "S"
                run_post_send(message)
            else:
                message.status = "E"
                message.detailed_status = (
                    f"Partner failed to process message: {detailed_status}")
            # Save the message and create the mdn
            message.save()
            Mdn.objects.create_from_as2mdn(as2mdn=as2mdn,
                                           message=message,
                                           status="R")

            return HttpResponse(_("AS2 ASYNC MDN has been received"))

        else:
            logger.debug("Payload is not an MDN parse it as an AS2 Message")
            as2message = As2Message()
            status, exception, as2mdn = as2message.parse(
                request_body,
                self.find_organization,
                self.find_partner,
                self.check_message_exists,
            )

            logger.info(
                f'Received an AS2 message with id {as2message.headers.get("message-id")} for '
                f'organization {as2message.headers.get("as2-to")} from '
                f'partner {as2message.headers.get("as2-from")}.')

            # In case of duplicates update message id
            if isinstance(exception[0], DuplicateDocument):
                as2message.message_id += "_duplicate"

            # Create the Message and MDN objects
            message, full_fn = Message.objects.create_from_as2message(
                as2message=as2message,
                filename=as2message.payload.get_filename(),
                payload=as2message.content,
                direction="IN",
                status="S" if status == "processed" else "E",
                detailed_status=exception[1],
            )

            # run post receive command on success
            if status == "processed":
                run_post_receive(message, full_fn)

            # Return the mdn in case of sync else return text message
            if as2mdn and as2mdn.mdn_mode == "SYNC":
                message.mdn = Mdn.objects.create_from_as2mdn(as2mdn=as2mdn,
                                                             message=message,
                                                             status="S")
                response = HttpResponse(as2mdn.content)
                for key, value in as2mdn.headers.items():
                    response[key] = value
                return response

            elif as2mdn and as2mdn.mdn_mode == "ASYNC":
                Mdn.objects.create_from_as2mdn(
                    as2mdn=as2mdn,
                    message=message,
                    status="P",
                    return_url=as2mdn.mdn_url,
                )
            return HttpResponse(_("AS2 message has been received"))
Example #4
0
    def send_message(self, header, payload):
        """ Send the message to the partner"""
        # Set up the http auth if specified in the partner profile
        auth = None
        if self.partner.http_auth:
            auth = (self.partner.http_auth_user, self.partner.http_auth_pass)

        # Send the message to the partner
        try:
            response = requests.post(self.partner.target_url,
                                     auth=auth,
                                     headers=header,
                                     data=payload)
            response.raise_for_status()
        except requests.exceptions.RequestException as e:
            self.status = 'R'
            self.detailed_status = \
                'Failed to send message, error:\n%s' % traceback.format_exc()
            self.save()
            return

        # Process the MDN based on the partner profile settings
        if self.partner.mdn:
            if self.partner.mdn_mode == 'ASYNC':
                self.status = 'P'
            else:
                # Process the synchronous MDN received as response

                # Get the response headers, convert key to lower case
                # for normalization
                mdn_headers = dict(
                    (k.lower().replace('_', '-'), response.headers[k])
                    for k in response.headers)

                # create the mdn content with message-id and content-type
                # header and response content
                mdn_content = '%s: %s\n' % ('message-id',
                                            mdn_headers.get(
                                                'message-id', self.message_id))
                mdn_content += '%s: %s\n\n' % ('content-type',
                                               mdn_headers['content-type'])
                mdn_content = mdn_content.encode('utf-8') + response.content

                # Parse the as2 mdn received
                as2mdn = As2Mdn()
                status, detailed_status = as2mdn.parse(
                    mdn_content, lambda x, y: self.as2message)

                # Update the message status and return the response
                if status == 'processed':
                    self.status = 'S'
                    run_post_send(self)
                else:
                    self.status = 'E'
                    self.detailed_status = \
                        'Partner failed to process message: %s' % detailed_status
                Mdn.objects.create_from_as2mdn(as2mdn=as2mdn,
                                               message=self,
                                               status='R')
        else:
            # No MDN requested mark message as success and run command
            self.status = 'S'
            run_post_send(self)

        self.save()
Example #5
0
    def post(self, request, *args, **kwargs):

        # extract the  headers from the http request
        as2headers = ''
        for key in request.META:
            if key.startswith('HTTP') or key.startswith('CONTENT'):
                as2headers += f'{key.replace("HTTP_", "").replace("_", "-").lower()}: ' \
                              f'{request.META[key]}\n'

        # build the body along with the headers
        request_body = as2headers.encode() + b'\r\n' + request.body
        logger.debug(
            f'Received an HTTP POST from {request.META["REMOTE_ADDR"]} '
            f'with payload :\n{request_body}'
        )

        # First try to see if this is an MDN
        logger.debug('Check to see if payload is an Asynchronous MDN.')
        as2mdn = As2Mdn()

        # Parse the mdn and get the message status
        status, detailed_status = as2mdn.parse(request_body, self.find_message)

        if not detailed_status == 'mdn-not-found':
            message = Message.objects.get(message_id=as2mdn.orig_message_id, direction='OUT')
            logger.info(
                f'Asynchronous MDN received for AS2 message {as2mdn.message_id} to organization '
                f'{message.organization.as2_name} from partner {message.partner.as2_name}')

            # Update the message status and return the response
            if status == 'processed':
                message.status = 'S'
                run_post_send(message)
            else:
                message.status = 'E'
                message.detailed_status = f'Partner failed to process message: {detailed_status}'
                run_post_failure(message)
            # Save the message and create the mdn
            message.save()
            Mdn.objects.create_from_as2mdn(as2mdn=as2mdn, message=message, status='R')

            return HttpResponse(_('AS2 ASYNC MDN has been received'))

        else:
            logger.debug('Payload is not an MDN parse it as an AS2 Message')
            as2message = As2Message()
            status, exception, as2mdn = as2message.parse(
                request_body, self.find_organization, self.find_partner, self.check_message_exists)

            logger.info(
                f'Received an AS2 message with id {as2message.headers.get("message-id")} for '
                f'organization {as2message.headers.get("as2-to")} from '
                f'partner {as2message.headers.get("as2-from")}.'
            )

            # In case of duplicates update message id
            if isinstance(exception[0], DuplicateDocument):
                as2message.message_id += '_duplicate'

            # Create the Message and MDN objects
            message, full_fn = Message.objects.create_from_as2message(
                as2message=as2message,
                filename=as2message.payload.get_filename(),
                payload=as2message.content,
                direction='IN',
                status='S' if status == 'processed' else 'E',
                detailed_status=exception[1]
            )

            # run post receive command on success
            if status == 'processed':
                run_post_receive(message, full_fn)

            # Return the mdn in case of sync else return text message
            if as2mdn and as2mdn.mdn_mode == 'SYNC':
                message.mdn = Mdn.objects.create_from_as2mdn(
                    as2mdn=as2mdn, message=message, status='S')
                response = HttpResponse(as2mdn.content)
                for key, value in as2mdn.headers.items():
                    response[key] = value
                return response

            elif as2mdn and as2mdn.mdn_mode == 'ASYNC':
                Mdn.objects.create_from_as2mdn(
                    as2mdn=as2mdn, message=message, status='P', return_url=as2mdn.mdn_url)
            return HttpResponse(_('AS2 message has been received'))