diff --git a/enzevalos_iphone/AppDelegate.swift b/enzevalos_iphone/AppDelegate.swift index fd183d980291c096196d13cfbe6ff4f7027814f4..eb432d529935d4d72270fbf902abfaccfc08be94 100644 --- a/enzevalos_iphone/AppDelegate.swift +++ b/enzevalos_iphone/AppDelegate.swift @@ -90,8 +90,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate { self.credentialsFailed() return } - print("Google authetication successful") - print("User Email: \(userEmail)") UserManager.storeUserValue(userEmail as AnyObject, attribute: Attribute.userName) UserManager.storeUserValue(userEmail as AnyObject, attribute: Attribute.userAddr) UserManager.storeUserValue("imap.gmail.com" as AnyObject, attribute: Attribute.imapHostname) diff --git a/enzevalos_iphone/MailHandler.swift b/enzevalos_iphone/MailHandler.swift index 98068a79119bf469a8ea56a4de7411df4786d06f..b35405d56156b6c7a08d8bb9557df40783067575 100644 --- a/enzevalos_iphone/MailHandler.swift +++ b/enzevalos_iphone/MailHandler.swift @@ -155,6 +155,13 @@ class MailHandler { var IMAPIdleSession: MCOIMAPSession? var IMAPIdleSupported: Bool? + + var shouldTryRefreshOAUTH: Bool { + get { + return (UserManager.loadImapAuthType() == MCOAuthType.xoAuth2 || UserManager.loadSmtpAuthType() == MCOAuthType.xoAuth2) && + !(EmailHelper.singleton().authorization?.authState.isTokenFresh() ?? false) + } + } func addAutocryptHeader(_ builder: MCOMessageBuilder) { let adr = (UserManager.loadUserValue(Attribute.userAddr) as! String).lowercased() @@ -251,7 +258,16 @@ class MailHandler { builder.addAttachment(keyAttachment) let sendOperation = session.sendOperation(with: builder.data() , from: userID, recipients: [userID]) - sendOperation?.start(callback) + sendOperation?.start({ error in + guard error == nil else { + self.retryWithRefreshedOAuth { + self.sendSecretKey(key: key, passcode: passcode, callback: callback) + } + return + } + + callback(nil) + }) //createSendCopy(sendData: builder.openPGPEncryptedMessageData(withEncryptedData: keyData)) } @@ -391,6 +407,7 @@ class MailHandler { } } + // TODO: add OAuth refresh fileprivate func createSendCopy(sendData: Data) { let sentFolder = UserManager.backendSentFolderPath if !DataHandler.handler.existsFolder(with: sentFolder) { @@ -406,6 +423,7 @@ class MailHandler { } } + // TODO: add OAuth refresh fileprivate func createLoggingSendCopy(sendData: Data) { let sentFolder = UserManager.loadUserValue(.loggingFolderPath) as! String if !DataHandler.handler.existsFolder(with: sentFolder) { @@ -502,11 +520,12 @@ class MailHandler { if let connType = UserManager.loadUserValue(Attribute.imapConnectionType) as? Int{ imapsession.connectionType = MCOConnectionType(rawValue: connType) } - - let y = imapsession.folderStatusOperation(INBOX) - y?.start{(error, status) -> Void in - print("Folder status: \(status.debugDescription)") - } + + //TODO @Olli: was this for debug purposes or is there a use for this in production +// let y = imapsession.folderStatusOperation(INBOX) +// y?.start{(error, status) -> Void in +// print("Folder status: \(status.debugDescription)") +// } return imapsession } @@ -536,6 +555,12 @@ class MailHandler { let op = setupIMAPSession().capabilityOperation() op?.start({ (error, capabilities) in guard error == nil else { + if self.shouldTryRefreshOAUTH { + self.retryWithRefreshedOAuth { + self.checkIdleSupport(addNewMail: addNewMail) + } + return + } print("Error checking IMAP Idle capabilities: \(String(describing: error))") return } @@ -552,7 +577,9 @@ class MailHandler { let session = MCOSMTPSession() session.authType = UserManager.loadSmtpAuthType() if UserManager.loadSmtpAuthType() == MCOAuthType.xoAuth2 { - session.oAuth2Token = EmailHelper.singleton().authorization?.authState.lastTokenResponse?.accessToken + if let lastToken = EmailHelper.singleton().authorization?.authState.lastTokenResponse { + session.oAuth2Token = lastToken.accessToken + } } else { session.password = UserManager.loadUserValue(Attribute.userPW) as! String } @@ -564,6 +591,7 @@ class MailHandler { return session } + // TODO: add OAuth refresh func addFlag(_ uid: UInt64, flags: MCOMessageFlag, folder: String?) { var folderName = INBOX if let folder = folder{ @@ -594,7 +622,13 @@ class MailHandler { op?.start { error -> Void in if let err = error { - print("Error while updating flags: \(err)") + if self.shouldTryRefreshOAUTH { + self.retryWithRefreshedOAuth { + self.removeFlag(uid, flags: flags, folder: folder) + } + } else { + print("Error while updating flags: \(err)") + } } } } @@ -612,6 +646,12 @@ class MailHandler { searchOperation.start { (err, indices) -> Void in guard err == nil else { + if self.shouldTryRefreshOAUTH { + self.retryWithRefreshedOAuth { + self.loadMailsForRecord(record, folderPath: folderPath, newMailCallback: newMailCallback, completionCallback: completionCallback) + } + return + } completionCallback(true) return } @@ -648,6 +688,12 @@ class MailHandler { } fetchOperation.start { (err, msg, vanished) -> Void in guard err == nil else { + if self.shouldTryRefreshOAUTH { + self.retryWithRefreshedOAuth { + self.loadMessagesFromServer(uids, folderPath: folderPath, maxLoad: maxLoad, record: record, newMailCallback: newMailCallback, completionCallback: completionCallback) + } + return + } print("Error while fetching inbox: \(String(describing: err))") completionCallback(true) return @@ -1063,6 +1109,12 @@ class MailHandler { searchOperation?.start{(err, uids)-> Void in guard err == nil else{ + if self.shouldTryRefreshOAUTH { + self.retryWithRefreshedOAuth { + self.loadMailsSinceDate(folder: folder, since: since, newMailCallback: newMailCallback, completionCallback: completionCallback) + } + return + } completionCallback(true) return } @@ -1076,4 +1128,18 @@ class MailHandler { } } + + func retryWithRefreshedOAuth(completion: @escaping () -> ()) { + guard shouldTryRefreshOAUTH else { + print("Please only call retryWithRefreshedOAuth after checking shouldTryRefreshOAUTH or your request might be lost.") + return + } + + EmailHelper.singleton().checkIfAuthorizationIsValid({authorized in + if authorized { + self.IMAPSes = nil + } + completion() + }) + } } diff --git a/enzevalos_iphone/OAuth/EmailHelper.h b/enzevalos_iphone/OAuth/EmailHelper.h index 86c6fca61253b39f106a37d25256f5ae3a6f555c..133edca10a1e74b5204eace2efa3f7a7923b377f 100644 --- a/enzevalos_iphone/OAuth/EmailHelper.h +++ b/enzevalos_iphone/OAuth/EmailHelper.h @@ -19,5 +19,6 @@ @property(nonatomic, nullable) GTMAppAuthFetcherAuthorization *authorization; - (void)doEmailLoginIfRequiredOnVC:(UIViewController*)vc completionBlock:(dispatch_block_t)completionBlock; +- (void)checkIfAuthorizationIsValid:(void (^)(BOOL authorized))completionBlock; @end diff --git a/enzevalos_iphone/OAuth/EmailHelper.m b/enzevalos_iphone/OAuth/EmailHelper.m index 03c6da23c57833f40fe8f0c64c72a84893b1f16a..77f5563142efeaabbdaef57b15a61c3a0486b7f0 100644 --- a/enzevalos_iphone/OAuth/EmailHelper.m +++ b/enzevalos_iphone/OAuth/EmailHelper.m @@ -7,7 +7,6 @@ // #import "EmailHelper.h" -#import "AuthStateDelegate.h" #import <GTMSessionFetcher/GTMSessionFetcherService.h> #import <GTMSessionFetcher/GTMSessionFetcher.h> //#import "enzevalos_iphone-Swift.h" @@ -36,8 +35,9 @@ static NSString *const kRedirectURI = */ static NSString *const kExampleAuthorizerKey = @"googleOAuthCodingKey"; -//static GTMAppAuthDelegate *delegate = [GTMAppAuthDelegate init]; -//static OIDAuthStateChangeDelegate * delegate = GTMAppAuthDelegate(); +@interface EmailHelper () <OIDAuthStateChangeDelegate, + OIDAuthStateErrorDelegate> +@end @implementation EmailHelper @@ -97,12 +97,9 @@ static EmailHelper *shared = nil; [GTMAppAuthFetcherAuthorization authorizationFromKeychainForName:kExampleAuthorizerKey]; if (authorization.canAuthorize) { -// GTMAppAuthDelegate *delegate = [GTMAppAuthDelegate init]; - AuthStateDelegate *delegate = [[AuthStateDelegate alloc] init]; - self.authorization = authorization; - self.authorization.authState.stateChangeDelegate = delegate; - self.authorization.authState.errorDelegate = delegate; + self.authorization.authState.stateChangeDelegate = self; + self.authorization.authState.errorDelegate = self; } else { NSLog(@"EmailHelper: WARNING, loaded google authorization cannot authorize, discarding"); [GTMAppAuthFetcherAuthorization removeAuthorizationFromKeychainForName:kExampleAuthorizerKey]; @@ -189,4 +186,12 @@ static EmailHelper *shared = nil; }]; } +- (void)didChangeState:(nonnull OIDAuthState *)state { + [self saveState]; +} + +- (void)authState:(nonnull OIDAuthState *)state didEncounterAuthorizationError:(nonnull NSError *)error { + NSLog(@"Received authorization error: %@", error); +} + @end diff --git a/enzevalos_iphone/SendViewController.swift b/enzevalos_iphone/SendViewController.swift index 5138db35aed428d6258a2d771ac74174d4ec0d06..2f51a00dc1cf9da5ecd81081776bb095b412882f 100644 --- a/enzevalos_iphone/SendViewController.swift +++ b/enzevalos_iphone/SendViewController.swift @@ -461,6 +461,11 @@ class SendViewController: UIViewController { func mailSend(_ error: Error?) { if (error != nil) { + if AppDelegate.getAppDelegate().mailHandler.shouldTryRefreshOAUTH { + AppDelegate.getAppDelegate().mailHandler.retryWithRefreshedOAuth { [weak self] in + self?.pressSend(nil) + } + } NSLog("Error sending email: \(String(describing: error))") // AppDelegate.getAppDelegate().showMessage("An error occured", completion: nil) @jakob: wofür ist dieses showMessage aus AppDelegate gut? let alert = UIAlertController(title: NSLocalizedString("ReceiveError", comment: "There was an error"), message: NSLocalizedString("ErrorText", comment: ""), preferredStyle: UIAlertControllerStyle.alert) @@ -636,7 +641,7 @@ class SendViewController: UIViewController { } } - @IBAction func pressSend(_ sender: AnyObject) { + @IBAction func pressSend(_ sender: AnyObject?) { let toEntrys = toText.mailTokens let ccEntrys = ccText.mailTokens let subject = subjectText.inputText()!