in NIOSMTP/NIOSMTP/SendEmailHandler.swift [111:180]
func channelRead(context: ChannelHandlerContext, data: NIOAny) {
let result = self.unwrapInboundIn(data)
switch result {
case .error(let message):
self.allDonePromise.fail(NSError(domain: "sending email", code: 1, userInfo: ["reason": message]))
return
case .ok:
() // cool
}
switch self.currentlyWaitingFor {
case .initialMessageFromServer:
self.send(context: context, command: .sayHello(serverName: self.serverConfiguration.hostname))
self.currentlyWaitingFor = .okForOurHello
case .okForOurHello:
if self.useStartTLS {
self.send(context: context, command: .startTLS)
self.currentlyWaitingFor = .okForStartTLS
} else {
self.sendAuthenticationStart(context: context)
}
case .okForStartTLS:
self.currentlyWaitingFor = .tlsHandlerToBeAdded
context.channel.pipeline.addHandler(try! NIOSSLClientHandler(context: sslContext,
serverHostname: serverConfiguration.hostname),
position: .first).whenComplete { result in
guard case .tlsHandlerToBeAdded = self.currentlyWaitingFor else {
preconditionFailure("wrong state \(self.currentlyWaitingFor)")
}
switch result {
case .failure(let error):
self.currentlyWaitingFor = .error(error)
case .success:
self.sendAuthenticationStart(context: context)
}
}
case .okForOurAuthBegin:
self.send(context: context, command: .authUser(self.serverConfiguration.username))
self.currentlyWaitingFor = .okAfterUsername
case .okAfterUsername:
self.send(context: context, command: .authPassword(self.serverConfiguration.password))
self.currentlyWaitingFor = .okAfterPassword
case .okAfterPassword:
self.send(context: context, command: .mailFrom(self.email.senderEmail))
self.currentlyWaitingFor = .okAfterMailFrom
case .okAfterMailFrom:
self.send(context: context, command: .recipient(self.email.recipientEmail))
self.currentlyWaitingFor = .okAfterRecipient
case .okAfterRecipient:
self.send(context: context, command: .data)
self.currentlyWaitingFor = .okAfterDataCommand
case .okAfterDataCommand:
self.send(context: context, command: .transferData(email))
self.currentlyWaitingFor = .okAfterMailData
case .okAfterMailData:
self.send(context: context, command: .quit)
self.currentlyWaitingFor = .okAfterQuit
case .okAfterQuit:
self.allDonePromise.succeed(())
context.close(promise: nil)
self.currentlyWaitingFor = .nothing
case .nothing:
() // ignoring more data whilst quit (it's odd though)
case .error:
fatalError("error state")
case .tlsHandlerToBeAdded:
fatalError("bug in NIOTS: we shouldn't hit this state here")
}
}