/// <summary> /// Get the pop3 server information from /// the configuration file, the host and /// port of the pop3 server is located in /// the default section, this data is used /// to connect to the pop3 server. /// </summary> private void GetPop3ServerHost() { try { // Create a new connection adapter. _connection = new Pop3ConnectionAdapter(); // If no host name set then // use the defualt values. if (String.IsNullOrEmpty(_pop3ServerName)) { // Create a new default host type // an load the values from the configuration // file into the default host type. ProxyPop3ServerDefaultHost defaultHost = (ProxyPop3ServerDefaultHost)System.Configuration.ConfigurationManager.GetSection( "ProxyPop3ServerGroup/ProxyPop3ServerDefaultHost"); // If the port is greater than zero then // assign the port number. if (defaultHost.HostSection.PortAttribute > 0) { _connection.Port = defaultHost.HostSection.PortAttribute; } // Get the pop3 server. _connection.Server = defaultHost.HostSection.HostAttribute; } else { // Create a new host type // an load the values from the configuration // file into the host type. ProxyPop3ServerHosts hosts = (ProxyPop3ServerHosts)System.Configuration.ConfigurationManager.GetSection( "ProxyPop3ServerGroup/ProxyPop3ServerHosts"); // If the port is greater than zero then // assign the port number. if (hosts.HostSection[_pop3ServerName].PortAttribute > 0) { _connection.Port = hosts.HostSection[_pop3ServerName].PortAttribute; } // Get the pop3 server. _connection.Server = hosts.HostSection[_pop3ServerName].HostAttribute; } } catch (Exception e) { // Detect a thread abort exception. if (e is ThreadAbortException) { Thread.ResetAbort(); } base.Write("Pop3SslProxyServer", "GetListeningPort", e.Message, 246, WriteTo.EventLog, LogType.Error); } }
/// <summary> /// Default constructor. /// </summary> /// <param name="tcpClient">The tcp client channel connection from server to client.</param> /// <param name="connection">The connection adapter used to connect to the server.</param> public Pop3TlsProxyConnection(TcpClient tcpClient, Pop3ConnectionAdapter connection) { try { // The tcp client to server channel. // Assign the network stream from the client // channel stream. _tcpClient = tcpClient; _connection = connection; // Create a new state object. ServerSocketState state = new ServerSocketState(); state.TcpClient = _tcpClient; // This starts the asynchronous read thread. // The data will be saved into readBuffer. _tcpClient.Client.BeginReceive(_readBuffer, 0, READ_BUFFER_SIZE, SocketFlags.None, new AsyncCallback(InitializingSSLDataReceiver), state); // Send a welcome message to the client. SendNonSSLClientCommand("* OK Welcome to Secure Pop3 Proxy Server - Authorized Accounts Only"); } catch (Exception e) { // Detect a thread abort exception. if (e is ThreadAbortException) { Thread.ResetAbort(); } base.Write("Pop3TlsProxyConnection", "Constructor", e.Message, 65, WriteTo.EventLog, LogType.Error); } }
/// <summary> /// General message constructor. /// </summary> /// <param name="contentType">The content type.</param> /// <param name="data">The body data.</param> /// <param name="writeAttachmentToFile">Write to file.</param> /// <param name="connection">The connection object.</param> public MessageAttachment(string contentType, string data, bool writeAttachmentToFile, Pop3ConnectionAdapter connection) { _data = data; _connection = connection; _contentType = contentType; _writeAttachmentToFile = writeAttachmentToFile; }
/// <summary> /// Attachment message constructor. /// </summary> /// <param name="contentType">Content type.</param> /// <param name="name">The attachment name.</param> /// <param name="filename">The attachment file name.</param> /// <param name="contentTransferEncoding">The encoding type.</param> /// <param name="contentDescription">The description.</param> /// <param name="contentDisposition">The content disposition.</param> /// <param name="data">The attachment data.</param> /// <param name="writeAttachmentToFile">Write to file.</param> /// <param name="connection">The connection object.</param> public MessageAttachment(string contentType, string name, string filename, string contentTransferEncoding, string contentDescription, string contentDisposition, string data, bool writeAttachmentToFile, Pop3ConnectionAdapter connection) { _data = data; _name = name; _filename = filename; _connection = connection; _contentType = contentType; _contentDescription = contentDescription; _contentDisposition = contentDisposition; _writeAttachmentToFile = writeAttachmentToFile; _contentTransferEncoding = contentTransferEncoding; // Decode the attachment data. DecodeData(writeAttachmentToFile); }
/// <summary> /// Default constructor. /// </summary> /// <param name="tcpClient">The tcp client channel connection from server to client.</param> /// <param name="connection">The connection adapter used to connect to the server.</param> public Pop3SslProxyConnection(TcpClient tcpClient, Pop3ConnectionAdapter connection) { try { // The tcp client to server channel. // Assign the network stream from the client // channel stream. _tcpClient = tcpClient; _connection = connection; _sslStream = new SslStream(tcpClient.GetStream()); // Certificate file containing a public key // and private key for secure data transfer. X509Certificate2 certificate = GetServerCredentials(); // Load the certificate into the // secure stream used for secure communication. _sslStream.AuthenticateAsServer(certificate, false, SslProtocols.Ssl3, false); // Create a new state object. ServerSocketState state = new ServerSocketState(); state.SslStream = _sslStream; // This starts the asynchronous read thread. // The data will be saved into readBuffer. _sslStream.BeginRead(_readBuffer, 0, READ_BUFFER_SIZE, new AsyncCallback(DataReceiver), state); // Create a new pop3 client and // attempt to make a connection // get the response from the server. bool ret = GetSocket(); // If return false. if (!ret) { // Write an error response back to // the pop3 client. _sslStream.Write(Encoding.ASCII.GetBytes("-ERR" + "\r\n")); } else { // Create a new state object. ServerSocketState stateSocket = new ServerSocketState(); stateSocket.EmailMessage = new StringBuilder(); stateSocket.SslStream = _sslStream; stateSocket.Socket = _socket; // Start receiving data asynchrounusly. _socket.BeginReceive(_receiveBuffer, 0, READ_BUFFER_SIZE, SocketFlags.None, new AsyncCallback(ReceiveCallback), stateSocket); } } catch (Exception e) { // Detect a thread abort exception. if (e is ThreadAbortException) { Thread.ResetAbort(); } base.Write("Pop3SslProxyConnection", "Constructor", e.Message, 65, WriteTo.EventLog, LogType.Error); } }
/// <summary> /// Message body and attachment constructor. /// </summary> /// <param name="lines">The array of lines in the message.</param> /// <param name="startOfBody">The start of the body data.</param> /// <param name="multipartBoundary">The multipary boundary.</param> /// <param name="mainContentType">The main content type.</param> /// <param name="writeAttachmentToFile">Write to file.</param> /// <param name="connection">The connection object.</param> public MessageBody(string[] lines, long startOfBody, string multipartBoundary, string mainContentType, bool writeAttachmentToFile, Pop3ConnectionAdapter connection) { // Get the number of message lines. long stopOfBody = lines.Length; // If the multipart boudary is null then // only a body part exists. if (multipartBoundary == null) { // Create a new string builder. StringBuilder sbText = new StringBuilder(); // For each line in the message // append the body lines. for (long i = startOfBody; i < stopOfBody; i++) { sbText.Append(lines[i].Replace("\n", "").Replace("\r", "")); } // Add a new body to the component // list store. _component.Add(new MessageAttachment(mainContentType, sbText.ToString(), writeAttachmentToFile, connection)); } // Multipart boundary exists then a body and attachment // exists in the message. else { // Get the multipart boundary // string in the message. string boundary = multipartBoundary; // Set as first component or body // of the message to get. bool firstComponent = true; // Loop through whole of email message // get the bodt all attachments. for (long i = startOfBody; i < stopOfBody;) { bool boundaryFound = true; string contentType = null; string name = null; string filename = null; string contentTransferEncoding = null; string contentDescription = null; string contentDisposition = null; string data = null; // If the first component is to be added // this is the body of a multipart message. if (firstComponent) { boundaryFound = false; firstComponent = false; // For all the lines in the message. while (i < stopOfBody) { // Get the current line in the message. string line = lines[i].Replace("\n", "").Replace("\r", ""); // If the end of the body boundary // has been found then exit the loop // all body data has been found. if (EmailMessageParse.GetContentMappingHeaderType(line, boundary) == Nequeo.Net.Mail.MesssageContentMappingType.MultipartBoundaryFound) { boundaryFound = true; ++i; break; } else { ++i; } } } // Check to see whether multipart boundary // was not found. This will indicate that // the message data is corrupt. if (!boundaryFound) { throw new Exception("Missing multipart boundary: " + boundary); } // Initalise the end of header indicator. bool endOfHeader = false; // Read all header information. // For all other lines in the // messsage. while ((i < stopOfBody)) { // Get the current line in the message. string line = lines[i].Replace("\n", "").Replace("\r", ""); // Get the current content mapping type. Nequeo.Net.Mail.MesssageContentMappingType lineType = EmailMessageParse.GetContentMappingHeaderType(line, boundary); // Get the mapping type. switch (lineType) { case Nequeo.Net.Mail.MesssageContentMappingType.ContentType: // Mapping type is content type header. // Get the content type data. contentType = EmailMessageParse.ContentType(line); break; case Nequeo.Net.Mail.MesssageContentMappingType.ContentTransferEncoding: // Mapping type is content transfer encoding header. // Get the content transfer encoding data. contentTransferEncoding = EmailMessageParse.ContentTransferEncoding(line); break; case Nequeo.Net.Mail.MesssageContentMappingType.ContentDisposition: // Mapping type is content disposition header. // Get the content disposition data. contentDisposition = EmailMessageParse.ContentDisposition(line); break; case Nequeo.Net.Mail.MesssageContentMappingType.ContentDescription: // Mapping type is content description header. // Get the content description data. contentDescription = EmailMessageParse.ContentDescription(line); break; case Nequeo.Net.Mail.MesssageContentMappingType.EndOfHeader: // End of header has been found. endOfHeader = true; break; } // Increment to the next line after // find the content mapping type in // the prevoius line. ++i; // If end of header found then search // for the next component starting point // search for the next attachment. break // out of the loop and end the process. if (endOfHeader) { break; } else { // Read all header information. // For all other lines in the // messsage. while (i < stopOfBody) { // If more lines to read for this line. if (line.Substring(line.Length - 1, 1).Equals(";")) { // Get the current line in the message. string nextLine = lines[i].Replace("\r", "").Replace("\n", ""); // Get the current attachment header type. // interate through each attachment data. switch (EmailMessageParse.GetAttachmenHeaderType(nextLine)) { case Nequeo.Net.Mail.MesssageAttachmentType.Name: // Attachment name header type. // Get the attachment name in the message. name = EmailMessageParse.Name(nextLine); break; case Nequeo.Net.Mail.MesssageAttachmentType.Filename: // Attachment file nale header type. // Get the attachment file name in the message. filename = EmailMessageParse.Filename(nextLine); break; case Nequeo.Net.Mail.MesssageAttachmentType.EndOfHeader: // End of header has been found. endOfHeader = true; break; } // If the end of the attachment // data has not been found if (!endOfHeader) { // Assign the current line to // the next line line = nextLine; ++i; } else { // End the loop. break; } } else { // End the loop. break; } } } } // Boundary found to false. boundaryFound = false; // Create a new string builder. StringBuilder sbText = new StringBuilder(); // Initailise the emial composed indicator. bool emailComposed = false; // For each remaining line in // the message store the body // and the attachment. while (i < stopOfBody) { // Get the current line in the message. string line = lines[i].Replace("\n", ""); // If the end of the body boundary // has been found then exit the loop // all component data has been found. if (EmailMessageParse.GetContentMappingHeaderType(line, boundary) == Nequeo.Net.Mail.MesssageContentMappingType.MultipartBoundaryFound) { boundaryFound = true; ++i; break; } // If the component is done then // the email is composed, this // component has been completed // composed. else if (EmailMessageParse.GetContentMappingHeaderType(line, boundary) == Nequeo.Net.Mail.MesssageContentMappingType.ComponentDone) { emailComposed = true; break; } // Add the current line of component // data to the string builder. // Move to the next line in the message. sbText.Append(lines[i]); ++i; } // If data has been built // then this is the component data // that is body or attachment data. if (sbText.Length > 0) { data = sbText.ToString(); } // Add a new message body or attachment to the // component list store. _component.Add(new MessageAttachment(contentType, name, filename, contentTransferEncoding, contentDescription, contentDisposition, data, writeAttachmentToFile, connection)); // If all multiparts have been // composed then exit break // out of the loop. if (emailComposed) { break; } } } }
/// <summary> /// Email message constructor. /// </summary> /// <param name="position">The position of the message.</param> /// <param name="size">The size of the complete message.</param> /// <param name="headersOnly">The should only header data be returned.</param> /// <param name="headerLineCount">The number of header data lines to return.</param> /// <param name="client">The current client socket.</param> /// <param name="sslStream">The current secure socket layer client.</param> /// <param name="message">The message object that will contain the message data.</param> /// <param name="writeAttachmentToFile">Write the attachment to file.</param> /// <param name="rawEmailMessageOnly">Get the complete raw email message only.</param> /// <param name="connection">The current connection object.</param> /// <param name="callbackHandler">The progress call back handler.</param> public EmailMessage(long position, long size, bool headersOnly, long headerLineCount, Socket client, SslStream sslStream, Message message, bool writeAttachmentToFile, bool rawEmailMessageOnly, Pop3ConnectionAdapter connection, Nequeo.Threading.ActionHandler <long> callbackHandler) { try { _size = size; _client = client; _sslStream = sslStream; _connection = connection; _inboxPosition = position; _headersOnly = headersOnly; _headerLineCount = headerLineCount; _callbackHandler = callbackHandler; _rawEmailMessageOnly = rawEmailMessageOnly; _writeAttachmentToFile = writeAttachmentToFile; // Load the email asynchronously. // This point is blocked until the // receive is complete. LoadEmail(message); // If the decoded email message is // to be returned. if (!rawEmailMessageOnly) { // Get body (if it exists) IEnumerator multipartEnumerator = MultipartEnumerator; // For each multipart content, including // attachments iterate through the array. while (multipartEnumerator.MoveNext()) { // Get the multipart object index. MessageAttachment multipart = (MessageAttachment) multipartEnumerator.Current; // If this multipart object is a body type // then get the data stored. if (multipart.IsBody) { _body = multipart.Data; } // If this multipart object is an attachment type // then add the file name to the collection. if (multipart.IsAttachment) { // Create a new attachment class // and add the file data. Attachment attachment = new Attachment() { FileName = multipart.Filename, File = multipart.FileData, FileExtention = multipart.FileExtension, FileNoExtention = multipart.FileNoExtension, Name = multipart.Name, ContentTransferEncoding = multipart.ContentTransferEncoding, Decoded = multipart.Decoded, ContentDescription = multipart.ContentDescription, ContentType = multipart.ContentType }; // Add the attachment to the list. message.Attachments.Add(attachment); } } // Load the message data into the // message class. message.To = _to; message.Cc = _cc; message.Bcc = _bcc; message.Size = _size; message.Date = _date; message.From = _from; message.Subject = _subject; message.ReplyTo = _replyTo; message.Priority = _priority; message.Received = _received; message.ReturnPath = _returnPath; message.Importance = _importance; message.IsMultipart = _isMultipart; message.Organization = _organization; message.InboxPosition = _inboxPosition; // If the message body is a html message. if (_body.IndexOf("<html") > -1) { // A html message has been sent. message.MessageType = Nequeo.Net.Mail.MessageType.Html; // Get the starting index of the string // and the ending index of the string. int start = _body.IndexOf("<html"); int end = _body.LastIndexOf("</html>") + 7; // Extract only the html part of the message body. message.Body = _body.Substring(start, end - start); } else if (_body.IndexOf("<HTML") > -1) { // A rich text or html message has been sent. message.MessageType = Nequeo.Net.Mail.MessageType.RichText; // Get the starting index of the string // and the ending index of the string. int start = _body.IndexOf("<HTML"); int end = _body.LastIndexOf("</HTML>") + 7; // Extract only the html part of the message body. message.Body = _body.Substring(start, end - start); } else if (_body.ToLower().IndexOf("<xml") > -1) { // A xml message has been sent. message.MessageType = Nequeo.Net.Mail.MessageType.Xml; // Get the starting index of the string // and the ending index of the string. int start = _body.ToLower().IndexOf("<xml"); int end = _body.ToLower().LastIndexOf("</xml>") + 6; // Extract only the xml part of the message body. message.Body = _body.Substring(start, end - start); } else { // A normal text message has been sent. message.MessageType = Nequeo.Net.Mail.MessageType.Text; message.Body = _body; } } } catch (Exception ex) { throw new Exception(ex.Message); } }