Code:
/ DotNET / DotNET / 8.0 / untmp / whidbey / REDBITS / ndp / fx / src / Net / System / Net / Mail / smtpconnection.cs / 2 / smtpconnection.cs
namespace System.Net.Mail { using System; using System.Net; using System.Security.Cryptography.X509Certificates; using System.IO; using System.Threading; using System.Globalization; using System.Security.Principal; using System.Security.Permissions; class SmtpConnection { private static PooledStream CreateSmtpPooledStream(ConnectionPool pool) { return (PooledStream) new SmtpPooledStream(pool, TimeSpan.MaxValue, false); } private static readonly CreateConnectionDelegate m_CreateConnectionCallback = new CreateConnectionDelegate(CreateSmtpPooledStream); private static readonly ContextCallback s_AuthenticateCallback = new ContextCallback(AuthenticateCallback); BufferBuilder bufferBuilder = new BufferBuilder(); bool isConnected; bool isClosed; bool isStreamOpen; bool sawNegotiate; EventHandler onCloseHandler; internal SmtpTransport parent; internal SmtpClient client; SmtpReplyReaderFactory responseReader; PooledStream pooledStream; ConnectionPool connectionPool; SupportedAuth supportedAuth = SupportedAuth.None; bool serverSupportsStartTls = false; ISmtpAuthenticationModule[] authenticationModules; ICredentialsByHost credentials; int timeout = 100000; string[] extensions; bool enableSsl; X509CertificateCollection clientCertificates; internal SmtpConnection(SmtpTransport parent, SmtpClient client, ICredentialsByHost credentials, ISmtpAuthenticationModule[] authenticationModules) { this.client = client; this.credentials = credentials; this.authenticationModules = authenticationModules; this.parent = parent; onCloseHandler = new EventHandler(OnClose); } internal BufferBuilder BufferBuilder { get { return bufferBuilder; } } internal bool IsConnected { get { return isConnected; } } internal bool IsStreamOpen { get { return isStreamOpen; } } internal bool DSNEnabled { get { if (pooledStream != null) return ((SmtpPooledStream)pooledStream).dsnEnabled; else return false; } } internal SmtpReplyReaderFactory Reader { get { return responseReader; } } internal bool EnableSsl { get { return enableSsl; } set { #if !FEATURE_PAL enableSsl = value; #else throw new NotImplementedException("ROTORTODO"); #endif } } internal int Timeout { get { return timeout; } set { timeout = value; } } internal X509CertificateCollection ClientCertificates { get { return clientCertificates; } set { clientCertificates = value; } } internal IAsyncResult BeginGetConnection(string host, int port, ContextAwareResult outerResult, AsyncCallback callback, object state) { ServicePoint servicePoint = ServicePointManager.FindServicePoint(host,port); if(Logging.On)Logging.Associate(Logging.Web, this, servicePoint); if (EnableSsl && ClientCertificates != null && ClientCertificates.Count > 0) connectionPool = ConnectionPoolManager.GetConnectionPool(servicePoint, ClientCertificates.GetHashCode().ToString(NumberFormatInfo.InvariantInfo), m_CreateConnectionCallback); else connectionPool = ConnectionPoolManager.GetConnectionPool(servicePoint, "", m_CreateConnectionCallback); ConnectAndHandshakeAsyncResult result = new ConnectAndHandshakeAsyncResult(this, host, port, outerResult, callback, state); result.GetConnection(false); return result; } internal IAsyncResult BeginFlush(AsyncCallback callback, object state) { return pooledStream.UnsafeBeginWrite(bufferBuilder.GetBuffer(), 0, bufferBuilder.Length, callback, state); } internal void EndFlush(IAsyncResult result) { pooledStream.EndWrite(result); bufferBuilder.Reset(); } internal void Flush() { pooledStream.Write(bufferBuilder.GetBuffer(), 0, bufferBuilder.Length); bufferBuilder.Reset(); } internal void ReleaseConnection() { if (!isClosed) { lock (this) { if (!isClosed && pooledStream != null){ GlobalLog.Print("SmtpConnectiont#" + ValidationHelper.HashString(this) + "::Close Transport#"+ValidationHelper.HashString(parent)+"putting back pooledStream#"+ValidationHelper.HashString(pooledStream)); ((SmtpPooledStream)pooledStream).previouslyUsed = true; connectionPool.PutConnection(pooledStream, pooledStream.Owner, Timeout); } isClosed = true; } } isConnected = false; } internal void Abort() { if (!isClosed) { lock (this) { if (!isClosed && pooledStream != null){ GlobalLog.Print("SmtpConnectiont#" + ValidationHelper.HashString(this) + "::Close Transport#"+ValidationHelper.HashString(parent)+"closing and putting back pooledStream#"+ValidationHelper.HashString(pooledStream)); pooledStream.Close(0); connectionPool.PutConnection(pooledStream, pooledStream.Owner, Timeout); } isClosed = true; } } isConnected = false; } internal void ParseExtensions(string[] extensions) { supportedAuth = SupportedAuth.None; foreach (string extension in extensions) { if (String.Compare(extension, 0, "auth ", 0, 5, StringComparison.OrdinalIgnoreCase) == 0) { string[] authTypes = extension.Split(' '); foreach (string authType in authTypes){ if (String.Compare(authType, "login", StringComparison.OrdinalIgnoreCase) == 0) { supportedAuth |= SupportedAuth.Login; } #if !FEATURE_PAL else if (String.Compare(authType, "ntlm", StringComparison.OrdinalIgnoreCase) == 0) { supportedAuth|=SupportedAuth.NTLM; } else if (String.Compare(authType, "gssapi", StringComparison.OrdinalIgnoreCase) == 0) { supportedAuth |= SupportedAuth.GGSAPI; } else if (String.Compare(authType, "wdigest", StringComparison.OrdinalIgnoreCase) == 0) { supportedAuth |= SupportedAuth.WDigest; } #endif // FEATURE_PAL } } else if (String.Compare(extension, 0, "dsn ", 0, 3, StringComparison.OrdinalIgnoreCase) == 0) { ((SmtpPooledStream)pooledStream).dsnEnabled = true; } else if (String.Compare(extension, 0, "STARTTLS", 0, 8, StringComparison.OrdinalIgnoreCase) == 0) { serverSupportsStartTls = true; } } } internal bool AuthSupported(ISmtpAuthenticationModule module){ if (module is SmtpLoginAuthenticationModule) { if ((supportedAuth & SupportedAuth.Login) > 0) { return true; } } #if !FEATURE_PAL else if (module is SmtpNegotiateAuthenticationModule) { if ((supportedAuth & SupportedAuth.GGSAPI) > 0) { sawNegotiate = true; return true; } } else if (module is SmtpNtlmAuthenticationModule) { //don't try ntlm if negotiate has been tried if ((!sawNegotiate && (supportedAuth & SupportedAuth.NTLM) > 0)) { return true; } } else if (module is SmtpDigestAuthenticationModule) { if ((supportedAuth & SupportedAuth.WDigest) > 0) { return true; } } #endif // FEATURE_PAL return false; } internal void GetConnection(string host, int port) { if (isConnected) { throw new InvalidOperationException(SR.GetString(SR.SmtpAlreadyConnected)); } ServicePoint servicePoint = ServicePointManager.FindServicePoint(host,port); if(Logging.On)Logging.Associate(Logging.Web, this, servicePoint); connectionPool = ConnectionPoolManager.GetConnectionPool(servicePoint, "", m_CreateConnectionCallback); PooledStream pooledStream = connectionPool.GetConnection((object)this, null, Timeout); while (((SmtpPooledStream)pooledStream).creds != null && ((SmtpPooledStream)pooledStream).creds != credentials) { pooledStream.Close(); connectionPool.PutConnection(pooledStream, pooledStream.Owner, Timeout); 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.localHostName); ParseExtensions(extensions); } catch (SmtpException e) { if ((e.StatusCode != SmtpStatusCode.CommandUnrecognized) && (e.StatusCode != SmtpStatusCode.CommandNotImplemented)){ throw e; } HelloCommand.Send(this, client.localHostName); //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; 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.localHostName); 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(host, 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); 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; } // // We may need to impersonate in this method // [SecurityPermission(SecurityAction.Assert, Flags=SecurityPermissionFlag.ControlPrincipal)] private Authorization SetContextAndTryAuthenticate(ISmtpAuthenticationModule module, NetworkCredential credential, ContextAwareResult context) { #if !FEATURE_PAL // We may need to restore user thread token here if (credential is SystemNetworkCredential && ComNetOS.IsWinNt) { // #if DEBUG GlobalLog.Assert(context == null || context.IdentityRequested, "SmtpConnection#{0}::SetContextAndTryAuthenticate|Authentication required when it wasn't expected. (Maybe Credentials was changed on another thread?)", ValidationHelper.HashString(this)); #endif WindowsIdentity w = context == null ? null : context.Identity; try { IDisposable ctx = w == null ? null : w.Impersonate(); if (ctx != null) { using (ctx) { return module.Authenticate(null, credential, this); } } else { ExecutionContext x = context == null ? null : context.ContextCopy; if (x != null) { ExecutionContext.Run(x, s_AuthenticateCallback, new AuthenticateCallbackContext(this, module, credential)); } else { return module.Authenticate(null, credential, this); } } } catch { // Prevent the impersonation from leaking to upstack exception filters. throw; } } #endif // !FEATURE_PAL return module.Authenticate(null, credential, this); } private static void AuthenticateCallback(object state) { AuthenticateCallbackContext context = (AuthenticateCallbackContext) state; context.module.Authenticate(null, context.credential, context.thisPtr); } private class AuthenticateCallbackContext { internal AuthenticateCallbackContext(SmtpConnection thisPtr, ISmtpAuthenticationModule module, NetworkCredential credential) { this.thisPtr = thisPtr; this.module = module; this.credential = credential; } internal readonly SmtpConnection thisPtr; internal readonly ISmtpAuthenticationModule module; internal readonly NetworkCredential credential; } internal void EndGetConnection(IAsyncResult result) { ConnectAndHandshakeAsyncResult.End(result); } internal Stream GetClosableStream() { ClosableStream cs = new ClosableStream(pooledStream.NetworkStream, onCloseHandler); isStreamOpen = true; return cs; } void OnClose(object sender, EventArgs args) { isStreamOpen = false; DataStopCommand.Send(this); } class ConnectAndHandshakeAsyncResult : LazyAsyncResult { private static readonly GeneralAsyncDelegate m_ConnectionCreatedCallback = new GeneralAsyncDelegate(ConnectionCreatedCallback); string authResponse; SmtpConnection connection; int currentModule = -1; int port; static AsyncCallback handshakeCallback = new AsyncCallback(HandshakeCallback); static AsyncCallback sendEHelloCallback = new AsyncCallback(SendEHelloCallback); static AsyncCallback sendHelloCallback = new AsyncCallback(SendHelloCallback); static AsyncCallback authenticateCallback = new AsyncCallback(AuthenticateCallback); static AsyncCallback authenticateContinueCallback = new AsyncCallback(AuthenticateContinueCallback); string host; private readonly ContextAwareResult m_OuterResult; internal ConnectAndHandshakeAsyncResult(SmtpConnection connection, string host, int port, ContextAwareResult outerResult, AsyncCallback callback, object state) : base(null, state, callback) { this.connection = connection; this.host = host; this.port = port; m_OuterResult = outerResult; } private static void ConnectionCreatedCallback(object request, object state) { GlobalLog.Enter("ConnectAndHandshakeAsyncResult#" + ValidationHelper.HashString(request) + "::ConnectionCreatedCallback"); ConnectAndHandshakeAsyncResult ConnectAndHandshakeAsyncResult = (ConnectAndHandshakeAsyncResult) request; if (state is Exception) { ConnectAndHandshakeAsyncResult.InvokeCallback((Exception)state); return; } SmtpPooledStream pooledStream = (SmtpPooledStream)(PooledStream)state; try { while (pooledStream.creds != null && pooledStream.creds != ConnectAndHandshakeAsyncResult.connection.credentials) { GlobalLog.Print("ConnectAndHandshakeAsyncResult#" + ValidationHelper.HashString(request) + "::Connect pooledStream has wrong creds "+ValidationHelper.HashString(pooledStream)); pooledStream.Close(); ConnectAndHandshakeAsyncResult.connection.connectionPool.PutConnection(pooledStream, pooledStream.Owner, ConnectAndHandshakeAsyncResult.connection.Timeout); pooledStream = (SmtpPooledStream)ConnectAndHandshakeAsyncResult.connection.connectionPool.GetConnection((object)ConnectAndHandshakeAsyncResult,ConnectAndHandshakeAsyncResult.m_ConnectionCreatedCallback, ConnectAndHandshakeAsyncResult.connection.Timeout); if (pooledStream == null) { GlobalLog.Leave("ConnectAndHandshakeAsyncResult#" + ValidationHelper.HashString(request) + "::Connect returning asynchronously"); return; } } if(Logging.On)Logging.Associate(Logging.Web, ConnectAndHandshakeAsyncResult.connection, pooledStream); pooledStream.Owner = ConnectAndHandshakeAsyncResult.connection; //needs to be updated for gc reasons pooledStream.creds = ConnectAndHandshakeAsyncResult.connection.credentials; lock(ConnectAndHandshakeAsyncResult.connection){ //if we were cancelled while getting the connection, we should close and return if(ConnectAndHandshakeAsyncResult.connection.isClosed){ pooledStream.Close(); ConnectAndHandshakeAsyncResult.connection.connectionPool.PutConnection(pooledStream, pooledStream.Owner, ConnectAndHandshakeAsyncResult.connection.Timeout); GlobalLog.Print("ConnectAndHandshakeAsyncResult#" + ValidationHelper.HashString(request) + "::ConnectionCreatedCallback Connect was aborted "+ValidationHelper.HashString(pooledStream)); ConnectAndHandshakeAsyncResult.InvokeCallback(null); return; } ConnectAndHandshakeAsyncResult.connection.pooledStream = pooledStream; } ConnectAndHandshakeAsyncResult.Handshake(); } catch (Exception e) { ConnectAndHandshakeAsyncResult.InvokeCallback(e); } GlobalLog.Leave("ConnectAndHandshakeAsyncResult#" + ValidationHelper.HashString(request) + "::ConnectionCreatedCallback pooledStream#"+ValidationHelper.HashString(pooledStream)); } internal static void End(IAsyncResult result) { ConnectAndHandshakeAsyncResult thisPtr = (ConnectAndHandshakeAsyncResult)result; object connectResult = thisPtr.InternalWaitForCompletion(); if(connectResult is Exception){ throw (Exception)connectResult; } } internal void GetConnection(bool synchronous) { GlobalLog.Enter("ConnectAndHandshakeAsyncResult#" + ValidationHelper.HashString(this) + "::Connect: sync=" + (synchronous?"true":"false")); if (connection.isConnected) { throw new InvalidOperationException(SR.GetString(SR.SmtpAlreadyConnected)); } SmtpPooledStream pooledStream = (SmtpPooledStream)connection.connectionPool.GetConnection((object)this, (synchronous?null:m_ConnectionCreatedCallback), connection.Timeout); GlobalLog.Print("ConnectAndHandshakeAsyncResult#" + ValidationHelper.HashString(this) + "::Connect returned" + ValidationHelper.HashString(this)); if (pooledStream != null) { try { while (pooledStream.creds != null && pooledStream.creds != connection.credentials) { GlobalLog.Print("ConnectAndHandshakeAsyncResult#" + ValidationHelper.HashString(this) + "::Connect pooledStream has wrong creds "+ValidationHelper.HashString(pooledStream)); pooledStream.Close(); connection.connectionPool.PutConnection(pooledStream, pooledStream.Owner, connection.Timeout); pooledStream = (SmtpPooledStream)connection.connectionPool.GetConnection((object)this,(synchronous?null:m_ConnectionCreatedCallback), connection.Timeout); if (pooledStream == null) { GlobalLog.Leave("ConnectAndHandshakeAsyncResult#" + ValidationHelper.HashString(this) + "::Connect returning asynchronously"); return; } } pooledStream.creds = connection.credentials; pooledStream.Owner = this.connection; //needs to be updated for gc reasons lock(connection){ connection.pooledStream = pooledStream; } Handshake(); } catch (Exception e) { InvokeCallback(e); } } GlobalLog.Leave("ConnectAndHandshakeAsyncResult#" + ValidationHelper.HashString(this) + "::Connect pooledStream#"+ValidationHelper.HashString(pooledStream)); } void Handshake() { connection.responseReader = new SmtpReplyReaderFactory(connection.pooledStream.NetworkStream); //if we've already used this stream, then we've already done the handshake //set connectionlease connection.pooledStream.UpdateLifetime(); if(((SmtpPooledStream)connection.pooledStream).previouslyUsed == true){ connection.isConnected = true; InvokeCallback(); return; } SmtpReplyReader reader = connection.Reader.GetNextReplyReader(); IAsyncResult result = reader.BeginReadLine(handshakeCallback, this); if (!result.CompletedSynchronously) { return; } LineInfo info = reader.EndReadLine(result); if (info.StatusCode != SmtpStatusCode.ServiceReady) { throw new SmtpException(info.StatusCode, info.Line, true); } try { if (!SendEHello()) { return; } } catch { if (!SendHello()) { return; } } } static void HandshakeCallback(IAsyncResult result) //3 { if (!result.CompletedSynchronously) { ConnectAndHandshakeAsyncResult thisPtr = (ConnectAndHandshakeAsyncResult)result.AsyncState; try { try { LineInfo info = thisPtr.connection.Reader.CurrentReader.EndReadLine(result); if (info.StatusCode != SmtpStatusCode.ServiceReady) { thisPtr.InvokeCallback(new SmtpException(info.StatusCode,info.Line,true)); return; } if (!thisPtr.SendEHello()) { return; } } catch (SmtpException) { if (!thisPtr.SendHello()) { return; } } } catch (Exception e) { thisPtr.InvokeCallback(e); } } } bool SendEHello()//4 { IAsyncResult result = EHelloCommand.BeginSend(connection, connection.client.localHostName, sendEHelloCallback, this); if (result.CompletedSynchronously) { connection.extensions = EHelloCommand.EndSend(result); connection.ParseExtensions(connection.extensions); // If we already have a TlsStream, this is the second EHLO cmd // that we sent after TLS handshake compelted. So skip TLS and // continue with Authenticate. if (connection.pooledStream.NetworkStream is TlsStream) { Authenticate(); return true; } if (connection.EnableSsl) { #if !FEATURE_PAL if (!connection.serverSupportsStartTls) { // Either TLS is already established or server does not support TLS if (!(connection.pooledStream.NetworkStream is TlsStream)) { throw new SmtpException(SR.GetString(SR.MailServerDoesNotSupportStartTls)); } } SendStartTls(); #else // FEATURE_PAL throw new NotSupportedException("ROTORTODO"); #endif // !FEATURE_PAL } else { Authenticate(); } return true; } return false; } static void SendEHelloCallback(IAsyncResult result)//5 { if (!result.CompletedSynchronously) { ConnectAndHandshakeAsyncResult thisPtr = (ConnectAndHandshakeAsyncResult)result.AsyncState; try { try { thisPtr.connection.extensions = EHelloCommand.EndSend(result); thisPtr.connection.ParseExtensions(thisPtr.connection.extensions); // If we already have a TlsStream, this is the second EHLO cmd // that we sent after TLS handshake compelted. So skip TLS and // continue with Authenticate. if (thisPtr.connection.pooledStream.NetworkStream is TlsStream) { thisPtr.Authenticate(); return; } } catch (SmtpException e) { if ((e.StatusCode != SmtpStatusCode.CommandUnrecognized) && (e.StatusCode != SmtpStatusCode.CommandNotImplemented)){ throw e; } if (!thisPtr.SendHello()) { return; } } if (thisPtr.connection.EnableSsl) { #if !FEATURE_PAL if (!thisPtr.connection.serverSupportsStartTls) { // Either TLS is already established or server does not support TLS if (!(thisPtr.connection.pooledStream.NetworkStream is TlsStream)) { throw new SmtpException(SR.GetString(SR.MailServerDoesNotSupportStartTls)); } } thisPtr.SendStartTls(); #else // FEATURE_PAL throw new NotSupportedException("ROTORTODO"); #endif // !FEATURE_PAL } else { thisPtr.Authenticate(); } } catch (Exception e) { thisPtr.InvokeCallback(e); } } } bool SendHello()//6 { IAsyncResult result = HelloCommand.BeginSend(connection, connection.client.localHostName, sendHelloCallback, this); //if ehello isn't supported, assume basic auth if (result.CompletedSynchronously) { connection.supportedAuth = SupportedAuth.Login; HelloCommand.EndSend(result); Authenticate(); return true; } return false; } static void SendHelloCallback(IAsyncResult result) //7 { if (!result.CompletedSynchronously) { ConnectAndHandshakeAsyncResult thisPtr = (ConnectAndHandshakeAsyncResult)result.AsyncState; try { HelloCommand.EndSend(result); thisPtr.Authenticate(); } catch (Exception e) { thisPtr.InvokeCallback(e); } } } #if !FEATURE_PAL bool SendStartTls()//6 { IAsyncResult result = StartTlsCommand.BeginSend(connection, SendStartTlsCallback, this); if (result.CompletedSynchronously) { StartTlsCommand.EndSend(result); TlsStream TlsStream = new TlsStream(connection.pooledStream.ServicePoint.Host, connection.pooledStream.NetworkStream, connection.ClientCertificates, connection.pooledStream.ServicePoint, connection.client, m_OuterResult.ContextCopy); connection.pooledStream.NetworkStream= TlsStream; connection.responseReader = new SmtpReplyReaderFactory(connection.pooledStream.NetworkStream); SendEHello(); return true; } return false; } static void SendStartTlsCallback(IAsyncResult result) //7 { if (!result.CompletedSynchronously) { ConnectAndHandshakeAsyncResult thisPtr = (ConnectAndHandshakeAsyncResult)result.AsyncState; try { StartTlsCommand.EndSend(result); TlsStream TlsStream = new TlsStream(thisPtr.connection.pooledStream.ServicePoint.Host, thisPtr.connection.pooledStream.NetworkStream, thisPtr.connection.ClientCertificates, thisPtr.connection.pooledStream.ServicePoint, thisPtr.connection.client, thisPtr.m_OuterResult.ContextCopy); thisPtr.connection.pooledStream.NetworkStream= TlsStream; thisPtr.connection.responseReader = new SmtpReplyReaderFactory(thisPtr.connection.pooledStream.NetworkStream); thisPtr.SendEHello(); } catch (Exception e) { thisPtr.InvokeCallback(e); } } } #endif // !FEATURE_PAL void Authenticate() //8 { //if no credentials were supplied, try anonymous //servers don't appear to anounce that they support anonymous login. if (connection.credentials != null) { while (++currentModule < connection.authenticationModules.Length) { //only authenticate if the auth protocol is supported ISmtpAuthenticationModule module = connection.authenticationModules[currentModule]; if (!connection.AuthSupported(module)) { continue; } NetworkCredential credential = connection.credentials.GetCredential(host, port, module.AuthenticationType); if (credential ==null) continue; Authorization auth = connection.SetContextAndTryAuthenticate(module, credential, m_OuterResult); if (auth != null && auth.Message != null) { IAsyncResult result = AuthCommand.BeginSend(connection, connection.authenticationModules[currentModule].AuthenticationType, auth.Message, authenticateCallback, this); if (!result.CompletedSynchronously) { return; } LineInfo info = AuthCommand.EndSend(result); if ((int)info.StatusCode == 334) { authResponse = info.Line; if (!AuthenticateContinue()) { return; } } else if ((int)info.StatusCode == 235) { module.CloseContext(connection); connection.isConnected = true; break; } } } //try anonymous if didn't authenticate //if (!connection.isConnected) { // throw new SmtpException(SR.GetString(SR.SmtpAuthenticationFailed)); // } } connection.isConnected = true; InvokeCallback(); } static void AuthenticateCallback(IAsyncResult result) //9 { if (!result.CompletedSynchronously) { ConnectAndHandshakeAsyncResult thisPtr = (ConnectAndHandshakeAsyncResult)result.AsyncState; try { LineInfo info = AuthCommand.EndSend(result); if ((int)info.StatusCode == 334) { thisPtr.authResponse = info.Line; if (!thisPtr.AuthenticateContinue()) { return; } } else if ((int)info.StatusCode == 235) { thisPtr.connection.authenticationModules[thisPtr.currentModule].CloseContext(thisPtr.connection); thisPtr.connection.isConnected = true; thisPtr.InvokeCallback(); return; } thisPtr.Authenticate(); } catch (Exception e) { thisPtr.InvokeCallback(e); } } } bool AuthenticateContinue() //10 { for (;;) { // We don't need credential on the continued auth assuming they were captured on the first call. // That should always work, otherwise what if a new credential has been returned? Authorization auth = connection.authenticationModules[currentModule].Authenticate(authResponse, null, connection); if (auth == null) { throw new SmtpException(SR.GetString(SR.SmtpAuthenticationFailed)); } IAsyncResult result = AuthCommand.BeginSend(connection, auth.Message, authenticateContinueCallback, this); if (!result.CompletedSynchronously) { return false; } LineInfo info = AuthCommand.EndSend(result); if ((int)info.StatusCode == 235) { connection.authenticationModules[currentModule].CloseContext(connection); connection.isConnected = true; InvokeCallback(); return false; } else if ((int)info.StatusCode != 334) { return true; } authResponse = info.Line; } } static void AuthenticateContinueCallback(IAsyncResult result) //11 { if (!result.CompletedSynchronously) { ConnectAndHandshakeAsyncResult thisPtr = (ConnectAndHandshakeAsyncResult)result.AsyncState; try { LineInfo info = AuthCommand.EndSend(result); if ((int)info.StatusCode == 235) { thisPtr.connection.authenticationModules[thisPtr.currentModule].CloseContext(thisPtr.connection); thisPtr.connection.isConnected = true; thisPtr.InvokeCallback(); return; } else if ((int)info.StatusCode == 334) { thisPtr.authResponse = info.Line; if (!thisPtr.AuthenticateContinue()) { return; } } thisPtr.Authenticate(); } catch (Exception e) { thisPtr.InvokeCallback(e); } } } } } }
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- TraceFilter.cs
- PenCursorManager.cs
- ContainerSelectorGlyph.cs
- ComponentResourceKey.cs
- ExpandSegmentCollection.cs
- LayoutUtils.cs
- HttpApplication.cs
- AssemblyHash.cs
- _HTTPDateParse.cs
- SendMessageRecord.cs
- CollectionContainer.cs
- DataGridColumnHeader.cs
- GridSplitterAutomationPeer.cs
- WindowsNonControl.cs
- messageonlyhwndwrapper.cs
- GridViewPageEventArgs.cs
- MimeBasePart.cs
- DataGridDesigner.cs
- RequestContext.cs
- PerfService.cs
- SiteMapNodeItemEventArgs.cs
- OledbConnectionStringbuilder.cs
- DataContext.cs
- ArgumentOutOfRangeException.cs
- SecurityTokenValidationException.cs
- ManagedCodeMarkers.cs
- followingquery.cs
- ServiceParser.cs
- XmlConvert.cs
- ComplexPropertyEntry.cs
- TemplatedMailWebEventProvider.cs
- ThrowHelper.cs
- WebServiceHandlerFactory.cs
- MethodBuilderInstantiation.cs
- MonitoringDescriptionAttribute.cs
- CookielessHelper.cs
- ExpandCollapsePattern.cs
- HtmlTableCellCollection.cs
- ToolCreatedEventArgs.cs
- ActiveDocumentEvent.cs
- X509Utils.cs
- DecimalConstantAttribute.cs
- base64Transforms.cs
- PartitionResolver.cs
- BoundingRectTracker.cs
- CompilerGlobalScopeAttribute.cs
- XmlBinaryWriterSession.cs
- ReadOnlyCollection.cs
- XPathNodeIterator.cs
- GetBrowserTokenRequest.cs
- GeneratedContractType.cs
- AttachmentService.cs
- SqlRetyper.cs
- _SslStream.cs
- ObjectListField.cs
- XPathCompileException.cs
- DataGridViewIntLinkedList.cs
- CSharpCodeProvider.cs
- PartialTrustVisibleAssembly.cs
- GCHandleCookieTable.cs
- BufferModesCollection.cs
- ToolStripItemEventArgs.cs
- AnimationClock.cs
- Int64Storage.cs
- NativeMethods.cs
- StopStoryboard.cs
- ExtensionFile.cs
- ConfigXmlCDataSection.cs
- DocumentPageTextView.cs
- ItemAutomationPeer.cs
- CollectionEditor.cs
- HttpResponseInternalBase.cs
- VisualStateGroup.cs
- UInt64.cs
- PageThemeBuildProvider.cs
- PermissionRequestEvidence.cs
- FaultCode.cs
- SerializationHelper.cs
- ObjectSet.cs
- ImageList.cs
- ToolStripItemEventArgs.cs
- PrimitiveDataContract.cs
- x509utils.cs
- StringFreezingAttribute.cs
- SessionEndingCancelEventArgs.cs
- NativeCompoundFileAPIs.cs
- ConditionalAttribute.cs
- OleDbCommand.cs
- EventPrivateKey.cs
- Int16Storage.cs
- EmptyReadOnlyDictionaryInternal.cs
- ReferenceAssemblyAttribute.cs
- DisplayClaim.cs
- PersonalizationStateInfoCollection.cs
- TableCellCollection.cs
- XPathArrayIterator.cs
- NavigationCommands.cs
- FontWeights.cs
- RegionData.cs
- SystemInformation.cs