Friday, 11 July 2014

Using C# with Gmail - Part 2, SMTP

POP3 isn't actually natively supported in .NET, but as has been shown, it's pretty easy to do. Next up is SMTP. This is much simpler as .NET has this built into the System.Net.Mail class.

Sending email


Really, the only thing hard about sending email is getting things in the correct order... Here I've the send email method as an event - it would be very simple to write a wrapper around it

This event is linked to a very simple winform which you can see if you download the source code

void SendClick(object sender, EventArgs e)
{
   MailMessage mail = new MailMessage();
   mail.To.Add("second_user@gmail.com");


It's always a good idea to say who you're email is from. Nice thing here is that if you have a wrapper around the SMTP code, you can email different people. For my example here, I just wanted to email another user account to ensure it works. When you do this sort of thing, having a second account always helps...

   mail.From =
      new System.Net.Mail.MailAddress("your_username@gmail.com");
   if (subject.Text.Length != 0)
      mail.Subject = subject.Text;
   else
      mail.Subject = "I forgot to fill it in";


While there is nothing that says you must have a subject, it's a good idea to. Quite a lot of email spam blockers user a NULL in the message as a fairly high scorer on the factors when it decides if email is spam or not

   mail.Body = message.Text;

If you had any attachments can be added on here. Effectively, this is the header of the email done. Now all that needs to be done is to send it
   
   System.Net.Mail.SmtpClient smtp =
       new System.Net.Mail.SmtpClient("smtp.gmail.com");
   smtp.EnableSsl = true;
   smtp.Credentials =
       new System.Net.NetworkCredential("your_username",
                                        "your_password");
   try
   {
      smtp.Send(mail);
   }
   catch (System.Net.Mail.SmtpException ex)
   {
      MessageBox.Show(ex.Message.ToString(),
                      "Unable to connect to the remote server",
                      MessageBoxButtons.OK);
      return;
   }
}

I did say it wasn't difficult!

Using C# with Gmail - Part 1, POP3

While this part is for gmail, it can also be used for other email providers. I'm also assuming that you have a gmail account. If you haven't, you can still use the code, but you'll need to alter some parts.

Introduction


There are two parts to any form of email application - the sending and the receiving. Neither of these are hard to code, but but they can get a bit messy. POP3 is not natively supported in .NET, so it will need coding up. Thankfully, it's not difficult.

Connecting to POP3


The POP3 system allows software to connect to a remote server and using a predefined set of instructions, access emails. Gmail requires an SSL connection. SSL is supported in System.Net.Security. The actual connection is quite simple.

The strings username and password are exactly what they say they are - your username and password

SslStream nstream;
       
public SslStream Connect(string username, string password)
{
   string message;
   string response;
   TcpClient tcpClient = new TcpClient();
   tcpClient.Connect("pop.gmail.com", 995);

995 is the port needed to connect to the gmail POP3 server. Notice at this point, nothing has been done with the SSL connection - all that has happened is that a connection has been made by the software to a port.

   nstream = new SslStream(tcpClient.GetStream());
   nstream.AuthenticateAsClient("pop.gmail.com");
   response = Response(nstream);

OK, we've now connected to the server using SSL (tcpClient.GetStream() is used to obtain the underlying network stream in use) and it's time to listen to the server

   if (response.Substring(0, 3) != "+OK")
   {
      throw new Pop3Exception(response);
   }

   message = "USER " + username + "\r\n";
   Write(message, nstream);
   response = Response(nstream);
   if (response.Substring(0, 3) != "+OK")
   {
      throw new Pop3Exception(response);
   }

   message = "PASS " + password + "\r\n";
   Write(message, nstream);
   response = Response(nstream);
   if (response.Substring(0, 3) != "+OK")
   {
      throw new Pop3Exception(response);
   }
   return nstream;
}

At this point the software has connected to the server. The above method has two helper methods associated with it, Response and Write. These are the main communication methods for the server, so let's detail them now.

private void Write(string message, SslStream nstream)
{
   System.Text.ASCIIEncoding en = new System.Text.ASCIIEncoding() ;
   byte[] WriteBuffer = new byte[1024] ;
   WriteBuffer = en.GetBytes(message) ;
    nstream.Write(WriteBuffer, 0, WriteBuffer.Length);
}
       
private string Response(SslStream stream)
{
   System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
   byte[] serverbuff = new Byte[1024];
   int count = 0;
   while (true)
   {
      byte[] buff = new Byte[2];
      int bytes = stream.Read(buff, 0, 1 );
      if (bytes == 1)
      {
          serverbuff[count] = buff[0];
          count++;

          if (buff[0] == '\n')
          {
             break;
          }
       }
       else
       {
          break;
       };
    };

    string retval = enc.GetString(serverbuff, 0, count );
    return retval;
}

Disconnecting from the server is just a case of sending the disconnect message, waiting for the reply and well, that's about it

public void Disconnect(SslStream netstream)
{
   string message;
   string response;
   message = "QUIT\r\n";
   Write(message, netstream);
   response = Response(netstream);
   if (response.Substring(0, 3) != "+OK")
   {
      throw new Pop3Exception(response);
    }
}