TF-2168 Fix mailto invalid recipient

(cherry picked from commit c559daeb1029c96103e3bca951317d878a837a5c)
This commit is contained in:
dab246
2023-09-26 16:50:55 +07:00
committed by Dat H. Pham
parent 92dc0dbe7e
commit 6710702924
8 changed files with 91 additions and 39 deletions
@@ -440,14 +440,16 @@ class ComposerController extends BaseController {
toAddressExpandMode.value = ExpandMode.COLLAPSE; toAddressExpandMode.value = ExpandMode.COLLAPSE;
_updateStatusEmailSendButton(); _updateStatusEmailSendButton();
break; break;
case EmailActionType.composeFromMailtoURL: case EmailActionType.composeFromMailtoUri:
if (GetUtils.isEmail(arguments.uri ?? '')) { if (arguments.subject != null) {
listToEmailAddress.add(EmailAddress(null, arguments.uri)); setSubjectEmail(arguments.subject!);
} else { subjectEmailInputController.text = arguments.subject!;
listToEmailAddress.add(EmailAddress(null, 'invalid')); }
if (arguments.emailAddress != null) {
listToEmailAddress.add(arguments.emailAddress!);
isInitialRecipient.value = true;
toAddressExpandMode.value = ExpandMode.COLLAPSE;
} }
isInitialRecipient.value = true;
toAddressExpandMode.value = ExpandMode.COLLAPSE;
_updateStatusEmailSendButton(); _updateStatusEmailSendButton();
break; break;
case EmailActionType.reply: case EmailActionType.reply:
@@ -16,7 +16,7 @@ class ComposerArguments extends RouterArguments {
final List<Attachment>? attachments; final List<Attachment>? attachments;
final Role? mailboxRole; final Role? mailboxRole;
final SendingEmail? sendingEmail; final SendingEmail? sendingEmail;
final String? uri; final String? subject;
final MessageIdsHeaderValue? messageId; final MessageIdsHeaderValue? messageId;
final MessageIdsHeaderValue? references; final MessageIdsHeaderValue? references;
@@ -29,7 +29,7 @@ class ComposerArguments extends RouterArguments {
this.emailAddress, this.emailAddress,
this.listSharedMediaFile, this.listSharedMediaFile,
this.sendingEmail, this.sendingEmail,
this.uri, this.subject,
this.messageId, this.messageId,
this.references, this.references,
}); });
@@ -58,10 +58,11 @@ class ComposerArguments extends RouterArguments {
emailAddress: emailAddress emailAddress: emailAddress
); );
factory ComposerArguments.fromMailtoURL(String? uri) => factory ComposerArguments.fromMailtoUri({EmailAddress? emailAddress, String? subject}) =>
ComposerArguments( ComposerArguments(
emailActionType: EmailActionType.composeFromMailtoURL, emailActionType: EmailActionType.composeFromMailtoUri,
uri: uri emailAddress: emailAddress,
subject: subject,
); );
factory ComposerArguments.editDraftEmail(PresentationEmail presentationEmail) => factory ComposerArguments.editDraftEmail(PresentationEmail presentationEmail) =>
@@ -140,7 +141,7 @@ class ComposerArguments extends RouterArguments {
emailAddress, emailAddress,
listSharedMediaFile, listSharedMediaFile,
sendingEmail, sendingEmail,
uri, subject,
messageId, messageId,
references, references,
]; ];
@@ -405,7 +405,10 @@ class MailboxController extends BaseMailboxController with MailboxActionHandlerM
if (isHasDataFromRoute) { if (isHasDataFromRoute) {
if (isRedirectToMailtoURL) { if (isRedirectToMailtoURL) {
mailboxDashBoardController.goToComposer( mailboxDashBoardController.goToComposer(
ComposerArguments.fromMailtoURL(navigationRouter?.emailAddress) ComposerArguments.fromMailtoUri(
emailAddress: navigationRouter?.emailAddress,
subject: navigationRouter?.subject
)
); );
} }
@@ -39,7 +39,7 @@ class MailtoUrlController extends ReloadableController {
if (parameters.containsKey('uri')) { if (parameters.containsKey('uri')) {
final mailtoArgument = MailtoArguments( final mailtoArgument = MailtoArguments(
session: session, session: session,
emailAddress: parameters['uri'] mailtoUri: parameters['uri']
); );
popAndPush( popAndPush(
RouteUtils.generateNavigationRoute( RouteUtils.generateNavigationRoute(
@@ -1,22 +1,17 @@
import 'package:jmap_dart_client/jmap/core/session/session.dart'; import 'package:jmap_dart_client/jmap/core/session/session.dart';
import 'package:tmail_ui_user/main/routes/app_routes.dart'; import 'package:tmail_ui_user/main/routes/route_utils.dart';
import 'package:tmail_ui_user/main/routes/router_arguments.dart'; import 'package:tmail_ui_user/main/routes/router_arguments.dart';
class MailtoArguments extends RouterArguments { class MailtoArguments extends RouterArguments {
final Session session; final Session session;
final String? emailAddress; final String? mailtoUri;
MailtoArguments({required this.session, this.emailAddress}); MailtoArguments({required this.session, this.mailtoUri});
Map<String, String?> toMapRouter() { Map<String, String?> toMapRouter() => RouteUtils.parseMapMailtoFromUri(mailtoUri);
return {
'routeName': AppRoutes.mailtoURL,
'emailAddress': emailAddress
};
}
@override @override
List<Object?> get props => [session, emailAddress]; List<Object?> get props => [session, mailtoUri];
} }
+5 -1
View File
@@ -1,6 +1,7 @@
import 'package:equatable/equatable.dart'; import 'package:equatable/equatable.dart';
import 'package:jmap_dart_client/jmap/mail/email/email.dart'; import 'package:jmap_dart_client/jmap/mail/email/email.dart';
import 'package:jmap_dart_client/jmap/mail/email/email_address.dart';
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart'; import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
import 'package:tmail_ui_user/features/thread/domain/model/search_query.dart'; import 'package:tmail_ui_user/features/thread/domain/model/search_query.dart';
@@ -15,7 +16,8 @@ class NavigationRouter with EquatableMixin {
final DashboardType dashboardType; final DashboardType dashboardType;
final SearchQuery? searchQuery; final SearchQuery? searchQuery;
final String? routeName; final String? routeName;
final String? emailAddress; final EmailAddress? emailAddress;
final String? subject;
NavigationRouter({ NavigationRouter({
this.emailId, this.emailId,
@@ -24,6 +26,7 @@ class NavigationRouter with EquatableMixin {
this.dashboardType = DashboardType.normal, this.dashboardType = DashboardType.normal,
this.routeName, this.routeName,
this.emailAddress, this.emailAddress,
this.subject,
}); });
factory NavigationRouter.initial() => NavigationRouter(); factory NavigationRouter.initial() => NavigationRouter();
@@ -36,5 +39,6 @@ class NavigationRouter with EquatableMixin {
dashboardType, dashboardType,
routeName, routeName,
emailAddress, emailAddress,
subject,
]; ];
} }
+59 -12
View File
@@ -3,16 +3,31 @@ import 'package:core/data/model/query/query_parameter.dart';
import 'package:core/data/network/config/service_path.dart'; import 'package:core/data/network/config/service_path.dart';
import 'package:core/utils/app_logger.dart'; import 'package:core/utils/app_logger.dart';
import 'package:core/utils/platform_info.dart'; import 'package:core/utils/platform_info.dart';
import 'package:get/get.dart';
import 'package:jmap_dart_client/jmap/core/id.dart'; import 'package:jmap_dart_client/jmap/core/id.dart';
import 'package:jmap_dart_client/jmap/mail/email/email.dart'; import 'package:jmap_dart_client/jmap/mail/email/email.dart';
import 'package:jmap_dart_client/jmap/mail/email/email_address.dart';
import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart'; import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart';
import 'package:tmail_ui_user/features/login/data/extensions/service_path_extension.dart'; import 'package:tmail_ui_user/features/login/data/extensions/service_path_extension.dart';
import 'package:tmail_ui_user/features/thread/domain/model/search_query.dart'; import 'package:tmail_ui_user/features/thread/domain/model/search_query.dart';
import 'package:tmail_ui_user/main/routes/app_routes.dart';
import 'package:tmail_ui_user/main/routes/navigation_router.dart'; import 'package:tmail_ui_user/main/routes/navigation_router.dart';
import 'package:universal_html/html.dart' as html; import 'package:universal_html/html.dart' as html;
abstract class RouteUtils { abstract class RouteUtils {
static const String paramID = 'id';
static const String paramType = 'type';
static const String paramContext = 'context';
static const String paramQuery = 'q';
static const String paramRouteName = 'routeName';
static const String paramMailtoAddress = 'mailtoAddress';
static const String paramSubject = 'subject';
static const String mailtoPrefix = 'mailto:';
static const String INVALID_VALUE = 'invalid';
static String get baseOriginUrl => Uri.base.origin; static String get baseOriginUrl => Uri.base.origin;
static String get baseUrl => Uri.base.path; static String get baseUrl => Uri.base.path;
@@ -24,11 +39,11 @@ abstract class RouteUtils {
servicePath = servicePath.withPathParameter(router.emailId!.id.value); servicePath = servicePath.withPathParameter(router.emailId!.id.value);
} }
servicePath = servicePath.withQueryParameters([ servicePath = servicePath.withQueryParameters([
StringQueryParameter('type', router.dashboardType.name), StringQueryParameter(paramType, router.dashboardType.name),
if (router.mailboxId != null) if (router.mailboxId != null)
StringQueryParameter('context', router.mailboxId!.id.value), StringQueryParameter(paramContext, router.mailboxId!.id.value),
if (router.searchQuery != null) if (router.searchQuery != null)
StringQueryParameter('q', router.searchQuery!.value), StringQueryParameter(paramQuery, router.searchQuery!.value),
]); ]);
return servicePath.path; return servicePath.path;
} else { } else {
@@ -43,23 +58,24 @@ abstract class RouteUtils {
servicePath = servicePath.withPathParameter(router.emailId!.id.value); servicePath = servicePath.withPathParameter(router.emailId!.id.value);
} }
servicePath = servicePath.withQueryParameters([ servicePath = servicePath.withQueryParameters([
StringQueryParameter('type', router.dashboardType.name), StringQueryParameter(paramType, router.dashboardType.name),
if (router.mailboxId != null) if (router.mailboxId != null)
StringQueryParameter('context', router.mailboxId!.id.value), StringQueryParameter(paramContext, router.mailboxId!.id.value),
if (router.searchQuery != null) if (router.searchQuery != null)
StringQueryParameter('q', router.searchQuery!.value), StringQueryParameter(paramQuery, router.searchQuery!.value),
]); ]);
return Uri.parse(servicePath.path); return Uri.parse(servicePath.path);
} }
static NavigationRouter parsingRouteParametersToNavigationRouter(Map<String, String?> parameters) { static NavigationRouter parsingRouteParametersToNavigationRouter(Map<String, String?> parameters) {
final idParam = parameters['id']; final idParam = parameters[paramID];
final typeParam = parameters['type']; final typeParam = parameters[paramType];
final contextPram = parameters['context']; final contextPram = parameters[paramContext];
final queryParam = parameters['q']; final queryParam = parameters[paramQuery];
final routeName = parameters['routeName']; final routeName = parameters[paramRouteName];
final emailAddress = parameters['emailAddress']; final mailtoAddress = parameters[paramMailtoAddress];
final subject = parameters[paramSubject];
final emailId = idParam != null ? EmailId(Id(idParam)) : null; final emailId = idParam != null ? EmailId(Id(idParam)) : null;
final mailboxId = contextPram != null ? MailboxId(Id(contextPram)) : null; final mailboxId = contextPram != null ? MailboxId(Id(contextPram)) : null;
@@ -67,6 +83,9 @@ abstract class RouteUtils {
final dashboardType = typeParam == DashboardType.search.name final dashboardType = typeParam == DashboardType.search.name
? DashboardType.search ? DashboardType.search
: DashboardType.normal; : DashboardType.normal;
final emailAddress = mailtoAddress != null && GetUtils.isEmail(mailtoAddress)
? EmailAddress(null, mailtoAddress)
: EmailAddress(null, INVALID_VALUE);
return NavigationRouter( return NavigationRouter(
emailId: emailId, emailId: emailId,
@@ -75,6 +94,7 @@ abstract class RouteUtils {
dashboardType: dashboardType, dashboardType: dashboardType,
routeName: routeName, routeName: routeName,
emailAddress: emailAddress, emailAddress: emailAddress,
subject: subject,
); );
} }
@@ -83,4 +103,31 @@ abstract class RouteUtils {
log('RouteUtils::updateRouteOnBrowser(): newRoute: $newRoute'); log('RouteUtils::updateRouteOnBrowser(): newRoute: $newRoute');
html.window.history.replaceState(null, title, newRoute.toString()); html.window.history.replaceState(null, title, newRoute.toString());
} }
static Map<String, String?> parseMapMailtoFromUri(String? mailtoUri) {
log('RouteUtils::parseMapMailtoFromUri:mailtoUri: $mailtoUri');
final mapMailto = <String, String?>{
RouteUtils.paramRouteName: AppRoutes.mailtoURL,
};
if (mailtoUri?.startsWith(mailtoPrefix) == true) {
final mailtoUrlDecoded = Uri.decodeFull(mailtoUri!);
final uri = Uri.tryParse(mailtoUrlDecoded);
if (uri == null) return mapMailto;
final mailtoAddress = uri.path;
final mapQueryParam = uri.queryParameters;
mapMailto[paramMailtoAddress] = mailtoAddress;
if (mapQueryParam.containsKey(paramSubject)) {
mapMailto[paramSubject] = mapQueryParam[paramSubject];
}
} else if (mailtoUri != null) {
final mailtoUrlDecoded = Uri.decodeFull(mailtoUri);
mapMailto[paramMailtoAddress] = mailtoUrlDecoded;
} else {
mapMailto[paramMailtoAddress] = mailtoUri;
}
log('RouteUtils::parseMapMailtoFromUri:mapMailto: $mapMailto');
return mapMailto;
}
} }
+1 -1
View File
@@ -14,7 +14,7 @@ enum EmailActionType {
composeFromContentShared, composeFromContentShared,
composeFromFileShared, composeFromFileShared,
composeFromEmailAddress, composeFromEmailAddress,
composeFromMailtoURL, composeFromMailtoUri,
reopenComposerBrowser, reopenComposerBrowser,
moveToTrash, moveToTrash,
deletePermanently, deletePermanently,