TF-2168 Fix mailto invalid recipient
(cherry picked from commit c559daeb1029c96103e3bca951317d878a837a5c)
This commit is contained in:
@@ -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];
|
||||||
}
|
}
|
||||||
@@ -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,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -14,7 +14,7 @@ enum EmailActionType {
|
|||||||
composeFromContentShared,
|
composeFromContentShared,
|
||||||
composeFromFileShared,
|
composeFromFileShared,
|
||||||
composeFromEmailAddress,
|
composeFromEmailAddress,
|
||||||
composeFromMailtoURL,
|
composeFromMailtoUri,
|
||||||
reopenComposerBrowser,
|
reopenComposerBrowser,
|
||||||
moveToTrash,
|
moveToTrash,
|
||||||
deletePermanently,
|
deletePermanently,
|
||||||
|
|||||||
Reference in New Issue
Block a user