SMTP AUTH LOGIN Cram-Md5認証をC#でやる

SMTP AUTH LOGIN Cram-Md5認証

public static void ConnectCramMd5( string server, int port, string user, string pass ) {
	var client = new TcpClient();
	client.Connect( server,  port );

	var stream = new SslStream( client.GetStream() );
	stream.AuthenticateAsClient(server);
	ReceiveString( stream );

	SendAndReceive( stream, string.Format( "EHLO {0}\r\n", Dns.GetHostName() ) );
	var code = PickChallengeCode( SendAndReceive( stream, "AUTH CRAM-MD5\r\n" ) );
	var source = string.Format( "{0} {1}", user, GetAsciiToHMACMD5( Base64ToAscii( code ), pass ) );

	SendAndReceive( stream, AsciiToBase64( source ) + "\r\n" );
	SendAndReceive( stream, "QUIT\r\n" );
}

static string PickChallengeCode( string source ) {
	return source.Split(' ')[1];
}

static string GetAsciiToHMACMD5( string value, string key ) {
	var hmacmd5 = new HMACMD5( Encoding.ASCII.GetBytes( key ) );
	var hashBytes = hmacmd5.ComputeHash( Encoding.ASCII.GetBytes( value ) );
	return BitConverter.ToString( hashBytes ).Replace( "-", "" ).ToLower();
}


static private string SendAndReceive( Stream stream, string request ) {
	SendString( stream, request );
	return ReceiveString( stream );
}

private static void SendString( Stream stream, string request ) {
	var sendData = _encoding.GetBytes( request );
	stream.Write( sendData, 0, sendData.Length );
	stream.Flush();
	Console.WriteLine( "< " + request );
}

private static string ReceiveString( Stream stream ) {
	byte[] buff = new byte[1024 * 1024 - 1];

	int receiveSize = stream.Read( buff, 0, buff.Length );
	if ( receiveSize > 0 ) {
		Array.Resize( ref buff, receiveSize - 2 );
		var res = _encoding.GetString( buff );
		Console.WriteLine( "> " + res );
		return res;
	}
	throw new Exception( "Read Error." );
}

static string Base64ToAscii( string base64 ) {
	var buff = Convert.FromBase64String( base64 );
	return Encoding.ASCII.GetString( buff );
}

static string AsciiToBase64( string s ) {
	var buff = Encoding.ASCII.GetBytes( s );
	return  Convert.ToBase64String( buff );
}