From 35f5687f4f86d0d54550182ca1cd9bb7b28c48e8 Mon Sep 17 00:00:00 2001
From: Chris Offner <chrisoffner@pm.me>
Date: Tue, 23 Mar 2021 11:24:47 +0100
Subject: [PATCH] Code cleanup & style, commented out redundant, incomplete
 code that caused warnings.

---
 enzevalos_iphone.xcodeproj/project.pbxproj    |   1 -
 enzevalos_iphone/MailSession.swift            | 450 +++++++++++-------
 enzevalos_iphone/PGP/SwiftPGP.swift           |  97 ++--
 .../SwiftUI/Compose/ComposeModel.swift        |   7 +-
 .../SwiftUI/Compose/ComposeView.swift         | 225 +++++----
 .../SwiftUI/Compose/RecipientFieldModel.swift |  43 +-
 .../SwiftUI/Compose/RecipientListView.swift   |  11 +-
 .../SwiftUI/Compose/RecipientRowView.swift    |   2 +-
 .../SwiftUI/Compose/RecipientsModel.swift     |   1 +
 .../SwiftUI/Inbox/InboxView.swift             |  41 +-
 .../SwiftUI/Inbox/MailListView.swift          |  60 ++-
 .../persistentData/AddressRecord.swift        |   5 +-
 .../persistentData/MailRecord.swift           |  15 +-
 13 files changed, 605 insertions(+), 353 deletions(-)

diff --git a/enzevalos_iphone.xcodeproj/project.pbxproj b/enzevalos_iphone.xcodeproj/project.pbxproj
index 262cbaeb..c2030646 100644
--- a/enzevalos_iphone.xcodeproj/project.pbxproj
+++ b/enzevalos_iphone.xcodeproj/project.pbxproj
@@ -1945,7 +1945,6 @@
 				3EC35F2420037651008BDF95 /* InvitationHelper.swift in Sources */,
 				47C112C22531D72E00621A07 /* PublicKeyRecord.swift in Sources */,
 				3FB75DCD25FFD37400919925 /* RecipientListView.swift in Sources */,
-				472F39901E252470009260FB /* CNMailAddressesExtension.swift in Sources */,
 				477120CD254C76AE00B28C64 /* FolderOverView.swift in Sources */,
 				4733B202252B142C00AB5600 /* Properties.swift in Sources */,
 				47FAE3492524FB58005A1BCB /* AddressRecord.swift in Sources */,
diff --git a/enzevalos_iphone/MailSession.swift b/enzevalos_iphone/MailSession.swift
index c9ccdd74..d4d6cf2c 100644
--- a/enzevalos_iphone/MailSession.swift
+++ b/enzevalos_iphone/MailSession.swift
@@ -32,7 +32,11 @@ class MailServer: Comparable {
     }
     
     static func == (lhs: MailServer, rhs: MailServer) -> Bool {
-        return lhs.sessionType == rhs.sessionType && lhs.hostname == rhs.hostname && lhs.port == rhs.port && lhs.connectionType == rhs.connectionType && lhs.authType == rhs.authType
+        return lhs.sessionType == rhs.sessionType
+            && lhs.hostname == rhs.hostname
+            && lhs.port == rhs.port
+            && lhs.connectionType == rhs.connectionType
+            && lhs.authType == rhs.authType
     }
     
     private static let maxWaitingSeconds = 15
@@ -60,16 +64,18 @@ class MailServer: Comparable {
     
     var possibleAuthTypes: [MCOAuthType] = []
     var toTestConnType: Set<MCOConnectionType> = []
-    var toTestServers: [(hostname: String, port: UInt32, authTyp: MCOAuthType, connType: MCOConnectionType)] = []
+    var toTestServers: [(hostname: String,
+                         port: UInt32,
+                         authTyp: MCOAuthType,
+                         connType: MCOConnectionType)] = []
     var createdTestServers = false
-    
     var receivedAuthTypes = false
     var loggerCalled = false
     var works = false
     var sendCallback = false
     
     var isTLS: Bool {
-        get{
+        get {
             return connectionType == MCOConnectionType.TLS
         }
     }
@@ -90,9 +96,16 @@ class MailServer: Comparable {
             return msg
         }
     }
-   
     
-    init(sessionType: SessionType, username: String, password: String, hostname: String, port: UInt32, connectionType: MCOConnectionType?, authType: MCOAuthType? = nil, callback: @escaping (_ error: MailServerConnectionError?, _ server: MailServer) -> ()) {
+    
+    init(sessionType: SessionType,
+         username: String,
+         password: String,
+         hostname: String,
+         port: UInt32,
+         connectionType: MCOConnectionType?,
+         authType: MCOAuthType? = nil,
+         callback: @escaping (_ error: MailServerConnectionError?, _ server: MailServer) -> ()) {
         self.sessionType = sessionType
         self.hostname = hostname
         self.port = port
@@ -101,78 +114,115 @@ class MailServer: Comparable {
         if let connectionType = connectionType {
             self.connectionType = connectionType
             self.toTestConnType = []
-        }
-        else if port == 143 || port == 587 || port == 25 {
+        } else if port == 143 || port == 587 || port == 25 {
             self.connectionType = .startTLS
-            
-        }
-        else {
-             self.connectionType = .TLS
+        } else {
+            self.connectionType = .TLS
         }
         self.username = username
         self.password = password
-    
         self.callback = callback
     }
     
-    convenience init(sessionType: SessionType, username: String, password: String, serverConfig: MCONetService, callback: @escaping (_ error: MailServerConnectionError?, _ server: MailServer) -> ()) throws {
-        if let serverInfo = serverConfig.info(), let hostname = serverInfo["hostname"] as? String, let port = serverInfo["port"] as? UInt32 {
+    convenience init(sessionType: SessionType,
+                     username: String,
+                     password: String,
+                     serverConfig: MCONetService,
+                     callback: @escaping (_ error: MailServerConnectionError?,
+                                          _ server: MailServer) -> ()) throws {
+        if let serverInfo = serverConfig.info(),
+           let hostname = serverInfo["hostname"] as? String,
+           let port = serverInfo["port"] as? UInt32 {
             var conn: MCOConnectionType? = nil
+            
             if let trans = serverInfo["ssl"] as? Bool, trans {
                 conn = MCOConnectionType.TLS
             }
+            
             if let trans = serverInfo["starttls"] as? Bool, trans {
                 conn = MCOConnectionType.startTLS
             }
-            self.init(sessionType: sessionType, username: username, password: password, hostname: hostname, port: port, connectionType: conn, callback: callback)
-        }
-        else {
-           throw MailServerConnectionError.NoData
+            
+            self.init(sessionType: sessionType,
+                      username: username,
+                      password: password,
+                      hostname: hostname,
+                      port: port,
+                      connectionType: conn,
+                      callback: callback)
+        } else {
+            throw MailServerConnectionError.NoData
         }
     }
     
-    convenience init(userValues sessionType: SessionType, callback: @escaping (_ error: MailServerConnectionError?, _ server: MailServer) -> ())  throws{
+    convenience init(userValues sessionType: SessionType,
+                     callback: @escaping (_ error: MailServerConnectionError?,
+                                          _ server: MailServer) -> ()) throws {
         if let username = UserManager.loadUserValue(Attribute.accountname) as? String,
-            let password = UserManager.loadUserValue(Attribute.userPW) as? String {
-                if sessionType == SessionType.IMAP, let hostname = UserManager.loadUserValue(Attribute.imapHostname) as? String, let port = UserManager.loadUserValue(Attribute.imapPort) as? UInt32{
-                    var connType: MCOConnectionType? = nil
-                    if let rawtype = UserManager.loadUserValue(Attribute.imapConnectionType) as? Int {
-                        connType = MCOConnectionType.init(rawValue: rawtype)
-                    }
-                    var authType: MCOAuthType? = nil
-                    if let rawtype = UserManager.loadUserValue(Attribute.smtpAuthType) as? Int {
-                        authType = MCOAuthType.init(rawValue: rawtype)
-                    }
-                    self.init(sessionType: sessionType, username: username, password: password, hostname: hostname , port: port, connectionType: connType, authType: authType, callback: callback)
-                    if let authType = UserManager.loadUserValue(Attribute.imapAuthType) as? Int {
-                        self.authType = MCOAuthType.init(rawValue: authType)
-                    }
-                    
+           let password = UserManager.loadUserValue(Attribute.userPW) as? String {
+            if sessionType == SessionType.IMAP,
+               let hostname = UserManager.loadUserValue(Attribute.imapHostname) as? String,
+               let port = UserManager.loadUserValue(Attribute.imapPort) as? UInt32 {
+                var connType: MCOConnectionType? = nil
+                if let rawtype = UserManager.loadUserValue(Attribute.imapConnectionType) as? Int {
+                    connType = MCOConnectionType.init(rawValue: rawtype)
                 }
-                else if let hostname = UserManager.loadUserValue(Attribute.smtpHostname) as? String, let port = UserManager.loadUserValue(Attribute.smtpPort) as? UInt32  {
-                    var connType: MCOConnectionType? = nil
-                    if let rawtype = UserManager.loadUserValue(Attribute.smtpConnectionType) as? Int {
-                        connType = MCOConnectionType.init(rawValue: rawtype)
-                    }
-                    var authType: MCOAuthType? = nil
-                    if let rawtype = UserManager.loadUserValue(Attribute.smtpAuthType) as? Int {
-                        authType = MCOAuthType.init(rawValue: rawtype)
-                    }
-                    self.init(sessionType: sessionType, username: username, password: password, hostname: hostname, port: port, connectionType: connType, authType: authType, callback: callback)
-                    if let authType = UserManager.loadUserValue(Attribute.smtpAuthType) as? Int {
-                        self.authType = MCOAuthType.init(rawValue: authType)
-                    }
+                
+                var authType: MCOAuthType? = nil
+                if let rawtype = UserManager.loadUserValue(Attribute.smtpAuthType) as? Int {
+                    authType = MCOAuthType.init(rawValue: rawtype)
                 }
-                else {
-                    throw MailServerConnectionError.NoData
+                
+                self.init(sessionType: sessionType,
+                          username: username,
+                          password: password,
+                          hostname: hostname,
+                          port: port,
+                          connectionType: connType,
+                          authType: authType,
+                          callback: callback)
+                if let authType = UserManager.loadUserValue(Attribute.imapAuthType) as? Int {
+                    self.authType = MCOAuthType.init(rawValue: authType)
                 }
-        }
-        else {
+            } else if let hostname = UserManager.loadUserValue(Attribute.smtpHostname) as? String,
+                      let port = UserManager.loadUserValue(Attribute.smtpPort) as? UInt32 {
+                var connType: MCOConnectionType? = nil
+                
+                if let rawtype = UserManager.loadUserValue(Attribute.smtpConnectionType) as? Int {
+                    connType = MCOConnectionType.init(rawValue: rawtype)
+                }
+                
+                var authType: MCOAuthType? = nil
+                if let rawtype = UserManager.loadUserValue(Attribute.smtpAuthType) as? Int {
+                    authType = MCOAuthType.init(rawValue: rawtype)
+                }
+                
+                self.init(sessionType: sessionType,
+                          username: username,
+                          password: password,
+                          hostname: hostname,
+                          port: port,
+                          connectionType: connType,
+                          authType: authType,
+                          callback: callback)
+                
+                if let authType = UserManager.loadUserValue(Attribute.smtpAuthType) as? Int {
+                    self.authType = MCOAuthType.init(rawValue: authType)
+                }
+            } else {
+                throw MailServerConnectionError.NoData
+            }
+        } else {
             throw MailServerConnectionError.NoData
         }
     }
     
-    convenience init(defaultValues sessionType: SessionType, mailAddr: String, username: String, password: String, callback: @escaping (_ error: MailServerConnectionError?, _ server: MailServer) -> ()) {
+    convenience init(defaultValues sessionType: SessionType,
+                     mailAddr: String,
+                     username: String,
+                     password: String,
+                     callback: @escaping (_ error: MailServerConnectionError?,
+                                          _ server: MailServer) -> ()) {
         var auth = MCOAuthType.init(rawValue: 0)
         var conn = MCOConnectionType.TLS
         var port: UInt32 = 111
@@ -186,43 +236,51 @@ class MailServer: Comparable {
             if let authTypeValue = Attribute.imapAuthType.defaultValue as? Int {
                 auth = MCOAuthType.init(rawValue: authTypeValue)
             }
+            
             if let connectionTypeValue = Attribute.imapConnectionType.defaultValue as? Int {
                 conn = MCOConnectionType.init(rawValue: connectionTypeValue)
             }
+            
             if let name = Attribute.imapHostname.defaultValue as? String, domain == nil {
                 hostname = name
+            } else if !MailSession.IMAPPREFIX.isEmpty{
+                hostname = MailSession.IMAPPREFIX[0] + "." + hostname
             }
-            else if !MailSession.IMAPPREFIX.isEmpty{
-                hostname = MailSession.IMAPPREFIX[0]+"."+hostname
-            }
+            
             if let p = Attribute.imapPort.defaultValue as? UInt32 {
                 port = p
-            }
-            else if !MailSession.IMAPPORT.isEmpty {
+            } else if !MailSession.IMAPPORT.isEmpty {
                 port = MailSession.IMAPPORT[0]
             }
-        }
-        else {
+        } else {
             if let authTypeValue = Attribute.smtpAuthType.defaultValue as? Int {
                 auth = MCOAuthType.init(rawValue: authTypeValue)
             }
+            
             if let connectionTypeValue = Attribute.smtpConnectionType.defaultValue as? Int {
                 conn = MCOConnectionType.init(rawValue: connectionTypeValue)
             }
+            
             if let name = Attribute.smtpHostname.defaultValue as? String, domain == nil {
                 hostname = name
-            }
-            else if !MailSession.SMTPPREFIX.isEmpty{
+            } else if !MailSession.SMTPPREFIX.isEmpty{
                 hostname = MailSession.SMTPPREFIX[0]+"."+hostname
             }
+            
             if let p = Attribute.smtpPort.defaultValue as? UInt32 {
                 port = p
-            }
-            else if !MailSession.SMTPPORT.isEmpty {
+            } else if !MailSession.SMTPPORT.isEmpty {
                 port = MailSession.SMTPPORT[0]
             }
         }
-        self.init(sessionType: sessionType, username: username, password: password, hostname: hostname, port: port, connectionType: conn, authType: auth, callback: callback)
+        self.init(sessionType: sessionType,
+                  username: username,
+                  password: password,
+                  hostname: hostname,
+                  port: port,
+                  connectionType: conn,
+                  authType: auth,
+                  callback: callback)
     }
     
     func storeToUserDefaults(mailAddr: String) -> Bool {
@@ -230,91 +288,124 @@ class MailServer: Comparable {
             let connectionTypeValue = connectionType.rawValue
             let authTypeValue = authType.rawValue
             if sessionType == SessionType.IMAP {
-                UserManager.storeUserValue(hostname as AnyObject, attribute: Attribute.imapHostname)
-                UserManager.storeUserValue(port as AnyObject, attribute: Attribute.imapPort)
-                UserManager.storeUserValue(connectionTypeValue as AnyObject, attribute: Attribute.imapConnectionType)
-                UserManager.storeUserValue(authTypeValue as AnyObject, attribute: Attribute.imapAuthType)
-            }
-            else {
-                UserManager.storeUserValue(hostname as AnyObject, attribute: Attribute.smtpHostname)
-                UserManager.storeUserValue(port as AnyObject, attribute: Attribute.smtpPort)
-                UserManager.storeUserValue(connectionTypeValue as AnyObject, attribute: Attribute.smtpConnectionType)
-                UserManager.storeUserValue(authTypeValue as AnyObject, attribute: Attribute.smtpAuthType)
-            }
-            UserManager.storeUserValue(password as AnyObject, attribute: Attribute.userPW)
-            UserManager.storeUserValue(username as AnyObject, attribute: Attribute.accountname)
-            UserManager.storeUserValue(mailAddr.lowercased() as AnyObject, attribute: Attribute.userAddr)
-            UserManager.storeUserValue(mailAddr.lowercased() as AnyObject, attribute: Attribute.userDisplayName) 
+                UserManager.storeUserValue(hostname as AnyObject,
+                                           attribute: Attribute.imapHostname)
+                UserManager.storeUserValue(port as AnyObject,
+                                           attribute: Attribute.imapPort)
+                UserManager.storeUserValue(connectionTypeValue as AnyObject,
+                                           attribute: Attribute.imapConnectionType)
+                UserManager.storeUserValue(authTypeValue as AnyObject,
+                                           attribute: Attribute.imapAuthType)
+            } else {
+                UserManager.storeUserValue(hostname as AnyObject,
+                                           attribute: Attribute.smtpHostname)
+                UserManager.storeUserValue(port as AnyObject,
+                                           attribute: Attribute.smtpPort)
+                UserManager.storeUserValue(connectionTypeValue as AnyObject,
+                                           attribute: Attribute.smtpConnectionType)
+                UserManager.storeUserValue(authTypeValue as AnyObject,
+                                           attribute: Attribute.smtpAuthType)
+            }
+            UserManager.storeUserValue(password as AnyObject,
+                                       attribute: Attribute.userPW)
+            UserManager.storeUserValue(username as AnyObject,
+                                       attribute: Attribute.accountname)
+            UserManager.storeUserValue(mailAddr.lowercased() as AnyObject,
+                                       attribute: Attribute.userAddr)
+            UserManager.storeUserValue(mailAddr.lowercased() as AnyObject,
+                                       attribute: Attribute.userDisplayName)
             return true
         }
-       return false
+        return false
     }
     
-    func createSMTPSession(logging: Bool = true, credentials: Bool = false, withAuthType: Bool = true) -> MCOSMTPSession? {
+    func createSMTPSession(logging: Bool = true,
+                           credentials: Bool = false,
+                           withAuthType: Bool = true) -> MCOSMTPSession? {
         loggerCalled = false
         guard sessionType == .SMTP else {
             return nil
         }
         let session = MCOSMTPSession()
         session.timeout = TimeInterval(MailServer.maxWaitingSeconds)
-        
         session.hostname = hostname.remove(seperatedBy: .whitespacesAndNewlines)
         session.port = port
         session.connectionType = connectionType
+        
         if logging {
             session.connectionLogger = parseLog
         }
+        
         if withAuthType, let auth = authType {
             session.authType = auth
             if session.authType == MCOAuthType.xoAuth2 {
-                session.oAuth2Token = EmailHelper.singleton().authorization?.authState.lastTokenResponse?.accessToken
+                session.oAuth2Token = EmailHelper
+                    .singleton()
+                    .authorization?
+                    .authState
+                    .lastTokenResponse?
+                    .accessToken
             }
         }
+        
         if credentials {
             session.username = username.lowercased()
             session.password = password
         }
+        
         return session
     }
     
-    func createIMAPSession(logging: Bool = true, credentials: Bool = false, withAuthType: Bool = true) -> MCOIMAPSession? {
+    func createIMAPSession(logging: Bool = true,
+                           credentials: Bool = false,
+                           withAuthType: Bool = true) -> MCOIMAPSession? {
         loggerCalled = false
+        
         guard sessionType == .IMAP else {
             return nil
         }
+        
         let session = MCOIMAPSession()
         session.timeout = TimeInterval(MailServer.maxWaitingSeconds)
-
         session.hostname = hostname.remove(seperatedBy: .whitespacesAndNewlines)
         session.port = port
         session.connectionType = connectionType
+        
         if logging {
             session.connectionLogger = parseLog
         }
+        
         if withAuthType, let auth = authType {
             session.authType = auth
             if session.authType == MCOAuthType.xoAuth2 {
-                session.oAuth2Token = EmailHelper.singleton().authorization?.authState.lastTokenResponse?.accessToken
+                session.oAuth2Token = EmailHelper
+                    .singleton()
+                    .authorization?
+                    .authState
+                    .lastTokenResponse?
+                    .accessToken
             }
         }
+        
         if credentials {
             session.username = username
             session.password = password
         }
+        
         return session
     }
     
     func findHost() -> Bool{
-        guard LetterboxModel.currentReachabilityStatus != .notReachable  else {
+        guard LetterboxModel.currentReachabilityStatus != .notReachable else {
             sendCallback = true
             self.callback(MailServerConnectionError.NoInternetconnection, self)
             return false
         }
+        
         toTestConnType.remove(connectionType)
         if sessionType == SessionType.IMAP {
             return findIMAPHost()
-        }
-        else {
+        } else {
             if self.possibleAuthTypes.isEmpty {
                 self.possibleAuthTypes = MailSession.AUTHTYPE
             }
@@ -330,8 +421,7 @@ class MailServer: Comparable {
                         if let newType = self.toTestConnType.popFirst() {
                             self.connectionType = newType
                             _ = self.findHost()
-                        }
-                        else if self.toTestConnType.isEmpty && !self.sendCallback {
+                        } else if self.toTestConnType.isEmpty && !self.sendCallback {
                             self.sendCallback = true
                             self.callback(MailServerConnectionError.ImapSetupError, self)
                         }
@@ -351,12 +441,16 @@ class MailServer: Comparable {
     }
     
     private func findSMTPHost() -> Bool {
-        guard let session = createSMTPSession(logging: true, credentials: true, withAuthType: true) else {
+        guard let session = createSMTPSession(logging: true,
+                                              credentials: true,
+                                              withAuthType: true) else {
             return false
         }
+        
         guard let op = session.loginOperation() else {
             return false
         }
+        
         op.start({[unowned self] (error: Error?) -> () in
             guard error == nil else {
                 self.failedAttempts = self.failedAttempts + 1
@@ -364,8 +458,7 @@ class MailServer: Comparable {
                     let serverError = MailServerConnectionError.findErrorCode(error: error)
                     if self.sendCallback(session: session, error: serverError) {
                         self.callback(MailServerConnectionError.SmtpSetupError, self)
-                    }
-                    else {
+                    } else {
                         if !self.findSMTPHost() {
                             self.callback(MailServerConnectionError.SmtpSetupError, self)
                         }
@@ -391,7 +484,10 @@ class MailServer: Comparable {
             return true
         }
         switch error {
-        case .AuthenticationError, .AuthenticationRequiredError, .CertificateError, .GmailIMAPNotEnabledError:
+        case .AuthenticationError,
+             .AuthenticationRequiredError,
+             .CertificateError,
+             .GmailIMAPNotEnabledError:
             return true
         default:
             if toTestServers.count == 0 && createdTestServers {
@@ -406,7 +502,6 @@ class MailServer: Comparable {
             self.authType = next.authTyp
             self.connectionType = next.connType
             return false
-            
         }
     }
     
@@ -417,7 +512,7 @@ class MailServer: Comparable {
         }
         createdTestServers = true
     }
-
+    
     
     private func parseLog(logger: Any, type: MCOConnectionLogType, data: Data?) {
         self.loggerCalled = true
@@ -441,7 +536,9 @@ class MailServer: Comparable {
         if let auth = possibleAuthTypes.last {
             possibleAuthTypes.removeLast()
             self.authType = auth
-            if let session = createIMAPSession(logging: true, credentials: false, withAuthType: true) {
+            if let session = createIMAPSession(logging: true,
+                                               credentials: false,
+                                               withAuthType: true) {
                 if let x = session.connectOperation(){
                     x.start({[unowned self](error: Error?) -> () in
                         guard error == nil else {
@@ -470,18 +567,17 @@ class MailServer: Comparable {
                         self.authType = self.possibleAuthTypes.removeLast()
                         self.testUsernameAndPW()
                         return
-                    }
-                    else if conError != MailServerConnectionError.AuthenticationError && (!self.receivedAuthTypes || !self.possibleAuthTypes.isEmpty) && !self.possibleAuthTypes.isEmpty{
+                    } else if conError != MailServerConnectionError.AuthenticationError
+                                && (!self.receivedAuthTypes || !self.possibleAuthTypes.isEmpty)
+                                && !self.possibleAuthTypes.isEmpty {
                         self.authType = self.possibleAuthTypes.removeLast()
                         self.testUsernameAndPW()
                         return
-                    }
-                    else if !self.sendCallback {
+                    } else if !self.sendCallback {
                         self.sendCallback = true
                         self.callback(conError, self)
                     }
-                }
-                else {
+                } else {
                     self.works = true
                     if !self.sendCallback {
                         self.sendCallback = true
@@ -499,13 +595,24 @@ class MailSession {
     static let SMTPPREFIX = ["smtp", "mail", "outgoing", "", "mx"]
     static let IMAPPREFIX = ["imap", "mail", "", "mx"]
     static let IMAPPORT: [UInt32] = [993, 143]
-    static let AUTHTYPE = [MCOAuthType.saslPlain, MCOAuthType.saslLogin, MCOAuthType.SASLNTLM, MCOAuthType.saslKerberosV4, MCOAuthType.SASLCRAMMD5, MCOAuthType.SASLDIGESTMD5, MCOAuthType.SASLGSSAPI, MCOAuthType.SASLSRP, MCOAuthType.init(rawValue: 0)]
-    static let CONNTECTIONTYPE = [MCOConnectionType.TLS, MCOConnectionType.startTLS] // We do not test for plain connections!
+    static let AUTHTYPE = [MCOAuthType.saslPlain,
+                           MCOAuthType.saslLogin,
+                           MCOAuthType.SASLNTLM,
+                           MCOAuthType.saslKerberosV4,
+                           MCOAuthType.SASLCRAMMD5,
+                           MCOAuthType.SASLDIGESTMD5,
+                           MCOAuthType.SASLGSSAPI,
+                           MCOAuthType.SASLSRP,
+                           MCOAuthType.init(rawValue: 0)]
+    // We do not test for plain connections!
+    static let CONNTECTIONTYPE = [MCOConnectionType.TLS, MCOConnectionType.startTLS]
     
     var defaultIMAPSession: MCOIMAPSession? {
         get {
             if let server = try? MailServer(userValues: sessionType, callback: callback) {
-                if let session = server.createIMAPSession(logging: false, credentials: true, withAuthType: true) {
+                if let session = server.createIMAPSession(logging: false,
+                                                          credentials: true,
+                                                          withAuthType: true) {
                     return session
                 }
             }
@@ -515,8 +622,11 @@ class MailSession {
     
     var defaultSMTPSession: MCOSMTPSession? {
         get {
-            if let server = try? MailServer(userValues: sessionType, callback: callback) , let session = server.createSMTPSession(logging: false, credentials: true, withAuthType: true){
-                
+            if let server = try? MailServer(userValues: sessionType,
+                                            callback: callback),
+               let session = server.createSMTPSession(logging: false,
+                                                      credentials: true,
+                                                      withAuthType: true) {
                 return session
             }
             return nil
@@ -528,7 +638,7 @@ class MailSession {
     var username: String
     var password: String
     var errors: Set<MailServerConnectionError> = Set()
-
+    
     private var possibleServers: [MailServer] = []
     private var counter = -1
     private var success = false
@@ -555,40 +665,45 @@ class MailSession {
                     return server
                 }
             }
-            return MailServer(defaultValues: sessionType, mailAddr: mailAddr, username: username, password: password, callback: callback)
+            return MailServer(defaultValues: sessionType,
+                              mailAddr: mailAddr,
+                              username: username,
+                              password: password,
+                              callback: callback)
         }
     }
     
-    
-    
-    init(configSession sessionType: SessionType, mailAddress: String, password: String, username: String?) {
+    init(configSession sessionType: SessionType,
+         mailAddress: String,
+         password: String,
+         username: String?) {
         self.sessionType = sessionType
         self.mailAddr = mailAddress
         self.password = password
         if let name = username, !name.isEmpty {
             self.username = name
-        }
-        else {
+        } else {
             self.username = mailAddr
         }
     }
     
     init(loadUserDefaults sessionType: SessionType) throws{
         self.sessionType = sessionType
+        
         if let username = UserManager.loadUserValue(Attribute.accountname) as? String {
             self.username = username
-        }
-        else if let username = UserManager.loadUserValue(Attribute.userAddr) as? String {
+        } else if let username = UserManager.loadUserValue(Attribute.userAddr) as? String {
             self.username = username
-        }
-        else {
+        } else {
             throw MailServerConnectionError.AuthenticationError
         }
+        
         if let pw = UserManager.loadUserValue(Attribute.userPW) as? String {
             self.password = pw
-        }else {
+        } else {
             throw MailServerConnectionError.AuthenticationError
         }
+        
         if let addr = UserManager.loadUserValue(Attribute.userAddr) as? String {
             mailAddr = addr
         } else {
@@ -600,9 +715,8 @@ class MailSession {
         listeners.append(listener)
     }
     
-    /*
-     Stores a working server configuration to user defaults.
-    */
+    
+    /// Stores a working server configuration to user defaults.
     func storeToUserDefaults() -> Bool {
         workingServers.sort()
         workingServers.reverse()
@@ -627,7 +741,14 @@ class MailSession {
         if let rawValue = authType {
             auth = MCOAuthType.init(rawValue: rawValue)
         }
-        let server = MailServer(sessionType: sessionType, username: username, password: password, hostname: hostname, port: port, connectionType: MCOConnectionType.init(rawValue: connType), authType: auth, callback: callback)
+        let server = MailServer(sessionType: sessionType,
+                                username: username,
+                                password: password,
+                                hostname: hostname,
+                                port: port,
+                                connectionType: MCOConnectionType.init(rawValue: connType),
+                                authType: auth,
+                                callback: callback)
         possibleServers.append(server)
     }
     
@@ -635,18 +756,20 @@ class MailSession {
         return searchForServerConfig(hostFromAdr: false)
     }
     
-    /*
-     We test all common server configurations (common prefixe x common ports x {TLS, startTLS} ). This may take some time.
-     */
+    // We test all common server configurations (common prefixe x common ports x {TLS, startTLS} ).
+    // This may take some time.
     func startLongSearchOfServerConfig(hostFromAdr: Bool) -> Bool {
         // Try to find a possible config
         let (_, server) = MailSession.splitAddr(userAddr: self.mailAddr)
         if let domain = server {
             if self.sessionType == SessionType.IMAP {
-                createServers(domain: domain, prefixes: MailSession.IMAPPREFIX, ports: [UInt32(111)])
-            }
-            else {
-                createServers(domain: domain, prefixes: MailSession.SMTPPREFIX, ports: MailSession.SMTPPORT)
+                createServers(domain: domain,
+                              prefixes: MailSession.IMAPPREFIX,
+                              ports: [UInt32(111)])
+            } else {
+                createServers(domain: domain,
+                              prefixes: MailSession.SMTPPREFIX,
+                              ports: MailSession.SMTPPORT)
             }
         }
         return searchForServerConfig(hostFromAdr: hostFromAdr)
@@ -678,14 +801,23 @@ class MailSession {
         possibleServers = []
         for prefix in prefixes {
             for port in ports {
-                // We check both connection types in parallel
-                // because it takes a long time if we start with the wrong conntection type (TLS or startTLS)
+                // We check both connection types in parallel because it takes a long
+                // time if we start with the wrong conntection type (TLS or startTLS)
                 for conType in MailSession.CONNTECTIONTYPE {
-                    var hostname = prefix+"."+domain
+                    var hostname = prefix + "." + domain
+                    
                     if prefix.isEmpty {
                         hostname = domain
                     }
-                    let server = MailServer(sessionType: sessionType, username: username, password: password, hostname: hostname, port: port, connectionType: conType, authType: nil, callback: callback)
+                    
+                    let server = MailServer(sessionType: sessionType,
+                                            username: username,
+                                            password: password,
+                                            hostname: hostname,
+                                            port: port,
+                                            connectionType: conType,
+                                            authType: nil,
+                                            callback: callback)
                     possibleServers.append(server)
                 }
             }
@@ -702,13 +834,12 @@ class MailSession {
     }
     
     private func callback(error: MailServerConnectionError?, server: MailServer) {
-        DispatchQueue.main.async(execute:{
+        DispatchQueue.main.async {
             if error == nil {
                 self.success = true
                 self.workingServers.append(server)
                 self.notifyListener()
-            }
-            else {
+            } else {
                 if let error = error {
                     self.errors.insert(error)
                 }
@@ -718,7 +849,7 @@ class MailSession {
                     self.notifyListener()
                 }
             }
-        })
+        }
     }
     
     private func readJson() -> [MCONetService] {
@@ -729,8 +860,7 @@ class MailSession {
             if let provider = manager.provider(forEmail: mailAddr){
                 if sessionType == SessionType.IMAP {
                     servers = provider.imapServices()
-                }
-                else {
+                } else {
                     servers = provider.smtpServices()
                 }
             }
@@ -785,7 +915,7 @@ extension MCOConnectionType: Equatable, Hashable {
         }
     }
     
-    static func parseConnType(msg: String) -> MCOConnectionType?{
+    static func parseConnType(msg: String) -> MCOConnectionType? {
         /*
          RFC 3501 (IMAP):
          See: https://tools.ietf.org/html/rfc3501#section-6.1.1
@@ -794,7 +924,7 @@ extension MCOConnectionType: Equatable, Hashable {
         if msg.contains("starttls".lowercased()) {
             return MCOConnectionType.startTLS
         }
-        else if msg.contains("tls".lowercased()) && msg.contains("CAPABILITY".lowercased()){
+        else if msg.contains("tls".lowercased()) && msg.contains("CAPABILITY".lowercased()) {
             return MCOConnectionType.TLS
         }
         return nil
@@ -842,10 +972,8 @@ extension MCOAuthType: Comparable {
     }
     
     static func parseAuthType(msg: String) -> [MCOAuthType] {
-        /*
-         RFC 3501 (IMAP):
-         See: https://tools.ietf.org/html/rfc3501#section-6.1.1
-         */
+        // RFC 3501 (IMAP):
+        // See: https://tools.ietf.org/html/rfc3501#section-6.1.1
         let msg = msg.lowercased()
         var authTypes: [MCOAuthType] = []
         if msg.contains("CAPABILITY".lowercased()) { // IMAP
@@ -861,23 +989,23 @@ extension MCOAuthType: Comparable {
             if msg.contains("AUTH=GSSAPI".lowercased()) {
                 authTypes.append(MCOAuthType.SASLGSSAPI)
             }
-            if msg.contains("AUTH=Kerberos".lowercased()){
+            if msg.contains("AUTH=Kerberos".lowercased()) {
                 authTypes.append(MCOAuthType.saslKerberosV4)
             }
-            if msg.contains("AUTH=LSRP".lowercased()){
+            if msg.contains("AUTH=LSRP".lowercased()) {
                 authTypes.append(MCOAuthType.SASLSRP)
             }
-            if msg.contains("AUTH=LNTLM".lowercased()){
+            if msg.contains("AUTH=LNTLM".lowercased()) {
                 authTypes.append(MCOAuthType.SASLNTLM)
             }
-            if msg.contains("AUTH=CRAMMD5".lowercased()){
+            if msg.contains("AUTH=CRAMMD5".lowercased()) {
                 authTypes.append(MCOAuthType.SASLCRAMMD5)
             }
-            if msg.contains("AUTH=DIGESTMD5".lowercased()){
+            if msg.contains("AUTH=DIGESTMD5".lowercased()) {
                 authTypes.append(MCOAuthType.SASLDIGESTMD5)
             }
-        }
-        else if msg.contains("250-AUTH".lowercased()) { // SMTP
+        } else if msg.contains("250-AUTH".lowercased()) {
+            // SMTP
             if msg.contains("XOAUTH2".lowercased()) {
                 authTypes.append(MCOAuthType.xoAuth2)
             }
@@ -890,19 +1018,19 @@ extension MCOAuthType: Comparable {
             if msg.contains("GSSAPI".lowercased()) {
                 authTypes.append(MCOAuthType.SASLGSSAPI)
             }
-            if msg.contains("Kerberos".lowercased()){
+            if msg.contains("Kerberos".lowercased()) {
                 authTypes.append(MCOAuthType.saslKerberosV4)
             }
-            if msg.contains("LSRP".lowercased()){
+            if msg.contains("LSRP".lowercased()) {
                 authTypes.append(MCOAuthType.SASLSRP)
             }
-            if msg.contains("LNTLM".lowercased()){
+            if msg.contains("LNTLM".lowercased()) {
                 authTypes.append(MCOAuthType.SASLNTLM)
             }
-            if msg.contains("CRAMMD5".lowercased()){
+            if msg.contains("CRAMMD5".lowercased()) {
                 authTypes.append(MCOAuthType.SASLCRAMMD5)
             }
-            if msg.contains("DIGESTMD5".lowercased()){
+            if msg.contains("DIGESTMD5".lowercased()) {
                 authTypes.append(MCOAuthType.SASLDIGESTMD5)
             }
         }
diff --git a/enzevalos_iphone/PGP/SwiftPGP.swift b/enzevalos_iphone/PGP/SwiftPGP.swift
index 1a7ece17..64ad54fe 100644
--- a/enzevalos_iphone/PGP/SwiftPGP.swift
+++ b/enzevalos_iphone/PGP/SwiftPGP.swift
@@ -367,14 +367,14 @@ class SwiftPGP: Encryption {
                         passcode = generatePW(size: PasscodeSize, splitInBlocks: true)
                     }
                     exportPwKeyChain[id] = passcode
-                    if let message = armoredKey.data(using: .utf8) {
-                        /*
-                        if let cipher = try? ObjectivePGP.symmetricEncrypt(message, signWith: nil, encryptionKey: passcode, passphrase: passcode, armored: false){
-                            let armorMessage =  Armor.armored(cipher, as: PGPArmorType.message)
-                            return armorMessage
-                        }
-                        */
-                    }
+//                    if let message = armoredKey.data(using: .utf8) {
+//
+//                        if let cipher = try? ObjectivePGP.symmetricEncrypt(message, signWith: nil, encryptionKey: passcode, passphrase: passcode, armored: false){
+//                            let armorMessage =  Armor.armored(cipher, as: PGPArmorType.message)
+//                            return armorMessage
+//                        }
+//
+//                    }
                     return nil
                 }
                 return armoredKey
@@ -384,13 +384,20 @@ class SwiftPGP: Encryption {
     }
     
     func importKey(_ passcode: String, key: String) -> [String] {
-        if let keyData = try? Armor.readArmored(key) {
-            /*
-            if let plaintext = try? ObjectivePGP.symmetricDecrypt(keyData, key: passcode, verifyWith: nil, signed: nil, valid: nil, integrityProtected: nil), let ids = try? importKeys(data: plaintext, pw: nil, secret: true) {
-                return ids
-            }
- */
-        }
+//        if let keyData = try? Armor.readArmored(key) {
+//            if let plaintext = try? ObjectivePGP
+//                .symmetricDecrypt(keyData,
+//                                  key: passcode,
+//                                  verifyWith: nil,
+//                                  signed: nil,
+//                                  valid: nil,
+//                                  integrityProtected: nil),
+//               let ids = try? importKeys(data: plaintext,
+//                                         pw: nil,
+//                                         secret: true) {
+//                return ids
+//            }
+//        }
         return []
     }
     
@@ -817,39 +824,45 @@ class SwiftPGP: Encryption {
         if let p = password{
             pw = p
         }
-        var chiphers = [String]()
+        let chiphers = [String]()
         
-        for text in textToEncrypt{
-            if let data = text.data(using: .utf8){
-                /*
-                if let chipher = try? ObjectivePGP.symmetricEncrypt(data, signWith: nil, encryptionKey: password, passphrase: pw, armored: false){
-                    if armored{
-                        chiphers.append(Armor.armored(chipher, as: PGPArmorType.message))
-                    }
-                    else{
-                        chiphers.append(chipher.base64EncodedString(options: .init(arrayLiteral: .lineLength76Characters, .endLineWithLineFeed)))
-                    }
-                }
- */
-            }
-        }
+//        for text in textToEncrypt {
+//            if let data = text.data(using: .utf8) {
+//                if let chipher = try? ObjectivePGP
+//                    .symmetricEncrypt(data,
+//                                      signWith: nil,
+//                                      encryptionKey: password,
+//                                      passphrase: pw,
+//                                      armored: false) {
+//                    if armored {
+//                        chiphers.append(Armor.armored(chipher, as: PGPArmorType.message))
+//                    } else {
+//                        chiphers.append(chipher.base64EncodedString(options: .init(arrayLiteral: .lineLength76Characters, .endLineWithLineFeed)))
+//                    }
+//                }
+//            }
+//        }
         return (chiphers, pw)
     }
     
     func symmetricDecrypt(chipherTexts: [String], password: String) -> [String]{
-        var plaintexts = [String]()
+        let plaintexts = [String]()
         
-        for chipher in chipherTexts{
-            if let data = chipher.data(using: .utf8){
-                /*
-                if let plainData = try? ObjectivePGP.symmetricDecrypt(data, key: password, verifyWith: nil, signed: nil, valid: nil, integrityProtected: nil){
-                    if let plainText = String(data: plainData, encoding: .utf8){
-                        plaintexts.append(plainText)
-                    }
-                }
- */
-            }
-        }
+//        for chipher in chipherTexts {
+//            if let data = chipher.data(using: .utf8) {
+//                if let plainData = try? ObjectivePGP
+//                    .symmetricDecrypt(data,
+//                                      key: password,
+//                                      verifyWith: nil,
+//                                      signed: nil,
+//                                      valid: nil,
+//                                      integrityProtected: nil) {
+//                    if let plainText = String(data: plainData, encoding: .utf8){
+//                        plaintexts.append(plainText)
+//                    }
+//                }
+//            }
+//        }
         return plaintexts
     }
 }
diff --git a/enzevalos_iphone/SwiftUI/Compose/ComposeModel.swift b/enzevalos_iphone/SwiftUI/Compose/ComposeModel.swift
index 7d3dae27..1b8c21ae 100644
--- a/enzevalos_iphone/SwiftUI/Compose/ComposeModel.swift
+++ b/enzevalos_iphone/SwiftUI/Compose/ComposeModel.swift
@@ -34,8 +34,9 @@ class ComposeModel: ObservableObject {
     
     /// Adds email addresses to given RecipientFieldModel.
     ///
-    /// - Parameter addresses: String array of email addresses to add.
-    /// - Parameter model: RecipientFieldModel to which to add the addresses.
+    /// - Parameters:
+    ///   - addresses: String array of email addresses to add.
+    ///   - model: RecipientFieldModel to which to add the addresses.
     private func addAddresses(_ addresses: [String], model: RecipientFieldModel) {
         for address in addresses {
             model.addNewAddress(address)
@@ -43,6 +44,8 @@ class ComposeModel: ObservableObject {
     }
     
     /// Generates OutgoingMail with given email contents.
+    ///
+    /// - Returns: Outgoing mail filled out with relevant information from RecipientsModel.
     private func generateMail() -> OutgoingMail {
         OutgoingMail(toAddresses: recipientsModel.toEMails,
                      ccAddresses: recipientsModel.ccEMails,
diff --git a/enzevalos_iphone/SwiftUI/Compose/ComposeView.swift b/enzevalos_iphone/SwiftUI/Compose/ComposeView.swift
index b95ef946..74b57b46 100644
--- a/enzevalos_iphone/SwiftUI/Compose/ComposeView.swift
+++ b/enzevalos_iphone/SwiftUI/Compose/ComposeView.swift
@@ -48,94 +48,14 @@ struct ComposeView: View {
         }
         .padding()
         .animation(.default)
-        Spacer()
     }
 }
 
-struct CcAndBccFields: View {
-    @ObservedObject var model: RecipientsModel
-    
-    var body: some View {
-        VStack {
-            RecipientField(model: model.ccModel)
-            
-            Divider()
-            
-            if model.showBccField {
-                RecipientField(model: model.bccModel)
-                
-                Divider()
-            }
-        }
-    }
-}
-
-/// A view in which recipients get added or removed.
-struct RecipientField: View {
-    @ObservedObject var model: RecipientFieldModel
-    @State var showList = false
-    
-    var body: some View {
-        VStack {
-            HStack {
-                // Recipient text field
-                Text(model.type.asString)
-                    .foregroundColor(Color(UIColor.tertiaryLabel))
-                
-                // Shows selected recipients as blue capsules
-                // followed by TextField for new recipients
-                ScrollView(.horizontal) {
-                    HStack(spacing: 4) {
-                        ForEach(model.selectedContacts) { (recipient: AddressRecord) in
-                            Text(recipient.displayname ?? recipient.email)
-                                .foregroundColor(.white)
-                                .padding(.horizontal, 12)
-                                .padding(.vertical, 2)
-                                .background(Color.accentColor)
-                                .clipShape(Capsule())
-                        }
-                        TextField("", text: $model.text) { isEditing in
-                            model.parent?.isEditingCcOrBcc = isEditing
-                        } onCommit: {
-                            model.commitText()
-                            // TODO: Fix bug on first Cc or Bcc recipient commit
-                            // For some reason, model.selectedContacts.count stays 0
-                            // after the first committed recipient, leading to the Cc
-                            // and Bcc fields getting collapsed again despite the
-                            // first recipient clearly getting rendered as a blue
-                            // capsule in the ForEach loop above. 🤔🤔🤔
-                            print(model.selectedContacts.count)
-                        }
-                        .frame(minWidth: 200)
-                        .autocapitalization(.none)
-                        .keyboardType(.emailAddress)
-                    }
-                }
-                
-                // Toggles contact list
-                if model.type != .ccBcc {
-                    Button(action: { showList.toggle() }) {
-                        Image(systemName: !showList ? "plus.circle" : "chevron.up.circle")
-                    }
-                }
-            }
-            .frame(height: 20)
-            
-            // Contact list
-            if showList {
-                Divider()
-                RecipientListView()
-                    .frame(height: 460)
-            }
-        }
-        .environmentObject(model)
-    }
-}
-
-/// A view containing the Cancel and Send buttons for an email.
+/// A view that contains the Cancel and Send buttons for an email.
 struct ComposeViewHeader: View {
     @Environment(\.presentationMode) var presentationMode
     @EnvironmentObject var model: ComposeModel
+    @State var encryptionOn = true
     
     var body: some View {
         VStack {
@@ -152,6 +72,13 @@ struct ComposeViewHeader: View {
                 
                 Spacer()
                 
+                //                    Toggle("Use Encryption", isOn: $encryptionOn)
+                //                        .foregroundColor(.accentColor)
+                //                        .labelsHidden()
+                //                        .position(x: geometry.size.width / 3)
+                //
+                //                    Spacer()
+                
                 // Send button
                 Button {
                     model.sendMail()
@@ -207,6 +134,140 @@ struct UnencryptedSendButton: View {
     }
 }
 
+/// A view in which recipients get added or removed.
+struct RecipientField: View {
+    @ObservedObject var model: RecipientFieldModel
+    @State var showList = false
+    @State var indexOfSelected: Int?
+    
+    var body: some View {
+        VStack {
+            HStack {
+                // Recipient text field
+                Text(model.type.asString)
+                    .foregroundColor(Color(UIColor.tertiaryLabel))
+                
+                // Selected recipients as blue capsules,
+                // followed by TextField for new recipients.
+                ScrollView(.horizontal) {
+                    HStack(spacing: 3) {
+                        CommittedRecipients
+                        NewRecipientTextField
+                    }
+                }
+                
+                // Toggles contact list
+                if model.type != .ccBcc {
+                    Button(action: { showList.toggle() }) {
+                        Image(systemName: !showList ? "plus.circle" : "chevron.up.circle")
+                    }
+                }
+            }
+            .frame(height: 20)
+            
+            // Contact list
+            if showList || !model.suggestions.isEmpty {
+                Divider()
+                RecipientListView()
+                    .frame(maxHeight: .infinity)
+                    .environmentObject(model)
+            }
+        }
+    }
+    
+    /// A view that lists all recipients that have been committed to this RecipientField.
+    var CommittedRecipients: some View {
+        ForEach(model.selectedContacts) { (recipient: AddressRecord) in
+            let isSelected = model.selectedContacts.firstIndex(of: recipient) == indexOfSelected
+            
+            RecipientCapsule(recipient: recipient,
+                             isSelected: isSelected,
+                             model: model,
+                             indexOfSelected: $indexOfSelected)
+                .onTapGesture {
+                    indexOfSelected = isSelected ? nil : model.selectedContacts
+                        .firstIndex(of: recipient)
+                }
+        }
+    }
+    
+    /// A TextField into which new recipients can be entered.
+    var NewRecipientTextField: some View {
+        TextField("", text: $model.text) { isEditing in
+            model.parent?.isEditingCcOrBcc = isEditing
+        } onCommit: {
+            model.commitText()
+            // TODO: Fix bug on first Cc or Bcc recipient commit
+            // For some reason, model.selectedContacts.count stays 0
+            // after the first committed recipient, leading to the Cc
+            // and Bcc fields getting collapsed again despite the
+            // first recipient clearly getting rendered as a blue
+            // capsule in the ForEach loop above. 🤔🤔🤔
+            print(model.selectedContacts.count)
+        }
+        .frame(minWidth: 200)
+        .autocapitalization(.none)
+        .keyboardType(.emailAddress)
+    }
+}
+
+/// A view that shows either a single "Cc/Bcc" field or separate "Cc" and "Bcc" fields.
+struct CcAndBccFields: View {
+    @ObservedObject var model: RecipientsModel
+    
+    var body: some View {
+        VStack {
+            RecipientField(model: model.ccModel)
+            
+            Divider()
+            
+            if model.showBccField {
+                RecipientField(model: model.bccModel)
+                Divider()
+            }
+        }
+    }
+}
+
+/// A view that shows a recipient committed to a recipient field.
+struct RecipientCapsule: View {
+    var recipient: AddressRecord
+    var isSelected: Bool
+    @ObservedObject var model: RecipientFieldModel
+    @Binding var indexOfSelected: Int?
+    
+    var body: some View {
+        HStack {
+            Text(name)
+            
+            if isSelected {
+                Button(action: removeRecipient) {
+                    Image(systemName: "xmark")
+                        .font(.caption2)
+                }
+            }
+        }
+        .foregroundColor(isSelected ? .white : .accentColor)
+        .padding(.horizontal, 12)
+        .padding(.vertical, 2)
+        .background(Capsule().fill(isSelected ? Color.accentColor : Color(UIColor.tertiaryLabel)))
+    }
+    
+    // TODO: Use actual displayname once it's implemented.
+    // Currently just uses first part of email before "@".
+    var name: String {
+        recipient.displayname ?? recipient.email.components(separatedBy: "@")[0]
+    }
+    
+    func removeRecipient() {
+        if let index = model.selectedContacts.firstIndex(of: recipient) {
+            model.deselectContact(at: index)
+            indexOfSelected = nil
+        }
+    }
+}
+
+/// Canvas Preview
 struct ComposeView_Previews: PreviewProvider {
     static var previews: some View {
         ComposeView()
diff --git a/enzevalos_iphone/SwiftUI/Compose/RecipientFieldModel.swift b/enzevalos_iphone/SwiftUI/Compose/RecipientFieldModel.swift
index c85b7b56..dc4906c7 100644
--- a/enzevalos_iphone/SwiftUI/Compose/RecipientFieldModel.swift
+++ b/enzevalos_iphone/SwiftUI/Compose/RecipientFieldModel.swift
@@ -35,7 +35,11 @@ class RecipientFieldModel: ObservableObject {
             
             // TODO: Show suggestions in ComposeView.
             if !text.isEmpty {
-                let frc = dataprovider.createFetchResultController(fetchRequest: AddressRecord.lookForPrefix(prefix: text))
+                let frc = dataprovider
+                    .createFetchResultController(
+                        fetchRequest: AddressRecord.lookForPrefix(prefix: text)
+                    )
+                
                 if let addresses = frc.fetchedObjects {
                     suggestions = addresses
                 } else {
@@ -47,6 +51,29 @@ class RecipientFieldModel: ObservableObject {
         }
     }
     
+    /// Gets array of contacts sorted by name or recency.
+    ///
+    /// - Parameter sortBy: Determines what key the contacts get sorted by.
+    /// - Returns: Sorted array of contacts.
+    func getContacts(sortBy: AddressRecord.SortBy) -> [AddressRecord] {
+        if !suggestions.isEmpty {
+            return suggestions
+        }
+        
+        let frc = LetterboxModel
+            .instance
+            .dataProvider
+            .createFetchResultController(
+                fetchRequest: AddressRecord
+                    .all(sortBy: sortBy)
+            )
+        
+        if let addresses = frc.fetchedObjects {
+            return addresses
+        }
+        return []
+    }
+    
     /// Adds contact at index to recipients.
     func selectContact(addr: AddressRecord) {
         selectedContacts.append(addr)
@@ -55,11 +82,11 @@ class RecipientFieldModel: ObservableObject {
     }
     
     /// Removes contact at index from recipients.
-    func unselectContactAt(i: Int) {
-        if i < selectedContacts.count {
-            selectedContacts.remove(at: i)
+    func deselectContact(at index: Int) {
+        if index < selectedContacts.count {
+            selectedContacts.remove(at: index)
         } else {
-            print("ERROR wrong index! \(i) but \(selectedContacts.count)")
+            print("ERROR wrong index! \(index) but \(selectedContacts.count)")
         }
     }
     
@@ -79,7 +106,11 @@ class RecipientFieldModel: ObservableObject {
         }
         
         dataprovider.importNewData(from: [AddressProperties(email: address)]) { error in
-            let frc = self.dataprovider.createFetchResultController(fetchRequest: AddressRecord.lookForExisting(email: address))
+            let frc = self
+                .dataprovider
+                .createFetchResultController(
+                    fetchRequest: AddressRecord.lookForExisting(email: address)
+                )
             
             if let addresses = frc.fetchedObjects, let addr = addresses.first {
                 self.selectedContacts.append(addr)
diff --git a/enzevalos_iphone/SwiftUI/Compose/RecipientListView.swift b/enzevalos_iphone/SwiftUI/Compose/RecipientListView.swift
index 09897319..f29165df 100644
--- a/enzevalos_iphone/SwiftUI/Compose/RecipientListView.swift
+++ b/enzevalos_iphone/SwiftUI/Compose/RecipientListView.swift
@@ -12,15 +12,6 @@ struct RecipientListView: View {
     @EnvironmentObject var model: RecipientFieldModel
     @State var sortByName = true
     
-    // Array of contacts sorted by name or recency.
-    var contacts: [AddressRecord] {
-        let frc = LetterboxModel.instance.dataProvider.createFetchResultController(fetchRequest: AddressRecord.all(sortBy: sortByName ? .name : .recency))
-        if let addresses = frc.fetchedObjects {
-            return addresses
-        }
-        return []
-    }
-    
     var body: some View {
         VStack(alignment: .leading) {
             // Sorting options
@@ -37,7 +28,7 @@ struct RecipientListView: View {
             
             // Contact list
             ScrollView {
-                ForEach(contacts) { contact in
+                ForEach(model.getContacts(sortBy: sortByName ? .name : .recency)) { contact in
                     RecipientRowView(contact: contact)
                     Divider()
                 }
diff --git a/enzevalos_iphone/SwiftUI/Compose/RecipientRowView.swift b/enzevalos_iphone/SwiftUI/Compose/RecipientRowView.swift
index 93b85aca..64bff666 100644
--- a/enzevalos_iphone/SwiftUI/Compose/RecipientRowView.swift
+++ b/enzevalos_iphone/SwiftUI/Compose/RecipientRowView.swift
@@ -48,7 +48,7 @@ struct RecipientRowView: View {
             // Adds or removes contact from recipients.
             Button(action: {
                 if let index = model.selectedContacts.firstIndex(where: { $0.email == contact.email }) {
-                    model.unselectContactAt(i: index)
+                    model.deselectContact(at: index)
                 } else {
                     model.selectContact(addr: contact)
                 }
diff --git a/enzevalos_iphone/SwiftUI/Compose/RecipientsModel.swift b/enzevalos_iphone/SwiftUI/Compose/RecipientsModel.swift
index 04b61012..c89fa559 100644
--- a/enzevalos_iphone/SwiftUI/Compose/RecipientsModel.swift
+++ b/enzevalos_iphone/SwiftUI/Compose/RecipientsModel.swift
@@ -85,6 +85,7 @@ class RecipientsModel: ObservableObject {
         }
     }
     
+    /// Updates whether to display  "Bcc" field based on state of recipient fields.
     func updateShowBccField() {
         showBccField = isEditingCcOrBcc
             || !ccModel.selectedContacts.isEmpty
diff --git a/enzevalos_iphone/SwiftUI/Inbox/InboxView.swift b/enzevalos_iphone/SwiftUI/Inbox/InboxView.swift
index 21718661..d24de44c 100644
--- a/enzevalos_iphone/SwiftUI/Inbox/InboxView.swift
+++ b/enzevalos_iphone/SwiftUI/Inbox/InboxView.swift
@@ -9,39 +9,48 @@
 import SwiftUI
 import CoreData
 // TODO:    Refactor to Model!
-//          Updating text -> Last update, updating, no connection....
+//          Updating text -> Last update, updating, no connection...
 
 struct InboxView: View {    
     var folderpath: String
     var name: String
     
     @State var goToFolders = false
-   
+    
     var body: some View {
         NavigationView{
             MailListView(folderpath: folderpath, name: name)
-                .environment(\.managedObjectContext, PersistentDataProvider.dataProvider.persistentContainer.viewContext)
+                .environment(\.managedObjectContext,
+                             PersistentDataProvider
+                                .dataProvider
+                                .persistentContainer
+                                .viewContext)
                 .navigationBarItems(leading: self.folderButton, trailing: keyManagementButton)
         }
     }
     
     private var keyManagementButton: some View {
-        NavigationLink(
-            destination: KeyManagementOverview(),
-            label: {
-                Image(systemName: "slider.horizontal.3").imageScale(.large)
-            })
+        NavigationLink(destination: KeyManagementOverview()) {
+            Image(systemName: "slider.horizontal.3")
+                .imageScale(.large)
+        }
     }
     
     private var folderButton: some View {
-        Button(action:{
+        Button(action: {
             goToFolders = true
-        }, label: {
-            Image(systemName: "tray.2").imageScale(.large)
-        })
+        }) {
+            Image(systemName: "tray.2")
+                .imageScale(.large)
+        }
         .background(
             NavigationLink(destination: FolderOverView()
-                            .environment(\.managedObjectContext, PersistentDataProvider.dataProvider.persistentContainer.viewContext), isActive: $goToFolders) {
+                            .environment(\.managedObjectContext,
+                                         PersistentDataProvider
+                                            .dataProvider
+                                            .persistentContainer
+                                            .viewContext),
+                           isActive: $goToFolders) {
                 EmptyView()
             }
             .hidden()
@@ -55,6 +64,10 @@ struct InboxView: View {
 struct InboxView_Previews: PreviewProvider {
     static var previews: some View {
         return InboxView(folderpath: "INBOX", name: "INBOX")
-            .environment(\.managedObjectContext, PersistentDataProvider.proxyPersistentDataProvider.persistentContainer.viewContext)
+            .environment(\.managedObjectContext,
+                         PersistentDataProvider
+                            .proxyPersistentDataProvider
+                            .persistentContainer
+                            .viewContext)
     }
 }
diff --git a/enzevalos_iphone/SwiftUI/Inbox/MailListView.swift b/enzevalos_iphone/SwiftUI/Inbox/MailListView.swift
index c88f1a30..d0f58a6b 100644
--- a/enzevalos_iphone/SwiftUI/Inbox/MailListView.swift
+++ b/enzevalos_iphone/SwiftUI/Inbox/MailListView.swift
@@ -35,9 +35,9 @@ struct MailListView: View {
         mainView
             .navigationBarTitle(name, displayMode: .inline)
             
-            .onAppear(perform: {
+            .onAppear {
                 self.updateMails()
-            })
+            }
             .sheet(isPresented: $composeMail) {
                 ComposeView()
             }
@@ -61,7 +61,7 @@ struct MailListView: View {
     }
     
     private var mailList: some View {
-        List (self.mails.filter(filterKeyRecord), id: \.self){ record in
+        List (self.mails.filter(filterKeyRecord), id: \.self) { record in
             NavigationLink(
                 destination: ReadMainView(model: ReadModel(mail: record))) {
                 MailRow(mail: record)
@@ -69,17 +69,18 @@ struct MailListView: View {
         }
         .resignKeyboardOnDragGesture() // hide keyboard when dragging
     }
-
+    
     private var composeButton: some View {
         Button(action: {
             composeMail = true
-        }, label: {
+        }) {
             Image(systemName: "square.and.pencil").imageScale(.large)
-        })
+        }
     }
     
     private var lastUpdate: some View {
         var text = NSLocalizedString("Updating", comment: "updating...")
+        
         if !updating {
             let last = Date()
             let dateFormatter = DateFormatter()
@@ -88,41 +89,52 @@ struct MailListView: View {
             let dateString = dateFormatter.string(from: last)
             text = NSLocalizedString("LastUpdate", comment: "") + " " + dateString
         }
-        return Button(action: updateMails, label: {Text(text)
-            .font(.callout)
-            
-        })
+        
+        return Button(action: updateMails)  {
+            Text(text)
+                .font(.callout)
+        }
     }
     
     func updateMails() {
         guard !updating else {
             return
         }
-        LetterboxModel.instance.mailHandler.updateFolder(folderpath: folderpath, completionCallback: {error in
-            if error == nil {
-                self.updating = false
-            }
-            // TODO: Add error message            
-        })
+        LetterboxModel
+            .instance
+            .mailHandler
+            .updateFolder(folderpath: folderpath,
+                          completionCallback: { error in
+                            if error == nil {
+                                self.updating = false
+                            }
+                            // TODO: Add error message
+                          })
         updating = true
     }
     
     func filterKeyRecord(keyRecord: MailRecord) -> Bool {
         let searchType = SearchType.findType(i: searchField)
-        if self.searchText.isEmpty || self.searchText == NSLocalizedString("Searchbar.Title", comment: "Search") {
+        if self.searchText.isEmpty
+            || self.searchText == NSLocalizedString("Searchbar.Title", comment: "Search") {
             return true
         }
+        
         let query = self.searchText.lowercased()
-        if (searchType == .All || searchType == .Sender) && (containsSearchTerms(content: keyRecord.sender.displayname, searchText: query) || containsSearchTerms(content: keyRecord.sender.email, searchText: query)) {
+        if (searchType == .All || searchType == .Sender)
+            && (containsSearchTerms(content: keyRecord.sender.displayname, searchText: query)
+                    || containsSearchTerms(content: keyRecord.sender.email, searchText: query)) {
             return true
-        }
-        else if (searchType == .All || searchType == .Sender) && keyRecord.addresses.filter({containsSearchTerms(content: $0.email, searchText: query)}).count > 0 {
+        } else if (searchType == .All || searchType == .Sender)
+                    && keyRecord.addresses.filter({
+            containsSearchTerms(content: $0.email,
+                                searchText: query) }).count > 0 {
             return true
-        }
-        else if (searchType == .All || searchType == .Subject) && containsSearchTerms(content: keyRecord.subject, searchText: query){
+        } else if (searchType == .All || searchType == .Subject)
+                    && containsSearchTerms(content: keyRecord.subject, searchText: query) {
             return true
-        }
-        else if (searchType == .All || searchType == .Body) && containsSearchTerms(content: keyRecord.body, searchText: query){
+        } else if (searchType == .All || searchType == .Body)
+                    && containsSearchTerms(content: keyRecord.body, searchText: query) {
             return true
         }
         return false
diff --git a/enzevalos_iphone/persistentData/AddressRecord.swift b/enzevalos_iphone/persistentData/AddressRecord.swift
index 20828173..5b7e1ab1 100644
--- a/enzevalos_iphone/persistentData/AddressRecord.swift
+++ b/enzevalos_iphone/persistentData/AddressRecord.swift
@@ -82,9 +82,8 @@ extension AddressRecord {
     
     public var name: String {
         get {
-            if let contact = self.phoneBookID {
-                // TODO Look up cn contact name!
-            }
+            // TODO: Look up CN contact name!
+//            if let contact = self.phoneBookID {}
             if let displayname = self.displayname {
                 return displayname
             }
diff --git a/enzevalos_iphone/persistentData/MailRecord.swift b/enzevalos_iphone/persistentData/MailRecord.swift
index c107320e..5cd89e4c 100644
--- a/enzevalos_iphone/persistentData/MailRecord.swift
+++ b/enzevalos_iphone/persistentData/MailRecord.swift
@@ -205,14 +205,15 @@ extension MailRecord: DisplayMail {
     }
     
     func markAsRead(isRead: Bool) {
+        
+        // TODO: FIX! Faults the current objects...
+//        if let context = self.managedObjectContext {
+//            var newFlag = self.messageFlag
+//            newFlag.insert(.seen)
+//            flag = Int16(newFlag.rawValue)
+//            try? PersistentDataProvider.dataProvider.save(taskContext: context) // <- later?
+//        }
         return
-        // TODO FIX! Faults the current objects...
-        if let context = self.managedObjectContext {
-            var newFlag = self.messageFlag
-            newFlag.insert(.seen)
-            flag = Int16(newFlag.rawValue)
-            try? PersistentDataProvider.dataProvider.save(taskContext: context) // <- later?
-        }
     }
     
     var transportEnc: Bool {
-- 
GitLab