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.Diagnostics;
35 namespace System.Web.Mail {
37 internal class SmtpStream {
39 protected Stream stream;
40 protected Encoding encoding;
41 protected SmtpResponse lastResponse;
42 protected string command = "";
44 public SmtpStream( Stream stream ) {
46 encoding = new ASCIIEncoding();
49 public Stream Stream {
50 get { return stream; }
53 public SmtpResponse LastResponse {
54 get { return lastResponse; }
57 public void WriteRset() {
61 CheckForStatusCode( 250 );
65 public void WriteAuthLogin()
67 command = "AUTH LOGIN";
72 public bool WriteStartTLS( )
77 return LastResponse.StatusCode == 220;
81 public void WriteEhlo( string hostName )
83 command = "EHLO " + hostName;
86 CheckForStatusCode( 250 );
90 public void WriteHelo( string hostName ) {
91 command = "HELO " + hostName;
94 CheckForStatusCode( 250 );
98 public void WriteMailFrom( string from ) {
99 command = "MAIL FROM: <" + from + ">";
100 WriteLine( command );
102 CheckForStatusCode( 250 );
106 public void WriteRcptTo( string to ) {
107 command = "RCPT TO: <" + to + ">";
108 WriteLine( command );
110 CheckForStatusCode( 250 );
115 public void WriteData() {
117 WriteLine( command );
119 CheckForStatusCode( 354 );
123 public void WriteQuit() {
125 WriteLine( command );
127 CheckForStatusCode( 221 );
131 public void WriteBoundary( string boundary ) {
133 WriteLine( "\r\n--{0}" , boundary );
137 public void WriteFinalBoundary( string boundary ) {
139 WriteLine( "\r\n--{0}--" , boundary );
143 // single dot by itself
144 public void WriteDataEndTag() {
146 WriteLine( command );
148 CheckForStatusCode( 250 );
153 public void WriteHeader( MailHeader header ) {
155 foreach( string key in header.Data.AllKeys )
156 WriteLine( "{0}: {1}" , key , header.Data[ key ] );
158 // write the header end tag
162 public void CheckForStatusCode( int statusCode ) {
164 if( LastResponse.StatusCode != statusCode ) {
167 "Server reponse: '" + lastResponse.RawResponse + "';" +
168 "Status code: '" + lastResponse.StatusCode + "';" +
169 "Expected status code: '" + statusCode + "';" +
170 "Last command: '" + command + "'";
172 throw new SmtpException( msg );
178 // write buffer's bytes to the stream
179 public void WriteBytes( byte[] buffer ) {
180 stream.Write( buffer , 0 , buffer.Length );
183 // writes a formatted line to the server
184 public void WriteLine( string format , params object[] args ) {
185 WriteLine( String.Format( format , args ) );
188 // writes a line to the server
189 public void WriteLine( string line ) {
190 byte[] buffer = encoding.GetBytes( line + "\r\n" );
192 stream.Write( buffer , 0 , buffer.Length );
194 Debug.WriteLine ("smtp: {0}", line);
197 // read a line from the server
198 public void ReadResponse( ) {
200 byte[] buffer = new byte [512];
202 bool lastLine = false;
205 int readLength = stream.Read (buffer , position , buffer.Length - position);
206 if (readLength > 0) {
207 int available = position + readLength - 1;
208 if (available > 4 && (buffer [available] == '\n' || buffer [available] == '\r'))
209 for (int index = available - 3; ; index--) {
210 if (index < 0 || buffer [index] == '\n' || buffer [index] == '\r') {
211 lastLine = buffer [index + 4] == ' ';
217 position += readLength;
219 // check if buffer is full
220 if (position == buffer.Length) {
221 byte [] newBuffer = new byte [buffer.Length * 2];
222 Array.Copy (buffer, 0, newBuffer, 0, buffer.Length);
228 string line = encoding.GetString (buffer , 0 , position - 1);
230 // parse the line to the lastResponse object
231 lastResponse = SmtpResponse.Parse (line);
233 Debug.WriteLine ("smtp: {0}", line);