2 // System.Web.Mail.SmtpStream.cs
5 // Per Arneng <pt99par@student.bth.se>
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 using System.Collections;
33 using System.Security.Cryptography;
34 using System.Diagnostics;
36 namespace System.Web.Mail {
38 internal class SmtpStream {
40 protected Stream stream;
41 protected Encoding encoding;
42 protected SmtpResponse lastResponse;
43 protected string command = "";
45 public SmtpStream( Stream stream ) {
47 encoding = new ASCIIEncoding();
50 public Stream Stream {
51 get { return stream; }
54 public SmtpResponse LastResponse {
55 get { return lastResponse; }
58 public void WriteRset() {
62 CheckForStatusCode( 250 );
66 public void WriteAuthLogin()
68 command = "AUTH LOGIN";
73 public bool WriteStartTLS( )
78 return LastResponse.StatusCode == 220;
82 public void WriteEhlo( string hostName )
84 command = "EHLO " + hostName;
87 CheckForStatusCode( 250 );
91 public void WriteHelo( string hostName ) {
92 command = "HELO " + hostName;
95 CheckForStatusCode( 250 );
99 public void WriteMailFrom( string from ) {
100 command = "MAIL FROM: <" + from + ">";
101 WriteLine( command );
103 CheckForStatusCode( 250 );
107 public void WriteRcptTo( string to ) {
108 command = "RCPT TO: <" + to + ">";
109 WriteLine( command );
111 CheckForStatusCode( 250 );
116 public void WriteData() {
118 WriteLine( command );
120 CheckForStatusCode( 354 );
124 public void WriteQuit() {
126 WriteLine( command );
128 CheckForStatusCode( 221 );
132 public void WriteBoundary( string boundary ) {
134 WriteLine( "\r\n--{0}" , boundary );
138 public void WriteFinalBoundary( string boundary ) {
140 WriteLine( "\r\n--{0}--" , boundary );
144 // single dot by itself
145 public void WriteDataEndTag() {
147 WriteLine( command );
149 CheckForStatusCode( 250 );
154 public void WriteHeader( MailHeader header ) {
156 foreach( string key in header.Data.AllKeys )
157 WriteLine( "{0}: {1}" , key , header.Data[ key ] );
159 // write the header end tag
163 public void CheckForStatusCode( int statusCode ) {
165 if( LastResponse.StatusCode != statusCode ) {
168 "Server reponse: '" + lastResponse.RawResponse + "';" +
169 "Status code: '" + lastResponse.StatusCode + "';" +
170 "Expected status code: '" + statusCode + "';" +
171 "Last command: '" + command + "'";
173 throw new SmtpException( msg );
179 // write buffer's bytes to the stream
180 public void WriteBytes( byte[] buffer ) {
181 stream.Write( buffer , 0 , buffer.Length );
184 // writes a formatted line to the server
185 public void WriteLine( string format , params object[] args ) {
186 WriteLine( String.Format( format , args ) );
189 // writes a line to the server
190 public void WriteLine( string line ) {
191 byte[] buffer = encoding.GetBytes( line + "\r\n" );
193 stream.Write( buffer , 0 , buffer.Length );
195 Debug.WriteLine ("smtp: {0}", line);
198 // read a line from the server
199 public void ReadResponse( ) {
201 byte[] buffer = new byte [512];
203 bool lastLine = false;
206 int readLength = stream.Read (buffer , position , buffer.Length - position);
207 if (readLength > 0) {
208 int available = position + readLength - 1;
209 if (available > 4 && (buffer [available] == '\n' || buffer [available] == '\r'))
210 for (int index = available - 3; ; index--) {
211 if (index < 0 || buffer [index] == '\n' || buffer [index] == '\r') {
212 lastLine = buffer [index + 4] == ' ';
218 position += readLength;
220 // check if buffer is full
221 if (position == buffer.Length) {
222 byte [] newBuffer = new byte [buffer.Length * 2];
223 Array.Copy (buffer, 0, newBuffer, 0, buffer.Length);
229 string line = encoding.GetString (buffer , 0 , position - 1);
231 // parse the line to the lastResponse object
232 lastResponse = SmtpResponse.Parse (line);
234 Debug.WriteLine ("smtp: {0}", line);