This is an automated email from the ASF dual-hosted git repository.

chibenwa pushed a commit to branch dlx-deleted-message-vault
in repository https://gitbox.apache.org/repos/asf/james-project.git

commit a6bed2ee57790a869743a0a464af2e28d53ceda0
Author: Benoit TELLIER <[email protected]>
AuthorDate: Mon Jun 29 17:16:07 2026 +0200

    [FIX] DistributedDeletedMessageVaultDeletionCallback - be tolerant for 
messages without internal dates
---
 .../metadata/DeletedMessageVaultDeletionCallback.java      | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git 
a/mailbox/plugin/deleted-messages-vault-cassandra/src/main/java/org/apache/james/vault/metadata/DeletedMessageVaultDeletionCallback.java
 
b/mailbox/plugin/deleted-messages-vault-cassandra/src/main/java/org/apache/james/vault/metadata/DeletedMessageVaultDeletionCallback.java
index 40b6bf02f4..a177f8b5dd 100644
--- 
a/mailbox/plugin/deleted-messages-vault-cassandra/src/main/java/org/apache/james/vault/metadata/DeletedMessageVaultDeletionCallback.java
+++ 
b/mailbox/plugin/deleted-messages-vault-cassandra/src/main/java/org/apache/james/vault/metadata/DeletedMessageVaultDeletionCallback.java
@@ -72,12 +72,13 @@ public class DeletedMessageVaultDeletionCallback implements 
DeleteMessageListene
         return Mono.from(blobStore.readBytes(blobStore.getDefaultBucketName(), 
copyCommand.getHeaderId(), BlobStore.StoragePolicy.LOW_COST))
             .flatMap(bytes -> {
                 Optional<Message> mimeMessage = parseMessage(new 
ByteArrayInputStream(bytes), copyCommand.getMessageId());
+                ZonedDateTime deletionDate = 
ZonedDateTime.ofInstant(clock.instant(), ZoneOffset.UTC);
                 DeletedMessage deletedMessage = DeletedMessage.builder()
                     .messageId(copyCommand.getMessageId())
                     .originMailboxes(copyCommand.getMailboxId())
                     .user(copyCommand.getOwner())
-                    
.deliveryDate(ZonedDateTime.ofInstant(copyCommand.getInternalDate().toInstant(),
 ZoneOffset.UTC))
-                    .deletionDate(ZonedDateTime.ofInstant(clock.instant(), 
ZoneOffset.UTC))
+                    .deliveryDate(deliveryDate(copyCommand, deletionDate))
+                    .deletionDate(deletionDate)
                     .sender(retrieveSender(mimeMessage))
                     .recipients(retrieveRecipients(mimeMessage))
                     .hasAttachment(copyCommand.hasAttachments())
@@ -92,6 +93,15 @@ public class DeletedMessageVaultDeletionCallback implements 
DeleteMessageListene
     }
 
 
+    private ZonedDateTime 
deliveryDate(DeleteMessageListener.DeletedMessageCopyCommand copyCommand, 
ZonedDateTime fallback) {
+        if (copyCommand.getInternalDate() == null) {
+            LOGGER.warn("Message {} has no internal date (likely a partially 
deleted Cassandra row), " +
+                "falling back to the deletion date for the deleted message 
vault delivery date", copyCommand.getMessageId());
+            return fallback;
+        }
+        return 
ZonedDateTime.ofInstant(copyCommand.getInternalDate().toInstant(), 
ZoneOffset.UTC);
+    }
+
     private Optional<Message> parseMessage(InputStream inputStream, MessageId 
messageId) {
         DefaultMessageBuilder messageBuilder = new DefaultMessageBuilder();
         messageBuilder.setMimeEntityConfig(MimeConfig.PERMISSIVE);


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to