Пример #1
0
def send_message(message, payload):
    """ Sends the AS2 message to the partner. Takes the message and payload as arguments and posts the as2 message to
     the partner."""

    try:
        # Parse the message header to a dictionary
        header_parser = HeaderParser()
        message_header = header_parser.parsestr(message.headers)

        # Set up the http auth if specified in the partner profile
        auth = None
        if message.partner.http_auth:
            auth = (message.partner.http_auth_user, message.partner.http_auth_pass)
        verify = True
        if message.partner.https_ca_cert:
            verify = message.partner.https_ca_cert.path

        # Send the AS2 message to the partner
        try:
            response = requests.post(message.partner.target_url,
                                     auth=auth,
                                     verify=verify,
                                     headers=dict(message_header.items()),
                                     data=payload)
            response.raise_for_status()
        except Exception, e:
            # Send mail here
            as2utils.senderrorreport(message, _(u'Failure during transmission of message to partner with error '
                                                u'"%s".\n\nTo retry transmission run the management '
                                                u'command "retryfailedas2comms".' % e))
            message.status = 'R'
            models.Log.objects.create(message=message, status='E', text=_(u'Message send failed with error %s' % e))
            return
        models.Log.objects.create(message=message, status='S', text=_(u'AS2 message successfully sent to partner'))

        # Process the MDN based on the partner profile settings
        if message.partner.mdn:
            if message.partner.mdn_mode == 'ASYNC':
                models.Log.objects.create(message=message, status='S',
                                          text=_(u'Requested ASYNC MDN from partner, waiting for it ........'))
                message.status = 'P'
                return
            # In case of Synchronous MDN the response content will be the MDN. So process it.
            # 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['message-id'])
            mdn_content += '%s: %s\n\n' % ('content-type', mdn_headers['content-type'])
            mdn_content += response.content
            models.Log.objects.create(message=message, status='S', text=_(u'Synchronous mdn received from partner'))
            pyas2init.logger.debug('Synchronous MDN for message %s received:\n%s' % (message.message_id, mdn_content))
            save_mdn(message, mdn_content)
        else:
            message.status = 'S'
            models.Log.objects.create(message=message,
                                      status='S',
                                      text=_(u'No MDN needed, File Transferred successfully to the partner'))

            # Run the post successful send command
            run_post_send(message)
Пример #2
0
def send_message(message, payload):
    """ Sends the AS2 message to the partner """
    try:
        hparser = HeaderParser()
        message_header = hparser.parsestr(message.headers)
        auth = None
        if message.partner.http_auth:
            auth = (message.partner.http_auth_user, message.partner.http_auth_pass)
        verify = True
        if message.partner.https_ca_cert:
            verify = message.partner.https_ca_cert.path
        try:
            response = requests.post(
                message.partner.target_url, auth=auth, verify=verify, headers=dict(message_header.items()), data=payload
            )
            response.raise_for_status()
        except Exception, e:
            ### Send mail here
            as2utils.senderrorreport(
                message,
                _(
                    u'Failure during transmission of message to partner with error "%s".\n\nTo retry transmission run the management command "retryfailedas2comms".'
                    % e
                ),
            )
            message.status = "R"
            models.Log.objects.create(message=message, status="E", text=_(u"Message send failed with error %s" % e))
            return
        models.Log.objects.create(message=message, status="S", text=_(u"AS2 message successfully sent to partner"))
        if message.partner.mdn:
            if message.partner.mdn_mode == "ASYNC":
                models.Log.objects.create(
                    message=message, status="S", text=_(u"Requested ASYNC MDN from partner, waiting for it ........")
                )
                message.status = "P"
                return
            mdnContent = ""
            for key in response.headers:
                mdnContent = mdnContent + "%s: %s\n" % (key, response.headers[key])
            mdnContent = mdnContent + "\n" + response.content
            models.Log.objects.create(message=message, status="S", text=_(u"Synchronous mdn received from partner"))
            pyas2init.logger.debug("Synchronus MDN from message %s received:\n%s" % (message.message_id, mdnContent))
            save_mdn(message, mdnContent)
        else:
            message.status = "S"
            models.Log.objects.create(
                message=message, status="S", text=_(u"No MDN needed, File Transferred successfully to the partner")
            )
            run_postsend(message)
Пример #3
0
def send_message(message, payload):
    """ Sends the AS2 message to the partner. Takes the message and payload as arguments and posts the as2 message to
     the partner."""

    try:
        # Parse the message header to a dictionary
        header_parser = HeaderParser()
        message_header = header_parser.parsestr(message.headers)

        # Set up the http auth if specified in the partner profile
        auth = None
        if message.partner.http_auth:
            auth = (message.partner.http_auth_user,
                    message.partner.http_auth_pass)
        verify = True
        if message.partner.https_ca_cert:
            verify = message.partner.https_ca_cert.path

        # Send the AS2 message to the partner
        try:
            response = requests.post(message.partner.target_url,
                                     auth=auth,
                                     verify=verify,
                                     headers=dict(message_header.items()),
                                     data=payload)
            response.raise_for_status()
        except Exception, e:
            # Send mail here
            as2utils.senderrorreport(
                message,
                _(u'Failure during transmission of message to partner with error '
                  u'"%s".\n\nTo retry transmission run the management '
                  u'command "retryfailedas2comms".' % e))
            message.status = 'R'
            models.Log.objects.create(
                message=message,
                status='E',
                text=_(u'Message send failed with error %s' % e)[:250])
            return
        models.Log.objects.create(
            message=message,
            status='S',
            text=_(u'AS2 message successfully sent to partner'))

        # Process the MDN based on the partner profile settings
        if message.partner.mdn:
            if message.partner.mdn_mode == 'ASYNC':
                models.Log.objects.create(
                    message=message,
                    status='S',
                    text=
                    _(u'Requested ASYNC MDN from partner, waiting for it ........'
                      ))
                message.status = 'P'
                return
            # In case of Synchronous MDN the response content will be the MDN. So process it.
            # 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', message.message_id))
            mdn_content += '%s: %s\n\n' % ('content-type',
                                           mdn_headers['content-type'])
            mdn_content += response.content
            models.Log.objects.create(
                message=message,
                status='S',
                text=_(u'Synchronous mdn received from partner'))
            pyas2init.logger.debug(
                'Synchronous MDN for message %s received:\n%s' %
                (message.message_id, mdn_content))
            save_mdn(message, mdn_content)
        else:
            message.status = 'S'
            models.Log.objects.create(
                message=message,
                status='S',
                text=
                _(u'No MDN needed, File Transferred successfully to the partner'
                  ))

            # Run the post successful send command
            run_post_send(message)
Пример #4
0
def build_mdn(message, status, **kwargs):
    """ Function builds AS2 MDN report for the received message.
    Takes message status as input and returns the mdn content."""

    try:
        # Initialize variables
        mdn_body, mdn_message = None, None

        # Set the confirmation text message here
        confirmation_text = str()
        if message.organization and message.organization.confirmation_message:
            confirmation_text = message.organization.confirmation_message
        # overwrite with partner specific message
        if message.partner and message.partner.confirmation_message:
            confirmation_text = message.partner.confirmation_message
        # default message
        if confirmation_text.strip() == '':
            confirmation_text = _(
                u'The AS2 message has been processed. '
                u'Thank you for exchanging AS2 messages with Pyas2.')

        # Update message status and send mail here based on the created MDN
        if status != 'success':
            as2utils.senderrorreport(
                message,
                _(u'Failure in processing message from partner,\n '
                  u'Basic status : %s \n Advanced Status: %s' %
                  (kwargs['adv_status'], kwargs['status_message'])))
            confirmation_text = _(
                u'The AS2 message could not be processed. '
                u'The disposition-notification report has additional details.')
            models.Log.objects.create(message=message,
                                      status='E',
                                      text=kwargs['status_message'])
            message.status = 'E'
            message.adv_status = kwargs['status_message']
        else:
            message.status = 'S'

        # In case no MDN is requested exit from process
        header_parser = HeaderParser()
        message_header = header_parser.parsestr(message.headers)
        if not message_header.get('disposition-notification-to'):
            models.Log.objects.create(
                message=message,
                status='S',
                text=_(u'MDN not requested by partner, closing request.'))
            return mdn_body, mdn_message

        # Build the MDN report
        models.Log.objects.create(
            message=message,
            status='S',
            text=_(u'Building the MDN response to the request'))
        mdn_report = MIMEMultipart('report',
                                   report_type="disposition-notification")

        # Build the text message with confirmation text and add to report
        mdn_text = email.Message.Message()
        mdn_text.set_payload("%s\n" % confirmation_text)
        mdn_text.set_type('text/plain')
        mdn_text.set_charset('us-ascii')
        del mdn_text['MIME-Version']
        mdn_report.attach(mdn_text)

        # Build the MDN message and add to report
        mdn_base = email.Message.Message()
        mdn_base.set_type('message/disposition-notification')
        mdn_base.set_charset('us-ascii')
        mdn = 'Reporting-UA: Bots Opensource EDI Translator\n'
        mdn += 'Original-Recipient: rfc822; %s\n' % message_header.get(
            'as2-to')
        mdn += 'Final-Recipient: rfc822; %s\n' % message_header.get('as2-to')
        mdn += 'Original-Message-ID: <%s>\n' % message.message_id
        if status != 'success':
            mdn += 'Disposition: automatic-action/MDN-sent-automatically; ' \
                   'processed/%s: %s\n' % (status, kwargs['adv_status'])
        else:
            mdn += 'Disposition: automatic-action/MDN-sent-automatically; processed\n'
        if message.mic:
            mdn += 'Received-content-MIC: %s\n' % message.mic
        mdn_base.set_payload(mdn)
        del mdn_base['MIME-Version']
        mdn_report.attach(mdn_base)
        del mdn_report['MIME-Version']

        # If signed MDN is requested by partner then sign the MDN and attach to report
        pyas2init.logger.debug('MDN for message %s created:\n%s' %
                               (message.message_id, mdn_report.as_string()))
        mdn_signed = False
        if message_header.get('disposition-notification-options') and message.organization \
                and message.organization.signature_key:
            models.Log.objects.create(
                message=message,
                status='S',
                text=_(u'Signing the MDN using private key {0:s}'.format(
                    message.organization.signature_key)))
            mdn_signed = True
            # options = message_header.get('disposition-notification-options').split(";")
            # algorithm = options[1].split(",")[1].strip()
            signed_report = MIMEMultipart(
                'signed', protocol="application/pkcs7-signature")
            signed_report.attach(mdn_report)
            mic_alg, signature = as2utils.sign_payload(
                as2utils.canonicalize(
                    as2utils.mimetostring(mdn_report, 0) + '\n'),
                str(message.organization.signature_key.certificate.path),
                str(message.organization.signature_key.certificate_passphrase))
            pyas2init.logger.debug('Signature for MDN created:\n%s' %
                                   signature.as_string())
            signed_report.set_param('micalg', mic_alg)
            signed_report.attach(signature)
            mdn_message = signed_report
        else:
            mdn_message = mdn_report

        # Extract the MDN boy from the mdn message.
        # Add new line between the MDN message and the signature,
        # Found that without this MDN signature verification fails on Mendelson AS2
        main_boundary = '--' + mdn_report.get_boundary() + '--'
        mdn_body = as2utils.canonicalize(
            as2utils.extractpayload(mdn_message).replace(
                main_boundary, main_boundary + '\n'))

        # Add the relevant headers to the MDN message
        mdn_message.add_header('ediint-features', 'CEM')
        mdn_message.add_header('as2-from', message_header.get('as2-to'))
        mdn_message.add_header('as2-to', message_header.get('as2-from'))
        mdn_message.add_header('AS2-Version', '1.2')
        mdn_message.add_header('date', email.Utils.formatdate(localtime=True))
        mdn_message.add_header('Message-ID', email.utils.make_msgid())
        mdn_message.add_header('user-agent', 'PYAS2, A pythonic AS2 server')

        # Save the MDN to the store
        filename = mdn_message.get('message-id').strip('<>') + '.mdn'
        full_filename = as2utils.storefile(
            pyas2init.gsettings['mdn_send_store'], filename, mdn_body, True)

        # Extract the MDN headers as string
        mdn_headers = ''
        for key in mdn_message.keys():
            mdn_headers += '%s: %s\n' % (key, mdn_message[key])

        # Is Async mdn is requested mark MDN as pending and return None
        if message_header.get('receipt-delivery-option'):
            message.mdn = models.MDN.objects.create(
                message_id=filename,
                file=full_filename,
                status='P',
                signed=mdn_signed,
                headers=mdn_headers,
                return_url=message_header['receipt-delivery-option'])
            message.mdn_mode = 'ASYNC'
            mdn_body, mdn_message = None, None
            models.Log.objects.create(
                message=message,
                status='S',
                text=_(
                    u'Asynchronous MDN requested, setting status to pending'))

        # Else mark MDN as sent and return the MDN message
        else:
            message.mdn = models.MDN.objects.create(message_id=filename,
                                                    file=full_filename,
                                                    status='S',
                                                    signed=mdn_signed,
                                                    headers=mdn_headers)
            message.mdn_mode = 'SYNC'
            models.Log.objects.create(
                message=message,
                status='S',
                text=_(u'MDN created successfully and sent to partner'))
        return mdn_body, mdn_message
    finally:
        message.save()
Пример #5
0
def build_mdn(message, status, **kwargs):
    ''' Function builds AS2 MDN report '''
    try:
        hparser = HeaderParser()
        message_header = hparser.parsestr(message.headers)

        text = str()

        # check for default orginization message
        if message.organization.confirmation_message:
            text = message.organization.confirmation_message

        # overwrite with partner specific message
        if message.partner.confirmation_message:
            text = message.partner.confirmation_message

        # default message
        if text.strip() == '':
            text = _(u'The AS2 message has been processed. Thank you for exchanging AS2 messages with Pyas2.')

        if status != 'success':
            #### Send mail here
            as2utils.senderrorreport(message, _(u'Failure in processing message from partner,\n Basic status : %s \n Advanced Status: %s'%(kwargs['adv_status'],kwargs['status_message'])))
            text = _(u'The AS2 message could not be processed. The disposition-notification report has additional details.')
            models.Log.objects.create(message=message, status='E', text = kwargs['status_message'])
            message.status = 'E'
        else:
            message.status = 'S'
        if not message_header.get('disposition-notification-to'):
            models.Log.objects.create(message=message, status='S', text=_(u'MDN not requested by partner, closing request.'))
            return None, None
        models.Log.objects.create(message=message, status='S', text=_(u'Building the MDN response to the request'))
        main = MIMEMultipart('report', report_type="disposition-notification")
        textmessage = email.Message.Message()
        textmessage.set_payload("%s\n"%text)
        textmessage.set_type('text/plain')
        textmessage.set_charset('us-ascii')
        del textmessage['MIME-Version']
        main.attach(textmessage)
        mdnbase = email.Message.Message()
        mdnbase.set_type('message/disposition-notification')
        mdnbase.set_charset('us-ascii')
        mdn = 'Reporting-UA: Bots Opensource EDI Translator\n'
        mdn = mdn + 'Original-Recipient: rfc822; %s\n'%message_header.get('as2-to')
        mdn = mdn + 'Final-Recipient: rfc822; %s\n'%message_header.get('as2-to')
        mdn = mdn + 'Original-Message-ID: <%s>\n'%message.message_id
        if status != 'success':
            mdn = mdn + 'Disposition: automatic-action/MDN-sent-automatically; processed/%s: %s\n'%(status, kwargs['adv_status'])
        else:
            mdn = mdn + 'Disposition: automatic-action/MDN-sent-automatically; processed\n'
        if message.mic:
            mdn = mdn + 'Received-content-MIC: %s\n'%message.mic
        mdnbase.set_payload(mdn)
        del mdnbase['MIME-Version']
        main.attach(mdnbase)
        del main['MIME-Version']
        pyas2init.logger.debug('MDN for message %s created:\n%s'%(message.message_id,main.as_string()))
        mdnsigned = False
        if message_header.get('disposition-notification-options') and message.organization and message.organization.signature_key: 
            models.Log.objects.create(message=message, status='S', text=_(u'Signing the MDN using private key %s'%message.organization.signature_key))
            mdnsigned = True
            options = message_header.get('disposition-notification-options').split(";")
            algorithm = options[1].split(",")[1].strip()
            signed = MIMEMultipart('signed', protocol="application/pkcs7-signature")
            signed.attach(main)
            micalg, signature = as2utils.sign_payload(
                    as2utils.canonicalize(as2utils.mimetostring(main, 0)+'\n'),
                    str(message.organization.signature_key.certificate.path), 
                    str(message.organization.signature_key.certificate_passphrase)
            )
            pyas2init.logger.debug('Signature for MDN created:\n%s'%signature.as_string())
            signed.set_param('micalg',micalg)
            signed.attach(signature)
            mdnmessage = signed
        else:
            mdnmessage = main
        ### Add new line between the MDN message and the signature
        mdnbody = as2utils.extractpayload(mdnmessage)
        mainboundary = '--' + main.get_boundary() + '--'
        mdnbody = as2utils.canonicalize(mdnbody.replace(mainboundary, mainboundary + '\n'))
        mdnmessage.add_header('ediint-features', 'CEM')
        mdnmessage.add_header('as2-from', message_header.get('as2-to'))
        mdnmessage.add_header('as2-to', message_header.get('as2-from')) 
        mdnmessage.add_header('AS2-Version', '1.2')
        mdnmessage.add_header('date', email.Utils.formatdate(localtime=True))
        mdnmessage.add_header('Message-ID', email.utils.make_msgid())
        mdnmessage.add_header('user-agent', 'PYAS2, A pythonic AS2 server')
        filename = mdnmessage.get('message-id').strip('<>') + '.mdn'
        fullfilename = as2utils.storefile(pyas2init.gsettings['mdn_send_store'],filename,mdnbody,True)
        mdn_headers = ''
        for key in mdnmessage.keys():
            mdn_headers = mdn_headers + '%s: %s\n'%(key, mdnmessage[key])
        if message_header.get('receipt-delivery-option'):
            message.mdn = models.MDN.objects.create(message_id=filename, file=fullfilename, status='P', signed=mdnsigned, headers=mdn_headers, return_url= message_header['receipt-delivery-option'])
            message.mdn_mode = 'ASYNC'
            mdnbody, mdnmessage = None, None
            models.Log.objects.create(message=message, status='S', text=_(u'Asynchronous MDN requested, setting status to pending'))
        else:
            message.mdn = models.MDN.objects.create(message_id=filename,file=fullfilename, status='S', signed=mdnsigned, headers=mdn_headers)
            message.mdn_mode = 'SYNC'
            models.Log.objects.create(message=message, status='S', text=_(u'MDN created successfully and sent to partner'))
        return mdnbody, mdnmessage
    finally:
        message.save()	
Пример #6
0
def build_mdn(message, status, **kwargs):
    """ Function builds AS2 MDN report for the received message.
    Takes message status as input and returns the mdn content."""

    try:
        # Initialize variables
        mdn_body, mdn_message = None, None

        # Set the confirmation text message here
        confirmation_text = str()
        if message.organization and message.organization.confirmation_message:
            confirmation_text = message.organization.confirmation_message
        # overwrite with partner specific message
        if message.partner and message.partner.confirmation_message:
            confirmation_text = message.partner.confirmation_message
        # default message
        if confirmation_text.strip() == '':
            confirmation_text = _(u'The AS2 message has been processed. '
                                  u'Thank you for exchanging AS2 messages with Pyas2.')

        # Update message status and send mail here based on the created MDN
        if status != 'success':
            as2utils.senderrorreport(message, _(u'Failure in processing message from partner,\n '
                                                u'Basic status : %s \n Advanced Status: %s' %
                                                (kwargs['adv_status'], kwargs['status_message'])))
            confirmation_text = _(u'The AS2 message could not be processed. '
                                  u'The disposition-notification report has additional details.')
            models.Log.objects.create(message=message, status='E', text=kwargs['status_message'])
            message.status = 'E'
        else:
            message.status = 'S'

        # In case no MDN is requested exit from process
        header_parser = HeaderParser()
        message_header = header_parser.parsestr(message.headers)
        if not message_header.get('disposition-notification-to'):
            models.Log.objects.create(message=message, status='S',
                                      text=_(u'MDN not requested by partner, closing request.'))
            return mdn_body, mdn_message

        # Build the MDN report
        models.Log.objects.create(message=message, status='S', text=_(u'Building the MDN response to the request'))
        mdn_report = MIMEMultipart('report', report_type="disposition-notification")

        # Build the text message with confirmation text and add to report
        mdn_text = email.Message.Message()
        mdn_text.set_payload("%s\n" % confirmation_text)
        mdn_text.set_type('text/plain')
        mdn_text.set_charset('us-ascii')
        del mdn_text['MIME-Version']
        mdn_report.attach(mdn_text)

        # Build the MDN message and add to report
        mdn_base = email.Message.Message()
        mdn_base.set_type('message/disposition-notification')
        mdn_base.set_charset('us-ascii')
        mdn = 'Reporting-UA: Bots Opensource EDI Translator\n'
        mdn += 'Original-Recipient: rfc822; %s\n' % message_header.get('as2-to')
        mdn += 'Final-Recipient: rfc822; %s\n' % message_header.get('as2-to')
        mdn += 'Original-Message-ID: <%s>\n' % message.message_id
        if status != 'success':
            mdn += 'Disposition: automatic-action/MDN-sent-automatically; ' \
                   'processed/%s: %s\n' % (status, kwargs['adv_status'])
        else:
            mdn += 'Disposition: automatic-action/MDN-sent-automatically; processed\n'
        if message.mic:
            mdn += 'Received-content-MIC: %s\n' % message.mic
        mdn_base.set_payload(mdn)
        del mdn_base['MIME-Version']
        mdn_report.attach(mdn_base)
        del mdn_report['MIME-Version']

        # If signed MDN is requested by partner then sign the MDN and attach to report
        pyas2init.logger.debug('MDN for message %s created:\n%s' % (message.message_id, mdn_report.as_string()))
        mdn_signed = False
        if message_header.get('disposition-notification-options') and message.organization \
                and message.organization.signature_key:
            models.Log.objects.create(message=message,
                                      status='S',
                                      text=_(u'Signing the MDN using private key {0:s}'.format(
                                          message.organization.signature_key)))
            mdn_signed = True
            # options = message_header.get('disposition-notification-options').split(";")
            # algorithm = options[1].split(",")[1].strip()
            signed_report = MIMEMultipart('signed', protocol="application/pkcs7-signature")
            signed_report.attach(mdn_report)
            mic_alg, signature = as2utils.sign_payload(
                    as2utils.canonicalize(as2utils.mimetostring(mdn_report, 0)+'\n'),
                    str(message.organization.signature_key.certificate.path),
                    str(message.organization.signature_key.certificate_passphrase)
            )
            pyas2init.logger.debug('Signature for MDN created:\n%s' % signature.as_string())
            signed_report.set_param('micalg', mic_alg)
            signed_report.attach(signature)
            mdn_message = signed_report
        else:
            mdn_message = mdn_report

        # Extract the MDN boy from the mdn message.
        # Add new line between the MDN message and the signature,
        # Found that without this MDN signature verification fails on Mendelson AS2
        main_boundary = '--' + mdn_report.get_boundary() + '--'
        mdn_body = as2utils.canonicalize(
            as2utils.extractpayload(mdn_message).replace(main_boundary, main_boundary+'\n'))

        # Add the relevant headers to the MDN message
        mdn_message.add_header('ediint-features', 'CEM')
        mdn_message.add_header('as2-from', message_header.get('as2-to'))
        mdn_message.add_header('as2-to', message_header.get('as2-from'))
        mdn_message.add_header('AS2-Version', '1.2')
        mdn_message.add_header('date', email.Utils.formatdate(localtime=True))
        mdn_message.add_header('Message-ID', email.utils.make_msgid())
        mdn_message.add_header('user-agent', 'PYAS2, A pythonic AS2 server')

        # Save the MDN to the store
        filename = mdn_message.get('message-id').strip('<>') + '.mdn'
        full_filename = as2utils.storefile(pyas2init.gsettings['mdn_send_store'], filename, mdn_body, True)

        # Extract the MDN headers as string
        mdn_headers = ''
        for key in mdn_message.keys():
            mdn_headers += '%s: %s\n' % (key, mdn_message[key])

        # Is Async mdn is requested mark MDN as pending and return None
        if message_header.get('receipt-delivery-option'):
            message.mdn = models.MDN.objects.create(message_id=filename,
                                                    file=full_filename,
                                                    status='P',
                                                    signed=mdn_signed,
                                                    headers=mdn_headers,
                                                    return_url=message_header['receipt-delivery-option'])
            message.mdn_mode = 'ASYNC'
            mdn_body, mdn_message = None, None
            models.Log.objects.create(message=message,
                                      status='S',
                                      text=_(u'Asynchronous MDN requested, setting status to pending'))

        # Else mark MDN as sent and return the MDN message
        else:
            message.mdn = models.MDN.objects.create(message_id=filename,
                                                    file=full_filename,
                                                    status='S',
                                                    signed=mdn_signed,
                                                    headers=mdn_headers)
            message.mdn_mode = 'SYNC'
            models.Log.objects.create(message=message,
                                      status='S',
                                      text=_(u'MDN created successfully and sent to partner'))
        return mdn_body, mdn_message
    finally:
        message.save()
Пример #7
0
def build_mdn(message, status, **kwargs):
    """ Function builds AS2 MDN report """
    try:
        hparser = HeaderParser()
        message_header = hparser.parsestr(message.headers)
        text = _(u"The AS2 message has been processed. Thank you for exchanging AS2 messages with Pyas2.")
        if status != "success":
            #### Send mail here
            as2utils.senderrorreport(
                message,
                _(
                    u"Failure in processing message from partner,\n Basic status : %s \n Advanced Status: %s"
                    % (kwargs["adv_status"], kwargs["status_message"])
                ),
            )
            text = _(
                u"The AS2 message could not be processed. The disposition-notification report has additional details."
            )
            models.Log.objects.create(message=message, status="E", text=kwargs["status_message"])
            message.status = "E"
        else:
            message.status = "S"
        if not message_header.get("disposition-notification-to"):
            models.Log.objects.create(
                message=message, status="S", text=_(u"MDN not requested by partner, closing request.")
            )
            return None, None
        models.Log.objects.create(message=message, status="S", text=_(u"Building the MDN response to the request"))
        main = MIMEMultipart("report", report_type="disposition-notification")
        textmessage = email.Message.Message()
        textmessage.set_payload("%s\n" % text)
        textmessage.set_type("text/plain")
        textmessage.set_charset("us-ascii")
        del textmessage["MIME-Version"]
        main.attach(textmessage)
        mdnbase = email.Message.Message()
        mdnbase.set_type("message/disposition-notification")
        mdnbase.set_charset("us-ascii")
        mdn = "Reporting-UA: Bots Opensource EDI Translator\n"
        mdn = mdn + "Original-Recipient: rfc822; %s\n" % message_header.get("as2-to")
        mdn = mdn + "Final-Recipient: rfc822; %s\n" % message_header.get("as2-to")
        mdn = mdn + "Original-Message-ID: <%s>\n" % message.message_id
        if status != "success":
            mdn = mdn + "Disposition: automatic-action/MDN-sent-automatically; processed/%s: %s\n" % (
                status,
                kwargs["adv_status"],
            )
        else:
            mdn = mdn + "Disposition: automatic-action/MDN-sent-automatically; processed\n"
        if message.mic:
            mdn = mdn + "Received-content-MIC: %s\n" % message.mic
        mdnbase.set_payload(mdn)
        del mdnbase["MIME-Version"]
        main.attach(mdnbase)
        del main["MIME-Version"]
        pyas2init.logger.debug("MDN for message %s created:\n%s" % (message.message_id, main.as_string()))
        mdnsigned = False
        if (
            message_header.get("disposition-notification-options")
            and message.organization
            and message.organization.signature_key
        ):
            models.Log.objects.create(
                message=message,
                status="S",
                text=_(u"Signing the MDN using private key %s" % message.organization.signature_key),
            )
            mdnsigned = True
            options = message_header.get("disposition-notification-options").split(";")
            algorithm = options[1].split(",")[1].strip()
            signed = MIMEMultipart("signed", protocol="application/pkcs7-signature")
            signed.attach(main)
            micalg, signature = as2utils.sign_payload(
                as2utils.canonicalize(as2utils.mimetostring(main, 0) + "\n"),
                str(message.organization.signature_key.certificate.path),
                str(message.organization.signature_key.certificate_passphrase),
            )
            pyas2init.logger.debug("Signature for MDN created:\n%s" % signature.as_string())
            signed.set_param("micalg", micalg)
            signed.attach(signature)
            mdnmessage = signed
        else:
            mdnmessage = main
        ### Add new line between the MDN message and the signature
        mdnbody = as2utils.extractpayload(mdnmessage)
        mainboundary = "--" + main.get_boundary() + "--"
        mdnbody = as2utils.canonicalize(mdnbody.replace(mainboundary, mainboundary + "\n"))
        mdnmessage.add_header("ediint-features", "CEM")
        mdnmessage.add_header("as2-from", message_header.get("as2-to"))
        mdnmessage.add_header("as2-to", message_header.get("as2-from"))
        mdnmessage.add_header("AS2-Version", "1.2")
        mdnmessage.add_header("date", email.Utils.formatdate(localtime=True))
        mdnmessage.add_header("Message-ID", email.utils.make_msgid())
        mdnmessage.add_header("user-agent", "PYAS2, A pythonic AS2 server")
        filename = mdnmessage.get("message-id").strip("<>") + ".mdn"
        fullfilename = as2utils.storefile(pyas2init.gsettings["mdn_send_store"], filename, mdnbody, True)
        mdn_headers = ""
        for key in mdnmessage.keys():
            mdn_headers = mdn_headers + "%s: %s\n" % (key, mdnmessage[key])
        if message_header.get("receipt-delivery-option"):
            message.mdn = models.MDN.objects.create(
                message_id=filename,
                file=fullfilename,
                status="P",
                signed=mdnsigned,
                headers=mdn_headers,
                return_url=message_header["receipt-delivery-option"],
            )
            message.mdn_mode = "ASYNC"
            mdnbody, mdnmessage = None, None
            models.Log.objects.create(
                message=message, status="S", text=_(u"Asynchronous MDN requested, setting status to pending")
            )
        else:
            message.mdn = models.MDN.objects.create(
                message_id=filename, file=fullfilename, status="S", signed=mdnsigned, headers=mdn_headers
            )
            message.mdn_mode = "SYNC"
            models.Log.objects.create(
                message=message, status="S", text=_(u"MDN created successfully and sent to partner")
            )
        return mdnbody, mdnmessage
    finally:
        message.save()