def as2message(self): """ Returns an object of pyas2lib's Message class""" if self.direction == 'IN': as2m = As2Message(sender=self.partner.as2partner, receiver=self.organization.as2org) else: as2m = As2Message(sender=self.organization.as2org, receiver=self.partner.as2partner) as2m.message_id = self.message_id as2m.mic = self.mic return as2m
def form_valid(self, form): # Send the file to the partner payload = form.cleaned_data['file'].read() as2message = As2Message( sender=form.cleaned_data['organization'].as2org, receiver=form.cleaned_data['partner'].as2partner ) logger.debug(f'Building message from {form.cleaned_data["file"].name} to send to partner ' f'{as2message.receiver.as2_name} from org {as2message.sender.as2_name}.') as2message.build( payload, filename=form.cleaned_data['file'].name, subject=form.cleaned_data['partner'].subject, content_type=form.cleaned_data['partner'].content_type ) message, _ = Message.objects.create_from_as2message( as2message=as2message, payload=payload, filename=form.cleaned_data['file'].name, direction='OUT', status='P' ) message.send_message(as2message.headers, as2message.content) if message.status in ['S', 'P']: messages.success( self.request, 'Message has been successfully send to Partner.') else: messages.error( self.request, 'Message transmission failed, check Messages tab for details.') return super(SendAs2Message, self).form_valid(form)
def test_manageserver_command(self): """ Test the command for managing the as2 server """ settings.MAX_ARCH_DAYS = -1 # Create a message as2message = As2Message( sender=self.organization.as2org, receiver=self.partner.as2partner) as2message.build( self.payload, filename='testmessage.edi', subject=self.partner.subject, content_type=self.partner.content_type ) out_message, _ = Message.objects.create_from_as2message( as2message=as2message, payload=self.payload, direction='OUT', status='P' ) out_message.send_message(as2message.headers, as2message.content) # Test the retry command out_message.refresh_from_db() self.assertEqual(out_message.status, 'R') management.call_command('manageas2server', retry=True) out_message.refresh_from_db() self.assertEqual(out_message.retries, 1) # Test max retry setting settings.MAX_RETRIES = 1 management.call_command('manageas2server', retry=True) out_message.refresh_from_db() self.assertEqual(out_message.retries, 2) self.assertEqual(out_message.status, 'E') # Test the async mdn command for outbound messages out_message.status = 'P' out_message.save() settings.ASYNC_MDN_WAIT = 0 management.call_command('manageas2server', async_mdns=True) out_message.refresh_from_db() self.assertEqual(out_message.status, 'E') # Test the clean command management.call_command('manageas2server', clean=True) self.assertEqual( Message.objects.filter( message_id=out_message.message_id).count(), 0)
def test_duplicate_error(self, mock_request): partner = Partner.objects.create( name='AS2 Server', as2_name='as2server', target_url='http://localhost:8080/pyas2/as2receive', signature='sha1', signature_cert=self.server_crt, encryption='tripledes_192_cbc', encryption_cert=self.server_crt, mdn=True, mdn_mode='SYNC', mdn_sign='sha1', ) # Send the message once as2message = As2Message( sender=self.organization.as2org, receiver=partner.as2partner) as2message.build( self.payload, filename='testmessage.edi', subject=partner.subject, content_type=partner.content_type ) in_message, _ = Message.objects.create_from_as2message( as2message=as2message, payload=self.payload, direction='OUT', status='P' ) mock_request.side_effect = SendMessageMock(self.client) in_message.send_message(as2message.headers, as2message.content) # Check the status of the message self.assertEqual(in_message.status, 'S') out_message = Message.objects.get( message_id=in_message.message_id, direction='IN') self.assertEqual(out_message.status, 'S') # send it again to cause duplicate error in_message.send_message(as2message.headers, as2message.content) # Make sure out message was created self.assertEqual(in_message.status, 'E') out_message = Message.objects.get( message_id=in_message.message_id + '_duplicate', direction='IN') self.assertEqual(out_message.status, 'E')
def test_duplicate_error(self, mock_request): partner = Partner.objects.create( name="AS2 Server", as2_name="as2server", target_url="http://localhost:8080/pyas2/as2receive", signature="sha1", signature_cert=self.server_crt, encryption="tripledes_192_cbc", encryption_cert=self.server_crt, mdn=True, mdn_mode="SYNC", mdn_sign="sha1", ) # Send the message once as2message = As2Message(sender=self.organization.as2org, receiver=partner.as2partner) as2message.build( self.payload, filename="testmessage.edi", subject=partner.subject, content_type=partner.content_type, ) in_message, _ = Message.objects.create_from_as2message( as2message=as2message, payload=self.payload, direction="OUT", status="P") mock_request.side_effect = SendMessageMock(self.client) in_message.send_message(as2message.headers, as2message.content) # Check the status of the message self.assertEqual(in_message.status, "S") out_message = Message.objects.get(message_id=in_message.message_id, direction="IN") self.assertEqual(out_message.status, "S") # send it again to cause duplicate error in_message.send_message(as2message.headers, as2message.content) # Make sure out message was created self.assertEqual(in_message.status, "E") out_message = Message.objects.get(message_id=in_message.message_id + "_duplicate", direction="IN") self.assertEqual(out_message.status, "E")
def build_and_send(self, partner, mock_request, smudge=False): # Build and send the message to server as2message = As2Message(sender=self.organization.as2org, receiver=partner.as2partner) as2message.build(self.payload, filename='testmessage.edi', subject=partner.subject, content_type=partner.content_type) out_message, _ = Message.objects.create_from_as2message( as2message=as2message, payload=self.payload, direction='OUT', status='P') mock_request.side_effect = SendMessageMock(self.client) out_message.send_message( as2message.headers, b'xxxx' + as2message.content if smudge else as2message.content) return out_message
def form_valid(self, form): # Send the file to the partner payload = form.cleaned_data["file"].read() as2message = As2Message( sender=form.cleaned_data["organization"].as2org, receiver=form.cleaned_data["partner"].as2partner, ) logger.debug( f'Building message from {form.cleaned_data["file"].name} to send to partner ' f"{as2message.receiver.as2_name} from org {as2message.sender.as2_name}." ) as2message.build( payload, filename=form.cleaned_data["file"].name, subject=form.cleaned_data["partner"].subject, content_type=form.cleaned_data["partner"].content_type, disposition_notification_to=form.cleaned_data["organization"].email_address or "*****@*****.**", ) message, _ = Message.objects.create_from_as2message( as2message=as2message, payload=payload, filename=form.cleaned_data["file"].name, direction="OUT", status="P", ) message.send_message(as2message.headers, as2message.content) if message.status in ["S", "P"]: messages.success( self.request, "Message has been successfully send to Partner." ) else: messages.error( self.request, "Message transmission failed, check Messages tab for details.", ) return super().form_valid(form)
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"))
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'))