diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md
index d6eccfda..637e51ad 100644
--- a/RELEASE-NOTES.md
+++ b/RELEASE-NOTES.md
@@ -1,19 +1,19 @@
# OpenAS2 Server
-# Version 4.6.3
+# Version 4.7.0
# RELEASE NOTES
-----
-The OpenAS2 project is pleased to announce the release of OpenAS2 4.6.3
+The OpenAS2 project is pleased to announce the release of OpenAS2 4.7.0
-The release download file is: OpenAS2Server-4.6.3.zip
+The release download file is: OpenAS2Server-4.7.0.zip
The zip file contains a PDF document (OpenAS2HowTo.pdf) providing information on installing and using the application.
## NOTE: Testing covers Java 11 to 21.
## Java 8 is NO LONGER SUPPORTED.
-Version 4.6.3 - 2025-09-29
+Version 4.7.0 - 2025-10-28
-This is a bugfix release.
-1. Avoid concurrent processing error that occurs after files after sent as part of the cleanup process.
+This is a minor enhancement release.
+1. Enhance MDN processing to extract possible responses from partner that provide information on why the partner rejected the AS2 transaction.
##Upgrade Notes
diff --git a/Server/pom.xml b/Server/pom.xml
index 264b39c9..4865d992 100644
--- a/Server/pom.xml
+++ b/Server/pom.xml
@@ -7,7 +7,7 @@
net.sf.openas2
OpenAS2
- 4.6.3
+ 4.7.0
../pom.xml
diff --git a/Server/src/main/java/org/openas2/processor/receiver/AS2MDNReceiverHandler.java b/Server/src/main/java/org/openas2/processor/receiver/AS2MDNReceiverHandler.java
index b4db286d..da00ca57 100644
--- a/Server/src/main/java/org/openas2/processor/receiver/AS2MDNReceiverHandler.java
+++ b/Server/src/main/java/org/openas2/processor/receiver/AS2MDNReceiverHandler.java
@@ -109,10 +109,10 @@ public void handle(NetModule owner, Socket s) {
logger.trace("Incoming ASYNC MDN message - MDN struct: " + mdn.toString());
}
try {
- boolean partnerIdentificationProblem = AS2Util.processMDN(msg, data, s.getOutputStream(), true, getModule().getSession(), this.getClass());
+ boolean mdnResponseIssue = AS2Util.processMDN(msg, data, s.getOutputStream(), true, getModule().getSession(), this.getClass());
// Assume that appropriate logging and state handling was done upstream if an error occurred so only log state change for success
- if (!partnerIdentificationProblem) {
- // Logger state
+ if (!mdnResponseIssue) {
+ // Log state
msg.setOption("STATE", Message.MSG_STATE_MSG_SENT_MDN_RECEIVED_OK);
msg.trackMsgState(getModule().getSession());
}
diff --git a/Server/src/main/java/org/openas2/processor/sender/AS2SenderModule.java b/Server/src/main/java/org/openas2/processor/sender/AS2SenderModule.java
index b7e0d6d1..6dd84f3d 100644
--- a/Server/src/main/java/org/openas2/processor/sender/AS2SenderModule.java
+++ b/Server/src/main/java/org/openas2/processor/sender/AS2SenderModule.java
@@ -234,12 +234,11 @@ private void processResponse(Message msg, ResponseWrapper response) {
}
msg.setStatus(Message.MSG_STATUS_MDN_PROCESS_INIT);
try {
- @SuppressWarnings("unused")
- boolean partnerIdentificationProblem = AS2Util.processMDN((AS2Message) msg, response.getBody(), null, false, getSession(), this.getClass());
- // Possibly a place for adding suspicious activity tracking here?
- // if (partnerIdentificationProblem) {
- // trackSuspiciousActivity(msg);
- // }
+ // Assume that appropriate logging and state handling was done upstream if an error occurred so only log state change for success
+ boolean mdnResponseIssue = AS2Util.processMDN((AS2Message) msg, response.getBody(), null, false, getSession(), this.getClass());
+ if (mdnResponseIssue) {
+ logger.warn("There was an issue identified processing the response fropm the p[artner. Review upstream log messages for details on the probklem.");
+ }
} catch (Exception e) {
/* Processing of the MDN would have done extensive error handling so only log an error if the error
* is an not OpenAS2 custom error.
diff --git a/Server/src/main/java/org/openas2/util/AS2Util.java b/Server/src/main/java/org/openas2/util/AS2Util.java
index 35079d60..8716640a 100644
--- a/Server/src/main/java/org/openas2/util/AS2Util.java
+++ b/Server/src/main/java/org/openas2/util/AS2Util.java
@@ -85,7 +85,13 @@ public static String generateMessageID(Message msg, boolean isMDN) throws Invali
return id;
}
- public static void parseMDN(Message msg, X509Certificate receiver) throws OpenAS2Exception {
+ /**
+ * @param msg- the AS2 message that is being processed
+ * @param receiver - the receivers X509 certificate
+ * @return - a boolean indicating if the extracted response indicated an issue processing the AS2 message that was sent. Message state is NOT updated in this method.
+ * @throws OpenAS2Exception - thrown if there are issues trying to extract the response from the partner
+ */
+ public static boolean parseMDN(Message msg, X509Certificate receiver) throws OpenAS2Exception {
Logger logger = LoggerFactory.getLogger(AS2Util.class);
MessageMDN mdn = msg.getMDN();
MimeBodyPart mainPart = mdn.getData();
@@ -106,13 +112,12 @@ public static void parseMDN(Message msg, X509Certificate receiver) throws OpenAS
} catch (Exception e1) {
logger.error("Error parsing MDN: " + org.openas2.util.Logging.getExceptionMsg(e1), e1);
throw new OpenAS2Exception("Failed to verify signature of received MDN.");
-
}
try {
MimeMultipart reportParts = new MimeMultipart(mainPart.getDataHandler().getDataSource());
- if (reportParts != null) {
+ if (reportParts != null && reportParts.getCount() > 0) {
ContentType reportType = new ContentType(reportParts.getContentType());
Charset charset = getCharset(reportType, msg, logger);
@@ -141,11 +146,27 @@ public static void parseMDN(Message msg, X509Certificate receiver) throws OpenAS
} else {
// No multipart/report so now what?
logger.warn("MDN received from partner but did not contain a multipart/report section. " + msg.getLogMsgID());
+ int reportCount = reportParts.getCount();
+ MimeBodyPart reportPart;
+ for (int j = 0; j < reportCount; j++) {
+ reportPart = (MimeBodyPart) reportParts.getBodyPart(j);
+ logger.warn("Received MimeBodyPart from Multipart for inbound MDN: " + msg.getLogMsgID() + "\n" + MimeUtil.toString(reportPart, true));
+ }
+ return false;
}
+ } else {
+ logger.error("The received MimeBodyPart for inbound MDN did not contain a standard MDN response. This is probably because an error occurred on the remote side processing the message. Review the response below for possible reasons: " + msg.getLogMsgID() + "\n" + MimeUtil.toString(mainPart, true));
+ return false;
}
} catch (Exception e) {
+ try {
+ logger.error("Failed to extract report from received MimeBodyPart for inbound MDN: " + msg.getLogMsgID() + "\n" + MimeUtil.toString(mainPart, true));
+ } catch (Exception e1) {
+ // Do nothing
+ }
throw new OpenAS2Exception("Failed to parse MDN: " + org.openas2.util.Logging.getExceptionMsg(e), e);
}
+ return true;
}
private static String getMimeBodyPartText(MimeBodyPart part, Charset charset) throws MessagingException, IOException {
@@ -180,7 +201,7 @@ private static Charset getCharset(ContentType contentType, Message msg, Logger l
* @param msg - the original message sent to the partner that the MDN
* relates to
* @return true if mdn processed
- * @throws DispositionException - something wrong t=with the Disposition
+ * @throws DispositionException - something wrong with the Disposition
* structure
* @throws OpenAS2Exception - an internally handled error has occurred
*/
@@ -473,12 +494,11 @@ public static boolean resend(Session session, Class> sourceClass, String how,
* @param session - Session object
* @param sourceClass - who invoked this method
- * @return partnerIdentificationProblem - boolean indicating that the partnership for this MDN not identified
+ * @return mdnResponseIssue - boolean indicating that the MDN processing identified an issue.
* @throws OpenAS2Exception - an internally handled error has occurred
* @throws IOException - the IO system has a problem
*
- * TODO:: Possibly do away with returning a boolean as it does not add value ATM
*/
public static boolean processMDN(AS2Message msg, byte[] data, OutputStream out, boolean isAsyncMDN, Session session, Class> sourceClass) throws OpenAS2Exception, IOException {
Logger logger = LoggerFactory.getLogger(AS2Util.class);
@@ -525,7 +545,12 @@ public static boolean processMDN(AS2Message msg, byte[] data, OutputStream out,
if (logger.isTraceEnabled()) {
logger.trace("Parsing MDN: " + mdn.toString() + msg.getLogMsgID());
}
- AS2Util.parseMDN(msg, senderCert);
+ if (!AS2Util.parseMDN(msg, senderCert)) {
+ msg.setStatus(Message.MSG_STATUS_MSG_TERMINATED_IN_ERROR);
+ msg.setOption("STATE", Message.MSG_STATE_MSG_SENT_MDN_RECEIVED_ERROR);
+ msg.trackMsgState(session);
+ return false;
+ }
if (isAsyncMDN) {
getMetaData(msg, session);
@@ -533,12 +558,12 @@ public static boolean processMDN(AS2Message msg, byte[] data, OutputStream out,
msg.setStatus(Message.MSG_STATUS_MDN_VERIFY);
if (logger.isTraceEnabled()) {
- logger.trace("MDN parsed. \n Payload file name: " + msg.getPayloadFilename() + "\n Checking MDN report..." + msg.getLogMsgID());
+ logger.trace("MDN parsed. Payload file name: " + msg.getPayloadFilename() + "\n Checking MDN report..." + msg.getLogMsgID());
}
try {
AS2Util.checkMDN(msg);
/*
- * If the MDN was successfully received send correct HTTP response irrespective
+ * If the MDN was successfully received, send correct HTTP response irrespective
* of possible error conditions due to disposition errors or MIC mismatch
*/
if (isAsyncMDN) {
@@ -652,6 +677,7 @@ public static void getMetaData(AS2Message msg, Session session) throws OpenAS2Ex
getMetaData(msg, iFile);
}
+ @SuppressWarnings("unchecked")
public static void getMetaData(AS2Message msg, File inFile) throws OpenAS2Exception {
Logger logger = LoggerFactory.getLogger(AS2Util.class);
ObjectInputStream pifois;
diff --git a/changes.txt b/changes.txt
index 18b252f5..23862e22 100644
--- a/changes.txt
+++ b/changes.txt
@@ -1,5 +1,11 @@
**IMPORTANT NOTE**: Please review upgrade notes in the RELEASE-NOTES.md if you are upgrading
+Version 4.7.0 - 2025-10-28
+
+This is a minor enhancement release.
+1. Enhance MDN processing to extract possible responses from partner that provide information on why the partner rejected the AS2 transaction.
+
+
Version 4.6.3 - 2025-09-29
This is a bugfix release.
diff --git a/pom.xml b/pom.xml
index 4d2909b8..983f7fb9 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
4.0.0
net.sf.openas2
OpenAS2
- 4.6.3
+ 4.7.0
OpenAS2
pom
@@ -76,7 +76,7 @@
org.apache.commons
commons-lang3
- 3.18.0
+ 3.19.0
commons-cli
@@ -91,7 +91,7 @@
com.h2database
h2
- 2.3.232
+ 2.4.240
@@ -146,7 +146,7 @@
ch.qos.logback
logback-classic
- 1.5.18
+ 1.5.19
jakarta.ws.rs