-
Oliver Wiese authoredOliver Wiese authored
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
MailServerConfigurationTest.swift 17.71 KiB
//
// MailServerConfigurationTest.swift
// enzevalos_iphoneTests
//
// Created by Oliver Wiese on 22.03.19.
// Copyright © 2019 fu-berlin. All rights reserved.
//
import XCTest
@testable import enzevalos_iphone
class MailServerConfigurationTest: XCTestCase, MailSessionListener{
let datahandler = DataHandler.handler
let mailHandler = AppDelegate.getAppDelegate().mailHandler
let pgp = SwiftPGP()
let msg1 = "* OK [CAPABILITY IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE IDLE AUTH=PLAIN AUTH=LOGIN] Dovecot ready.\r\n"
let msg2 = "1 LOGIN \"Adasd@XXXXX.YYY\" adafa\r\n"
let msg3 = "1 NO [AUTHENTICATIONFAILED] Authentication failed"
let msg4 = "* OK [CAPABILITY IMAP4 IMAP4REV1 STARTTLS CHILDREN I18NLEVEL=1 IDLE LIST-EXTENDED LITERAL+ MULTIAPPEND NAMESPACE QUOTA SORT THREAD=REFERENCES UIDPLUS UNSELECT LOGINDISABLED] perdition ready on XXXXX 0019343e4\r\n"
let msg5 = "1 STARTTLS\r\n"
let msg6 = "1 OK Begin TLS negotiation now\r\n"
let msg7 = "* OK XXX ready for requests from 12.34.567.89 e30mc94846126lfn\r\n"
let msg8 = "1 CAPABILITY\r\n"
let msg9 = "* CAPABILITY IMAP4rev1 UNSELECT IDLE NAMESPACE QUOTA ID XLIST CHILDREN X-GM-EXT-1 XYZZY SASL-IR AUTH=XOAUTH2 AUTH=PLAIN AUTH=PLAIN-CLIENTTOKEN AUTH=OAUTHBEARER AUTH=XOAUTH\r\n1 OK Thats all she wrote! e30mc94846126lfn\r\n"
let msg10 = "2 LOGIN \"sadasfai@asfaf.com\" asdadf3\r\n"
let msg11 = "2 NO [AUTHENTICATIONFAILED] Invalid credentials (Failure)\r\n"
let noJson = ["2", "5"]
var result: Bool?
var expect: XCTestExpectation?
var userAdr: String?
override func setUp() {
super.setUp()
datahandler.reset()
pgp.resetKeychains()
result = nil
expect = nil
}
override func tearDown() {
super.tearDown()
datahandler.reset()
pgp.resetKeychains()
result = nil
expect = nil
}
func testAuthParsing() {
checkAuthParsing(msg: msg1, res: [MCOAuthType.saslPlain, MCOAuthType.saslLogin])
checkAuthParsing(msg: msg2, res: [])
checkAuthParsing(msg: msg3, res: [])
checkAuthParsing(msg: msg4, res: [])
checkAuthParsing(msg: msg5, res: [])
checkAuthParsing(msg: msg6, res: [])
checkAuthParsing(msg: msg7, res: [])
checkAuthParsing(msg: msg8, res: [])
checkAuthParsing(msg: msg9, res: [MCOAuthType.xoAuth2, MCOAuthType.saslPlain])
checkAuthParsing(msg: msg10, res: [])
checkAuthParsing(msg: msg11, res: [])
}
func checkAuthParsing(msg: String, res: [MCOAuthType]) {
let auths = MCOAuthType.parseAuthType(msg: msg)
var found = false
for a in auths {
for r in res {
if r.rawValue == a.rawValue {
found = true
break;
}
}
XCTAssertTrue(found, "Too many authtypes! \(a) should be not in \(msg)")
found = false
}
for a in res {
for r in auths {
if r.rawValue == a.rawValue {
found = true
break;
}
}
XCTAssertTrue(found, "Too few authtypes! \(a) is not in \(msg)")
found = false
}
}
func testHappyPath() {
let accounts = MailServerConfigurationTest.loadAccounts()
guard accounts.count != 0 else {
XCTFail("No account for testing!")
return
}
for (key, account) in accounts {
testJsonFile(correctPW: true, account: account, imap: true, shouldFail: noJson.contains(key))
testJsonFile(correctPW: true, account: account, imap: false, shouldFail: noJson.contains(key))
}
}
func testJsonFileButWrongPW() {
let accounts = MailServerConfigurationTest.loadAccounts()
guard accounts.count > 0 else {
XCTFail("No account for testing!")
return
}
for (key, account) in accounts {
testJsonFile(correctPW: false, account: account, imap: true, shouldFail: noJson.contains(key))
testJsonFile(correctPW: false, account: account, imap: false, shouldFail: noJson.contains(key))
}
}
func testJsonFile(correctPW: Bool, account: (name: String, pw: String), imap: Bool, shouldFail: Bool = false){
setUp()
var pw = "password"
if correctPW {
pw = account.pw
}
var session = MailSession(configSession: .SMTP, mailAddress: account.name, password: pw, username: nil)
if imap {
session = MailSession(configSession: .IMAP, mailAddress: account.name, password: pw, username: nil)
}
session.addListener(listener: self)
XCTAssertEqual(account.name, session.username)
XCTAssertEqual(account.name, session.mailAddr)
XCTAssertEqual(pw, session.password)
if shouldFail {
XCTAssertFalse(session.loadFromProviderJson())
tearDown()
return
}
expect = expectation(description: "Login result")
if !session.loadFromProviderJson() {
XCTFail("No provider json file!")
}
if !session.startTestingServerConfig() {
XCTFail("No testing of config...")
}
if let expect = expect {
var time = 40
if !correctPW || shouldFail {
time = 60
}
wait(for: [expect], timeout: TimeInterval(time))
}
if correctPW {
XCTAssert(result ?? false, "\(account.name) failed to login")
}
else {
if let res = result {
XCTAssert(!res, "Wrong result for \(session.server.discription) and user: \(account.name)")
} else {
XCTFail("No results! for \(session.server.discription) and user: \(account.name)")
}
}
tearDown()
}
func testNoJson() {
let accounts = MailServerConfigurationTest.loadAccounts()
guard let account = accounts["2"] else {
XCTFail("No account for testing!")
return
}
testFindServerConfig(correctPW: true, account: account, imap: true)
testFindServerConfig(correctPW: true, account: account, imap: false)
testFindServerConfig(correctPW: false, account: account, imap: true, shouldFail: true)
testFindServerConfig(correctPW: false, account: account, imap: false, shouldFail: true)
}
func testFindServerConfig(correctPW: Bool, account: (name: String, pw: String), imap: Bool, shouldFail: Bool = false) {
setUp()
var pw = "password"
if correctPW {
pw = account.pw
}
var session = MailSession(configSession: .SMTP, mailAddress: account.name, password: pw, username: nil)
if imap {
session = MailSession(configSession: .IMAP, mailAddress: account.name, password: pw, username: nil)
}
session.addListener(listener: self)
if session.loadFromProviderJson() {
XCTFail("Wrong test case! Found in json file!")
}
if session.startTestingServerConfigFromList() {
XCTFail("Wrong test case! Json file exists.")
}
if !session.startLongSearchOfServerConfig(hostFromAdr: false) {
XCTFail("Could not start.")
}
expect = expectation(description: "Login result: \n \(session.server.discription) \n IMAP?: \(imap)")
if let expect = expect {
var waitingTime = 30
if !correctPW {
waitingTime = 250
}
wait(for: [expect], timeout: TimeInterval(waitingTime))
}
if let res = result {
XCTAssertEqual(res, !shouldFail)
}
else {
XCTFail("No result! We should be faster. \n \(session.server.discription) \n IMAP?: \(imap) Should fail? \(shouldFail)")
}
tearDown()
}
func testDetailSetup(account: (adr: String, pw: String, hostIMAP: String, portIMAP: String, conTypeIMAP: String, hostSMTP: String, portSMTP: String, conTypeSMTP: String), correctPW: Bool, imap: Bool, shouldFail: Bool = false) -> Bool {
var pw = "pw"
if correctPW {
pw = account.pw
}
setUp()
var session = MailSession(configSession: .SMTP, mailAddress: account.adr, password: pw, username: account.adr)
if imap {
session = MailSession(configSession: .IMAP, mailAddress: account.adr, password: pw, username: account.adr)
if let port = UInt32(account.portIMAP) {
var connType = MCOConnectionType.TLS.rawValue
if account.conTypeIMAP == "StartTLS" {
connType = MCOConnectionType.startTLS.rawValue
}
session.setServer(hostname: account.hostIMAP, port: port , connType: connType, authType: nil)
}
else {
XCTFail("Could not parse account data")
}
} else {
if let port = UInt32(account.portSMTP) {
var connType = MCOConnectionType.TLS.rawValue
if account.conTypeSMTP == "StartTLS" {
connType = MCOConnectionType.startTLS.rawValue
}
session.setServer(hostname: account.hostSMTP, port: port, connType: connType, authType: nil)
}
else {
XCTFail("Could not parse account data")
}
}
session.addListener(listener: self)
if !session.startTestingServerConfig() {
XCTFail("Could not test config.")
}
expect = expectation(description: "Login result")
if let expect = expect {
var time = 20
if !correctPW {
time = 50
}
if shouldFail {
time = 60
}
wait(for: [expect], timeout: TimeInterval(time))
}
var response = false
if let res = result {
XCTAssertEqual(res, !shouldFail && correctPW)
response = res
} else {
XCTFail("No results for \(account.adr) and host: \(session.server.discription)")
}
tearDown()
return response
}
func testDetail(){
let accounts = MailServerConfigurationTest.loadDetailAccounts()
guard accounts.count > 0 else {
XCTFail("No account for testing!")
return
}
for (_, account) in accounts {
var res = testDetailSetup(account: account, correctPW: true, imap: true, shouldFail: false)
XCTAssertTrue(res, "Failed for \(account.adr)")
res = testDetailSetup(account: account, correctPW: true, imap: false, shouldFail: false)
XCTAssertTrue(res, "Failed for \(account.adr)")
res = testDetailSetup(account: account, correctPW: false, imap: true, shouldFail: true)
XCTAssertFalse(res, "Failed for \(account.adr)")
res = testDetailSetup(account: account, correctPW: false, imap: false, shouldFail: true)
XCTAssertFalse(res, "Failed for \(account.adr)")
}
}
func testDetailSMTP() {
let accounts = MailServerConfigurationTest.loadAccounts()
guard let account = accounts["1"] else {
XCTFail("No account for testing!")
return
}
let session = MailSession(configSession: .SMTP, mailAddress: "text@example.com", password: "password", username: "user")
session.addListener(listener: self)
session.username = account.name
session.mailAddr = account.name
session.password = account.pw
session.setServer(hostname: "smtp.web.de", port: 587, connType: MCOConnectionType.startTLS.rawValue, authType: nil)
if !session.startTestingServerConfig() {
XCTFail("Could not test config.")
}
expect = expectation(description: "Login result")
if let expect = expect {
wait(for: [expect], timeout: 60)
}
XCTAssert(result ?? false, "Faild result for: \(account.name)")
}
func testMailFetch() {
let accounts = MailServerConfigurationTest.loadDetailAccounts()
guard accounts.count > 0 else {
XCTFail("No account for testing!")
return
}
if let account = accounts["1"] {
setAccount(adr: account.adr, pw: account.pw, hostIMAP: account.hostIMAP, portIMAP: account.portIMAP, conTypeIMAP: account.conTypeIMAP)
}
else {
XCTFail("No account for testing!")
}
}
private func setAccount(adr: String, pw: String, hostIMAP: String, portIMAP: String, conTypeIMAP: String) {
userAdr = adr
// IMAP
guard let imapPort = UInt32(portIMAP) else {
XCTFail("Could not set up account. Wrong imap port: \(portIMAP)")
return
}
var connType = MCOConnectionType.TLS
if conTypeIMAP == "StartTLS" {
connType = MCOConnectionType.startTLS
}
let promise = expectation(description: "Set up account: \(hostIMAP)")
let server = MailServer(sessionType: .IMAP, username: adr, password: pw, hostname: hostIMAP, port: imapPort, connectionType: connType , authType: nil, callback: {(error: MailServerConnectionError?, server: MailServer) -> () in
promise.fulfill()
self.callbackSetup(error: error, server: server)
} )
XCTAssertTrue(server.findHost())
wait(for: [promise], timeout: 1)
}
func testFinish(result: Bool) {
guard let expect = expect else {
XCTFail("No expectation!")
return
}
self.result = result
expect.fulfill()
}
private func callbackSetup(error: MailServerConnectionError?, server: MailServer) -> () {
guard error == nil else {
XCTFail("No connection to server! \(String(describing: error)) \(server.hostname) for \(server.discription)")
return
}
let store = server.storeToUserDefaults(mailAddr: userAdr!)
XCTAssertTrue(store)
// Test fetching mails!
let mailHandler = AppDelegate.getAppDelegate().mailHandler
let promise = expectation(description: "Call for mails!")
print(mailHandler.IMAPSession?.username)
print(mailHandler.IMAPSession?.password)
mailHandler.loadMailsForInbox(completionCallback: {(error: MailServerConnectionError?) -> () in
promise.fulfill()
print("Works!")
self.loadMailsCallback(error: error)
})
wait(for: [promise], timeout: 90)
}
private func loadMailsCallback(error: MailServerConnectionError?) {
print(error)
guard error == nil else {
XCTFail("Error! \(String(describing: error)) for \(String(describing: userAdr))")
return
}
var mails = 0
DataHandler.handler.allFolders.forEach{mails = mails + $0.counterMails}
result = true
}
private static func loadAccounts() -> [String:(name: String, pw: String)] {
let bundle = Bundle(for: self)
var newAccounts = [String:(name: String, pw: String)]()
guard let url = bundle.url(forResource: "accounts", withExtension: "json"), let data = try? Data(contentsOf: url), let jsonDic = try? JSONSerialization.jsonObject(with: data, options: .mutableLeaves) else {
XCTFail()
return [:]
}
if let dic = jsonDic as? Dictionary<String, Any>{
if let accounts = dic["accounts"], let array = accounts as? Array<Any> {
for elem in array {
if let account = elem as? Dictionary<String, String> {
if let id = account["id"], let username = account["username"] , let pw = account["password"] {
newAccounts[id] = (username, pw)
}
}
}
}
}
return newAccounts
}
private static func loadDetailAccounts() -> [String:(adr: String, pw: String, hostIMAP: String, portIMAP: String, conTypeIMAP: String, hostSMTP: String, portSMTP: String, conTypeSMTP: String)] {
let bundle = Bundle(for: self)
var newAccounts = [String:(adr: String, pw: String, hostIMAP: String, portIMAP: String, conTypeIMAP: String, hostSMTP: String, portSMTP: String, conTypeSMTP: String)]()
guard let url = bundle.url(forResource: "accounts", withExtension: "json"), let data = try? Data(contentsOf: url), let jsonDic = try? JSONSerialization.jsonObject(with: data, options: .mutableLeaves) else {
XCTFail("No file!")
return [:]
}
if let dic = jsonDic as? Dictionary<String, Any>{
if let accounts = dic["accounts"], let array = accounts as? Array<Any> {
for elem in array {
if let account = elem as? Dictionary<String, String> {
if let id = account["id"], let username = account["username"] , let pw = account["password"], let hostIMAP = account["hostIMAP"], let portIMAP = account["portIMAP"], let conTypeIMAP = account["conTypeIMAP"], let hostSMTP = account["hostSMTP"], let portSMTP = account["portSMTP"], let conTypeSMTP = account["conTypeSMTP"]{
newAccounts[id] = (username, pw, hostIMAP, portIMAP, conTypeIMAP, hostSMTP, portSMTP, conTypeSMTP)
}
}
}
}
}
XCTAssertGreaterThan(newAccounts.count, 0)
return newAccounts
}
private static func extractProvider(adr: String) -> String? {
return adr.components(separatedBy: "@").last
}
}