使用 Swift 中的 Stream 打开与 SMTP 服务器的套接字连接 3
Open socket connection to SMTP server using Stream in Swift 3
我需要连接到 SMTP 服务器,但无法打开连接。握手失败(缺少身份验证)是我到达这里最远的地方。我打开了连接到普通服务器的套接字,但未能在此处打开以发送电子邮件。
private func connect() throws {
var input: InputStream? = nil
var output: OutputStream? = nil
Stream.getStreamsToHost(withName: server, port: port, inputStream: &input, outputStream: &output)
guard let inputSafe = input, let outputSafe = output else {
throw FailerError.unableToConnectToHost
}
self.inputStream = inputSafe
self.outputStream = outputSafe
// TODO: Authentication using login
// Enable SSL/TLS on the streams
// inputStream!.setProperty(kCFStreamSocketSecurityLevelNegotiatedSSL, forKey: Stream.PropertyKey(rawValue: kCFStreamPropertySocketSecurityLevel as String))
// outputStream!.setProperty(kCFStreamSocketSecurityLevelNegotiatedSSL, forKey: Stream.PropertyKey(rawValue: kCFStreamPropertySocketSecurityLevel as String))
//
// // Define custom SSL/TLS settings
// let sslSettings: [NSString : Any] = [
// NSStream automatically sets up the socket, the streams and creates a trust object and evaulates it before you even get a chance to check the trust yourself. Only proper SSL certificates will work with this method. If you have a self signed certificate like I do, you need to disable the trust check here and evaulate the trust against your custom root CA yourself.
// NSString(format: kCFStreamSSLValidatesCertificateChain): kCFBooleanFalse,
// //
// NSString(format: kCFStreamSSLPeerName): kCFNull,
// // We are an SSL/TLS client, not a server
// NSString(format: kCFStreamSSLIsServer): kCFBooleanFalse,
//
// NSString(format: kCFStreamSocketSecurityLevelNegotiatedSSL): kCFBooleanTrue
// ]
//
// // Set the SSL/TLS settingson the streams
// inputStream!.setProperty(sslSettings, forKey: Stream.PropertyKey(rawValue: kCFStreamPropertySSLSettings as String))
// outputStream!.setProperty(sslSettings, forKey: Stream.PropertyKey(rawValue: kCFStreamPropertySSLSettings as String))
inputStream.delegate = self
outputStream.delegate = self
inputStream.schedule(in: .main, forMode: .commonModes)
outputStream.schedule(in: .main, forMode: .commonModes)
inputStream.open()
outputStream.open()
}
评论部分显示我正在尝试设置一些东西,但我真的不知道那里应该有什么。有人有什么想法吗?
澄清一下,这是针对使用 SMTP 接收数据的设计糟糕的 API(不是我的想法,但必须使用它)所以请不要建议 MessageUI 否则该应用程序将获得因为直接发邮件被拒:)
如果有人感兴趣,请查看 Playground 的完整要点:
https://gist.github.com/rafiki270/c004b92deca437934f702efd3508bd83
@Ondrej 根据 Apple 文档 "Introduction to Stream Programming Guide for Cocoa" 提到 NSStream ( Objective C ) / Stream (Swift) class 不支持连接到远程在 iOS 主持。您的替代方案是通过利用 CFStream 和 NSStream 之间的免费桥梁将您的 CFStreams 转换为 NSStreams 来使用 CFStream。
下面是一个关于如何使用 CFStream 执行此操作的示例。
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)[website host], 80, &readStream, &writeStream);
NSInputStream *inputStream = (__bridge_transfer NSInputStream *)readStream;
NSOutputStream *outputStream = (__bridge_transfer NSOutputStream *)writeStream;
[inputStream setDelegate:self];
[outputStream setDelegate:self];
[inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[inputStream open];
[outputStream open];
希望对您有所帮助。
我需要连接到 SMTP 服务器,但无法打开连接。握手失败(缺少身份验证)是我到达这里最远的地方。我打开了连接到普通服务器的套接字,但未能在此处打开以发送电子邮件。
private func connect() throws {
var input: InputStream? = nil
var output: OutputStream? = nil
Stream.getStreamsToHost(withName: server, port: port, inputStream: &input, outputStream: &output)
guard let inputSafe = input, let outputSafe = output else {
throw FailerError.unableToConnectToHost
}
self.inputStream = inputSafe
self.outputStream = outputSafe
// TODO: Authentication using login
// Enable SSL/TLS on the streams
// inputStream!.setProperty(kCFStreamSocketSecurityLevelNegotiatedSSL, forKey: Stream.PropertyKey(rawValue: kCFStreamPropertySocketSecurityLevel as String))
// outputStream!.setProperty(kCFStreamSocketSecurityLevelNegotiatedSSL, forKey: Stream.PropertyKey(rawValue: kCFStreamPropertySocketSecurityLevel as String))
//
// // Define custom SSL/TLS settings
// let sslSettings: [NSString : Any] = [
// NSStream automatically sets up the socket, the streams and creates a trust object and evaulates it before you even get a chance to check the trust yourself. Only proper SSL certificates will work with this method. If you have a self signed certificate like I do, you need to disable the trust check here and evaulate the trust against your custom root CA yourself.
// NSString(format: kCFStreamSSLValidatesCertificateChain): kCFBooleanFalse,
// //
// NSString(format: kCFStreamSSLPeerName): kCFNull,
// // We are an SSL/TLS client, not a server
// NSString(format: kCFStreamSSLIsServer): kCFBooleanFalse,
//
// NSString(format: kCFStreamSocketSecurityLevelNegotiatedSSL): kCFBooleanTrue
// ]
//
// // Set the SSL/TLS settingson the streams
// inputStream!.setProperty(sslSettings, forKey: Stream.PropertyKey(rawValue: kCFStreamPropertySSLSettings as String))
// outputStream!.setProperty(sslSettings, forKey: Stream.PropertyKey(rawValue: kCFStreamPropertySSLSettings as String))
inputStream.delegate = self
outputStream.delegate = self
inputStream.schedule(in: .main, forMode: .commonModes)
outputStream.schedule(in: .main, forMode: .commonModes)
inputStream.open()
outputStream.open()
}
评论部分显示我正在尝试设置一些东西,但我真的不知道那里应该有什么。有人有什么想法吗?
澄清一下,这是针对使用 SMTP 接收数据的设计糟糕的 API(不是我的想法,但必须使用它)所以请不要建议 MessageUI 否则该应用程序将获得因为直接发邮件被拒:)
如果有人感兴趣,请查看 Playground 的完整要点: https://gist.github.com/rafiki270/c004b92deca437934f702efd3508bd83
@Ondrej 根据 Apple 文档 "Introduction to Stream Programming Guide for Cocoa" 提到 NSStream ( Objective C ) / Stream (Swift) class 不支持连接到远程在 iOS 主持。您的替代方案是通过利用 CFStream 和 NSStream 之间的免费桥梁将您的 CFStreams 转换为 NSStreams 来使用 CFStream。
下面是一个关于如何使用 CFStream 执行此操作的示例。
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)[website host], 80, &readStream, &writeStream);
NSInputStream *inputStream = (__bridge_transfer NSInputStream *)readStream;
NSOutputStream *outputStream = (__bridge_transfer NSOutputStream *)writeStream;
[inputStream setDelegate:self];
[outputStream setDelegate:self];
[inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[inputStream open];
[outputStream open];
希望对您有所帮助。