简体   繁体   English

在Swift 3中使用Stream打开到SMTP服务器的套接字连接

[英]Open socket connection to SMTP server using Stream in Swift 3

I need to connect to an SMTP server and failing open the connection. 我需要连接到SMTP服务器,但无法打开连接。 Failing handshake (missing authentication) is furthest I got here. 握手失败(缺少身份验证)是我到这里来最远的一次。 I open the socket to a normal server but failing to do so in here to send an email. 我打开了普通服务器的套接字,但是在这里没有发送电子邮件。

    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()
    }

The commented part shows me trying to set some of the stuff but don't really know what is supposed to be there. 带注释的部分显示了我尝试设置一些东西,但实际上并不知道应该在那里。 Any ideas anyone please? 有任何想法吗?

Just to clarify, this is for a badly designed API that is using SMTP to receive data (not my idea but have to use it) so please don't suggest MessageUI or that the app will get rejected because of sending emails directly :) 只是为了澄清一下,这是针对使用SMTP接收数据(不是我的主意,但必须使用它)的,设计不良的API,因此请不要建议MessageUI,否则该应用程序会因为直接发送电子邮件而被拒绝:)

Full gist of the Playground is here if anyone is interested: https://gist.github.com/rafiki270/c004b92deca437934f702efd3508bd83 如果有人感兴趣的话,可以在下面找到游乐场的完整内容: https : //gist.github.com/rafiki270/c004b92deca437934f702efd3508bd83

@Ondrej As per Apple documentation "Introduction to Stream Programming Guide for Cocoa" it is mentioned that the NSStream ( Objective C ) / Stream (Swift) class does not support connecting to a remote host on iOS. @Ondrej根据Apple文档“可可流编程指南简介”,提到NSStream(Object C)/ Stream(Swift)类不支持连接到iOS上的远程主机。 Your alternate is to use CFStream by taking advantage of the toll-free bridge between CFStream and NSStream to cast your CFStreams to NSStreams. 您的替代方法是通过利用CFStream和NSStream之间的免费电话桥将CFStream转换为NSStream来使用CFStream。

Below is an example on how you do it with 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];

Hope this helps. 希望这可以帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM