Skip to content

Commit

Permalink
Merge pull request #931 from Infomaniak/handlingInvalidSignature
Browse files Browse the repository at this point in the history
Handling invalid signature, use default one.
  • Loading branch information
PhilippeWeidmann committed Aug 18, 2023
2 parents 30d4cc2 + 6103a31 commit a788eb5
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 7 deletions.
26 changes: 23 additions & 3 deletions MailCore/API/MailApiError.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,30 @@
import Foundation
import MailResources

/// Static definitions of Mail API error codes
enum MailApiErrorCode {
/// The email is not found
static let mailMessageNotFound = "mail__message_not_found"

/// Invalid credentials
static let invalidCredentials = "invalid_credentials"

/// The server does not know about the identity used in the request
static let identityNotFound = "identity__not_found"
}

public class MailApiError: MailError {
public static let apiMessageNotFound = MailApiError(code: "mail__message_not_found",
/// The email is not found
public static let apiMessageNotFound = MailApiError(code: MailApiErrorCode.mailMessageNotFound,
localizedDescription: MailResourcesStrings.Localizable
.errorMessageNotFound,
shouldDisplay: true)

public static let apiInvalidCredential = MailApiError(code: "invalid_credentials")
/// Invalid credentials
public static let apiInvalidCredential = MailApiError(code: MailApiErrorCode.invalidCredentials)

/// The server does not know bout the identity used in the request
public static let apiIdentityNotFound = MailApiError(code: MailApiErrorCode.identityNotFound, shouldDisplay: false)

static let allErrors: [MailApiError] = [
// General
Expand Down Expand Up @@ -112,7 +129,10 @@ public class MailApiError: MailError {
MailApiError(code: "attachment__store_to_drive_fail"),

// Message
MailApiError(code: "message__uid_is_not_valid")
MailApiError(code: "message__uid_is_not_valid"),

// Signatures / Identity
apiIdentityNotFound
]

static func mailApiErrorFromCode(_ code: String) -> MailApiError? {
Expand Down
52 changes: 48 additions & 4 deletions MailCore/Cache/DraftManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ public final class DraftManager {
}

/// Save a draft server side
private func saveDraftRemotely(draft: Draft, mailboxManager: MailboxManager) async {
private func saveDraftRemotely(draft: Draft, mailboxManager: MailboxManager, retry: Bool = true) async {
guard draft.identityId != nil else {
SentrySDK.capture(message: "We are trying to send a draft without an identityId, this will fail.")
return
Expand All @@ -92,13 +92,47 @@ public final class DraftManager {
do {
try await mailboxManager.save(draft: draft)
} catch {
guard error.shouldDisplay else { return }
alertDisplayable.show(message: error.localizedDescription)
// Retry with default signature on missing identity
if retry,
let mailError = error as? MailApiError,
mailError == MailApiError.apiIdentityNotFound {
guard let updatedDraft = await setDefaultSignature(draft: draft, mailboxManager: mailboxManager) else {
return
}
await saveDraftRemotely(draft: updatedDraft, mailboxManager: mailboxManager, retry: false)
}
// show error if needed
else {
guard error.shouldDisplay else { return }
alertDisplayable.show(message: error.localizedDescription)
}
}
await draftQueue.endBackgroundTask(uuid: draft.localUUID)
}

public func send(draft: Draft, mailboxManager: MailboxManager) async -> Date? {
private func setDefaultSignature(draft: Draft, mailboxManager: MailboxManager) async -> Draft? {
try? await mailboxManager.refreshAllSignatures()
let storedSignatures = mailboxManager.getStoredSignatures()
guard let defaultSignature = storedSignatures.defaultSignature else {
return nil
}

var updatedDraft: Draft?
let realm = mailboxManager.getRealm()
try? realm.write {
guard let liveDraft = realm.object(ofType: Draft.self, forPrimaryKey: draft.localUUID) else {
return
}
liveDraft.identityId = "\(defaultSignature.id)"

realm.add(liveDraft, update: .modified)

updatedDraft = liveDraft.detached()
}
return updatedDraft
}

public func send(draft: Draft, mailboxManager: MailboxManager, retry: Bool = true) async -> Date? {
alertDisplayable.show(message: MailResourcesStrings.Localizable.snackbarEmailSending)

var sendDate: Date?
Expand All @@ -110,6 +144,16 @@ public final class DraftManager {
alertDisplayable.show(message: MailResourcesStrings.Localizable.snackbarEmailSent)
sendDate = cancelableResponse.scheduledDate
} catch {
// Retry with default signature on missing identity
if retry,
let mailError = error as? MailApiError,
mailError == MailApiError.apiIdentityNotFound {
guard let updatedDraft = await setDefaultSignature(draft: draft, mailboxManager: mailboxManager) else {
return nil
}
return await send(draft: updatedDraft, mailboxManager: mailboxManager, retry: false)
}

alertDisplayable.show(message: error.localizedDescription)
}
await draftQueue.endBackgroundTask(uuid: draft.localUUID)
Expand Down
10 changes: 10 additions & 0 deletions MailCore/Cache/MailboxManager/MailboxManager+Draft.swift
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,11 @@ public extension MailboxManager {
try await deleteLocally(draft: draft)
throw error
} catch let error as MailApiError {
// Do not delete draft on invalid identity
guard error != MailApiError.apiIdentityNotFound else {
throw error
}

// The api returned an error
try await deleteLocally(draft: draft)
throw error
Expand All @@ -72,6 +77,11 @@ public extension MailboxManager {
}
}
} catch let error as MailApiError {
// Do not delete draft on invalid identity
guard error != MailApiError.apiIdentityNotFound else {
throw error
}

// The api returned an error for now we can do nothing about it so we delete the draft
try await deleteLocally(draft: draft)
throw error
Expand Down

0 comments on commit a788eb5

Please sign in to comment.