internal void GetConnection(ServicePoint servicePoint) { if (this.isConnected) { throw new InvalidOperationException(SR.GetString("SmtpAlreadyConnected")); } if (Logging.On) { Logging.Associate(Logging.Web, this, servicePoint); } this.connectionPool = ConnectionPoolManager.GetConnectionPool(servicePoint, "", m_CreateConnectionCallback); PooledStream pooledStream = this.connectionPool.GetConnection(this, null, this.Timeout); while ((((SmtpPooledStream) pooledStream).creds != null) && (((SmtpPooledStream) pooledStream).creds != this.credentials)) { this.connectionPool.PutConnection(pooledStream, pooledStream.Owner, this.Timeout, false); pooledStream = this.connectionPool.GetConnection(this, null, this.Timeout); } if (Logging.On) { Logging.Associate(Logging.Web, this, pooledStream); } lock (this) { this.pooledStream = pooledStream; } ((SmtpPooledStream) pooledStream).creds = this.credentials; this.responseReader = new SmtpReplyReaderFactory(pooledStream.NetworkStream); pooledStream.UpdateLifetime(); if (((SmtpPooledStream) pooledStream).previouslyUsed) { this.isConnected = true; } else { LineInfo info = this.responseReader.GetNextReplyReader().ReadLine(); if (info.StatusCode != SmtpStatusCode.ServiceReady) { throw new SmtpException(info.StatusCode, info.Line, true); } try { this.extensions = EHelloCommand.Send(this, this.client.clientDomain); this.ParseExtensions(this.extensions); } catch (SmtpException exception) { if ((exception.StatusCode != SmtpStatusCode.CommandUnrecognized) && (exception.StatusCode != SmtpStatusCode.CommandNotImplemented)) { throw exception; } HelloCommand.Send(this, this.client.clientDomain); this.supportedAuth = SupportedAuth.Login; } if (this.enableSsl) { if (!this.serverSupportsStartTls && !(pooledStream.NetworkStream is TlsStream)) { throw new SmtpException(SR.GetString("MailServerDoesNotSupportStartTls")); } StartTlsCommand.Send(this); TlsStream stream2 = new TlsStream(servicePoint.Host, pooledStream.NetworkStream, this.clientCertificates, servicePoint, this.client, null); pooledStream.NetworkStream = stream2; this.channelBindingToken = stream2.GetChannelBinding(ChannelBindingKind.Unique); this.responseReader = new SmtpReplyReaderFactory(pooledStream.NetworkStream); this.extensions = EHelloCommand.Send(this, this.client.clientDomain); this.ParseExtensions(this.extensions); } if (this.credentials != null) { for (int i = 0; i < this.authenticationModules.Length; i++) { Authorization authorization; if (this.AuthSupported(this.authenticationModules[i])) { NetworkCredential credential = this.credentials.GetCredential(servicePoint.Host, servicePoint.Port, this.authenticationModules[i].AuthenticationType); if (credential != null) { authorization = this.SetContextAndTryAuthenticate(this.authenticationModules[i], credential, null); if ((authorization != null) && (authorization.Message != null)) { info = AuthCommand.Send(this, this.authenticationModules[i].AuthenticationType, authorization.Message); if (info.StatusCode != SmtpStatusCode.CommandParameterNotImplemented) { goto Label_0363; } } } } continue; Label_02F2: authorization = this.authenticationModules[i].Authenticate(info.Line, null, this, this.client.TargetName, this.channelBindingToken); if (authorization == null) { throw new SmtpException(SR.GetString("SmtpAuthenticationFailed")); } info = AuthCommand.Send(this, authorization.Message); if (info.StatusCode == ((SmtpStatusCode) 0xeb)) { this.authenticationModules[i].CloseContext(this); this.isConnected = true; return; } Label_0363: if (info.StatusCode == ((SmtpStatusCode) 0x14e)) { goto Label_02F2; } } } this.isConnected = true; } }
internal void GetConnection(ServicePoint servicePoint) { if (isConnected) { throw new InvalidOperationException(SR.GetString(SR.SmtpAlreadyConnected)); } if (Logging.On) Logging.Associate(Logging.Web, this, servicePoint); Debug.Assert(servicePoint != null, "servicePoint was null from SmtpTransport"); connectionPool = ConnectionPoolManager.GetConnectionPool(servicePoint, "", m_CreateConnectionCallback); PooledStream pooledStream = connectionPool.GetConnection((object)this, null, Timeout); while (((SmtpPooledStream)pooledStream).creds != null && ((SmtpPooledStream)pooledStream).creds != credentials) { // destroy this connection so that a new connection can be created // in order to use the proper credentials. Do not just close the // connection since it's in a state where a QUIT could be sent connectionPool.PutConnection(pooledStream, pooledStream.Owner, Timeout, false); pooledStream = connectionPool.GetConnection((object)this, null, Timeout); } if (Logging.On) Logging.Associate(Logging.Web, this, pooledStream); lock (this) { this.pooledStream = pooledStream; } ((SmtpPooledStream)pooledStream).creds = credentials; responseReader = new SmtpReplyReaderFactory(pooledStream.NetworkStream); //set connectionlease pooledStream.UpdateLifetime(); //if the stream was already used, then we've already done the handshake if (((SmtpPooledStream)pooledStream).previouslyUsed == true) { isConnected = true; return; } LineInfo info = responseReader.GetNextReplyReader().ReadLine(); switch (info.StatusCode) { case SmtpStatusCode.ServiceReady: { break; } default: { throw new SmtpException(info.StatusCode, info.Line, true); } } try { extensions = EHelloCommand.Send(this, client.clientDomain); ParseExtensions(extensions); } catch (SmtpException e) { if ((e.StatusCode != SmtpStatusCode.CommandUnrecognized) && (e.StatusCode != SmtpStatusCode.CommandNotImplemented)) { throw e; } HelloCommand.Send(this, client.clientDomain); //if ehello isn't supported, assume basic login supportedAuth = SupportedAuth.Login; } #if !FEATURE_PAL // Establish TLS if (enableSsl) { if (!serverSupportsStartTls) { // Either TLS is already established or server does not support TLS if (!(pooledStream.NetworkStream is TlsStream)) { throw new SmtpException(SR.GetString(SR.MailServerDoesNotSupportStartTls)); } } StartTlsCommand.Send(this); TlsStream TlsStream = new TlsStream(servicePoint.Host, pooledStream.NetworkStream, clientCertificates, servicePoint, client, null); pooledStream.NetworkStream = TlsStream; //for SMTP, the CBT should be unique this.channelBindingToken = TlsStream.GetChannelBinding(ChannelBindingKind.Unique); responseReader = new SmtpReplyReaderFactory(pooledStream.NetworkStream); // According to RFC 3207: The client SHOULD send an EHLO command // as the first command after a successful TLS negotiation. extensions = EHelloCommand.Send(this, client.clientDomain); ParseExtensions(extensions); } #endif // !FEATURE_PAL //if no credentials were supplied, try anonymous //servers don't appear to anounce that they support anonymous login. if (credentials != null) { for (int i = 0; i < authenticationModules.Length; i++) { //only authenticate if the auth protocol is supported - [....] if (!AuthSupported(authenticationModules[i])) { continue; } NetworkCredential credential = credentials.GetCredential(servicePoint.Host, servicePoint.Port, authenticationModules[i].AuthenticationType); if (credential == null) continue; Authorization auth = SetContextAndTryAuthenticate(authenticationModules[i], credential, null); if (auth != null && auth.Message != null) { info = AuthCommand.Send(this, authenticationModules[i].AuthenticationType, auth.Message); if (info.StatusCode == SmtpStatusCode.CommandParameterNotImplemented) { continue; } while ((int)info.StatusCode == 334) { auth = authenticationModules[i].Authenticate(info.Line, null, this, this.client.TargetName, this.channelBindingToken); if (auth == null) { throw new SmtpException(SR.GetString(SR.SmtpAuthenticationFailed)); } info = AuthCommand.Send(this, auth.Message); if ((int)info.StatusCode == 235) { authenticationModules[i].CloseContext(this); isConnected = true; return; } } } } } isConnected = true; }