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)
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)
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)
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()
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()
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()
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()