Hacking SSL support into smtpop.dll

We use smtpop.dll in one application to retrieve email from a POP3 mailbox. Today we had to connect to a mailbox over SSL, which smtpop.dll does not support.

Our code to retrieve email is abstracted behind a façade class, so I expected to simply substitute a new library for smtpop.dll and to call new methods. However, the tight coupling of the façade to the interface of smtpop.dll meant that we needed the replacement to also expose the exact same interface.

After trying several things, I resigned to create a new class with the code from the decompilation of smtpop.dll. Fortunately, only two methods, Open and Quit, had to be changed.

namespace ClassLibrary4
{
    using System.IO;
    using System.Net.Security;
    using System.Net.Sockets;

    using SmtPop;

    public class Pop3ClientWithSsl : POP3Client
    {
        #region Fields

        private SslStream sslStream;

        #endregion

        #region Constructors and Destructors

        public Pop3ClientWithSsl()
        {
            this.UseSsl = true;
        }

        #endregion

        #region Public Properties

        public bool UseSsl { get; set; }

        #endregion

        #region Public Methods and Operators

        public new int Open(string hostname, int port, string username, string password)
        {
            if (this.UseSsl)
            {
                return this.OpenWithSsl(hostname, port, username, password);
            }

            return base.Open(hostname, port, username, password);
        }

        public new string Quit()
        {
            try
            {
                return base.Quit();
            }
            finally
            {
                this.m_streamReader.Close();
                this.m_streamWriter.Close();
                if (this.UseSsl)
                {
                    this.sslStream.Close();
                }
            }
        }

        #endregion

        #region Methods

        private int OpenWithSsl(string hostname, int port, string username, string password)
        {
            this.m_host = hostname;
            this.m_port = port;
            this.m_user = username;
            this.m_tcpClient = new TcpClient(hostname, port);

            this.m_netStream = this.m_tcpClient.GetStream();
            this.sslStream = new SslStream(this.m_netStream, false);
            this.sslStream.AuthenticateAsClient(hostname);

            this.m_streamReader = new StreamReader(this.sslStream);
            this.m_streamWriter = new StreamWriter(this.sslStream) { AutoFlush = true };

            string welcome = this.m_streamReader.ReadLine();
            if (welcome != null && welcome.StartsWith(+OK))
            {
                return this.SendLogin(username, password);
            }

            this.m_error = welcome;
            return -1;
        }

        #endregion
    }
}

The methods of class POP3Client were not virtual, but some of the class members were in protected scope and were accessible in the new class. I rewrote the Open and Quit methods as new methods, which made them no longer polymorphic, thus forcing us to replace calls to POP3Client with calls to Pop3ClientWithSsl everywhere in the code.

Leave a comment

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.