Skip to content

Commit aa0ba11

Browse files
Use externalMailInfo API call instead of mailboxes one to get ExternalMail info
1 parent b32ea90 commit aa0ba11

File tree

11 files changed

+98
-19
lines changed

11 files changed

+98
-19
lines changed

app/src/main/java/com/infomaniak/mail/data/api/ApiRepository.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ import com.infomaniak.mail.data.models.getMessages.ActivitiesResult
4646
import com.infomaniak.mail.data.models.getMessages.GetMessagesByUidsResult
4747
import com.infomaniak.mail.data.models.getMessages.NewMessagesResult
4848
import com.infomaniak.mail.data.models.mailbox.Mailbox
49+
import com.infomaniak.mail.data.models.mailbox.MailboxExternalMailInfo
4950
import com.infomaniak.mail.data.models.mailbox.MailboxLinkedResult
5051
import com.infomaniak.mail.data.models.mailbox.MailboxPermissions
5152
import com.infomaniak.mail.data.models.message.Message
@@ -145,6 +146,10 @@ object ApiRepository : ApiRepositoryCore() {
145146
return callApi(ApiRoutes.permissions(mailboxLinkId, mailboxHostingId), GET)
146147
}
147148

149+
fun getExternalMailInfo(mailboxHostingId: Int, mailboxName: String): ApiResponse<MailboxExternalMailInfo> {
150+
return callApi(ApiRoutes.externalMailInfo(mailboxHostingId, mailboxName), GET)
151+
}
152+
148153
fun markMessagesAsSeen(mailboxUuid: String, messagesUids: List<String>): ApiResponse<Unit> {
149154
return callApi(ApiRoutes.messagesSeen(mailboxUuid), POST, mapOf("uids" to messagesUids))
150155
}

app/src/main/java/com/infomaniak/mail/data/api/ApiRoutes.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,10 @@ object ApiRoutes {
7373
return "$MAIL_API/api/securedProxy"
7474
}
7575

76+
fun externalMailInfo(mailboxHostingId: Int, mailboxName: String): String {
77+
return "${securedProxy()}/1/mail_hostings/$mailboxHostingId/mailboxes/$mailboxName/external_mail_flag"
78+
}
79+
7680
fun updateMailboxPassword(mailboxId: Int): String {
7781
return "${securedProxy()}/cache/invalidation/profile/workspace/mailbox/$mailboxId/update_password"
7882
}

app/src/main/java/com/infomaniak/mail/data/cache/RealmDatabase.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ object RealmDatabase {
158158

159159
//region Configurations versions
160160
const val USER_INFO_SCHEMA_VERSION = 1L
161-
const val MAILBOX_INFO_SCHEMA_VERSION = 4L
161+
const val MAILBOX_INFO_SCHEMA_VERSION = 5L
162162
const val MAILBOX_CONTENT_SCHEMA_VERSION = 8L
163163
//endregion
164164

app/src/main/java/com/infomaniak/mail/data/models/correspondent/Recipient.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,9 @@ open class Recipient : EmbeddedRealmObject, Correspondent {
6464

6565
// Computes if the Recipient is external, according to the required conditions.
6666
// Does not tell anything about how to display the Recipient chip when composing a new Message.
67-
fun isExternal(emailDictionary: MergedContactDictionary, aliases: List<String>): Boolean {
67+
fun isExternal(emailDictionary: MergedContactDictionary, aliases: List<String>, trustedDomains: List<String>): Boolean {
6868
val isUnknownContact = email !in emailDictionary
6969
val isMailerDaemon = """mailer-daemon@(?:.+\.)?infomaniak\.ch""".toRegex(RegexOption.IGNORE_CASE).matches(email)
70-
val trustedDomains = listOf("@infomaniak.com", "@infomaniak.event", "@swisstransfer.com")
7170
val isUntrustedDomain = email.isEmail() && trustedDomains.none { email.endsWith(it) }
7271
val isAlias = email in aliases
7372

app/src/main/java/com/infomaniak/mail/data/models/mailbox/Mailbox.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,6 @@ class Mailbox : RealmObject {
6262
@SerialName("unseen_messages")
6363
var unreadCountRemote: Int = 0
6464
var aliases: RealmList<String> = realmListOf()
65-
@SerialName("external_mail_flag_enabled")
66-
var externalMailFlagEnabled: Boolean = false
6765
//endregion
6866

6967
//region Local data (Transient)
@@ -80,6 +78,10 @@ class Mailbox : RealmObject {
8078
var permissions: MailboxPermissions? = null
8179
@Transient
8280
private var _featureFlags: RealmSet<String> = realmSetOf()
81+
@Transient
82+
var externalMailFlagEnabled: Boolean = false
83+
@Transient
84+
var trustedDomains: RealmList<String> = realmListOf()
8385
//endregion
8486

8587
//region (Transient & Ignore)
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* Infomaniak Mail - Android
3+
* Copyright (C) 2024 Infomaniak Network SA
4+
*
5+
* This program is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
*/
18+
package com.infomaniak.mail.data.models.mailbox
19+
20+
import kotlinx.serialization.SerialName
21+
import kotlinx.serialization.Serializable
22+
23+
@Serializable
24+
data class MailboxExternalMailInfo(
25+
@SerialName("external_mail_flag_enabled")
26+
val externalMailFlagEnabled: Boolean = false,
27+
@SerialName("domains")
28+
val trustedDomains: List<String> = emptyList(),
29+
)

app/src/main/java/com/infomaniak/mail/ui/MainViewModel.kt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ import com.infomaniak.mail.utils.Utils.runCatchingRealm
6363
import com.infomaniak.mail.views.itemViews.AvatarMergedContactData
6464
import dagger.hilt.android.lifecycle.HiltViewModel
6565
import io.realm.kotlin.ext.copyFromRealm
66+
import io.realm.kotlin.ext.toRealmList
6667
import io.realm.kotlin.notifications.ResultsChange
6768
import kotlinx.coroutines.*
6869
import kotlinx.coroutines.flow.*
@@ -281,6 +282,7 @@ class MainViewModel @Inject constructor(
281282
updatePermissions(mailbox)
282283
updateSignatures(mailbox)
283284
updateFeatureFlag(mailbox)
285+
updateExternalMailInfo(mailbox)
284286

285287
// This update is blocking because we need it for the rest of the flow : `selectFolder()` needs the Folders.
286288
updateFolders(mailbox)
@@ -343,6 +345,16 @@ class MainViewModel @Inject constructor(
343345
sharedUtils.updateAiFeatureFlag(mailbox.objectId, mailbox.uuid)
344346
}
345347

348+
private fun updateExternalMailInfo(mailbox: Mailbox) = viewModelScope.launch(ioCoroutineContext) {
349+
SentryLog.d(TAG, "Force refresh External Mail info")
350+
with(ApiRepository.getExternalMailInfo(mailbox.hostingId, mailbox.mailboxName)) {
351+
if (isSuccess() && data != null) mailboxController.updateMailbox(mailbox.objectId) {
352+
it.externalMailFlagEnabled = data!!.externalMailFlagEnabled
353+
it.trustedDomains = data!!.trustedDomains.toRealmList()
354+
}
355+
}
356+
}
357+
346358
private fun updateFolders(mailbox: Mailbox) {
347359
SentryLog.d(TAG, "Force refresh Folders")
348360
ApiRepository.getFolders(mailbox.uuid).data?.let { folders ->

app/src/main/java/com/infomaniak/mail/ui/main/thread/ThreadFragment.kt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,7 @@ class ThreadFragment : Fragment() {
371371
emailDictionary = result.mergedContacts ?: emptyMap(),
372372
aliases = result.mailbox?.aliases ?: emptyList(),
373373
externalMailFlagEnabled = result.mailbox?.externalMailFlagEnabled ?: false,
374+
trustedDomains = result.mailbox?.trustedDomains ?: emptyList(),
374375
)
375376

376377
threadSubject.text = spannedSubject
@@ -547,11 +548,14 @@ class ThreadFragment : Fragment() {
547548
emailDictionary: MergedContactDictionary,
548549
aliases: List<String>,
549550
externalMailFlagEnabled: Boolean,
551+
trustedDomains: List<String>,
550552
): Pair<String, CharSequence> = with(binding) {
551553
val subject = context.formatSubject(thread.subject)
552554
if (!externalMailFlagEnabled) return subject to subject
553555

554-
val (externalRecipientEmail, externalRecipientQuantity) = thread.findExternalRecipients(emailDictionary, aliases)
556+
val (externalRecipientEmail, externalRecipientQuantity) = thread.findExternalRecipients(
557+
emailDictionary, aliases, trustedDomains,
558+
)
555559
if (externalRecipientQuantity == 0) return subject to subject
556560

557561
val spannedSubject = requireContext().postfixWithTag(

app/src/main/java/com/infomaniak/mail/ui/newMessage/NewMessageExternalsManager.kt

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -50,27 +50,40 @@ class NewMessageExternalsManager @Inject constructor() : NewMessageManager() {
5050
fun observeExternals(arrivedFromExistingDraft: Boolean) = with(newMessageViewModel) {
5151
Utils.waitInitMediator(initResult, mergedContacts).observe(viewLifecycleOwner) { (_, mergedContacts) ->
5252
val externalMailFlagEnabled = currentMailbox.externalMailFlagEnabled
53+
val trustedDomains = currentMailbox.trustedDomains
5354
val shouldWarnForExternal = externalMailFlagEnabled && !arrivedFromExistingDraft
5455
val emailDictionary = mergedContacts.second
5556
val aliases = currentMailbox.aliases
5657

57-
updateFields(shouldWarnForExternal, emailDictionary, aliases)
58-
updateBanner(shouldWarnForExternal, emailDictionary, aliases)
58+
updateFields(shouldWarnForExternal, emailDictionary, aliases, trustedDomains)
59+
updateBanner(shouldWarnForExternal, emailDictionary, aliases, trustedDomains)
5960
}
6061
}
6162

62-
private fun updateFields(shouldWarnForExternal: Boolean, emailDictionary: MergedContactDictionary, aliases: List<String>) {
63+
private fun updateFields(
64+
shouldWarnForExternal: Boolean,
65+
emailDictionary: MergedContactDictionary,
66+
aliases: List<String>,
67+
trustedDomains: List<String>,
68+
) {
6369
with(binding) {
64-
toField.updateExternals(shouldWarnForExternal, emailDictionary, aliases)
65-
ccField.updateExternals(shouldWarnForExternal, emailDictionary, aliases)
66-
bccField.updateExternals(shouldWarnForExternal, emailDictionary, aliases)
70+
toField.updateExternals(shouldWarnForExternal, emailDictionary, aliases, trustedDomains)
71+
ccField.updateExternals(shouldWarnForExternal, emailDictionary, aliases, trustedDomains)
72+
bccField.updateExternals(shouldWarnForExternal, emailDictionary, aliases, trustedDomains)
6773
}
6874
}
6975

70-
private fun updateBanner(shouldWarnForExternal: Boolean, emailDictionary: MergedContactDictionary, aliases: List<String>) {
76+
private fun updateBanner(
77+
shouldWarnForExternal: Boolean,
78+
emailDictionary: MergedContactDictionary,
79+
aliases: List<String>,
80+
trustedDomains: List<String>,
81+
) {
7182
with(newMessageViewModel) {
7283
if (shouldWarnForExternal && !isExternalBannerManuallyClosed) {
73-
val (externalEmail, externalQuantity) = draft.findExternalRecipientForNewMessage(aliases, emailDictionary)
84+
val (externalEmail, externalQuantity) = draft.findExternalRecipientForNewMessage(
85+
aliases, emailDictionary, trustedDomains,
86+
)
7487
externalRecipientCount.value = externalEmail to externalQuantity
7588
}
7689
}

app/src/main/java/com/infomaniak/mail/ui/newMessage/RecipientFieldView.kt

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -416,11 +416,16 @@ class RecipientFieldView @JvmOverloads constructor(
416416
return (if (recipientCount == 1) recipients.single().email else null) to recipientCount
417417
}
418418

419-
fun updateExternals(shouldWarnForExternal: Boolean, emailDictionary: MergedContactDictionary, aliases: List<String>) {
419+
fun updateExternals(
420+
shouldWarnForExternal: Boolean,
421+
emailDictionary: MergedContactDictionary,
422+
aliases: List<String>,
423+
trustedDomains: List<String>,
424+
) {
420425
for (recipient in contactChipAdapter.getRecipients()) {
421426
if (recipient.isManuallyEntered) continue
422427

423-
val shouldDisplayAsExternal = shouldWarnForExternal && recipient.isExternal(emailDictionary, aliases)
428+
val shouldDisplayAsExternal = shouldWarnForExternal && recipient.isExternal(emailDictionary, aliases, trustedDomains)
424429
recipient.initDisplayAsExternal(shouldDisplayAsExternal)
425430

426431
updateCollapsedChipValues(isSelfCollapsed)

0 commit comments

Comments
 (0)