Example #1
0
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)
Example #2
0
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)
Example #3
0
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)