TF-3413 Support Reply to list for email
This commit is contained in:
@@ -40,7 +40,9 @@ class EmailRequest with EquatableMixin {
|
||||
];
|
||||
|
||||
bool get isEmailAnswered => emailIdAnsweredOrForwarded != null &&
|
||||
(emailActionType == EmailActionType.reply || emailActionType == EmailActionType.replyAll);
|
||||
(emailActionType == EmailActionType.reply
|
||||
|| emailActionType == EmailActionType.replyToList
|
||||
|| emailActionType == EmailActionType.replyAll);
|
||||
|
||||
bool get isEmailForwarded => emailIdAnsweredOrForwarded != null && emailActionType == EmailActionType.forward;
|
||||
}
|
||||
@@ -74,6 +74,7 @@ import 'package:tmail_ui_user/features/email/domain/state/get_email_content_stat
|
||||
import 'package:tmail_ui_user/features/email/domain/state/transform_html_email_content_state.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/get_email_content_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/usecases/transform_html_email_content_interactor.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/extensions/presentation_email_extension.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/model/composer_arguments.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/utils/email_utils.dart';
|
||||
import 'package:tmail_ui_user/features/home/data/exceptions/session_exceptions.dart';
|
||||
@@ -640,11 +641,15 @@ class ComposerController extends BaseController
|
||||
_updateStatusEmailSendButton();
|
||||
break;
|
||||
case EmailActionType.reply:
|
||||
case EmailActionType.replyToList:
|
||||
case EmailActionType.replyAll:
|
||||
log('ComposerController::_initEmail:listPost = ${arguments.listPost}');
|
||||
_initEmailAddress(
|
||||
presentationEmail: arguments.presentationEmail!,
|
||||
actionType: arguments.emailActionType,
|
||||
mailboxRole: arguments.presentationEmail!.mailboxContain?.role ?? mailboxDashBoardController.selectedMailbox.value?.role
|
||||
mailboxRole: arguments.presentationEmail!.mailboxContain?.role
|
||||
?? mailboxDashBoardController.selectedMailbox.value?.role,
|
||||
listPost: arguments.listPost,
|
||||
);
|
||||
_initSubjectEmail(
|
||||
presentationEmail: arguments.presentationEmail!,
|
||||
@@ -798,12 +803,15 @@ class ComposerController extends BaseController
|
||||
required PresentationEmail presentationEmail,
|
||||
required EmailActionType actionType,
|
||||
Role? mailboxRole,
|
||||
String? listPost,
|
||||
}) {
|
||||
log('ComposerController::_initEmailAddress:listPost = $listPost');
|
||||
final recipients = presentationEmail.generateRecipientsEmailAddressForComposer(
|
||||
emailActionType: actionType,
|
||||
mailboxRole: mailboxRole
|
||||
mailboxRole: mailboxRole,
|
||||
listPost: listPost,
|
||||
);
|
||||
final userName = mailboxDashBoardController.sessionCurrent?.username;
|
||||
final userName = mailboxDashBoardController.sessionCurrent?.username;
|
||||
if (userName != null) {
|
||||
final isSender = presentationEmail.from.asList().every((element) => element.email == userName.value);
|
||||
if (isSender) {
|
||||
|
||||
@@ -74,6 +74,7 @@ extension CreateEmailRequestExtension on CreateEmailRequest {
|
||||
|
||||
MessageIdsHeaderValue? createInReplyTo() {
|
||||
if (emailActionType == EmailActionType.reply ||
|
||||
emailActionType == EmailActionType.replyToList ||
|
||||
emailActionType == EmailActionType.replyAll
|
||||
) {
|
||||
return messageId;
|
||||
@@ -83,6 +84,7 @@ extension CreateEmailRequestExtension on CreateEmailRequest {
|
||||
|
||||
MessageIdsHeaderValue? createReferences() {
|
||||
if (emailActionType == EmailActionType.reply ||
|
||||
emailActionType == EmailActionType.replyToList ||
|
||||
emailActionType == EmailActionType.replyAll ||
|
||||
emailActionType == EmailActionType.forward
|
||||
) {
|
||||
|
||||
@@ -12,6 +12,7 @@ extension EmailActionTypeExtension on EmailActionType {
|
||||
String getSubjectComposer(BuildContext? context, String subject) {
|
||||
switch(this) {
|
||||
case EmailActionType.reply:
|
||||
case EmailActionType.replyToList:
|
||||
case EmailActionType.replyAll:
|
||||
if (subject.toLowerCase().startsWith('re:')) {
|
||||
return subject;
|
||||
@@ -60,6 +61,7 @@ extension EmailActionTypeExtension on EmailActionType {
|
||||
final languageTag = locale.toLanguageTag();
|
||||
switch(this) {
|
||||
case EmailActionType.reply:
|
||||
case EmailActionType.replyToList:
|
||||
case EmailActionType.replyAll:
|
||||
final receivedAt = presentationEmail.receivedAt;
|
||||
final emailAddress = presentationEmail.from.toEscapeHtmlStringUseCommaSeparator();
|
||||
|
||||
@@ -80,6 +80,7 @@ class MobileEditorView extends StatelessWidget with EditorViewMixin {
|
||||
}
|
||||
);
|
||||
case EmailActionType.reply:
|
||||
case EmailActionType.replyToList:
|
||||
case EmailActionType.replyAll:
|
||||
case EmailActionType.forward:
|
||||
if (contentViewState == null) {
|
||||
|
||||
@@ -145,6 +145,7 @@ class WebEditorView extends StatelessWidget with EditorViewMixin {
|
||||
}
|
||||
);
|
||||
case EmailActionType.reply:
|
||||
case EmailActionType.replyToList:
|
||||
case EmailActionType.replyAll:
|
||||
case EmailActionType.forward:
|
||||
if (contentViewState == null) {
|
||||
|
||||
@@ -1425,6 +1425,20 @@ class SingleEmailController extends BaseController with AppLoaderMixin {
|
||||
)
|
||||
);
|
||||
break;
|
||||
case EmailActionType.replyToList:
|
||||
log('SingleEmailController::pressEmailAction:replyToList');
|
||||
mailboxDashBoardController.goToComposer(
|
||||
ComposerArguments.replyToListEmail(
|
||||
presentationEmail: presentationEmail,
|
||||
content: currentEmailLoaded.value?.htmlContent ?? '',
|
||||
inlineImages: currentEmailLoaded.value?.inlineImages ?? [],
|
||||
mailboxRole: presentationEmail.mailboxContain?.role,
|
||||
messageId: currentEmailLoaded.value?.emailCurrent?.messageId,
|
||||
references: currentEmailLoaded.value?.emailCurrent?.references,
|
||||
listPost: currentEmailLoaded.value?.emailCurrent?.listPost,
|
||||
)
|
||||
);
|
||||
break;
|
||||
case EmailActionType.replyAll:
|
||||
mailboxDashBoardController.goToComposer(
|
||||
ComposerArguments.replyAllEmail(
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
|
||||
import 'package:core/utils/app_logger.dart';
|
||||
import 'package:dartz/dartz.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/presentation_email.dart';
|
||||
import 'package:model/extensions/list_email_address_extension.dart';
|
||||
import 'package:model/mailbox/presentation_mailbox.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/utils/email_utils.dart';
|
||||
|
||||
extension PresentationEmailExtension on PresentationEmail {
|
||||
Tuple3<List<EmailAddress>, List<EmailAddress>, List<EmailAddress>> generateRecipientsEmailAddressForComposer({
|
||||
required EmailActionType emailActionType,
|
||||
Role? mailboxRole,
|
||||
String? listPost,
|
||||
}) {
|
||||
switch (emailActionType) {
|
||||
case EmailActionType.reply:
|
||||
if (mailboxRole == PresentationMailbox.roleSent) {
|
||||
return Tuple3(to.asList(), [], []);
|
||||
} else {
|
||||
final replyToAddress = replyTo.asList().isNotEmpty
|
||||
? replyTo.asList()
|
||||
: from.asList();
|
||||
return Tuple3(replyToAddress, [], []);
|
||||
}
|
||||
case EmailActionType.replyToList:
|
||||
final listEmailAddress = EmailUtils.parsingListPost(listPost ?? '') ?? [];
|
||||
log('PresentationEmailExtension::generateRecipientsEmailAddressForComposer:listEmailAddress = $listEmailAddress');
|
||||
return Tuple3(listEmailAddress, [], []);
|
||||
case EmailActionType.replyAll:
|
||||
if (mailboxRole == PresentationMailbox.roleSent) {
|
||||
return Tuple3(to.asList(), cc.asList(), bcc.asList());
|
||||
} else {
|
||||
final senderReplyToAddress = replyTo.asList().isNotEmpty
|
||||
? replyTo.asList()
|
||||
: from.asList();
|
||||
return Tuple3(
|
||||
to.asList() + senderReplyToAddress,
|
||||
cc.asList(),
|
||||
bcc.asList(),
|
||||
);
|
||||
}
|
||||
default:
|
||||
return Tuple3(to.asList(), cc.asList(), bcc.asList());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -32,6 +32,7 @@ class ComposerArguments extends RouterArguments {
|
||||
final ScreenDisplayMode displayMode;
|
||||
final List<EmailAddress>? cc;
|
||||
final List<EmailAddress>? bcc;
|
||||
final String? listPost;
|
||||
|
||||
ComposerArguments({
|
||||
this.emailActionType = EmailActionType.compose,
|
||||
@@ -54,6 +55,7 @@ class ComposerArguments extends RouterArguments {
|
||||
this.displayMode = ScreenDisplayMode.normal,
|
||||
this.cc,
|
||||
this.bcc,
|
||||
this.listPost,
|
||||
});
|
||||
|
||||
factory ComposerArguments.fromSendingEmail(SendingEmail sendingEmail) =>
|
||||
@@ -130,6 +132,25 @@ class ComposerArguments extends RouterArguments {
|
||||
references: references,
|
||||
);
|
||||
|
||||
factory ComposerArguments.replyToListEmail({
|
||||
required PresentationEmail presentationEmail,
|
||||
required String content,
|
||||
required List<Attachment> inlineImages,
|
||||
Role? mailboxRole,
|
||||
MessageIdsHeaderValue? messageId,
|
||||
MessageIdsHeaderValue? references,
|
||||
String? listPost,
|
||||
}) => ComposerArguments(
|
||||
emailActionType: EmailActionType.replyToList,
|
||||
presentationEmail: presentationEmail,
|
||||
emailContents: content,
|
||||
inlineImages: inlineImages,
|
||||
mailboxRole: mailboxRole,
|
||||
messageId: messageId,
|
||||
references: references,
|
||||
listPost: listPost,
|
||||
);
|
||||
|
||||
factory ComposerArguments.replyAllEmail({
|
||||
required PresentationEmail presentationEmail,
|
||||
required String content,
|
||||
@@ -206,6 +227,7 @@ class ComposerArguments extends RouterArguments {
|
||||
displayMode,
|
||||
cc,
|
||||
bcc,
|
||||
listPost,
|
||||
];
|
||||
|
||||
ComposerArguments copyWith({
|
||||
@@ -229,6 +251,7 @@ class ComposerArguments extends RouterArguments {
|
||||
ScreenDisplayMode? displayMode,
|
||||
List<EmailAddress>? cc,
|
||||
List<EmailAddress>? bcc,
|
||||
String? listPost,
|
||||
}) {
|
||||
return ComposerArguments(
|
||||
emailActionType: emailActionType ?? this.emailActionType,
|
||||
@@ -251,6 +274,7 @@ class ComposerArguments extends RouterArguments {
|
||||
displayMode: displayMode ?? this.displayMode,
|
||||
cc: cc ?? this.cc,
|
||||
bcc: bcc ?? this.bcc,
|
||||
listPost: listPost ?? this.listPost,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,10 +9,12 @@ import 'package:jmap_dart_client/jmap/account_id.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/capability/capability_identifier.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/properties/properties.dart';
|
||||
import 'package:jmap_dart_client/jmap/core/session/session.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/email/email_address.dart';
|
||||
import 'package:tmail_ui_user/features/email/domain/state/download_attachment_for_web_state.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/model/email_unsubscribe.dart';
|
||||
import 'package:tmail_ui_user/features/thread/domain/constants/thread_constants.dart';
|
||||
import 'package:tmail_ui_user/main/error/capability_validator.dart';
|
||||
import 'package:tmail_ui_user/main/routes/route_utils.dart';
|
||||
|
||||
class EmailUtils {
|
||||
|
||||
@@ -83,4 +85,38 @@ class EmailUtils {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static List<EmailAddress>? parsingListPost(String listPost) {
|
||||
try {
|
||||
if (listPost.isEmpty) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final regExpMailtoLinks = RegExp(r'mailto:([^>,]*)');
|
||||
final allMatchesMailtoLinks = regExpMailtoLinks.allMatches(listPost);
|
||||
final listMailtoLinks = allMatchesMailtoLinks
|
||||
.map((match) => match.group(0))
|
||||
.whereNotNull()
|
||||
.toList();
|
||||
log('EmailUtils::parsingListPost:listMailtoLinks: $listMailtoLinks');
|
||||
|
||||
if (listMailtoLinks.isNotEmpty) {
|
||||
return listMailtoLinks
|
||||
.map((mailto) {
|
||||
final mapMailto = RouteUtils.parseMapMailtoFromUri(mailto);
|
||||
final emailAddress = mapMailto[RouteUtils.paramMailtoAddress];
|
||||
return emailAddress != null
|
||||
? EmailAddress(null, emailAddress)
|
||||
: null;
|
||||
})
|
||||
.whereNotNull()
|
||||
.toList();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} catch (e) {
|
||||
logError('EmailUtils::parsingListPost:Exception = $e');
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:model/email/email_action_type.dart';
|
||||
import 'package:model/email/presentation_email.dart';
|
||||
import 'package:model/extensions/email_extension.dart';
|
||||
import 'package:model/extensions/presentation_email_extension.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/controller/single_email_controller.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/styles/email_view_bottom_bar_widget_styles.dart';
|
||||
@@ -73,6 +74,37 @@ class EmailViewBottomBarWidget extends StatelessWidget {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
}),
|
||||
Obx(() {
|
||||
final currentEmailLoaded = _singleEmailController.currentEmailLoaded.value;
|
||||
|
||||
if (currentEmailLoaded != null &&
|
||||
currentEmailLoaded.emailCurrent?.hasListPost == true) {
|
||||
return Expanded(
|
||||
child: TMailButtonWidget(
|
||||
key: const Key('reply_to_list_email_button'),
|
||||
text: AppLocalizations.of(context).replyToList,
|
||||
icon: _imagePaths.icReply,
|
||||
borderRadius: EmailViewBottomBarWidgetStyles.buttonRadius,
|
||||
iconSize: EmailViewBottomBarWidgetStyles.buttonIconSize,
|
||||
textAlign: TextAlign.center,
|
||||
flexibleText: true,
|
||||
padding: EmailViewBottomBarWidgetStyles.buttonPadding,
|
||||
backgroundColor: EmailViewBottomBarWidgetStyles.buttonBackgroundColor,
|
||||
textStyle: EmailViewBottomBarWidgetStyles.getButtonTextStyle(
|
||||
context,
|
||||
_responsiveUtils,
|
||||
),
|
||||
verticalDirection: _responsiveUtils.isPortraitMobile(context),
|
||||
onTapActionCallback: () => emailActionCallback.call(
|
||||
EmailActionType.replyToList,
|
||||
presentationEmail,
|
||||
),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
}),
|
||||
Obx(() {
|
||||
if (_singleEmailController.currentEmailLoaded.value != null) {
|
||||
return Expanded(
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"@@last_modified": "2024-12-31T12:11:05.777668",
|
||||
"@@last_modified": "2025-01-09T04:35:09.125475",
|
||||
"initializing_data": "Initializing data...",
|
||||
"@initializing_data": {
|
||||
"type": "text",
|
||||
@@ -4083,5 +4083,11 @@
|
||||
"type": "text",
|
||||
"placeholders_order": [],
|
||||
"placeholders": {}
|
||||
},
|
||||
"replyToList": "Reply to list",
|
||||
"@replyToList": {
|
||||
"type": "text",
|
||||
"placeholders_order": [],
|
||||
"placeholders": {}
|
||||
}
|
||||
}
|
||||
@@ -4286,4 +4286,12 @@ class AppLocalizations {
|
||||
name: 'getHelpOrReportABug',
|
||||
);
|
||||
}
|
||||
|
||||
String get replyToList {
|
||||
return Intl.message(
|
||||
'Reply to list',
|
||||
name: 'replyToList',
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
|
||||
enum EmailActionType {
|
||||
reply,
|
||||
replyToList,
|
||||
forward,
|
||||
replyAll,
|
||||
compose,
|
||||
|
||||
@@ -24,4 +24,5 @@ class EmailProperty {
|
||||
static const String references = 'references';
|
||||
static const String headerUnsubscribeKey = 'List-Unsubscribe';
|
||||
static const String headerSMimeStatusKey = 'X-SMIME-Status';
|
||||
static const String headerListPostKey = 'List-Post';
|
||||
}
|
||||
@@ -36,6 +36,10 @@ extension EmailExtension on Email {
|
||||
|
||||
String get sMimeStatusHeaderParsed => sMimeStatusHeader?[IndividualHeaderIdentifier.sMimeStatusHeader]?.trim() ?? '';
|
||||
|
||||
String get listPost => headers.listPost;
|
||||
|
||||
bool get hasListPost => listPost.isNotEmpty;
|
||||
|
||||
IdentityId? get identityIdFromHeader {
|
||||
final rawIdentityId = identityHeader?[IndividualHeaderIdentifier.identityHeader];
|
||||
if (rawIdentityId == null) return null;
|
||||
|
||||
@@ -24,4 +24,9 @@ extension ListEmailHeaderExtension on Set<EmailHeader>? {
|
||||
logger.log('ListEmailHeaderExtension::sMimeStatus: $sMimeStatus');
|
||||
return sMimeStatus?.value.trim() ?? '';
|
||||
}
|
||||
|
||||
String get listPost {
|
||||
final listPost = this?.firstWhereOrNull((header) => header.name == EmailProperty.headerListPostKey);
|
||||
return listPost?.value ?? '';
|
||||
}
|
||||
}
|
||||
@@ -6,11 +6,9 @@ import 'package:core/presentation/extensions/color_extension.dart';
|
||||
import 'package:core/utils/app_logger.dart';
|
||||
import 'package:http_parser/http_parser.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/email/email.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/keyword_identifier.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
|
||||
import 'package:model/email/email_action_type.dart';
|
||||
import 'package:model/email/eml_attachment.dart';
|
||||
import 'package:model/email/presentation_email.dart';
|
||||
import 'package:model/extensions/email_address_extension.dart';
|
||||
@@ -133,30 +131,6 @@ extension PresentationEmailExtension on PresentationEmail {
|
||||
return allEmailAddress.isNotEmpty ? allEmailAddress.join(', ') : '';
|
||||
}
|
||||
|
||||
Tuple3<List<EmailAddress>, List<EmailAddress>, List<EmailAddress>> generateRecipientsEmailAddressForComposer({
|
||||
required EmailActionType emailActionType,
|
||||
Role? mailboxRole
|
||||
}) {
|
||||
switch(emailActionType) {
|
||||
case EmailActionType.reply:
|
||||
if (mailboxRole == PresentationMailbox.roleSent) {
|
||||
return Tuple3(to.asList(), [], []);
|
||||
} else {
|
||||
final replyToAddress = replyTo.asList().isNotEmpty ? replyTo.asList() : from.asList();
|
||||
return Tuple3(replyToAddress, [], []);
|
||||
}
|
||||
case EmailActionType.replyAll:
|
||||
if (mailboxRole == PresentationMailbox.roleSent) {
|
||||
return Tuple3(to.asList(), cc.asList(), bcc.asList());
|
||||
} else {
|
||||
final senderReplyToAddress = replyTo.asList().isNotEmpty ? replyTo.asList() : from.asList();
|
||||
return Tuple3(to.asList() + senderReplyToAddress, cc.asList(), bcc.asList());
|
||||
}
|
||||
default:
|
||||
return Tuple3(to.asList(), cc.asList(), bcc.asList());
|
||||
}
|
||||
}
|
||||
|
||||
PresentationEmail toSearchPresentationEmail(Map<MailboxId, PresentationMailbox> mapMailboxes) {
|
||||
mailboxIds?.removeWhere((key, value) => !value);
|
||||
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:model/extensions/list_email_address_extension.dart';
|
||||
import 'package:tmail_ui_user/features/email/presentation/utils/email_utils.dart';
|
||||
|
||||
void main() {
|
||||
group('parsing email list post test', () {
|
||||
test('parsingListPost returns null for empty input', () {
|
||||
expect(EmailUtils.parsingListPost(''), isNull);
|
||||
});
|
||||
|
||||
test('parsingListPost returns null for input without links', () {
|
||||
expect(EmailUtils.parsingListPost('Some text without links'), isNull);
|
||||
});
|
||||
|
||||
test('parsingListPost parses mailto links', () {
|
||||
final listEmailAddress =
|
||||
EmailUtils.parsingListPost('<mailto:user@example.com>');
|
||||
expect(listEmailAddress, isNotNull);
|
||||
expect(listEmailAddress![0].email, contains('user@example.com'));
|
||||
});
|
||||
|
||||
test('parsingListPost parses both mailto without <>', () {
|
||||
final listEmailAddress =
|
||||
EmailUtils.parsingListPost('mailto:support@example.com');
|
||||
expect(listEmailAddress, isNotNull);
|
||||
expect(listEmailAddress![0].email, contains('support@example.com'));
|
||||
});
|
||||
|
||||
test('parsingListPost parses more mailto', () {
|
||||
final listEmailAddress = EmailUtils.parsingListPost(
|
||||
'<mailto:support@example.com>, <mailto:support@example2.com>, <mailto:support@example3.com>');
|
||||
expect(listEmailAddress, isNotNull);
|
||||
expect(listEmailAddress!.length, equals(3));
|
||||
expect(
|
||||
listEmailAddress.asSetAddress(),
|
||||
containsAll({
|
||||
'support@example.com',
|
||||
'support@example2.com',
|
||||
'support@example3.com'
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
test('parsingListPost returns null for input with invalid links', () {
|
||||
expect(EmailUtils.parsingListPost('Invalid link: invalid'), isNull);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -3,8 +3,9 @@ import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:jmap_dart_client/jmap/mail/email/email_address.dart';
|
||||
import 'package:model/email/email_action_type.dart';
|
||||
import 'package:model/email/presentation_email.dart';
|
||||
import 'package:model/extensions/presentation_email_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';
|
||||
|
||||
void main() {
|
||||
group('presentation email extension test', () {
|
||||
@@ -14,6 +15,7 @@ void main() {
|
||||
final userDEmailAddress = EmailAddress('User D', 'userD@domain.com');
|
||||
final userEEmailAddress = EmailAddress('User E', 'userE@domain.com');
|
||||
final replyToEmailAddress = EmailAddress('Reply To', 'replyToThis@domain.com');
|
||||
final replyToListEmailAddress = EmailAddress(null, 'replyToList@domain.com');
|
||||
|
||||
group('GIVEN user A is the sender AND send an email to user B and user E, cc to user C, bcc to user D', () {
|
||||
test('THEN user A click reply, generateRecipientsEmailAddressForComposer SHOULD return user B email + user E email to reply', () {
|
||||
@@ -141,6 +143,31 @@ void main() {
|
||||
expect(result.value2, containsAll(expectedResult.value2));
|
||||
expect(result.value3, containsAll(expectedResult.value3));
|
||||
});
|
||||
|
||||
test(
|
||||
'THEN user A click reply to list, generateRecipientsEmailAddressForComposer\n'
|
||||
'SHOULD return email address in mailto of List-Post to reply\n',
|
||||
() {
|
||||
final expectedResult = Tuple3([replyToListEmailAddress], [], []);
|
||||
|
||||
final emailToReplyToList = PresentationEmail(
|
||||
from: {userBEmailAddress},
|
||||
replyTo: {replyToEmailAddress},
|
||||
to: {userAEmailAddress, userEEmailAddress},
|
||||
cc: {userCEmailAddress},
|
||||
bcc: {userDEmailAddress},
|
||||
);
|
||||
|
||||
final result = emailToReplyToList.generateRecipientsEmailAddressForComposer(
|
||||
emailActionType: EmailActionType.replyToList,
|
||||
mailboxRole: PresentationMailbox.roleInbox,
|
||||
listPost: '<mailto:${replyToListEmailAddress.emailAddress}>',
|
||||
);
|
||||
|
||||
expect(result.value1, containsAll(expectedResult.value1));
|
||||
expect(result.value2, containsAll(expectedResult.value2));
|
||||
expect(result.value3, containsAll(expectedResult.value3));
|
||||
});
|
||||
});
|
||||
|
||||
group('Given user A is the sender AND send an email to user B + user E, cc to user C, bcc to user D THEN user B click forward', () {
|
||||
|
||||
Reference in New Issue
Block a user