fixup! TF-3649 Fix reply to own sent email
This commit is contained in:
@@ -0,0 +1,20 @@
|
|||||||
|
# 59. Reply to own sent email
|
||||||
|
|
||||||
|
Date: 2025-04-15
|
||||||
|
|
||||||
|
## Status
|
||||||
|
|
||||||
|
Accepted
|
||||||
|
|
||||||
|
## Context
|
||||||
|
|
||||||
|
- User want to reply to own sent email, keeping all "To" recipients
|
||||||
|
|
||||||
|
## Decision
|
||||||
|
|
||||||
|
- PresentationEmailExtension._handleReply is modified
|
||||||
|
- When `isSender` is `true`, all "To" recipients will be kept
|
||||||
|
|
||||||
|
## Consequences
|
||||||
|
|
||||||
|
- When replying to own sent email, "Reply-To" email will no longer be considered
|
||||||
@@ -1,12 +1,8 @@
|
|||||||
|
|
||||||
import 'package:collection/collection.dart';
|
|
||||||
import 'package:dartz/dartz.dart';
|
import 'package:dartz/dartz.dart';
|
||||||
import 'package:jmap_dart_client/jmap/mail/email/email_address.dart';
|
import 'package:jmap_dart_client/jmap/mail/email/email_address.dart';
|
||||||
import 'package:model/email/email_action_type.dart';
|
import 'package:model/email/email_action_type.dart';
|
||||||
import 'package:model/email/presentation_email.dart';
|
import 'package:model/email/presentation_email.dart';
|
||||||
import 'package:model/extensions/email_address_extension.dart';
|
|
||||||
import 'package:model/extensions/list_email_address_extension.dart';
|
import 'package:model/extensions/list_email_address_extension.dart';
|
||||||
import 'package:model/extensions/presentation_mailbox_extension.dart';
|
|
||||||
import 'package:tmail_ui_user/features/email/presentation/utils/email_utils.dart';
|
import 'package:tmail_ui_user/features/email/presentation/utils/email_utils.dart';
|
||||||
|
|
||||||
extension PresentationEmailExtension on PresentationEmail {
|
extension PresentationEmailExtension on PresentationEmail {
|
||||||
@@ -30,7 +26,6 @@ extension PresentationEmailExtension on PresentationEmail {
|
|||||||
newFromAddress: newFromAddress,
|
newFromAddress: newFromAddress,
|
||||||
newBccAddress: newBccAddress,
|
newBccAddress: newBccAddress,
|
||||||
newReplyToAddress: newReplyToAddress,
|
newReplyToAddress: newReplyToAddress,
|
||||||
replyOwnSentEmail: mailboxContain?.isSent == true,
|
|
||||||
userName: userName,
|
userName: userName,
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -59,27 +54,9 @@ extension PresentationEmailExtension on PresentationEmail {
|
|||||||
required List<EmailAddress> newFromAddress,
|
required List<EmailAddress> newFromAddress,
|
||||||
required List<EmailAddress> newBccAddress,
|
required List<EmailAddress> newBccAddress,
|
||||||
required List<EmailAddress> newReplyToAddress,
|
required List<EmailAddress> newReplyToAddress,
|
||||||
required replyOwnSentEmail,
|
|
||||||
String? userName,
|
String? userName,
|
||||||
}) {
|
}) {
|
||||||
if (isSender) {
|
if (isSender) return Tuple4(newToAddress, [], [], []);
|
||||||
if (replyOwnSentEmail) {
|
|
||||||
return Tuple4(newToAddress, [], [], []);
|
|
||||||
}
|
|
||||||
if (newBccAddress.isNotEmpty) {
|
|
||||||
return Tuple4(newToAddress, [], [], newReplyToAddress);
|
|
||||||
}
|
|
||||||
if (newReplyToAddress.isNotEmpty) {
|
|
||||||
return Tuple4(newReplyToAddress, [], [], []);
|
|
||||||
}
|
|
||||||
if (userName != null) {
|
|
||||||
final userEmail = newToAddress.firstWhereOrNull((address) => address.emailAddress == userName);
|
|
||||||
if (userEmail != null) {
|
|
||||||
return Tuple4([userEmail], [], [], []);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Tuple4(newToAddress, [], [], []);
|
|
||||||
}
|
|
||||||
|
|
||||||
final listToAddress = (newReplyToAddress.isNotEmpty ? newReplyToAddress : newFromAddress).withoutMe(userName);
|
final listToAddress = (newReplyToAddress.isNotEmpty ? newReplyToAddress : newFromAddress).withoutMe(userName);
|
||||||
return Tuple4(listToAddress, [], [], []);
|
return Tuple4(listToAddress, [], [], []);
|
||||||
|
|||||||
@@ -1,12 +1,9 @@
|
|||||||
import 'package:dartz/dartz.dart';
|
import 'package:dartz/dartz.dart';
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
import 'package:jmap_dart_client/jmap/core/id.dart';
|
|
||||||
import 'package:jmap_dart_client/jmap/mail/email/email_address.dart';
|
import 'package:jmap_dart_client/jmap/mail/email/email_address.dart';
|
||||||
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
|
|
||||||
import 'package:model/email/email_action_type.dart';
|
import 'package:model/email/email_action_type.dart';
|
||||||
import 'package:model/email/presentation_email.dart';
|
import 'package:model/email/presentation_email.dart';
|
||||||
import 'package:model/extensions/email_address_extension.dart';
|
import 'package:model/extensions/email_address_extension.dart';
|
||||||
import 'package:model/mailbox/presentation_mailbox.dart';
|
|
||||||
import 'package:tmail_ui_user/features/email/presentation/extensions/presentation_email_extension.dart';
|
import 'package:tmail_ui_user/features/email/presentation/extensions/presentation_email_extension.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
@@ -89,71 +86,6 @@ void main() {
|
|||||||
'GIVEN user A is the sender\n'
|
'GIVEN user A is the sender\n'
|
||||||
'AND sends an email to user B and user E, cc to user C, bcc to user D',
|
'AND sends an email to user B and user E, cc to user C, bcc to user D',
|
||||||
() {
|
() {
|
||||||
test(
|
|
||||||
'Email has Reply To and List-Post'
|
|
||||||
'THEN user A clicks reply, generateRecipientsEmailAddressForComposer\n'
|
|
||||||
'SHOULD return user B email + user E email to reply',
|
|
||||||
() {
|
|
||||||
final expectedResult = Tuple4(
|
|
||||||
[userBEmailAddress, userEEmailAddress],
|
|
||||||
<EmailAddress>[],
|
|
||||||
<EmailAddress>[],
|
|
||||||
[replyToEmailAddress],
|
|
||||||
);
|
|
||||||
|
|
||||||
final emailToReply = PresentationEmail(
|
|
||||||
from: {userAEmailAddress},
|
|
||||||
to: {userBEmailAddress, userEEmailAddress},
|
|
||||||
cc: {userCEmailAddress},
|
|
||||||
bcc: {userDEmailAddress},
|
|
||||||
replyTo: {replyToEmailAddress},
|
|
||||||
);
|
|
||||||
|
|
||||||
final result = emailToReply.generateRecipientsEmailAddressForComposer(
|
|
||||||
emailActionType: EmailActionType.reply,
|
|
||||||
isSender: true,
|
|
||||||
userName: userAEmailAddress.emailAddress,
|
|
||||||
listPost: listPost,
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(result.value1, containsAll(expectedResult.value1));
|
|
||||||
expect(result.value2, containsAll(expectedResult.value2));
|
|
||||||
expect(result.value3, containsAll(expectedResult.value3));
|
|
||||||
expect(result.value4, containsAll(expectedResult.value4));
|
|
||||||
});
|
|
||||||
|
|
||||||
test(
|
|
||||||
'Email has Reply To and not List-Post'
|
|
||||||
'THEN user A clicks reply, generateRecipientsEmailAddressForComposer\n'
|
|
||||||
'SHOULD return user B email + user E email to reply',
|
|
||||||
() {
|
|
||||||
final expectedResult = Tuple4(
|
|
||||||
[userBEmailAddress, userEEmailAddress],
|
|
||||||
<EmailAddress>[],
|
|
||||||
<EmailAddress>[],
|
|
||||||
[replyToEmailAddress],
|
|
||||||
);
|
|
||||||
|
|
||||||
final emailToReply = PresentationEmail(
|
|
||||||
from: {userAEmailAddress},
|
|
||||||
to: {userBEmailAddress, userEEmailAddress},
|
|
||||||
cc: {userCEmailAddress},
|
|
||||||
bcc: {userDEmailAddress},
|
|
||||||
replyTo: {replyToEmailAddress},
|
|
||||||
);
|
|
||||||
|
|
||||||
final result = emailToReply.generateRecipientsEmailAddressForComposer(
|
|
||||||
emailActionType: EmailActionType.reply,
|
|
||||||
isSender: true,
|
|
||||||
userName: userAEmailAddress.emailAddress,
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(result.value1, containsAll(expectedResult.value1));
|
|
||||||
expect(result.value2, containsAll(expectedResult.value2));
|
|
||||||
expect(result.value3, containsAll(expectedResult.value3));
|
|
||||||
expect(result.value4, containsAll(expectedResult.value4));
|
|
||||||
});
|
|
||||||
|
|
||||||
test(
|
test(
|
||||||
'Email has List-Post and not Reply To'
|
'Email has List-Post and not Reply To'
|
||||||
'THEN user A clicks reply, generateRecipientsEmailAddressForComposer\n'
|
'THEN user A clicks reply, generateRecipientsEmailAddressForComposer\n'
|
||||||
@@ -224,39 +156,6 @@ void main() {
|
|||||||
'GIVEN user A is the sender\n'
|
'GIVEN user A is the sender\n'
|
||||||
'AND sends an email to user A and user B, cc to user C, bcc to user D',
|
'AND sends an email to user A and user B, cc to user C, bcc to user D',
|
||||||
() {
|
() {
|
||||||
test(
|
|
||||||
'Email has Reply To and List-Post'
|
|
||||||
'THEN user A clicks reply, generateRecipientsEmailAddressForComposer\n'
|
|
||||||
'SHOULD return user A email + user B email to reply',
|
|
||||||
() {
|
|
||||||
final expectedResult = Tuple4(
|
|
||||||
[userBEmailAddress, userAEmailAddress],
|
|
||||||
<EmailAddress>[],
|
|
||||||
<EmailAddress>[],
|
|
||||||
[replyToEmailAddress],
|
|
||||||
);
|
|
||||||
|
|
||||||
final emailToReply = PresentationEmail(
|
|
||||||
from: {userAEmailAddress},
|
|
||||||
to: {userBEmailAddress, userAEmailAddress},
|
|
||||||
cc: {userCEmailAddress},
|
|
||||||
bcc: {userDEmailAddress},
|
|
||||||
replyTo: {replyToEmailAddress},
|
|
||||||
);
|
|
||||||
|
|
||||||
final result = emailToReply.generateRecipientsEmailAddressForComposer(
|
|
||||||
emailActionType: EmailActionType.reply,
|
|
||||||
isSender: true,
|
|
||||||
userName: userAEmailAddress.emailAddress,
|
|
||||||
listPost: listPost,
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(result.value1, containsAll(expectedResult.value1));
|
|
||||||
expect(result.value2, containsAll(expectedResult.value2));
|
|
||||||
expect(result.value3, containsAll(expectedResult.value3));
|
|
||||||
expect(result.value4, containsAll(expectedResult.value4));
|
|
||||||
});
|
|
||||||
|
|
||||||
test(
|
test(
|
||||||
'Email has Reply To'
|
'Email has Reply To'
|
||||||
'AND user is replying to own sent email'
|
'AND user is replying to own sent email'
|
||||||
@@ -268,10 +167,6 @@ void main() {
|
|||||||
to: {userBEmailAddress, userAEmailAddress},
|
to: {userBEmailAddress, userAEmailAddress},
|
||||||
cc: {userCEmailAddress},
|
cc: {userCEmailAddress},
|
||||||
replyTo: {replyToEmailAddress},
|
replyTo: {replyToEmailAddress},
|
||||||
mailboxContain: PresentationMailbox(
|
|
||||||
MailboxId(Id('value')),
|
|
||||||
role: PresentationMailbox.roleSent,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
final result = emailToReply.generateRecipientsEmailAddressForComposer(
|
final result = emailToReply.generateRecipientsEmailAddressForComposer(
|
||||||
@@ -286,38 +181,6 @@ void main() {
|
|||||||
expect(result.value4, isEmpty);
|
expect(result.value4, isEmpty);
|
||||||
});
|
});
|
||||||
|
|
||||||
test(
|
|
||||||
'Email has Reply To and not List-Post'
|
|
||||||
'THEN user A clicks reply, generateRecipientsEmailAddressForComposer\n'
|
|
||||||
'SHOULD return user A email + user B email to reply',
|
|
||||||
() {
|
|
||||||
final expectedResult = Tuple4(
|
|
||||||
[userBEmailAddress, userAEmailAddress],
|
|
||||||
<EmailAddress>[],
|
|
||||||
<EmailAddress>[],
|
|
||||||
[replyToEmailAddress],
|
|
||||||
);
|
|
||||||
|
|
||||||
final emailToReply = PresentationEmail(
|
|
||||||
from: {userAEmailAddress},
|
|
||||||
to: {userBEmailAddress, userAEmailAddress},
|
|
||||||
cc: {userCEmailAddress},
|
|
||||||
bcc: {userDEmailAddress},
|
|
||||||
replyTo: {replyToEmailAddress},
|
|
||||||
);
|
|
||||||
|
|
||||||
final result = emailToReply.generateRecipientsEmailAddressForComposer(
|
|
||||||
emailActionType: EmailActionType.reply,
|
|
||||||
isSender: true,
|
|
||||||
userName: userAEmailAddress.emailAddress,
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(result.value1, containsAll(expectedResult.value1));
|
|
||||||
expect(result.value2, containsAll(expectedResult.value2));
|
|
||||||
expect(result.value3, containsAll(expectedResult.value3));
|
|
||||||
expect(result.value4, containsAll(expectedResult.value4));
|
|
||||||
});
|
|
||||||
|
|
||||||
test(
|
test(
|
||||||
'Email has List-Post and not Reply To'
|
'Email has List-Post and not Reply To'
|
||||||
'THEN user A clicks reply, generateRecipientsEmailAddressForComposer\n'
|
'THEN user A clicks reply, generateRecipientsEmailAddressForComposer\n'
|
||||||
|
|||||||
Reference in New Issue
Block a user