e mail client error "unable to write data to transport connection"

fguihen

Junior Contributor
Joined
Nov 10, 2003
Messages
248
Location
Eire
ok, i have a tcpip client connecting to the server. i can send small files (below 17152 bytes in size). when my method has sent over 17152 bytes, i get the error "unable to write data to transport connection". here is my method. what it does is recieves a string which is an entire email. it breaks the email up into 128 byte bundles, and sends each bundle to the server, as specified in the SMTP spec. there doesnt seem to be a problem with the method, as i have stepped through it many times. its just the connection that causes the IO error after the 17152 bytes for no apparent reason.

Code:
public void WriteData(string line)//send out data to server
		{	
			int totalLength = line.Length;
			byte[] outMessage;
			int n = 0;
			string s= "";

			while(n < totalLength)
			{
				outStream = ClientConnection.GetStream();
				if(line.Length >=128)
				{
					outMessage = new byte [128];
					n += 128;
				}
				else
				{
					outMessage = new byte [line.Length];
					n += line.Length;
				}
				for(int j = 0; j < outMessage.Length ;j++)
				{
					outMessage[j] = (byte)line[0];
					line = line.Remove(0,1);//removes the charachter form the string as it is already sent
				}	
				//outMessage = encoder.GetBytes(line);
				try
				{
					outStream.Write(outMessage,0,outMessage.Length);
				}
				catch(System.IO.IOException e)
				{
					s = e.Message;
				}
				//outStream.Flush();
			}
		}

any help would be greatly appriciated. thanks
 
#1, Because of the nature of TCP, this 128byte rule is wrong. #2 The rule is wrong as that was never specified in the rfc.


Try this. If it doesn't work, it's definitely not these few lines of code =]
PHP:
public void WriteData(string line)
{
	//TcpClient ClientConnection;
	Stream output = ClientConnection.GetStream();
	//byte[] outMessage = System.Text.Encoding.ASCII.GetBytes(line);
	byte[] outMessage = System.Text.Encoding.Default.GetBytes(line);
	output.Write(outMessage, 0, outMessage.Length);
}


For reference, here's my smtp class
ArpaClientStream derives from NetworkStream.
PHP:
using System;
using System.Text;
using HB.Web;

namespace HB.Web.Mail
{
	/// <summary>
	/// Sends <see cref="IMailMessage"/> objects to a SMTP server.
	/// </summary>
	public class Smtp
	{
		/// <summary>
		/// Sends an e-mail message using arguments supplied in the 
		/// properties of the IMailMessage object.
		/// </summary>
		/// <param name="server">The ip of the SMTP mail server to use to send all e-mail messages.</param>
		/// <param name="username">The username of the account on the SMTP server.</param>
		/// <param name="password">The password of the account on the SMTP server.</param>
		/// <param name="message">The IMailMessage to send.</param>
		/// <exception cref="ApplicationException">When an unexpected reply code is received.</exception>
		/// <exception cref="ApplicationException">When an error occured while sending the email.</exception>
		/// <exception cref="ArgumentNullException">When paramater server, message, username or password is null.</exception>
		public static void Send(string server, IMailMessage message, string username, string password)
		{
			if(server == null)
				throw new ArgumentNullException("server");
			if(message == null)
				throw new ArgumentNullException("message");
			if(username == null)
				throw new ArgumentNullException("username");
			if(password == null)
				throw new ArgumentNullException("password");

			ArpaClientStream connection = null;
			try
			{
				connection = ArpaClientStream.CreateConnection(server, 25);
			}
			catch(Exception e)
			{
				throw new ApplicationException("A connection to the SMTP server could not be made.", e);
			}
			ArpaReply reply;
			try
			{
				reply = connection.ReadAll();
				if(reply.ReplyCode != 220)
					throw new InvalidReplyCodeException(220, reply);

				//connect
				connection.Write("EHLO " + System.Environment.MachineName);
				reply = connection.ReadAll();
				if(reply.ReplyCode != 250)
					throw new InvalidReplyCodeException(250, reply);

				//request login
				connection.Write("AUTH LOGIN");
				reply = connection.ReadAll();
				if(reply.ReplyCode != 334)
					throw new InvalidReplyCodeException(334, reply);

				//send username
				byte[] loginInfo = Encoding.ASCII.GetBytes(username);
				connection.Write(Convert.ToBase64String(loginInfo));
				reply = connection.ReadAll();
				if(reply.ReplyCode != 334)
					throw new InvalidReplyCodeException(334, reply);

				//send password
				loginInfo = Encoding.ASCII.GetBytes(password);
				connection.Write(Convert.ToBase64String(loginInfo));
				reply = connection.ReadAll();
				if(reply.ReplyCode != 235)
					throw new InvalidReplyCodeException(235, reply);
				SendData(connection, message);
			}
			catch(Exception e)
			{
				throw new ApplicationException("An error occurred while communicating with the SMTP server.", e);
			}
			finally
			{
				connection.Close();
			}
		}

		/// <summary>
		/// Sends an e-mail message using arguments supplied in the 
		/// properties of the IMailMessage object.
		/// </summary>
		/// <param name="server">The ip of the SMTP mail server to use to send all e-mail messages.</param>
		/// <param name="message">The IMailMessage to send.</param>
		/// <remarks>The HELO command is used to greet the server.</remarks>
		/// <exception cref="ApplicationException">When an unexpected reply code is received.</exception>
		/// <exception cref="ApplicationException">When an error occured while sending the email.</exception>
		/// <exception cref="ArgumentNullException">When parameter server or message is null.</exception>
		public static void Send(string server, IMailMessage message)
		{
			if(server == null)
				throw new ArgumentNullException("server");
			if(message == null)
				throw new ArgumentNullException("message");
			using(ArpaClientStream connection = ArpaClientStream.CreateConnection(server, 25))
			{
				try
				{
					ArpaReply reply = connection.ReadAll();
					if(reply.ReplyCode != 220)
						throw new InvalidReplyCodeException(220, reply);

					//connect
					connection.Write("HELO " + Environment.MachineName);
					reply = connection.ReadAll();
					if(reply.ReplyCode != 250)
						throw new InvalidReplyCodeException(250, reply);
				
					SendData(connection, message);
				}
				catch(Exception e)
				{
					throw new ApplicationException("An error occurred while sending the e-mail DATA to the SMTP server.", e);
				}
			}
		}

		/// <summary>
		/// Sends the DATA portion of an e-mail to a STMP server.
		/// </summary>
		/// <param name="connection">The connection to use to send the e-mail.</param>
		/// <param name="message">The e-mail to send.</param>
		/// <exception cref="ApplicationException">When an error occured while sending the email.</exception>
		/// <exception cref="ApplicationException">When an unexpected reply code is received.</exception>
		private static void SendData(ArpaClientStream connection, IMailMessage message)
		{
			//MAIL FROM
			if(message.From == null)
				throw new ArgumentException("From property cannot be null.", "message.From");
			connection.Write("MAIL FROM:<" + message.From.Address + ">");
			ArpaReply reply = connection.ReadAll();
			if(reply.ReplyCode != 250)
				throw new InvalidReplyCodeException(250, reply);

			//RCPT TO - TO			
			foreach(IMailAddress address in message.To)
			{
				connection.Write("RCPT TO:<" + address.Address + ">");
				reply = connection.ReadAll();
				if(reply.ReplyCode != 250)
					throw new InvalidReplyCodeException(250, reply);
			}

			//RCPT TO - CC
			foreach(IMailAddress address in message.Cc)
			{
				connection.Write("RCPT TO:<" + address.Address + ">");
				reply = connection.ReadAll();
				if(reply.ReplyCode != 250)
					throw new InvalidReplyCodeException(250, reply);
			}

			//RCPT TO - BCC
			foreach(IMailAddress address in message.Bcc)
			{
				connection.Write("RCPT TO:<" + address.Address + ">");
				reply = connection.ReadAll();
				if(reply.ReplyCode != 250)
					throw new InvalidReplyCodeException(250, reply);
			}

			//send DATA
			connection.Write("DATA");
			reply = connection.ReadAll();
			if(reply.ReplyCode != 354)
				throw new InvalidReplyCodeException(354, reply);

			message.ToData(connection);
			//end send DATA
			connection.Write(ArpaClientStream.CRLF + ".");
			reply = connection.ReadAll();
			if(reply.ReplyCode != 250)
				throw new InvalidReplyCodeException(250, reply);
		}
	}
}
 
Back
Top