From bfcdcc6ec1ede20b9be4a6ce9f0c599281b7215c Mon Sep 17 00:00:00 2001 From: paw Date: Tue, 3 Dec 2024 17:19:30 +0100 Subject: [PATCH] Add MailExportFacade and range request options Add a facade that handles mail exporting requests and tokens. Closes #7953 Co-authored-by: BijinDev --- src/common/api/entities/tutanota/ModelInfo.ts | 2 +- src/common/api/entities/tutanota/Services.ts | 11 + .../api/entities/tutanota/TypeModels.js | 308 +++++++++++------- src/common/api/entities/tutanota/TypeRefs.ts | 25 ++ .../worker/facades/lazy/MailExportFacade.ts | 132 ++++++++ src/mail-app/workerUtils/worker/WorkerImpl.ts | 6 + .../workerUtils/worker/WorkerLocator.ts | 6 + test/tests/Suite.ts | 1 + .../worker/facades/MailExportFacadeTest.ts | 121 +++++++ .../sdk/src/entities/generated/tutanota.rs | 32 ++ .../sdk/src/services/generated/tutanota.rs | 56 ++-- .../rust/sdk/src/type_models/tutanota.json | 308 +++++++++++------- 12 files changed, 741 insertions(+), 267 deletions(-) create mode 100644 src/common/api/worker/facades/lazy/MailExportFacade.ts create mode 100644 test/tests/api/worker/facades/MailExportFacadeTest.ts diff --git a/src/common/api/entities/tutanota/ModelInfo.ts b/src/common/api/entities/tutanota/ModelInfo.ts index 3f00db7b480d..acb8759087e1 100644 --- a/src/common/api/entities/tutanota/ModelInfo.ts +++ b/src/common/api/entities/tutanota/ModelInfo.ts @@ -1,5 +1,5 @@ const modelInfo = { - version: 77, + version: 78, compatibleSince: 77, } diff --git a/src/common/api/entities/tutanota/Services.ts b/src/common/api/entities/tutanota/Services.ts index e83f98ef79c0..006580b10b9c 100644 --- a/src/common/api/entities/tutanota/Services.ts +++ b/src/common/api/entities/tutanota/Services.ts @@ -16,6 +16,8 @@ import { GroupInvitationPostReturnTypeRef } from "./TypeRefs.js" import { GroupInvitationPutDataTypeRef } from "./TypeRefs.js" import { GroupInvitationDeleteDataTypeRef } from "./TypeRefs.js" import { ListUnsubscribeDataTypeRef } from "./TypeRefs.js" +import { MailExportTokenServicePostInTypeRef } from "./TypeRefs.js" +import { MailExportTokenServicePostOutTypeRef } from "./TypeRefs.js" import { CreateMailFolderDataTypeRef } from "./TypeRefs.js" import { CreateMailFolderReturnTypeRef } from "./TypeRefs.js" import { UpdateMailFolderDataTypeRef } from "./TypeRefs.js" @@ -128,6 +130,15 @@ export const ListUnsubscribeService = Object.freeze({ delete: null, } as const) +export const MailExportTokenService = Object.freeze({ + app: "tutanota", + name: "MailExportTokenService", + get: null, + post: { data: MailExportTokenServicePostInTypeRef, return: MailExportTokenServicePostOutTypeRef }, + put: null, + delete: null, +} as const) + export const MailFolderService = Object.freeze({ app: "tutanota", name: "MailFolderService", diff --git a/src/common/api/entities/tutanota/TypeModels.js b/src/common/api/entities/tutanota/TypeModels.js index 4420287d004e..994e001ecbb0 100644 --- a/src/common/api/entities/tutanota/TypeModels.js +++ b/src/common/api/entities/tutanota/TypeModels.js @@ -58,7 +58,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "AttachmentKeyData": { "name": "AttachmentKeyData", @@ -110,7 +110,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "Birthday": { "name": "Birthday", @@ -160,7 +160,7 @@ export const typeModels = { }, "associations": {}, "app": "tutanota", - "version": "77" + "version": "78" }, "Body": { "name": "Body", @@ -201,7 +201,7 @@ export const typeModels = { }, "associations": {}, "app": "tutanota", - "version": "77" + "version": "78" }, "CalendarDeleteData": { "name": "CalendarDeleteData", @@ -235,7 +235,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "CalendarEvent": { "name": "CalendarEvent", @@ -434,7 +434,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "CalendarEventAttendee": { "name": "CalendarEventAttendee", @@ -477,7 +477,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "CalendarEventIndexRef": { "name": "CalendarEventIndexRef", @@ -511,7 +511,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "CalendarEventUidIndex": { "name": "CalendarEventUidIndex", @@ -582,7 +582,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "CalendarEventUpdate": { "name": "CalendarEventUpdate", @@ -670,7 +670,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "CalendarEventUpdateList": { "name": "CalendarEventUpdateList", @@ -704,7 +704,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "CalendarGroupRoot": { "name": "CalendarGroupRoot", @@ -803,7 +803,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "CalendarRepeatRule": { "name": "CalendarRepeatRule", @@ -882,7 +882,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "Contact": { "name": "Contact", @@ -1205,7 +1205,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "ContactAddress": { "name": "ContactAddress", @@ -1255,7 +1255,7 @@ export const typeModels = { }, "associations": {}, "app": "tutanota", - "version": "77" + "version": "78" }, "ContactCustomDate": { "name": "ContactCustomDate", @@ -1305,7 +1305,7 @@ export const typeModels = { }, "associations": {}, "app": "tutanota", - "version": "77" + "version": "78" }, "ContactList": { "name": "ContactList", @@ -1394,7 +1394,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "ContactListEntry": { "name": "ContactListEntry", @@ -1471,7 +1471,7 @@ export const typeModels = { }, "associations": {}, "app": "tutanota", - "version": "77" + "version": "78" }, "ContactListGroupRoot": { "name": "ContactListGroupRoot", @@ -1550,7 +1550,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "ContactMailAddress": { "name": "ContactMailAddress", @@ -1600,7 +1600,7 @@ export const typeModels = { }, "associations": {}, "app": "tutanota", - "version": "77" + "version": "78" }, "ContactMessengerHandle": { "name": "ContactMessengerHandle", @@ -1650,7 +1650,7 @@ export const typeModels = { }, "associations": {}, "app": "tutanota", - "version": "77" + "version": "78" }, "ContactPhoneNumber": { "name": "ContactPhoneNumber", @@ -1700,7 +1700,7 @@ export const typeModels = { }, "associations": {}, "app": "tutanota", - "version": "77" + "version": "78" }, "ContactPronouns": { "name": "ContactPronouns", @@ -1741,7 +1741,7 @@ export const typeModels = { }, "associations": {}, "app": "tutanota", - "version": "77" + "version": "78" }, "ContactRelationship": { "name": "ContactRelationship", @@ -1791,7 +1791,7 @@ export const typeModels = { }, "associations": {}, "app": "tutanota", - "version": "77" + "version": "78" }, "ContactSocialId": { "name": "ContactSocialId", @@ -1841,7 +1841,7 @@ export const typeModels = { }, "associations": {}, "app": "tutanota", - "version": "77" + "version": "78" }, "ContactWebsite": { "name": "ContactWebsite", @@ -1891,7 +1891,7 @@ export const typeModels = { }, "associations": {}, "app": "tutanota", - "version": "77" + "version": "78" }, "ConversationEntry": { "name": "ConversationEntry", @@ -1980,7 +1980,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "CreateExternalUserGroupData": { "name": "CreateExternalUserGroupData", @@ -2039,7 +2039,7 @@ export const typeModels = { }, "associations": {}, "app": "tutanota", - "version": "77" + "version": "78" }, "CreateGroupPostReturn": { "name": "CreateGroupPostReturn", @@ -2073,7 +2073,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "CreateMailFolderData": { "name": "CreateMailFolderData", @@ -2143,7 +2143,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "CreateMailFolderReturn": { "name": "CreateMailFolderReturn", @@ -2177,7 +2177,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "CreateMailGroupData": { "name": "CreateMailGroupData", @@ -2238,7 +2238,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "CustomerAccountCreateData": { "name": "CustomerAccountCreateData", @@ -2410,7 +2410,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "DefaultAlarmInfo": { "name": "DefaultAlarmInfo", @@ -2442,7 +2442,7 @@ export const typeModels = { }, "associations": {}, "app": "tutanota", - "version": "77" + "version": "78" }, "DeleteGroupData": { "name": "DeleteGroupData", @@ -2485,7 +2485,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "DeleteMailData": { "name": "DeleteMailData", @@ -2529,7 +2529,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "DeleteMailFolderData": { "name": "DeleteMailFolderData", @@ -2563,7 +2563,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "DraftAttachment": { "name": "DraftAttachment", @@ -2625,7 +2625,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "DraftCreateData": { "name": "DraftCreateData", @@ -2695,7 +2695,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "DraftCreateReturn": { "name": "DraftCreateReturn", @@ -2729,7 +2729,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "DraftData": { "name": "DraftData", @@ -2876,7 +2876,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "DraftRecipient": { "name": "DraftRecipient", @@ -2917,7 +2917,7 @@ export const typeModels = { }, "associations": {}, "app": "tutanota", - "version": "77" + "version": "78" }, "DraftUpdateData": { "name": "DraftUpdateData", @@ -2961,7 +2961,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "DraftUpdateReturn": { "name": "DraftUpdateReturn", @@ -2995,7 +2995,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "EmailTemplate": { "name": "EmailTemplate", @@ -3092,7 +3092,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "EmailTemplateContent": { "name": "EmailTemplateContent", @@ -3133,7 +3133,7 @@ export const typeModels = { }, "associations": {}, "app": "tutanota", - "version": "77" + "version": "78" }, "EncryptTutanotaPropertiesData": { "name": "EncryptTutanotaPropertiesData", @@ -3185,7 +3185,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "EncryptedMailAddress": { "name": "EncryptedMailAddress", @@ -3226,7 +3226,7 @@ export const typeModels = { }, "associations": {}, "app": "tutanota", - "version": "77" + "version": "78" }, "EntropyData": { "name": "EntropyData", @@ -3267,7 +3267,7 @@ export const typeModels = { }, "associations": {}, "app": "tutanota", - "version": "77" + "version": "78" }, "ExternalUserData": { "name": "ExternalUserData", @@ -3400,7 +3400,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "File": { "name": "File", @@ -3535,7 +3535,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "FileSystem": { "name": "FileSystem", @@ -3614,7 +3614,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "GroupInvitationDeleteData": { "name": "GroupInvitationDeleteData", @@ -3648,7 +3648,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "GroupInvitationPostData": { "name": "GroupInvitationPostData", @@ -3692,7 +3692,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "GroupInvitationPostReturn": { "name": "GroupInvitationPostReturn", @@ -3746,7 +3746,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "GroupInvitationPutData": { "name": "GroupInvitationPutData", @@ -3816,7 +3816,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "GroupSettings": { "name": "GroupSettings", @@ -3887,7 +3887,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "Header": { "name": "Header", @@ -3928,7 +3928,7 @@ export const typeModels = { }, "associations": {}, "app": "tutanota", - "version": "77" + "version": "78" }, "ImapFolder": { "name": "ImapFolder", @@ -3989,7 +3989,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "ImapSyncConfiguration": { "name": "ImapSyncConfiguration", @@ -4059,7 +4059,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "ImapSyncState": { "name": "ImapSyncState", @@ -4120,7 +4120,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "InboxRule": { "name": "InboxRule", @@ -4172,7 +4172,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "InternalGroupData": { "name": "InternalGroupData", @@ -4296,7 +4296,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "InternalRecipientKeyData": { "name": "InternalRecipientKeyData", @@ -4364,7 +4364,7 @@ export const typeModels = { }, "associations": {}, "app": "tutanota", - "version": "77" + "version": "78" }, "KnowledgeBaseEntry": { "name": "KnowledgeBaseEntry", @@ -4461,7 +4461,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "KnowledgeBaseEntryKeyword": { "name": "KnowledgeBaseEntryKeyword", @@ -4493,7 +4493,7 @@ export const typeModels = { }, "associations": {}, "app": "tutanota", - "version": "77" + "version": "78" }, "ListUnsubscribeData": { "name": "ListUnsubscribeData", @@ -4545,7 +4545,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "Mail": { "name": "Mail", @@ -4820,7 +4820,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "MailAddress": { "name": "MailAddress", @@ -4872,7 +4872,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "MailAddressProperties": { "name": "MailAddressProperties", @@ -4913,7 +4913,7 @@ export const typeModels = { }, "associations": {}, "app": "tutanota", - "version": "77" + "version": "78" }, "MailBag": { "name": "MailBag", @@ -4947,7 +4947,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "MailBox": { "name": "MailBox", @@ -5095,7 +5095,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "MailDetails": { "name": "MailDetails", @@ -5177,7 +5177,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "MailDetailsBlob": { "name": "MailDetailsBlob", @@ -5256,7 +5256,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "MailDetailsDraft": { "name": "MailDetailsDraft", @@ -5335,7 +5335,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "MailDetailsDraftsRef": { "name": "MailDetailsDraftsRef", @@ -5369,7 +5369,73 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" + }, + "MailExportTokenServicePostIn": { + "name": "MailExportTokenServicePostIn", + "since": 78, + "type": "DATA_TRANSFER_TYPE", + "id": 1516, + "rootId": "CHR1dGFub3RhAAXs", + "versioned": false, + "encrypted": false, + "values": { + "_format": { + "final": false, + "name": "_format", + "id": 1517, + "since": 78, + "type": "Number", + "cardinality": "One", + "encrypted": false + } + }, + "associations": { + "mailGroup": { + "final": false, + "name": "mailGroup", + "id": 1518, + "since": 78, + "type": "ELEMENT_ASSOCIATION", + "cardinality": "One", + "refType": "Group", + "dependency": null + } + }, + "app": "tutanota", + "version": "78" + }, + "MailExportTokenServicePostOut": { + "name": "MailExportTokenServicePostOut", + "since": 78, + "type": "DATA_TRANSFER_TYPE", + "id": 1519, + "rootId": "CHR1dGFub3RhAAXv", + "versioned": false, + "encrypted": false, + "values": { + "_format": { + "final": false, + "name": "_format", + "id": 1520, + "since": 78, + "type": "Number", + "cardinality": "One", + "encrypted": false + }, + "mailExportToken": { + "final": false, + "name": "mailExportToken", + "id": 1521, + "since": 78, + "type": "String", + "cardinality": "One", + "encrypted": false + } + }, + "associations": {}, + "app": "tutanota", + "version": "78" }, "MailFolder": { "name": "MailFolder", @@ -5504,7 +5570,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "MailFolderRef": { "name": "MailFolderRef", @@ -5538,7 +5604,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "MailSetEntry": { "name": "MailSetEntry", @@ -5599,7 +5665,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "MailboxGroupRoot": { "name": "MailboxGroupRoot", @@ -5710,7 +5776,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "MailboxProperties": { "name": "MailboxProperties", @@ -5798,7 +5864,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "MailboxServerProperties": { "name": "MailboxServerProperties", @@ -5857,7 +5923,7 @@ export const typeModels = { }, "associations": {}, "app": "tutanota", - "version": "77" + "version": "78" }, "ManageLabelServiceDeleteIn": { "name": "ManageLabelServiceDeleteIn", @@ -5891,7 +5957,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "ManageLabelServiceLabelData": { "name": "ManageLabelServiceLabelData", @@ -5932,7 +5998,7 @@ export const typeModels = { }, "associations": {}, "app": "tutanota", - "version": "77" + "version": "78" }, "ManageLabelServicePostIn": { "name": "ManageLabelServicePostIn", @@ -5993,7 +6059,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "MoveMailData": { "name": "MoveMailData", @@ -6047,7 +6113,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "NewDraftAttachment": { "name": "NewDraftAttachment", @@ -6108,7 +6174,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "NewsId": { "name": "NewsId", @@ -6149,7 +6215,7 @@ export const typeModels = { }, "associations": {}, "app": "tutanota", - "version": "77" + "version": "78" }, "NewsIn": { "name": "NewsIn", @@ -6181,7 +6247,7 @@ export const typeModels = { }, "associations": {}, "app": "tutanota", - "version": "77" + "version": "78" }, "NewsOut": { "name": "NewsOut", @@ -6215,7 +6281,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "NotificationMail": { "name": "NotificationMail", @@ -6283,7 +6349,7 @@ export const typeModels = { }, "associations": {}, "app": "tutanota", - "version": "77" + "version": "78" }, "OutOfOfficeNotification": { "name": "OutOfOfficeNotification", @@ -6371,7 +6437,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "OutOfOfficeNotificationMessage": { "name": "OutOfOfficeNotificationMessage", @@ -6421,7 +6487,7 @@ export const typeModels = { }, "associations": {}, "app": "tutanota", - "version": "77" + "version": "78" }, "OutOfOfficeNotificationRecipientList": { "name": "OutOfOfficeNotificationRecipientList", @@ -6455,7 +6521,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "PhishingMarkerWebsocketData": { "name": "PhishingMarkerWebsocketData", @@ -6498,7 +6564,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "PhotosRef": { "name": "PhotosRef", @@ -6532,7 +6598,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "ReceiveInfoServiceData": { "name": "ReceiveInfoServiceData", @@ -6564,7 +6630,7 @@ export const typeModels = { }, "associations": {}, "app": "tutanota", - "version": "77" + "version": "78" }, "Recipients": { "name": "Recipients", @@ -6618,7 +6684,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "RemoteImapSyncInfo": { "name": "RemoteImapSyncInfo", @@ -6688,7 +6754,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "ReportMailPostData": { "name": "ReportMailPostData", @@ -6740,7 +6806,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "ReportedMailFieldMarker": { "name": "ReportedMailFieldMarker", @@ -6781,7 +6847,7 @@ export const typeModels = { }, "associations": {}, "app": "tutanota", - "version": "77" + "version": "78" }, "SecureExternalRecipientKeyData": { "name": "SecureExternalRecipientKeyData", @@ -6885,7 +6951,7 @@ export const typeModels = { }, "associations": {}, "app": "tutanota", - "version": "77" + "version": "78" }, "SendDraftData": { "name": "SendDraftData", @@ -7022,7 +7088,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "SendDraftReturn": { "name": "SendDraftReturn", @@ -7084,7 +7150,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "SharedGroupData": { "name": "SharedGroupData", @@ -7188,7 +7254,7 @@ export const typeModels = { }, "associations": {}, "app": "tutanota", - "version": "77" + "version": "78" }, "SimpleMoveMailPostIn": { "name": "SimpleMoveMailPostIn", @@ -7231,7 +7297,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "SpamResults": { "name": "SpamResults", @@ -7265,7 +7331,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "Subfiles": { "name": "Subfiles", @@ -7299,7 +7365,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "SymEncInternalRecipientKeyData": { "name": "SymEncInternalRecipientKeyData", @@ -7360,7 +7426,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "TemplateGroupRoot": { "name": "TemplateGroupRoot", @@ -7449,7 +7515,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "TranslationGetIn": { "name": "TranslationGetIn", @@ -7481,7 +7547,7 @@ export const typeModels = { }, "associations": {}, "app": "tutanota", - "version": "77" + "version": "78" }, "TranslationGetOut": { "name": "TranslationGetOut", @@ -7522,7 +7588,7 @@ export const typeModels = { }, "associations": {}, "app": "tutanota", - "version": "77" + "version": "78" }, "TutanotaProperties": { "name": "TutanotaProperties", @@ -7720,7 +7786,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "UnreadMailStatePostIn": { "name": "UnreadMailStatePostIn", @@ -7763,7 +7829,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "UpdateMailFolderData": { "name": "UpdateMailFolderData", @@ -7807,7 +7873,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "UserAccountCreateData": { "name": "UserAccountCreateData", @@ -7860,7 +7926,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "UserAccountUserData": { "name": "UserAccountUserData", @@ -8081,7 +8147,7 @@ export const typeModels = { }, "associations": {}, "app": "tutanota", - "version": "77" + "version": "78" }, "UserAreaGroupData": { "name": "UserAreaGroupData", @@ -8187,7 +8253,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "UserAreaGroupDeleteData": { "name": "UserAreaGroupDeleteData", @@ -8221,7 +8287,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "UserAreaGroupPostData": { "name": "UserAreaGroupPostData", @@ -8255,7 +8321,7 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" }, "UserSettingsGroupRoot": { "name": "UserSettingsGroupRoot", @@ -8361,6 +8427,6 @@ export const typeModels = { } }, "app": "tutanota", - "version": "77" + "version": "78" } } \ No newline at end of file diff --git a/src/common/api/entities/tutanota/TypeRefs.ts b/src/common/api/entities/tutanota/TypeRefs.ts index 3ed9a1d9e4ff..7985b23f90e5 100644 --- a/src/common/api/entities/tutanota/TypeRefs.ts +++ b/src/common/api/entities/tutanota/TypeRefs.ts @@ -1302,6 +1302,31 @@ export type MailDetailsDraftsRef = { list: Id; } +export const MailExportTokenServicePostInTypeRef: TypeRef = new TypeRef("tutanota", "MailExportTokenServicePostIn") + +export function createMailExportTokenServicePostIn(values: StrippedEntity): MailExportTokenServicePostIn { + return Object.assign(create(typeModels.MailExportTokenServicePostIn, MailExportTokenServicePostInTypeRef), values) +} + +export type MailExportTokenServicePostIn = { + _type: TypeRef; + + _format: NumberString; + + mailGroup: Id; +} +export const MailExportTokenServicePostOutTypeRef: TypeRef = new TypeRef("tutanota", "MailExportTokenServicePostOut") + +export function createMailExportTokenServicePostOut(values: StrippedEntity): MailExportTokenServicePostOut { + return Object.assign(create(typeModels.MailExportTokenServicePostOut, MailExportTokenServicePostOutTypeRef), values) +} + +export type MailExportTokenServicePostOut = { + _type: TypeRef; + + _format: NumberString; + mailExportToken: string; +} export const MailFolderTypeRef: TypeRef = new TypeRef("tutanota", "MailFolder") export function createMailFolder(values: StrippedEntity): MailFolder { diff --git a/src/common/api/worker/facades/lazy/MailExportFacade.ts b/src/common/api/worker/facades/lazy/MailExportFacade.ts new file mode 100644 index 000000000000..9d76674dc8f0 --- /dev/null +++ b/src/common/api/worker/facades/lazy/MailExportFacade.ts @@ -0,0 +1,132 @@ +import { MailExportTokenService } from "../../../entities/tutanota/Services" +import { createMailExportTokenServicePostIn } from "../../../entities/tutanota/TypeRefs" +import { assertWorkerOrNode } from "../../../common/Env" +import { IServiceExecutor } from "../../../common/ServiceRequest" +import { EntityClient } from "../../../common/EntityClient" +import { CacheMode, EntityRestClientLoadOptions } from "../../rest/EntityRestClient" +import type { ListElementEntity, SomeEntity } from "../../../common/EntityTypes" +import { TypeRef } from "@tutao/tutanota-utils" +import { AccessExpiredError } from "../../../common/error/RestError" + +assertWorkerOrNode() + +const TAG = "[MailExportFacade]" + +/** + * Denotes the header that will have the mail export token. + */ +export const MAIL_EXPORT_TOKEN_HEADER = "mailExportToken" + +/** + * Denotes an export token. This is internally just a string, but we want the TypeScript compiler to enforce strong + * typing. + */ +export type MailExportToken = string & { _exportToken: undefined } + +/** + * Mail exporter functions + * + * This implements loadForMailGroup and loadRangeForMailGroup which uses mail export tokens retrieved from the server + * and does not write to cache. Note that no loadAll method is implemented since tokens expire after a short period of + * time, and it is better to process in batches. + */ +export class MailExportFacade { + // Mail group ID -> export token + private readonly tokenCache: Map = new Map() + + constructor(private readonly serviceExecutor: IServiceExecutor, private readonly entityClient: EntityClient) {} + + /** + * Load a single element for export, (re-)generating a mail export token if needed + */ + async loadForMailGroup(mailGroup: Id, typeRef: TypeRef, id: PropertyType): Promise { + return await this.handleRequest(mailGroup, async (options) => { + return await this.entityClient.load(typeRef, id, options) + }) + } + + /** + * Load a multiple elements for export, (re-)generating a mail export token if needed + */ + async loadMultipleForMailGroup(mailGroup: Id, typeRef: TypeRef, listId: Id | null, elementIds: Id[]): Promise { + return await this.handleRequest(mailGroup, async (options) => { + return await this.entityClient.loadMultiple(typeRef, listId, elementIds, undefined, options) + }) + } + + /** + * Load a range of elements for export, (re-)generating a mail export token if needed + */ + async loadRangeForMailGroup( + mailGroup: Id, + typeRef: TypeRef, + listId: Id, + firstId: Id, + count: number, + reverse: boolean, + ): Promise { + return await this.handleRequest(mailGroup, async (options) => { + return await this.entityClient.loadRange(typeRef, listId, firstId, count, reverse, options) + }) + } + + /** + * Runs `request`. + * + * If `AccessExpiredError` is thrown, delete the cached token and re-run it again. + * @param mailGroup mail group to request a token + * @param request function to run + * @private + */ + private async handleRequest(mailGroup: Id, request: (options: EntityRestClientLoadOptions) => Promise): Promise { + try { + const options = await this.applyExportOptions(mailGroup) + return await request(options) + } catch (e) { + if (e instanceof AccessExpiredError) { + console.log(TAG, `token expired for exporting of mail group ${mailGroup} and will be renewed`) + this.tokenCache.delete(mailGroup) + const options = await this.applyExportOptions(mailGroup) + return await request(options) + } else { + throw e + } + } + } + + private async applyExportOptions(mailGroup: Id): Promise { + const options = { + cacheMode: CacheMode.ReadOnly, + extraHeaders: { + [MAIL_EXPORT_TOKEN_HEADER]: await this.getToken(mailGroup), + }, + } + return options + } + + private async getToken(mailGroup: Id): Promise { + return this.tokenCache.get(mailGroup) ?? (await this.requestNewToken(mailGroup)) + } + + /** + * Request a new token and write it to the tokenCache. + * + * This token will be valid for the mail group and current user for a short amount of time, after which you will get + * an `AccessExpiredError` when using the token (or `NotAuthorizedError` if the user lost access to the group in the + * meantime). + * @param mailGroup mail group the token is valid for + * @throws TooManyRequestsError the user cannot request any more tokens right now + * @throws NotAuthorizedError the user has no access to `mailGroup` + * @return the token + */ + private async requestNewToken(mailGroup: Id): Promise { + console.log(TAG, `generating new token for ${mailGroup}`) + const requestData = createMailExportTokenServicePostIn({ + mailGroup, + }) + const result = await this.serviceExecutor.post(MailExportTokenService, requestData) + const token = result.mailExportToken as MailExportToken + this.tokenCache.set(mailGroup, token) + return token + } +} diff --git a/src/mail-app/workerUtils/worker/WorkerImpl.ts b/src/mail-app/workerUtils/worker/WorkerImpl.ts index f88ad5c42acf..522f58b635c3 100644 --- a/src/mail-app/workerUtils/worker/WorkerImpl.ts +++ b/src/mail-app/workerUtils/worker/WorkerImpl.ts @@ -40,6 +40,7 @@ import { ExposedEventBus, MainInterface, WorkerRandomizer } from "../../../commo import { CryptoError } from "@tutao/tutanota-crypto/error.js" import { CryptoWrapper } from "../../../common/api/worker/crypto/CryptoWrapper.js" import { AsymmetricCryptoFacade } from "../../../common/api/worker/crypto/AsymmetricCryptoFacade.js" +import { MailExportFacade } from "../../../common/api/worker/facades/lazy/MailExportFacade" assertWorkerOrNode() @@ -75,6 +76,7 @@ export interface WorkerInterface { readonly entropyFacade: EntropyFacade readonly workerFacade: WorkerFacade readonly contactFacade: ContactFacade + readonly mailExportFacade: MailExportFacade } type WorkerRequest = Request @@ -256,6 +258,10 @@ export class WorkerImpl implements NativeInterface { async contactFacade() { return locator.contactFacade() }, + + async mailExportFacade() { + return locator.mailExport() + }, } } diff --git a/src/mail-app/workerUtils/worker/WorkerLocator.ts b/src/mail-app/workerUtils/worker/WorkerLocator.ts index e6e8ae9f6591..6adc7287c792 100644 --- a/src/mail-app/workerUtils/worker/WorkerLocator.ts +++ b/src/mail-app/workerUtils/worker/WorkerLocator.ts @@ -86,6 +86,7 @@ import { MailOfflineCleaner } from "../offline/MailOfflineCleaner.js" import type { QueuedBatch } from "../../../common/api/worker/EventQueue.js" import { Credentials } from "../../../common/misc/credentials/Credentials.js" import { AsymmetricCryptoFacade } from "../../../common/api/worker/crypto/AsymmetricCryptoFacade.js" +import type { MailExportFacade } from "../../../common/api/worker/facades/lazy/MailExportFacade" assertWorkerOrNode() @@ -143,6 +144,7 @@ export type WorkerLocatorType = { workerFacade: WorkerFacade sqlCipherFacade: SqlCipherFacade pdfWriter: lazyAsync + mailExport: lazyAsync // used to cache between resets _worker: WorkerImpl @@ -492,6 +494,10 @@ export async function initLocator(worker: WorkerImpl, browserData: BrowserData) const { ContactFacade } = await import("../../../common/api/worker/facades/lazy/ContactFacade.js") return new ContactFacade(new EntityClient(locator.cache)) }) + locator.mailExport = lazyMemoized(async () => { + const { MailExportFacade } = await import("../../../common/api/worker/facades/lazy/MailExportFacade.js") + return new MailExportFacade(locator.serviceExecutor, locator.cachingEntityClient) + }) } const RETRY_TIMOUT_AFTER_INIT_INDEXER_ERROR_MS = 30000 diff --git a/test/tests/Suite.ts b/test/tests/Suite.ts index 90f4838283c6..c7ac61e7eaf4 100644 --- a/test/tests/Suite.ts +++ b/test/tests/Suite.ts @@ -85,6 +85,7 @@ import "./subscription/SubscriptionUtilsTest.js" import "./subscription/CreditCardViewModelTest.js" import "./mail/TemplateSearchFilterTest.js" import "./mail/KnowledgeBaseSearchFilterTest.js" +import "./api/worker/facades/MailExportFacadeTest.js" import "./mail/export/ExporterTest.js" import "./mail/export/BundlerTest.js" import "./api/common/utils/FileUtilsTest.js" diff --git a/test/tests/api/worker/facades/MailExportFacadeTest.ts b/test/tests/api/worker/facades/MailExportFacadeTest.ts new file mode 100644 index 000000000000..5b7dd84c1e84 --- /dev/null +++ b/test/tests/api/worker/facades/MailExportFacadeTest.ts @@ -0,0 +1,121 @@ +import o from "@tutao/otest" +import { matchers, object, verify, when } from "testdouble" +import { MAIL_EXPORT_TOKEN_HEADER, MailExportFacade, MailExportToken } from "../../../../../src/common/api/worker/facades/lazy/MailExportFacade" +import { IServiceExecutor } from "../../../../../src/common/api/common/ServiceRequest" +import { EntityClient } from "../../../../../src/common/api/common/EntityClient" +import { createMailExportTokenServicePostOut, MailExportTokenServicePostIn, MailTypeRef } from "../../../../../src/common/api/entities/tutanota/TypeRefs" +import { CacheMode, EntityRestClientLoadOptions } from "../../../../../src/common/api/worker/rest/EntityRestClient" +import { MailExportTokenService } from "../../../../../src/common/api/entities/tutanota/Services" +import { AccessExpiredError } from "../../../../../src/common/api/common/error/RestError" +import { reset } from "../../../../../libs/linkify" + +o.spec("MailExportFacadeTest", () => { + let serviceExecutor!: IServiceExecutor + let entityClient!: EntityClient + let facade!: MailExportFacade + + o.beforeEach(() => { + serviceExecutor = object() + entityClient = object() + facade = new MailExportFacade(serviceExecutor, entityClient) + }) + + o.spec("loading", () => { + const groupId = "some group" + const mailId = ["some mail list", "some mail id"] as IdTuple + const token1 = "my token" as MailExportToken + const token2 = "my token 2" as MailExportToken + let latestToken!: MailExportToken + + const hasToken1AndCacheMode = (a: EntityRestClientLoadOptions) => { + return a.cacheMode === CacheMode.ReadOnly && a.extraHeaders![MAIL_EXPORT_TOKEN_HEADER] === token1 + } + const hasToken2AndCacheMode = (a: EntityRestClientLoadOptions) => { + return a.cacheMode === CacheMode.ReadOnly && a.extraHeaders![MAIL_EXPORT_TOKEN_HEADER] === token2 + } + + const requestingTokenForUser = (postIn: MailExportTokenServicePostIn) => { + return postIn.mailGroup === groupId + } + + o.beforeEach(() => { + // If it's not the latest token, simulate expiration! + latestToken = token1 + when(serviceExecutor.post(MailExportTokenService, matchers.argThat(requestingTokenForUser))).thenDo(() => + createMailExportTokenServicePostOut({ mailExportToken: latestToken }), + ) + const doesNotHaveLatestToken = (a: EntityRestClientLoadOptions) => a.extraHeaders?.[MAIL_EXPORT_TOKEN_HEADER] !== latestToken + when(entityClient.load(matchers.anything(), matchers.anything(), matchers.argThat(doesNotHaveLatestToken))).thenReject( + new AccessExpiredError("oh no :("), + ) + when( + entityClient.loadMultiple(matchers.anything(), matchers.anything(), matchers.anything(), undefined, matchers.argThat(doesNotHaveLatestToken)), + ).thenReject(new AccessExpiredError("oh no :(")) + when( + entityClient.loadRange( + matchers.anything(), + matchers.anything(), + matchers.anything(), + matchers.anything(), + matchers.anything(), + matchers.argThat(doesNotHaveLatestToken), + ), + ).thenReject(new AccessExpiredError("oh no :(")) + }) + + o("load has correct parameters", async () => { + await facade.loadForMailGroup(groupId, MailTypeRef, mailId) + verify(entityClient.load(MailTypeRef, mailId, matchers.argThat(hasToken1AndCacheMode))) + }) + o("loadMultiple has correct parameters", async () => { + await facade.loadMultipleForMailGroup(groupId, MailTypeRef, "some mail list", ["some mail id"]) + verify(entityClient.loadMultiple(MailTypeRef, "some mail list", ["some mail id"], undefined, matchers.argThat(hasToken1AndCacheMode))) + }) + o("loadRange has correct parameters", async () => { + await facade.loadRangeForMailGroup(groupId, MailTypeRef, "some mail list", "some mail id", 10, true) + verify(entityClient.loadRange(MailTypeRef, "some mail list", "some mail id", 10, true, matchers.argThat(hasToken1AndCacheMode))) + }) + + o("should re-request token on expiry", async () => { + await facade.loadForMailGroup(groupId, MailTypeRef, mailId) + verify(serviceExecutor.post(MailExportTokenService, matchers.argThat(requestingTokenForUser)), { times: 1 }) + verify(entityClient.load(MailTypeRef, mailId, matchers.argThat(hasToken1AndCacheMode)), { times: 1 }) + await facade.loadMultipleForMailGroup(groupId, MailTypeRef, "some mail list", ["some mail id"]) + verify(serviceExecutor.post(MailExportTokenService, matchers.argThat(requestingTokenForUser)), { times: 1 }) + verify(entityClient.loadMultiple(MailTypeRef, "some mail list", ["some mail id"], undefined, matchers.argThat(hasToken1AndCacheMode)), { times: 1 }) + await facade.loadRangeForMailGroup(groupId, MailTypeRef, "some mail list", "some mail id", 10, true) + verify(serviceExecutor.post(MailExportTokenService, matchers.argThat(requestingTokenForUser)), { times: 1 }) + verify(entityClient.loadRange(MailTypeRef, "some mail list", "some mail id", 10, true, matchers.argThat(hasToken1AndCacheMode)), { times: 1 }) + + // swap tokens to simulate expiry + + latestToken = token2 + + await facade.loadForMailGroup(groupId, MailTypeRef, mailId) + verify(serviceExecutor.post(MailExportTokenService, matchers.argThat(requestingTokenForUser)), { times: 2 }) + await facade.loadForMailGroup(groupId, MailTypeRef, mailId) + verify(serviceExecutor.post(MailExportTokenService, matchers.argThat(requestingTokenForUser)), { times: 2 }) + + verify(entityClient.load(MailTypeRef, mailId, matchers.argThat(hasToken1AndCacheMode)), { times: 2 }) // this attempt + the successful attempt above + verify(entityClient.load(MailTypeRef, mailId, matchers.argThat(hasToken2AndCacheMode)), { times: 2 }) + + latestToken = token1 + + await facade.loadMultipleForMailGroup(groupId, MailTypeRef, "some mail list", ["some mail id"]) + verify(serviceExecutor.post(MailExportTokenService, matchers.argThat(requestingTokenForUser)), { times: 3 }) + await facade.loadMultipleForMailGroup(groupId, MailTypeRef, "some mail list", ["some mail id"]) + verify(serviceExecutor.post(MailExportTokenService, matchers.argThat(requestingTokenForUser)), { times: 3 }) + verify(entityClient.loadMultiple(MailTypeRef, "some mail list", ["some mail id"], undefined, matchers.argThat(hasToken2AndCacheMode)), { times: 1 }) // the failure case + verify(entityClient.loadMultiple(MailTypeRef, "some mail list", ["some mail id"], undefined, matchers.argThat(hasToken1AndCacheMode)), { times: 3 }) // includes the first time above + + latestToken = token2 + + await facade.loadRangeForMailGroup(groupId, MailTypeRef, "some mail list", "some mail id", 10, true) + verify(serviceExecutor.post(MailExportTokenService, matchers.argThat(requestingTokenForUser)), { times: 4 }) + await facade.loadRangeForMailGroup(groupId, MailTypeRef, "some mail list", "some mail id", 10, true) + verify(serviceExecutor.post(MailExportTokenService, matchers.argThat(requestingTokenForUser)), { times: 4 }) + verify(entityClient.loadRange(MailTypeRef, "some mail list", "some mail id", 10, true, matchers.argThat(hasToken2AndCacheMode)), { times: 2 }) // this attempt + the successful attempt above + verify(entityClient.loadRange(MailTypeRef, "some mail list", "some mail id", 10, true, matchers.argThat(hasToken1AndCacheMode)), { times: 2 }) + }) + }) +}) diff --git a/tuta-sdk/rust/sdk/src/entities/generated/tutanota.rs b/tuta-sdk/rust/sdk/src/entities/generated/tutanota.rs index c90bcd6c6e6e..ae1eded91882 100644 --- a/tuta-sdk/rust/sdk/src/entities/generated/tutanota.rs +++ b/tuta-sdk/rust/sdk/src/entities/generated/tutanota.rs @@ -1656,6 +1656,38 @@ impl Entity for MailDetailsDraftsRef { } } +#[derive(uniffi::Record, Clone, Serialize, Deserialize)] +#[cfg_attr(test, derive(PartialEq, Debug))] +pub struct MailExportTokenServicePostIn { + pub _format: i64, + pub mailGroup: GeneratedId, +} + +impl Entity for MailExportTokenServicePostIn { + fn type_ref() -> TypeRef { + TypeRef { + app: "tutanota", + type_: "MailExportTokenServicePostIn", + } + } +} + +#[derive(uniffi::Record, Clone, Serialize, Deserialize)] +#[cfg_attr(test, derive(PartialEq, Debug))] +pub struct MailExportTokenServicePostOut { + pub _format: i64, + pub mailExportToken: String, +} + +impl Entity for MailExportTokenServicePostOut { + fn type_ref() -> TypeRef { + TypeRef { + app: "tutanota", + type_: "MailExportTokenServicePostOut", + } + } +} + #[derive(uniffi::Record, Clone, Serialize, Deserialize)] #[cfg_attr(test, derive(PartialEq, Debug))] pub struct MailFolder { diff --git a/tuta-sdk/rust/sdk/src/services/generated/tutanota.rs b/tuta-sdk/rust/sdk/src/services/generated/tutanota.rs index 90c0ba641568..1ab36f0330ad 100644 --- a/tuta-sdk/rust/sdk/src/services/generated/tutanota.rs +++ b/tuta-sdk/rust/sdk/src/services/generated/tutanota.rs @@ -23,6 +23,8 @@ use crate::entities::generated::tutanota::GroupInvitationPostReturn; use crate::entities::generated::tutanota::GroupInvitationPutData; use crate::entities::generated::tutanota::GroupInvitationDeleteData; use crate::entities::generated::tutanota::ListUnsubscribeData; +use crate::entities::generated::tutanota::MailExportTokenServicePostIn; +use crate::entities::generated::tutanota::MailExportTokenServicePostOut; use crate::entities::generated::tutanota::CreateMailFolderData; use crate::entities::generated::tutanota::CreateMailFolderReturn; use crate::entities::generated::tutanota::UpdateMailFolderData; @@ -46,58 +48,58 @@ use crate::entities::generated::tutanota::UnreadMailStatePostIn; use crate::entities::generated::tutanota::UserAccountCreateData; pub struct ApplyLabelService; -crate::service_impl!(declare, ApplyLabelService, "tutanota/applylabelservice", 77); +crate::service_impl!(declare, ApplyLabelService, "tutanota/applylabelservice", 78); crate::service_impl!(POST, ApplyLabelService, ApplyLabelServicePostIn, ()); pub struct CalendarService; -crate::service_impl!(declare, CalendarService, "tutanota/calendarservice", 77); +crate::service_impl!(declare, CalendarService, "tutanota/calendarservice", 78); crate::service_impl!(POST, CalendarService, UserAreaGroupPostData, CreateGroupPostReturn); crate::service_impl!(DELETE, CalendarService, CalendarDeleteData, ()); pub struct ContactListGroupService; -crate::service_impl!(declare, ContactListGroupService, "tutanota/contactlistgroupservice", 77); +crate::service_impl!(declare, ContactListGroupService, "tutanota/contactlistgroupservice", 78); crate::service_impl!(POST, ContactListGroupService, UserAreaGroupPostData, CreateGroupPostReturn); crate::service_impl!(DELETE, ContactListGroupService, UserAreaGroupDeleteData, ()); pub struct CustomerAccountService; -crate::service_impl!(declare, CustomerAccountService, "tutanota/customeraccountservice", 77); +crate::service_impl!(declare, CustomerAccountService, "tutanota/customeraccountservice", 78); crate::service_impl!(POST, CustomerAccountService, CustomerAccountCreateData, ()); pub struct DraftService; -crate::service_impl!(declare, DraftService, "tutanota/draftservice", 77); +crate::service_impl!(declare, DraftService, "tutanota/draftservice", 78); crate::service_impl!(POST, DraftService, DraftCreateData, DraftCreateReturn); crate::service_impl!(PUT, DraftService, DraftUpdateData, DraftUpdateReturn); pub struct EncryptTutanotaPropertiesService; -crate::service_impl!(declare, EncryptTutanotaPropertiesService, "tutanota/encrypttutanotapropertiesservice", 77); +crate::service_impl!(declare, EncryptTutanotaPropertiesService, "tutanota/encrypttutanotapropertiesservice", 78); crate::service_impl!(POST, EncryptTutanotaPropertiesService, EncryptTutanotaPropertiesData, ()); pub struct EntropyService; -crate::service_impl!(declare, EntropyService, "tutanota/entropyservice", 77); +crate::service_impl!(declare, EntropyService, "tutanota/entropyservice", 78); crate::service_impl!(PUT, EntropyService, EntropyData, ()); pub struct ExternalUserService; -crate::service_impl!(declare, ExternalUserService, "tutanota/externaluserservice", 77); +crate::service_impl!(declare, ExternalUserService, "tutanota/externaluserservice", 78); crate::service_impl!(POST, ExternalUserService, ExternalUserData, ()); pub struct GroupInvitationService; -crate::service_impl!(declare, GroupInvitationService, "tutanota/groupinvitationservice", 77); +crate::service_impl!(declare, GroupInvitationService, "tutanota/groupinvitationservice", 78); crate::service_impl!(POST, GroupInvitationService, GroupInvitationPostData, GroupInvitationPostReturn); crate::service_impl!(PUT, GroupInvitationService, GroupInvitationPutData, ()); crate::service_impl!(DELETE, GroupInvitationService, GroupInvitationDeleteData, ()); @@ -105,13 +107,19 @@ crate::service_impl!(DELETE, GroupInvitationService, GroupInvitationDeleteData, pub struct ListUnsubscribeService; -crate::service_impl!(declare, ListUnsubscribeService, "tutanota/listunsubscribeservice", 77); +crate::service_impl!(declare, ListUnsubscribeService, "tutanota/listunsubscribeservice", 78); crate::service_impl!(POST, ListUnsubscribeService, ListUnsubscribeData, ()); +pub struct MailExportTokenService; + +crate::service_impl!(declare, MailExportTokenService, "tutanota/mailexporttokenservice", 78); +crate::service_impl!(POST, MailExportTokenService, MailExportTokenServicePostIn, MailExportTokenServicePostOut); + + pub struct MailFolderService; -crate::service_impl!(declare, MailFolderService, "tutanota/mailfolderservice", 77); +crate::service_impl!(declare, MailFolderService, "tutanota/mailfolderservice", 78); crate::service_impl!(POST, MailFolderService, CreateMailFolderData, CreateMailFolderReturn); crate::service_impl!(PUT, MailFolderService, UpdateMailFolderData, ()); crate::service_impl!(DELETE, MailFolderService, DeleteMailFolderData, ()); @@ -119,81 +127,81 @@ crate::service_impl!(DELETE, MailFolderService, DeleteMailFolderData, ()); pub struct MailGroupService; -crate::service_impl!(declare, MailGroupService, "tutanota/mailgroupservice", 77); +crate::service_impl!(declare, MailGroupService, "tutanota/mailgroupservice", 78); crate::service_impl!(POST, MailGroupService, CreateMailGroupData, ()); crate::service_impl!(DELETE, MailGroupService, DeleteGroupData, ()); pub struct MailService; -crate::service_impl!(declare, MailService, "tutanota/mailservice", 77); +crate::service_impl!(declare, MailService, "tutanota/mailservice", 78); crate::service_impl!(DELETE, MailService, DeleteMailData, ()); pub struct ManageLabelService; -crate::service_impl!(declare, ManageLabelService, "tutanota/managelabelservice", 77); +crate::service_impl!(declare, ManageLabelService, "tutanota/managelabelservice", 78); crate::service_impl!(POST, ManageLabelService, ManageLabelServicePostIn, ()); crate::service_impl!(DELETE, ManageLabelService, ManageLabelServiceDeleteIn, ()); pub struct MoveMailService; -crate::service_impl!(declare, MoveMailService, "tutanota/movemailservice", 77); +crate::service_impl!(declare, MoveMailService, "tutanota/movemailservice", 78); crate::service_impl!(POST, MoveMailService, MoveMailData, ()); pub struct NewsService; -crate::service_impl!(declare, NewsService, "tutanota/newsservice", 77); +crate::service_impl!(declare, NewsService, "tutanota/newsservice", 78); crate::service_impl!(POST, NewsService, NewsIn, ()); crate::service_impl!(GET, NewsService, (), NewsOut); pub struct ReceiveInfoService; -crate::service_impl!(declare, ReceiveInfoService, "tutanota/receiveinfoservice", 77); +crate::service_impl!(declare, ReceiveInfoService, "tutanota/receiveinfoservice", 78); crate::service_impl!(POST, ReceiveInfoService, ReceiveInfoServiceData, ()); pub struct ReportMailService; -crate::service_impl!(declare, ReportMailService, "tutanota/reportmailservice", 77); +crate::service_impl!(declare, ReportMailService, "tutanota/reportmailservice", 78); crate::service_impl!(POST, ReportMailService, ReportMailPostData, ()); pub struct SendDraftService; -crate::service_impl!(declare, SendDraftService, "tutanota/senddraftservice", 77); +crate::service_impl!(declare, SendDraftService, "tutanota/senddraftservice", 78); crate::service_impl!(POST, SendDraftService, SendDraftData, SendDraftReturn); pub struct SimpleMoveMailService; -crate::service_impl!(declare, SimpleMoveMailService, "tutanota/simplemovemailservice", 77); +crate::service_impl!(declare, SimpleMoveMailService, "tutanota/simplemovemailservice", 78); crate::service_impl!(POST, SimpleMoveMailService, SimpleMoveMailPostIn, ()); pub struct TemplateGroupService; -crate::service_impl!(declare, TemplateGroupService, "tutanota/templategroupservice", 77); +crate::service_impl!(declare, TemplateGroupService, "tutanota/templategroupservice", 78); crate::service_impl!(POST, TemplateGroupService, UserAreaGroupPostData, CreateGroupPostReturn); crate::service_impl!(DELETE, TemplateGroupService, UserAreaGroupDeleteData, ()); pub struct TranslationService; -crate::service_impl!(declare, TranslationService, "tutanota/translationservice", 77); +crate::service_impl!(declare, TranslationService, "tutanota/translationservice", 78); crate::service_impl!(GET, TranslationService, TranslationGetIn, TranslationGetOut); pub struct UnreadMailStateService; -crate::service_impl!(declare, UnreadMailStateService, "tutanota/unreadmailstateservice", 77); +crate::service_impl!(declare, UnreadMailStateService, "tutanota/unreadmailstateservice", 78); crate::service_impl!(POST, UnreadMailStateService, UnreadMailStatePostIn, ()); pub struct UserAccountService; -crate::service_impl!(declare, UserAccountService, "tutanota/useraccountservice", 77); +crate::service_impl!(declare, UserAccountService, "tutanota/useraccountservice", 78); crate::service_impl!(POST, UserAccountService, UserAccountCreateData, ()); diff --git a/tuta-sdk/rust/sdk/src/type_models/tutanota.json b/tuta-sdk/rust/sdk/src/type_models/tutanota.json index d76537ba8bc4..3af7d24f82e1 100644 --- a/tuta-sdk/rust/sdk/src/type_models/tutanota.json +++ b/tuta-sdk/rust/sdk/src/type_models/tutanota.json @@ -51,7 +51,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "AttachmentKeyData": { "name": "AttachmentKeyData", @@ -103,7 +103,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "Birthday": { "name": "Birthday", @@ -153,7 +153,7 @@ }, "associations": {}, "app": "tutanota", - "version": "77" + "version": "78" }, "Body": { "name": "Body", @@ -194,7 +194,7 @@ }, "associations": {}, "app": "tutanota", - "version": "77" + "version": "78" }, "CalendarDeleteData": { "name": "CalendarDeleteData", @@ -228,7 +228,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "CalendarEvent": { "name": "CalendarEvent", @@ -427,7 +427,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "CalendarEventAttendee": { "name": "CalendarEventAttendee", @@ -470,7 +470,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "CalendarEventIndexRef": { "name": "CalendarEventIndexRef", @@ -504,7 +504,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "CalendarEventUidIndex": { "name": "CalendarEventUidIndex", @@ -575,7 +575,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "CalendarEventUpdate": { "name": "CalendarEventUpdate", @@ -663,7 +663,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "CalendarEventUpdateList": { "name": "CalendarEventUpdateList", @@ -697,7 +697,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "CalendarGroupRoot": { "name": "CalendarGroupRoot", @@ -796,7 +796,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "CalendarRepeatRule": { "name": "CalendarRepeatRule", @@ -875,7 +875,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "Contact": { "name": "Contact", @@ -1198,7 +1198,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "ContactAddress": { "name": "ContactAddress", @@ -1248,7 +1248,7 @@ }, "associations": {}, "app": "tutanota", - "version": "77" + "version": "78" }, "ContactCustomDate": { "name": "ContactCustomDate", @@ -1298,7 +1298,7 @@ }, "associations": {}, "app": "tutanota", - "version": "77" + "version": "78" }, "ContactList": { "name": "ContactList", @@ -1387,7 +1387,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "ContactListEntry": { "name": "ContactListEntry", @@ -1464,7 +1464,7 @@ }, "associations": {}, "app": "tutanota", - "version": "77" + "version": "78" }, "ContactListGroupRoot": { "name": "ContactListGroupRoot", @@ -1543,7 +1543,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "ContactMailAddress": { "name": "ContactMailAddress", @@ -1593,7 +1593,7 @@ }, "associations": {}, "app": "tutanota", - "version": "77" + "version": "78" }, "ContactMessengerHandle": { "name": "ContactMessengerHandle", @@ -1643,7 +1643,7 @@ }, "associations": {}, "app": "tutanota", - "version": "77" + "version": "78" }, "ContactPhoneNumber": { "name": "ContactPhoneNumber", @@ -1693,7 +1693,7 @@ }, "associations": {}, "app": "tutanota", - "version": "77" + "version": "78" }, "ContactPronouns": { "name": "ContactPronouns", @@ -1734,7 +1734,7 @@ }, "associations": {}, "app": "tutanota", - "version": "77" + "version": "78" }, "ContactRelationship": { "name": "ContactRelationship", @@ -1784,7 +1784,7 @@ }, "associations": {}, "app": "tutanota", - "version": "77" + "version": "78" }, "ContactSocialId": { "name": "ContactSocialId", @@ -1834,7 +1834,7 @@ }, "associations": {}, "app": "tutanota", - "version": "77" + "version": "78" }, "ContactWebsite": { "name": "ContactWebsite", @@ -1884,7 +1884,7 @@ }, "associations": {}, "app": "tutanota", - "version": "77" + "version": "78" }, "ConversationEntry": { "name": "ConversationEntry", @@ -1973,7 +1973,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "CreateExternalUserGroupData": { "name": "CreateExternalUserGroupData", @@ -2032,7 +2032,7 @@ }, "associations": {}, "app": "tutanota", - "version": "77" + "version": "78" }, "CreateGroupPostReturn": { "name": "CreateGroupPostReturn", @@ -2066,7 +2066,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "CreateMailFolderData": { "name": "CreateMailFolderData", @@ -2136,7 +2136,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "CreateMailFolderReturn": { "name": "CreateMailFolderReturn", @@ -2170,7 +2170,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "CreateMailGroupData": { "name": "CreateMailGroupData", @@ -2231,7 +2231,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "CustomerAccountCreateData": { "name": "CustomerAccountCreateData", @@ -2403,7 +2403,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "DefaultAlarmInfo": { "name": "DefaultAlarmInfo", @@ -2435,7 +2435,7 @@ }, "associations": {}, "app": "tutanota", - "version": "77" + "version": "78" }, "DeleteGroupData": { "name": "DeleteGroupData", @@ -2478,7 +2478,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "DeleteMailData": { "name": "DeleteMailData", @@ -2522,7 +2522,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "DeleteMailFolderData": { "name": "DeleteMailFolderData", @@ -2556,7 +2556,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "DraftAttachment": { "name": "DraftAttachment", @@ -2618,7 +2618,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "DraftCreateData": { "name": "DraftCreateData", @@ -2688,7 +2688,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "DraftCreateReturn": { "name": "DraftCreateReturn", @@ -2722,7 +2722,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "DraftData": { "name": "DraftData", @@ -2869,7 +2869,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "DraftRecipient": { "name": "DraftRecipient", @@ -2910,7 +2910,7 @@ }, "associations": {}, "app": "tutanota", - "version": "77" + "version": "78" }, "DraftUpdateData": { "name": "DraftUpdateData", @@ -2954,7 +2954,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "DraftUpdateReturn": { "name": "DraftUpdateReturn", @@ -2988,7 +2988,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "EmailTemplate": { "name": "EmailTemplate", @@ -3085,7 +3085,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "EmailTemplateContent": { "name": "EmailTemplateContent", @@ -3126,7 +3126,7 @@ }, "associations": {}, "app": "tutanota", - "version": "77" + "version": "78" }, "EncryptTutanotaPropertiesData": { "name": "EncryptTutanotaPropertiesData", @@ -3178,7 +3178,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "EncryptedMailAddress": { "name": "EncryptedMailAddress", @@ -3219,7 +3219,7 @@ }, "associations": {}, "app": "tutanota", - "version": "77" + "version": "78" }, "EntropyData": { "name": "EntropyData", @@ -3260,7 +3260,7 @@ }, "associations": {}, "app": "tutanota", - "version": "77" + "version": "78" }, "ExternalUserData": { "name": "ExternalUserData", @@ -3393,7 +3393,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "File": { "name": "File", @@ -3528,7 +3528,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "FileSystem": { "name": "FileSystem", @@ -3607,7 +3607,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "GroupInvitationDeleteData": { "name": "GroupInvitationDeleteData", @@ -3641,7 +3641,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "GroupInvitationPostData": { "name": "GroupInvitationPostData", @@ -3685,7 +3685,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "GroupInvitationPostReturn": { "name": "GroupInvitationPostReturn", @@ -3739,7 +3739,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "GroupInvitationPutData": { "name": "GroupInvitationPutData", @@ -3809,7 +3809,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "GroupSettings": { "name": "GroupSettings", @@ -3880,7 +3880,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "Header": { "name": "Header", @@ -3921,7 +3921,7 @@ }, "associations": {}, "app": "tutanota", - "version": "77" + "version": "78" }, "ImapFolder": { "name": "ImapFolder", @@ -3982,7 +3982,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "ImapSyncConfiguration": { "name": "ImapSyncConfiguration", @@ -4052,7 +4052,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "ImapSyncState": { "name": "ImapSyncState", @@ -4113,7 +4113,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "InboxRule": { "name": "InboxRule", @@ -4165,7 +4165,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "InternalGroupData": { "name": "InternalGroupData", @@ -4289,7 +4289,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "InternalRecipientKeyData": { "name": "InternalRecipientKeyData", @@ -4357,7 +4357,7 @@ }, "associations": {}, "app": "tutanota", - "version": "77" + "version": "78" }, "KnowledgeBaseEntry": { "name": "KnowledgeBaseEntry", @@ -4454,7 +4454,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "KnowledgeBaseEntryKeyword": { "name": "KnowledgeBaseEntryKeyword", @@ -4486,7 +4486,7 @@ }, "associations": {}, "app": "tutanota", - "version": "77" + "version": "78" }, "ListUnsubscribeData": { "name": "ListUnsubscribeData", @@ -4538,7 +4538,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "Mail": { "name": "Mail", @@ -4813,7 +4813,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "MailAddress": { "name": "MailAddress", @@ -4865,7 +4865,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "MailAddressProperties": { "name": "MailAddressProperties", @@ -4906,7 +4906,7 @@ }, "associations": {}, "app": "tutanota", - "version": "77" + "version": "78" }, "MailBag": { "name": "MailBag", @@ -4940,7 +4940,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "MailBox": { "name": "MailBox", @@ -5088,7 +5088,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "MailDetails": { "name": "MailDetails", @@ -5170,7 +5170,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "MailDetailsBlob": { "name": "MailDetailsBlob", @@ -5249,7 +5249,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "MailDetailsDraft": { "name": "MailDetailsDraft", @@ -5328,7 +5328,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "MailDetailsDraftsRef": { "name": "MailDetailsDraftsRef", @@ -5362,7 +5362,73 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" + }, + "MailExportTokenServicePostIn": { + "name": "MailExportTokenServicePostIn", + "since": 78, + "type": "DATA_TRANSFER_TYPE", + "id": 1516, + "rootId": "CHR1dGFub3RhAAXs", + "versioned": false, + "encrypted": false, + "values": { + "_format": { + "final": false, + "name": "_format", + "id": 1517, + "since": 78, + "type": "Number", + "cardinality": "One", + "encrypted": false + } + }, + "associations": { + "mailGroup": { + "final": false, + "name": "mailGroup", + "id": 1518, + "since": 78, + "type": "ELEMENT_ASSOCIATION", + "cardinality": "One", + "refType": "Group", + "dependency": null + } + }, + "app": "tutanota", + "version": "78" + }, + "MailExportTokenServicePostOut": { + "name": "MailExportTokenServicePostOut", + "since": 78, + "type": "DATA_TRANSFER_TYPE", + "id": 1519, + "rootId": "CHR1dGFub3RhAAXv", + "versioned": false, + "encrypted": false, + "values": { + "_format": { + "final": false, + "name": "_format", + "id": 1520, + "since": 78, + "type": "Number", + "cardinality": "One", + "encrypted": false + }, + "mailExportToken": { + "final": false, + "name": "mailExportToken", + "id": 1521, + "since": 78, + "type": "String", + "cardinality": "One", + "encrypted": false + } + }, + "associations": {}, + "app": "tutanota", + "version": "78" }, "MailFolder": { "name": "MailFolder", @@ -5497,7 +5563,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "MailFolderRef": { "name": "MailFolderRef", @@ -5531,7 +5597,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "MailSetEntry": { "name": "MailSetEntry", @@ -5592,7 +5658,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "MailboxGroupRoot": { "name": "MailboxGroupRoot", @@ -5703,7 +5769,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "MailboxProperties": { "name": "MailboxProperties", @@ -5791,7 +5857,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "MailboxServerProperties": { "name": "MailboxServerProperties", @@ -5850,7 +5916,7 @@ }, "associations": {}, "app": "tutanota", - "version": "77" + "version": "78" }, "ManageLabelServiceDeleteIn": { "name": "ManageLabelServiceDeleteIn", @@ -5884,7 +5950,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "ManageLabelServiceLabelData": { "name": "ManageLabelServiceLabelData", @@ -5925,7 +5991,7 @@ }, "associations": {}, "app": "tutanota", - "version": "77" + "version": "78" }, "ManageLabelServicePostIn": { "name": "ManageLabelServicePostIn", @@ -5986,7 +6052,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "MoveMailData": { "name": "MoveMailData", @@ -6040,7 +6106,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "NewDraftAttachment": { "name": "NewDraftAttachment", @@ -6101,7 +6167,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "NewsId": { "name": "NewsId", @@ -6142,7 +6208,7 @@ }, "associations": {}, "app": "tutanota", - "version": "77" + "version": "78" }, "NewsIn": { "name": "NewsIn", @@ -6174,7 +6240,7 @@ }, "associations": {}, "app": "tutanota", - "version": "77" + "version": "78" }, "NewsOut": { "name": "NewsOut", @@ -6208,7 +6274,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "NotificationMail": { "name": "NotificationMail", @@ -6276,7 +6342,7 @@ }, "associations": {}, "app": "tutanota", - "version": "77" + "version": "78" }, "OutOfOfficeNotification": { "name": "OutOfOfficeNotification", @@ -6364,7 +6430,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "OutOfOfficeNotificationMessage": { "name": "OutOfOfficeNotificationMessage", @@ -6414,7 +6480,7 @@ }, "associations": {}, "app": "tutanota", - "version": "77" + "version": "78" }, "OutOfOfficeNotificationRecipientList": { "name": "OutOfOfficeNotificationRecipientList", @@ -6448,7 +6514,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "PhishingMarkerWebsocketData": { "name": "PhishingMarkerWebsocketData", @@ -6491,7 +6557,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "PhotosRef": { "name": "PhotosRef", @@ -6525,7 +6591,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "ReceiveInfoServiceData": { "name": "ReceiveInfoServiceData", @@ -6557,7 +6623,7 @@ }, "associations": {}, "app": "tutanota", - "version": "77" + "version": "78" }, "Recipients": { "name": "Recipients", @@ -6611,7 +6677,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "RemoteImapSyncInfo": { "name": "RemoteImapSyncInfo", @@ -6681,7 +6747,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "ReportMailPostData": { "name": "ReportMailPostData", @@ -6733,7 +6799,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "ReportedMailFieldMarker": { "name": "ReportedMailFieldMarker", @@ -6774,7 +6840,7 @@ }, "associations": {}, "app": "tutanota", - "version": "77" + "version": "78" }, "SecureExternalRecipientKeyData": { "name": "SecureExternalRecipientKeyData", @@ -6878,7 +6944,7 @@ }, "associations": {}, "app": "tutanota", - "version": "77" + "version": "78" }, "SendDraftData": { "name": "SendDraftData", @@ -7015,7 +7081,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "SendDraftReturn": { "name": "SendDraftReturn", @@ -7077,7 +7143,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "SharedGroupData": { "name": "SharedGroupData", @@ -7181,7 +7247,7 @@ }, "associations": {}, "app": "tutanota", - "version": "77" + "version": "78" }, "SimpleMoveMailPostIn": { "name": "SimpleMoveMailPostIn", @@ -7224,7 +7290,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "SpamResults": { "name": "SpamResults", @@ -7258,7 +7324,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "Subfiles": { "name": "Subfiles", @@ -7292,7 +7358,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "SymEncInternalRecipientKeyData": { "name": "SymEncInternalRecipientKeyData", @@ -7353,7 +7419,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "TemplateGroupRoot": { "name": "TemplateGroupRoot", @@ -7442,7 +7508,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "TranslationGetIn": { "name": "TranslationGetIn", @@ -7474,7 +7540,7 @@ }, "associations": {}, "app": "tutanota", - "version": "77" + "version": "78" }, "TranslationGetOut": { "name": "TranslationGetOut", @@ -7515,7 +7581,7 @@ }, "associations": {}, "app": "tutanota", - "version": "77" + "version": "78" }, "TutanotaProperties": { "name": "TutanotaProperties", @@ -7713,7 +7779,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "UnreadMailStatePostIn": { "name": "UnreadMailStatePostIn", @@ -7756,7 +7822,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "UpdateMailFolderData": { "name": "UpdateMailFolderData", @@ -7800,7 +7866,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "UserAccountCreateData": { "name": "UserAccountCreateData", @@ -7853,7 +7919,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "UserAccountUserData": { "name": "UserAccountUserData", @@ -8074,7 +8140,7 @@ }, "associations": {}, "app": "tutanota", - "version": "77" + "version": "78" }, "UserAreaGroupData": { "name": "UserAreaGroupData", @@ -8180,7 +8246,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "UserAreaGroupDeleteData": { "name": "UserAreaGroupDeleteData", @@ -8214,7 +8280,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "UserAreaGroupPostData": { "name": "UserAreaGroupPostData", @@ -8248,7 +8314,7 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" }, "UserSettingsGroupRoot": { "name": "UserSettingsGroupRoot", @@ -8354,6 +8420,6 @@ } }, "app": "tutanota", - "version": "77" + "version": "78" } }