Skip to content

Commit

Permalink
fix: [CO-690] delegated account sent mail always read (#209)
Browse files Browse the repository at this point in the history
* fix: MailSender delegated send always read status
* When a delegated email is sent always set the status "read" in Sent folder.
* chore: MailSender add id of item in delegated request
test: add test to check delegated email is read and only in delegated user sent folder by default
* chore: add bug number
  • Loading branch information
frisonisland authored May 3, 2023
1 parent 37e7219 commit 3b0efc9
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 4 deletions.
16 changes: 12 additions & 4 deletions store/src/main/java/com/zimbra/cs/mailbox/MailSender.java
Original file line number Diff line number Diff line change
Expand Up @@ -556,6 +556,14 @@ public ItemId sendMimeMessage(OperationContext octxt, Mailbox mbox, Boolean save

/**
* Sends a message.
* If request is delegated, save to sent behavior follows
* {@link Provisioning#A_zimbraPrefDelegatedSendSaveTarget}:
* - owner: saves the email only to delegated account, status read
* - sender: saves the email to original user account, status read
* - both: performs both above
* - none: does not save sent email
* Note: the email is sent in any case.
*
*/
public ItemId sendMimeMessage(OperationContext octxt, Mailbox mbox, MimeMessage mm)
throws ServiceException {
Expand Down Expand Up @@ -712,13 +720,10 @@ public ItemId sendMimeMessage(OperationContext octxt, Mailbox mbox, MimeMessage
}
}

// for delegated sends automatically save a copy to the "From" user's mailbox, unless we've been
// specifically requested not to do the save (for instance BES does its own save to Sent, so does'nt
// want it done here).
if (allowSaveToSent && hasRecipients && !isDataSourceSender() && isDelegatedRequest &&
(PrefDelegatedSendSaveTarget.owner == acct.getPrefDelegatedSendSaveTarget() ||
PrefDelegatedSendSaveTarget.both == acct.getPrefDelegatedSendSaveTarget())) {
int flags = Flag.BITMASK_UNREAD | Flag.BITMASK_FROM_ME;
int flags = Flag.BITMASK_FROM_ME;
// save the sent copy using the target's credentials, as the sender doesn't necessarily have write access
OperationContext octxtTarget = new OperationContext(acct);
if (pm == null || pm.isAttachmentIndexingEnabled() != mbox.attachmentsIndexingEnabled()) {
Expand All @@ -734,6 +739,9 @@ public ItemId sendMimeMessage(OperationContext octxt, Mailbox mbox, MimeMessage
RuleManager.applyRulesToOutgoingMessage(octxtTarget, mbox, pm, sentFolderId, true, flags, null, convId);
for (ItemId itemId : addedItemIds) {
rollbacks.add(new RollbackData(mbox, itemId.getId()));
if (returnItemId == null) {
returnItemId = itemId;
}
}
}
}
Expand Down
96 changes: 96 additions & 0 deletions store/src/test/java/com/zimbra/cs/mailbox/MailSenderIT.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
// SPDX-FileCopyrightText: 2023 Zextras <https://www.zextras.com>
//
// SPDX-License-Identifier: AGPL-3.0-only

package com.zimbra.cs.mailbox;

import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;

import com.zimbra.cs.account.Account;
import com.zimbra.cs.account.Provisioning;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.UUID;
import javax.mail.Address;
import javax.mail.Session;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMessage.RecipientType;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.mockito.Mockito;

/**
* Bug: CO-690
*/
public class MailSenderIT {

private static Provisioning prov;

@BeforeClass
public static void init() throws Exception {
MailboxTestUtil.initServer();
prov = Provisioning.getInstance();
}

@Before
public void setUp() throws Exception {
MailboxTestUtil.clearData();
}

@Test
public void shouldSaveSentEmailInDelegatedAccountWithReadStatus() throws Exception {

String delegatedId = UUID.randomUUID().toString();
String delegatedEmail = delegatedId + "@test.com";

String userId = UUID.randomUUID().toString();
String userEmail = userId + "@test.com";
// create delegated account
Map<String, Object> delegatedAttrs = new HashMap<>();
delegatedAttrs.put(Provisioning.A_zimbraPrefAllowAddressForDelegatedSender, userEmail);
delegatedAttrs.put(Provisioning.A_zimbraId, delegatedId);
Account delegatedAccount = prov.createAccount(delegatedEmail, "secret", delegatedAttrs);

// create user account
Map<String, Object> userAttrs = new HashMap<>();
userAttrs.put(Provisioning.A_zimbraPrefAllowAddressForDelegatedSender, userEmail);
userAttrs.put(Provisioning.A_zimbraId, userId);
Account userAccount = prov.createAccount(userEmail, "secret", userAttrs);

final Mailbox delegatedMailbox = MailboxManager.getInstance().getMailboxByAccount(delegatedAccount);

final MimeMessage mimeMessage = new MimeMessage(Session.getInstance(new Properties()));

// spy MailSender to avoid sending real email
final MailSender mailSender = spy(MailSender.class);
Address[] recipients = new Address[]{new InternetAddress(userEmail)};
doReturn(List.of(recipients)).when(mailSender).sendMessage(Mockito.any(Mailbox.class), Mockito.any(MimeMessage.class), Mockito.any(
java.util.Collection.class));
final OperationContext operationContext = new OperationContext(userAccount);
mimeMessage.setFrom(new InternetAddress(delegatedEmail));
mimeMessage.setRecipients(RecipientType.TO, recipients);
mimeMessage.setSubject("Test email");
mimeMessage.setText("Hello there!");
mimeMessage.setSender(new InternetAddress(userEmail));
// send email logged in as user, using delegated account
mailSender.sendMimeMessage(operationContext, delegatedMailbox, mimeMessage);

final Mailbox userMailbox = MailboxManager.getInstance().getMailboxByAccount(userAccount);
final OperationContext delegatedAccountOpCtx = new OperationContext(delegatedAccount);
// Check email is in delegated sent and read
final Folder delegatedSent = delegatedMailbox.getFolderByPath(delegatedAccountOpCtx, "sent");
Assert.assertEquals(0, delegatedSent.getUnreadCount());
Assert.assertEquals(1, delegatedSent.getSize());
// Check email is in user sent and read
final Folder userSent = userMailbox.getFolderByPath(operationContext, "sent");
Assert.assertEquals(0, userSent.getUnreadCount());
Assert.assertEquals(0, userSent.getSize());
}

}

0 comments on commit 3b0efc9

Please sign in to comment.