Hot fix cannot send email on cyrus server when the first open app

Signed-off-by: dab246 <tdvu@linagora.com>
This commit is contained in:
dab246
2025-02-21 16:59:14 +07:00
committed by Dat H. Pham
parent 78dffe90b6
commit a8cc19ada2
13 changed files with 138 additions and 92 deletions
@@ -6,9 +6,7 @@ import 'package:tmail_ui_user/features/composer/presentation/composer_controller
extension GetOutboxMailboxIdForComposerExtension on ComposerController {
MailboxId? getOutboxMailboxIdForComposer() {
final defaultOutboxMailbox = mailboxDashBoardController.mapDefaultMailboxIdByRole[
PresentationMailbox.roleOutbox
];
final defaultOutboxMailboxId = mailboxDashBoardController.outboxMailbox?.mailboxId;
final lowercaseOutboxRole = PresentationMailbox.roleOutbox.value.toLowerCase();
return mailboxDashBoardController.mapMailboxById.entries
@@ -17,6 +15,6 @@ extension GetOutboxMailboxIdForComposerExtension on ComposerController {
return mailbox.emailTeamMailBoxes == identitySelected.value?.email &&
mailbox.name?.name.toLowerCase() == lowercaseOutboxRole;
})
?.key ?? defaultOutboxMailbox;
?.key ?? defaultOutboxMailboxId;
}
}
@@ -174,7 +174,8 @@ class EmailAPI with HandleSetErrorMixin {
final emailSubmissionId = EmailSubmissionId(ReferenceId(ReferencePrefix.defaultPrefix, submissionCreateId));
Map<EmailSubmissionId, PatchObject> mapEmailSubmissionUpdated = {
emailSubmissionId: PatchObject({
emailRequest.sentMailboxId!.generatePath() : true,
if (emailRequest.sentMailboxId != null)
emailRequest.sentMailboxId!.generatePath() : true,
outboxMailboxId!.generatePath() : null,
KeyWordIdentifier.emailSeen.generatePath(): true,
KeyWordIdentifier.emailDraft.generatePath(): null
@@ -52,9 +52,9 @@ abstract class MailboxDataSource {
Future<bool> handleMailboxRightRequest(Session session, AccountId accountId, MailboxRightRequest request);
Future<List<Mailbox>> createDefaultMailbox(Session session, AccountId accountId, List<Role> listRole);
Future<(List<Mailbox> mailboxes, Map<Id, SetError> mapErrors)> createDefaultMailbox(Session session, AccountId accountId, List<Role> listRole);
Future<void> setRoleDefaultMailbox(Session session, AccountId accountId, List<Mailbox> listMailbox);
Future<(List<Mailbox> mailboxes, Map<Id, SetError> mapErrors)> setRoleDefaultMailbox(Session session, AccountId accountId, List<Mailbox> listMailbox);
Future<GetMailboxByRoleResponse> getMailboxByRole(Session session, AccountId accountId, Role role);
@@ -141,12 +141,12 @@ class MailboxCacheDataSourceImpl extends MailboxDataSource {
}
@override
Future<List<Mailbox>> createDefaultMailbox(Session session, AccountId accountId, List<Role> listRole) {
Future<(List<Mailbox> mailboxes, Map<Id, SetError> mapErrors)> createDefaultMailbox(Session session, AccountId accountId, List<Role> listRole) {
throw UnimplementedError();
}
@override
Future<List<MailboxId>> setRoleDefaultMailbox(Session session, AccountId accountId, List<Mailbox> listMailbox) {
Future<(List<Mailbox> mailboxes, Map<Id, SetError> mapErrors)> setRoleDefaultMailbox(Session session, AccountId accountId, List<Mailbox> listMailbox) {
throw UnimplementedError();
}
@@ -130,14 +130,14 @@ class MailboxDataSourceImpl extends MailboxDataSource {
}
@override
Future<List<Mailbox>> createDefaultMailbox(Session session, AccountId accountId, List<Role> listRole) {
Future<(List<Mailbox> mailboxes, Map<Id, SetError> mapErrors)> createDefaultMailbox(Session session, AccountId accountId, List<Role> listRole) {
return Future.sync(() async {
return await mailboxAPI.createDefaultMailbox(session, accountId, listRole);
}).catchError(_exceptionThrower.throwException);
}
@override
Future<void> setRoleDefaultMailbox(Session session, AccountId accountId, List<Mailbox> listMailbox) {
Future<(List<Mailbox> mailboxes, Map<Id, SetError> mapErrors)> setRoleDefaultMailbox(Session session, AccountId accountId, List<Mailbox> listMailbox) {
return Future.sync(() async {
return await mailboxAPI.setRoleDefaultMailbox(session, accountId, listMailbox);
}).catchError(_exceptionThrower.throwException);
@@ -34,7 +34,6 @@ import 'package:tmail_ui_user/features/base/mixin/handle_error_mixin.dart';
import 'package:tmail_ui_user/features/composer/domain/exceptions/set_method_exception.dart';
import 'package:tmail_ui_user/features/mailbox/data/model/mailbox_change_response.dart';
import 'package:tmail_ui_user/features/mailbox/domain/exceptions/mailbox_exception.dart';
import 'package:tmail_ui_user/features/mailbox/domain/exceptions/set_mailbox_method_exception.dart';
import 'package:tmail_ui_user/features/mailbox/domain/exceptions/set_mailbox_rights_exception.dart';
import 'package:tmail_ui_user/features/mailbox/domain/extensions/list_mailbox_id_extension.dart';
import 'package:tmail_ui_user/features/mailbox/domain/extensions/role_extension.dart';
@@ -454,19 +453,19 @@ class MailboxAPI with HandleSetErrorMixin {
}
}
Future<List<Mailbox>> createDefaultMailbox(
Future<(List<Mailbox> mailboxes, Map<Id, SetError> mapErrors)> createDefaultMailbox(
Session session,
AccountId accountId,
List<Role> listRole
) async {
final mapId = {
final mapRoles = {
for (var role in listRole)
Id(_uuid.v1()) : role
};
final mapCreate = {
for (var id in mapId.keys)
id : Mailbox(name: MailboxName(mapId[id]!.mailboxName), isSubscribed: IsSubscribed(true))
for (var id in mapRoles.keys)
id : Mailbox(name: MailboxName(mapRoles[id]!.mailboxName), isSubscribed: IsSubscribed(true))
};
final setMailboxMethodForCreate = SetMailboxMethod(accountId)
@@ -488,53 +487,40 @@ class MailboxAPI with HandleSetErrorMixin {
);
final mapErrors = handleSetResponse([createResponse]);
final mapMailboxCreated = createResponse?.created ?? <Id, Mailbox>{};
if (mapErrors.isNotEmpty) {
throw SetMailboxMethodException(mapErrors);
} else {
final mapMailboxCreated = createResponse?.created ?? <Id, Mailbox>{};
log('MailboxAPI::createDefaultMailbox:mapMailboxCreated: $mapMailboxCreated');
final listMailboxCreated = _convertMapToListMailbox(
mapRoles: mapId,
mapMailboxName: mapCreate,
mapMailboxCreated: mapMailboxCreated
);
log('MailboxAPI::createDefaultMailbox:listMailboxCreated: ${listMailboxCreated.length}');
if (listMailboxCreated.isEmpty) {
throw NotFoundMailboxCreatedException();
} else {
return listMailboxCreated;
}
}
final listMailboxCreated = _convertMapToListMailbox(
mapRoles: mapRoles,
mapMailboxName: mapCreate,
mapMailboxCreated: mapMailboxCreated,
);
return (listMailboxCreated, mapErrors);
}
List<Mailbox> _convertMapToListMailbox({
required Map<Id, Role> mapRoles,
required Map<Id, Mailbox> mapMailboxName,
required Map<Id, Mailbox> mapMailboxCreated
required Map<Id, Mailbox> mapMailboxCreated,
}) {
return mapRoles.keys
.where((key) => mapMailboxCreated.containsKey(key))
.map((key) {
final mailboxName = mapMailboxName[key]?.name;
final mailboxRole = mapRoles[key];
if (mailboxName != null && mailboxRole != null) {
return mapMailboxCreated[key]?.toMailbox(
mailboxName,
mailboxRole: mailboxRole
);
} else {
return null;
}
return mapMailboxCreated
.entries
.map((mailboxEntry) {
final id = mailboxEntry.key;
final mailbox = mailboxEntry.value;
return mailbox.copyWith(
name: mapMailboxName[id]?.name,
role: mapRoles[id],
isSubscribed: IsSubscribed(true),
);
})
.whereNotNull()
.toList();
}
Future<void> setRoleDefaultMailbox(
Future<(List<Mailbox> mailboxes, Map<Id, SetError> mapErrors)> setRoleDefaultMailbox(
Session session,
AccountId accountId,
List<Mailbox> listMailbox
List<Mailbox> listMailbox,
) async {
final mapUpdated = {
for (var mailbox in listMailbox)
@@ -560,9 +546,27 @@ class MailboxAPI with HandleSetErrorMixin {
);
final mapErrors = handleSetResponse([updateResponse]);
if (mapErrors.isNotEmpty) {
throw SetMailboxMethodException(mapErrors);
final listUpdatedMailboxId = updateResponse?.updated?.keys ?? [];
if (listUpdatedMailboxId.isEmpty) {
final listMailboxWithoutRole = listMailbox
.map((mailbox) => mailbox.toMailboxWithoutRole())
.toList();
return (listMailboxWithoutRole, mapErrors);
}
final listUpdatedMailbox = listMailbox
.map((mailbox) {
if (listUpdatedMailboxId.contains(mailbox.id!.id)) {
return mailbox;
} else {
return mailbox.toMailboxWithoutRole();
}
})
.toList();
return (listUpdatedMailbox, mapErrors);
}
Future<GetMailboxByRoleResponse> getMailboxByRole(
@@ -292,12 +292,12 @@ class MailboxRepositoryImpl extends MailboxRepository {
}
@override
Future<List<Mailbox>> createDefaultMailbox(Session session, AccountId accountId, List<Role> listRole) {
Future<(List<Mailbox> mailboxes, Map<Id, SetError> mapErrors)> createDefaultMailbox(Session session, AccountId accountId, List<Role> listRole) {
return mapDataSource[DataSourceType.network]!.createDefaultMailbox(session, accountId, listRole);
}
@override
Future<void> setRoleDefaultMailbox(Session session, AccountId accountId, List<Mailbox> listMailbox) {
Future<(List<Mailbox> mailboxes, Map<Id, SetError> mapErrors)> setRoleDefaultMailbox(Session session, AccountId accountId, List<Mailbox> listMailbox) {
return mapDataSource[DataSourceType.network]!.setRoleDefaultMailbox(session, accountId, listMailbox);
}
@@ -1,14 +1,3 @@
import 'package:jmap_dart_client/jmap/core/error/set_error.dart';
import 'package:jmap_dart_client/jmap/core/id.dart';
class SetMailboxMethodException implements Exception {
final Map<Id, SetError> mapErrors;
SetMailboxMethodException(this.mapErrors);
}
class NotFoundMailboxCreatedException implements Exception {}
class NotFoundMailboxUpdatedRoleException implements Exception {}
@@ -49,9 +49,9 @@ abstract class MailboxRepository {
Future<bool> handleMailboxRightRequest(Session session, AccountId accountId, MailboxRightRequest request);
Future<List<Mailbox>> createDefaultMailbox(Session session, AccountId accountId, List<Role> listRole);
Future<(List<Mailbox> mailboxes, Map<Id, SetError> mapErrors)> createDefaultMailbox(Session session, AccountId accountId, List<Role> listRole);
Future<void> setRoleDefaultMailbox(Session session, AccountId accountId, List<Mailbox> listMailbox);
Future<(List<Mailbox> mailboxes, Map<Id, SetError> mapErrors)> setRoleDefaultMailbox(Session session, AccountId accountId, List<Mailbox> listMailbox);
Future<GetMailboxByRoleResponse> getMailboxByRole(Session session, AccountId accountId, Role role, {UnsignedInt? limit});
}
@@ -1,25 +1,20 @@
import 'package:core/presentation/state/failure.dart';
import 'package:core/presentation/state/success.dart';
import 'package:tmail_ui_user/features/base/state/ui_action_state.dart';
import 'package:jmap_dart_client/jmap/core/state.dart' as jmap;
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
class CreateDefaultMailboxLoading extends LoadingState {}
class CreateDefaultMailboxAllSuccess extends UIActionState {
CreateDefaultMailboxAllSuccess({
jmap.State? currentEmailState,
jmap.State? currentMailboxState,
}) : super(currentEmailState, currentMailboxState);
class CreateDefaultMailboxAllSuccess extends UIState {
final List<Mailbox> listMailbox;
CreateDefaultMailboxAllSuccess(this.listMailbox);
@override
List<Object?> get props => [...super.props];
List<Object?> get props => [listMailbox];
}
class CreateDefaultMailboxFailure extends FeatureFailure {
final jmap.State? currentMailboxState;
CreateDefaultMailboxFailure(this.currentMailboxState, dynamic exception) : super(exception: exception);
@override
List<Object?> get props => [currentMailboxState, exception];
CreateDefaultMailboxFailure(dynamic exception) : super(exception: exception);
}
@@ -4,8 +4,8 @@ import 'package:core/utils/app_logger.dart';
import 'package:dartz/dartz.dart' as dartz;
import 'package:jmap_dart_client/jmap/account_id.dart';
import 'package:jmap_dart_client/jmap/core/session/session.dart';
import 'package:jmap_dart_client/jmap/core/state.dart';
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
import 'package:tmail_ui_user/features/mailbox/domain/exceptions/set_mailbox_method_exception.dart';
import 'package:tmail_ui_user/features/mailbox/domain/repository/mailbox_repository.dart';
import 'package:tmail_ui_user/features/mailbox/domain/state/create_default_mailbox_state.dart';
@@ -19,32 +19,48 @@ class CreateDefaultMailboxInteractor {
AccountId accountId,
List<Role> listRole
) async* {
final currentMailboxState = await _getCurrentMailboxState(session, accountId);
try {
yield dartz.Right<Failure, Success>(CreateDefaultMailboxLoading());
final listMailboxCreated = await _mailboxRepository.createDefaultMailbox(
final mailboxesRecord = await _mailboxRepository.createDefaultMailbox(
session,
accountId,
listRole
);
await _mailboxRepository.setRoleDefaultMailbox(
final listMailboxCreated = mailboxesRecord.$1;
log('CreateDefaultMailboxInteractor::execute:listMailboxCreated = $listMailboxCreated');
if (listMailboxCreated.isEmpty) {
yield dartz.Left<Failure, Success>(CreateDefaultMailboxFailure(NotFoundMailboxCreatedException()));
return;
}
final listMailboxUpdated = await _updateRoleToListMailbox(
session,
accountId,
listMailboxCreated
listMailboxCreated,
);
yield dartz.Right<Failure, Success>(CreateDefaultMailboxAllSuccess(currentMailboxState: currentMailboxState));
yield dartz.Right<Failure, Success>(CreateDefaultMailboxAllSuccess(listMailboxUpdated));
} catch (e) {
yield dartz.Left<Failure, Success>(CreateDefaultMailboxFailure(currentMailboxState, e));
yield dartz.Left<Failure, Success>(CreateDefaultMailboxFailure(e));
}
}
Future<State?> _getCurrentMailboxState(Session session, AccountId accountId) async {
Future<List<Mailbox>> _updateRoleToListMailbox(
Session session,
AccountId accountId,
List<Mailbox> mailboxes,
) async {
try {
final currentMailboxState = await _mailboxRepository.getMailboxState(session, accountId);
log('CreateDefaultMailboxInteractor::_getCurrentMailboxState:currentMailboxState: $currentMailboxState');
return currentMailboxState;
final mailboxUpdatedRecord = await _mailboxRepository.setRoleDefaultMailbox(
session,
accountId,
mailboxes,
);
return mailboxUpdatedRecord.$1;
} catch (e) {
return null;
logError('CreateDefaultMailboxInteractor::_updateRoleToListMailbox:Exception = $e');
return mailboxes;
}
}
}
@@ -45,6 +45,7 @@ import 'package:tmail_ui_user/features/mailbox/domain/model/mailbox_right_reques
import 'package:tmail_ui_user/features/mailbox/domain/model/subscribe_mailbox_request.dart';
import 'package:tmail_ui_user/features/mailbox/domain/model/subscribe_multiple_mailbox_request.dart';
import 'package:tmail_ui_user/features/mailbox/domain/model/subscribe_request.dart';
import 'package:tmail_ui_user/features/mailbox/domain/state/create_default_mailbox_state.dart';
import 'package:tmail_ui_user/features/mailbox/domain/state/create_new_mailbox_state.dart';
import 'package:tmail_ui_user/features/mailbox/domain/state/delete_multiple_mailbox_state.dart';
import 'package:tmail_ui_user/features/mailbox/domain/state/get_all_mailboxes_state.dart';
@@ -203,6 +204,8 @@ class MailboxController extends BaseMailboxController
_handleUnsubscribeMultipleMailboxHasSomeSuccess(success);
} else if (success is SubaddressingSuccess) {
_handleSubaddressingSuccess(success);
} else if (success is CreateDefaultMailboxAllSuccess) {
_handleCreateDefaultFolderIfMissingSuccess(success);
}
}
@@ -657,6 +660,28 @@ class MailboxController extends BaseMailboxController
}
}
Future<void> _handleCreateDefaultFolderIfMissingSuccess(CreateDefaultMailboxAllSuccess success) async {
if (success.listMailbox.isEmpty) return;
Set<Role?> existingRoles = {};
Set<MailboxName> existingNamesWithoutParent = {};
for (var mailbox in success.listMailbox) {
if (mailbox.role != null && !existingRoles.add(mailbox.role)) continue;
if (mailbox.parentId == null && mailbox.name != null && !existingNamesWithoutParent.add(mailbox.name!)) continue;
allMailboxes.add(mailbox.toPresentationMailbox());
}
await buildTree(allMailboxes);
if (currentContext != null) {
syncAllMailboxWithDisplayName(currentContext!);
}
_setMapMailbox();
_setOutboxMailbox();
}
void _handleDataFromNavigationRouter() {
log('MailboxController::_handleDataFromNavigationRouter():navigationRouter: $_navigationRouter');
if (!PlatformInfo.isWeb || _navigationRouter == null) {
@@ -56,6 +56,24 @@ extension MailboxExtension on Mailbox {
);
}
Mailbox toMailboxWithoutRole() {
return Mailbox(
id: id,
name: name,
parentId: parentId,
role: null,
sortOrder: sortOrder,
totalEmails: totalEmails,
unreadEmails: unreadEmails,
totalThreads: totalThreads,
unreadThreads: unreadThreads,
myRights: myRights,
isSubscribed: isSubscribed,
namespace: namespace,
rights: rights,
);
}
Mailbox toMailbox(MailboxName mailboxName, {MailboxId? parentId, Role? mailboxRole}) {
return Mailbox(
id: id,