def as2receive(request, *args, **kwargs): """ Function receives AS2 requests from partners. Checks whether its an AS2 message or an MDN and acts accordingly. """ if request.method == 'POST': # Process the posted AS2 message request_body = request.read() # Create separate raw_payload with only message-id and content type as M2Crypto's signature # verification method does not like too many header raw_payload = '%s: %s\n' % ('message-id', request.META['HTTP_MESSAGE_ID']) raw_payload += '%s: %s\n\n' % ('content-type', request.META['CONTENT_TYPE']) raw_payload += request_body # Extract all the relevant headers from the http request as2headers = '' for key in request.META: if key.startswith('HTTP') or key.startswith('CONTENT'): as2headers += '%s: %s\n' % (key.replace("HTTP_", "").replace("_", "-").lower(), request.META[key]) pyas2init.logger.debug('Recevied an HTTP POST from %s with payload :\n%s' % (request.META['REMOTE_ADDR'], as2headers + '\n' + request_body)) try: pyas2init.logger.debug('Check payload to see if its an AS2 Message or ASYNC MDN.') # Load the request header and body as a MIME Email Message payload = email.message_from_string(as2headers + '\n' + request_body) # Get the message sender and receiver AS2 IDs message_org = as2utils.unescape_as2name(payload.get('as2-to')) message_partner = as2utils.unescape_as2name(payload.get('as2-from')) message = None # Check if this is an MDN message mdn_message = None if payload.get_content_type() == 'multipart/report': mdn_message = payload elif payload.get_content_type() == 'multipart/signed': for part in payload.walk(): if part.get_content_type() == 'multipart/report': mdn_message = part # If this is an MDN, get the message ID and check if it exists if mdn_message: msg_id = None for part in mdn_message.walk(): if part.get_content_type() == 'message/disposition-notification': msg_id = part.get_payload().pop().get('Original-Message-ID') pyas2init.logger.info('Asynchronous MDN received for AS2 message %s to organization %s ' 'from partner %s' % (msg_id, message_org, message_partner)) try: # Get the related organization, partner and message from the db. org = get_object_or_404(models.Organization, as2_name=message_org) partner = get_object_or_404(models.Partner, as2_name=message_partner) message = get_object_or_404(models.Message, message_id=msg_id.strip('<>'), organization=org, partner=partner) models.Log.objects.create(message=message, status='S', text=_(u'Processing asynchronous mdn received from partner')) as2lib.save_mdn(message, raw_payload) except Http404: # Send 404 response pyas2init.logger.error('Unknown Asynchronous MDN AS2 message %s. ' 'Either the partner, org or message was not found in the system' % msg_id) return HttpResponseServerError(_(u'Unknown AS2 MDN received. Will not be processed')) except Exception, e: message.status = 'E' models.Log.objects.create(message=message, status='E', text=_(u'Failed to send message, error is %s' % e)) # Send mail here as2utils.senderrorreport(message, _(u'Failed to send message, error is %s' % e)) finally: # Save message and send response to HTTP request if message: message.save() return HttpResponse(_(u'AS2 ASYNC MDN has been received')) else: try: # Process the received AS2 message from partner # Initialize the processing status variables status, adv_status, status_message = '', '', '' pyas2init.logger.info('Received an AS2 message with id %s for organization %s from partner %s' % (payload.get('message-id'), message_org, message_partner)) # Raise duplicate message error in case message already exists in the system # TODO: Create composite key (message_id, organization, partner) if models.Message.objects.filter(message_id=payload.get('message-id').strip('<>')).exists(): message = models.Message.objects.create( message_id='%s_%s' % (payload.get('message-id').strip('<>'), payload.get('date')), direction='IN', status='IP', headers=as2headers ) raise as2utils.As2DuplicateDocument(_(u'An identical message has already ' u'been sent to our server')) # Create a new message in the system message = models.Message.objects.create( message_id=payload.get('message-id').strip('<>'), direction='IN', status='IP', headers=as2headers) # Process the received payload to extract the actual message from partner payload = as2lib.save_message(message, payload, raw_payload) # Get the inbox folder for this partner and organization output_dir = as2utils.join(pyas2init.gsettings['root_dir'], 'messages', message.organization.as2_name, 'inbox', message.partner.as2_name) # Get the filename from the header and if not there set to message id if message.partner.keep_filename and payload.get_filename(): filename = payload.get_filename() else: filename = '%s.msg' % message.message_id # Save the message content to the store and inbox content = payload.get_payload(decode=True) full_filename = as2utils.storefile(output_dir, filename, content, False) store_filename = as2utils.storefile(pyas2init.gsettings['payload_receive_store'], message.message_id, content, True) models.Log.objects.create(message=message, status='S', text=_(u'Message has been saved successfully to %s' % full_filename)) message.payload = models.Payload.objects.create(name=filename, file=store_filename, content_type=payload.get_content_type()) # Set processing status and run the post receive command. status = 'success' as2lib.run_post_receive(message, full_filename) message.save() # Catch each of the possible exceptions while processing an as2 message except as2utils.As2DuplicateDocument, e: status = 'warning' adv_status = 'duplicate-document' status_message = _(u'An error occurred during the AS2 message processing: %s' % e) except as2utils.As2PartnerNotFound, e: status = 'error' adv_status = 'unknown-trading-partner' status_message = _(u'An error occurred during the AS2 message processing: %s' % e)
def as2receive(request, *args, **kwargs): """ Function receives AS2 requests from partners. Checks whether its an AS2 message or an MDN and acts accordingly. """ if request.method == 'POST': # Create separate raw_payload with only message-id and content type # as M2Crypto's signatur verification method does not like many headers raw_payload = '%s: %s\n' % ('message-id', request.META['HTTP_MESSAGE_ID']) raw_payload += '%s: %s\n\n' % ('content-type', request.META['CONTENT_TYPE']) raw_payload += request.body # Extract all the relevant headers from the http request as2headers = '' for key in request.META: if key.startswith('HTTP') or key.startswith('CONTENT'): h_key = key.replace("HTTP_", "").replace("_", "-").lower() as2headers += '%s: %s\n' % (h_key, request.META[key]) request_content = as2headers.encode('utf-8') + '\n'.encode( 'utf-8') + request.body pyas2init.logger.debug( 'Recevied an HTTP POST from %s with payload :\n%s' % (request.META['REMOTE_ADDR'], request_content)) try: pyas2init.logger.debug( 'Check payload to see if its an AS2 Message or ASYNC MDN.') # Load the request header and body as a MIME Email Message payload = email.message_from_string(request_content) # Get the message sender and receiver AS2 identifiers message_org_as2name = as2utils.unescape_as2name( payload.get('as2-to')) message_partner_as2name = as2utils.unescape_as2name( payload.get('as2-from')) message = None # Check if this is an MDN message mdn_message = None if payload.get_content_type() == 'multipart/report': mdn_message = payload elif payload.get_content_type() == 'multipart/signed': for part in payload.walk(): if part.get_content_type() == 'multipart/report': mdn_message = part # If this is an MDN, get the message ID and check if it exists if mdn_message: msg_id = None for part in mdn_message.walk(): if part.get_content_type( ) == 'message/disposition-notification': msg_id = part.get_payload().pop().get( 'Original-Message-ID') pyas2init.logger.info( 'Asynchronous MDN received for AS2 message %s to organization %s ' 'from partner %s' % (msg_id, message_org_as2name, message_partner_as2name)) try: # Get the related organization, partner and message from the db. org = get_object_or_404(models.Organization, as2_name=message_org_as2name) partner = as2lib.get_partner_from_payload(payload) if not partner: raise Http404('No Partner matches the given query.') message = get_object_or_404(models.Message, message_id=msg_id.strip('<>'), organization=org, partner=partner) models.Log.objects.create( message=message, status='S', text=_( u'Processing asynchronous mdn received from partner' )) as2lib.save_mdn(message, raw_payload) except Http404: # Send 404 response pyas2init.logger.error( 'Unknown Asynchronous MDN AS2 message %s. ' 'Either the partner, org or message was not found in the system' % msg_id) return HttpResponseServerError( _(u'Unknown AS2 MDN received. Will not be processed')) except Exception, e: message.status = 'E' message.adv_status = _( u'Failed to send message, error is:\n %s' % traceback.format_exc(None).decode('utf-8', 'ignore')) models.Log.objects.create(message=message, status='E', text=message.adv_status) # Send mail here as2utils.senderrorreport(message, message.adv_status) finally: # Save message and send response to HTTP request if message: message.save() return HttpResponse(_(u'AS2 ASYNC MDN has been received')) else: try: # Process the received AS2 message from partner # Initialize the processing status variables status, adv_status, status_message = '', '', '' pyas2init.logger.info( 'Received an AS2 message with id %s for organization %s from partner %s' % (payload.get('message-id'), message_org_as2name, message_partner_as2name)) # Raise duplicate message error in case message already exists in the system # TODO: Create composite key (message_id, organization, partner) if models.Message.objects.filter(message_id=payload.get( 'message-id').strip('<>')).exists(): message = models.Message.objects.create( message_id='%s_%s' % (payload.get('message-id').strip('<>'), payload.get('date')), direction='IN', status='IP', headers=as2headers) raise as2utils.As2DuplicateDocument( _(u'An identical message has already ' u'been sent to our server')) # Create a new message in the system message = models.Message.objects.create( message_id=payload.get('message-id').strip('<>'), direction='IN', status='IP', headers=as2headers) # Process the received payload to extract the actual message from partner payload = as2lib.save_message(message, payload, raw_payload) # Get the inbox folder for this partner and organization output_dir = as2utils.join(pyas2init.gsettings['root_dir'], 'messages', message.organization.as2_name, 'inbox', message.partner.as2_identifier) # Get the filename from the header and if not there set to message id if message.partner.keep_filename and payload.get_filename( ): filename = payload.get_filename()[:100] else: filename = '%s.msg' % uuid.uuid4() # Save the message content to the store and inbox content = payload.get_payload(decode=True) full_filename = as2utils.storefile(output_dir, filename, content, False) store_filename = as2utils.storefile( pyas2init.gsettings['payload_receive_store'], message.message_id, content, True) models.Log.objects.create( message=message, status='S', text=_(u'Message has been saved successfully to %s' % full_filename)) message.payload = models.Payload.objects.create( name=filename, file=store_filename, content_type=payload.get_content_type()) # Set processing status and run the post receive command. status = 'success' as2lib.run_post_receive(message, full_filename) message.save() # Catch each of the possible exceptions while processing an as2 message except as2utils.As2DuplicateDocument, e: status = 'warning' adv_status = 'duplicate-document' status_message = _( u'An error occurred during the AS2 message processing: %s' % e) except as2utils.As2PartnerNotFound, e: status = 'error' adv_status = 'unknown-trading-partner' status_message = _( u'An error occurred during the AS2 message processing: %s' % e)
def as2receive(request,*args,**kwargs): ''' Function receives requests from partners. Checks whether its an AS2 message or an MDN and acts accordingly. ''' if request.method == 'POST': as2payload = '' for key in request.META: if key.startswith('HTTP') or key.startswith('CONTENT'): as2payload = as2payload + '%s: %s\n'%(key.replace("HTTP_","").replace("_","-").lower(), request.META[key]) as2headers = as2payload as2payload = as2payload + '\n' + request.read() pyas2init.logger.debug('Recevied an HTTP POST from %s with payload :\n%s'%(request.META['REMOTE_ADDR'],as2payload)) try: pyas2init.logger.debug('Check payload to see if its an AS2 Message or ASYNC MDN.') payload = email.message_from_string(as2payload) mdn_message = None if payload.get_content_type() == 'multipart/report': mdn_message = payload elif payload.get_content_type() == 'multipart/signed': for part in payload.walk(): if part.get_content_type() == 'multipart/report': mdn_message = part if mdn_message: for part in mdn_message.walk(): if (part.get_content_type() == 'message/disposition-notification'): msg_id = part.get_payload().pop().get('Original-Message-ID') pyas2init.logger.debug('Received MDN for AS2 message %s'%msg_id) message = models.Message.objects.get(message_id=msg_id.strip('<>')) models.Log.objects.create(message=message, status='S', text=_(u'Processing asynchronous mdn received from partner')) try: as2lib.save_mdn(message, as2payload) except Exception,e: message.status = 'E' models.Log.objects.create(message=message, status='E', text=_(u'Failed to send message, error is %s' %e)) #### Send mail here as2utils.senderrorreport(message,_(u'Failed to send message, error is %s' %e)) finally: message.save() return HttpResponse(_(u'AS2 ASYNC MDN has been received')) else: try: pyas2init.logger.debug('Received an AS2 message with id %s'%payload.get('message-id')) if models.Message.objects.filter(message_id=payload.get('message-id').strip('<>')).exists(): message = models.Message.objects.create(message_id='%s_%s'%(payload.get('message-id').strip('<>'),payload.get('date')),direction='IN', status='IP', headers=as2headers) raise as2utils.as2duplicatedocument(_(u'An identical message has already been sent to our server')) message = models.Message.objects.create(message_id=payload.get('message-id').strip('<>'),direction='IN', status='IP', headers=as2headers) payload = as2lib.save_message(message, as2payload) outputdir = as2utils.join(pyas2init.gsettings['root_dir'], 'messages', message.organization.as2_name, 'inbox', message.partner.as2_name) storedir = pyas2init.gsettings['payload_receive_store'] if message.partner.keep_filename and payload.get_filename(): filename = payload.get_filename() else: filename = '%s.msg' %message.message_id content = payload.get_payload(decode=True) fullfilename = as2utils.storefile(outputdir,filename,content,False) storefilename = as2utils.storefile(pyas2init.gsettings['payload_receive_store'],message.message_id,content,True) models.Log.objects.create(message=message, status='S', text=_(u'Message has been saved successfully to %s'%fullfilename)) message.payload = models.Payload.objects.create(name=filename, file=storefilename, content_type=payload.get_content_type()) status, adv_status, status_message = 'success', '', '' as2lib.run_postreceive(message,fullfilename) message.save() except as2utils.as2duplicatedocument,e: status, adv_status, status_message = 'warning', 'duplicate-document', _(u'An error occured during the AS2 message processing: %s'%e) except as2utils.as2partnernotfound,e: status, adv_status, status_message = 'error', 'unknown-trading-partner', _(u'An error occured during the AS2 message processing: %s'%e)