Saturday, March 24, 2012

Sending emails with SMTP

In this post, I'm going to show you how to send an email from the command-line without needing any sort of email client. We're going to be using a protocol called SMTP, which stands for Simple Mail Transport Protocol. This is the protocol that millions of email servers all over the world use to send emails to one another. The protocol is made up of a number of text-based commands and it actually is pretty simple. :-P

For this demonstration, let's send an email to ourselves. That way, once we've sent the email, we can open our inbox and confirm that it was successfully sent. I'll be using my own email address, mike.angstadt@gmail.com, in this blog post, but you should use your own instead obviously.

Finding the SMTP server address

Before we can start sending our email, we need to know where to send it to! In other words, we need to get the address of the SMTP server that our email address belongs to. To do this, we need to perform an MX record lookup against the "host" part of our email address, which is located to the right of the "@" symbol (the part to the left is called the "user" or "mailbox"). In my case, the host is "gmail.com".

To perform an MX record lookup on Linux, type the command dig mx HOST where HOST is the host address.

To perform an MX record lookup on Windows, type the command nslookup. Then, type set type=MX followed by the host name.

Performing an MX record lookup will most likely return a list of SMTP servers. So, which one should you pick? Well, any one will work, but the one with the lowest MX preference indicator should be used. On Linux, this is the number directly to the left of the SMTP address. On Windows, this is the number labeled "MX preference". If you were writing an SMTP server yourself, you would sort this list of addresses by preference indicator and then send the email to the one with the lowest value. If that server happens to be down, then you would keep going down the list until you found a server that worked. If all servers have the same preference indicator, then you should choose one randomly. This helps to evenly spread the load amongst all servers and thus make the server admins happy.

If the MX record lookup does not return any SMTP servers, that means you can use the host part of the email address itself as the SMTP server address.

Sending the email

Now that we have the address of the SMTP server, we can go ahead and send the email. The standard SMTP port is 25, so let's open a telnet connection on that port. To do this, run the command telnet ADDRESS 25, where ADDRESS is the SMTP server address.

Warning: In my experience, some SMTP servers are not very friendly toward "human" SMTP connections--they will terminate the connection if it's idle for only a few seconds. Yahoo is one such example.

The first command that is sent is the EHLO command. This allows the SMTP client (us) to introduce itself to the server. It contains the email host address of the SMTP client. For example, if I was a Hotmail server, I might enter EHLO hotmail.com. This is optional though, so you can just enter EHLO if you want.

Next, we'll specify who the email is from. This is done using the MAIL command. The syntax for this command is MAIL FROM:<address@website.com>. The syntax is very specific--there must be NO space after the colon and the email address MUST be surrounded by < and > characters.

Then, we specify who the email should be sent to using the RCPT command. The snytax for this command is RCPT TO:<mike.angstadt@gmail.com>. If the email has multiple recipients, then this command can be entered multiple times. Just as with the MAIL command, there must be NO space after the colon and the email address MUST be surrounded by < and > characters.

Now, we're ready to send the actual body of the email. Send the DATA command to let the server know that we're ready send the acutal message.

Next, enter the email data. The email data consists of a series of headers, followed by a blank line, followed by the email text, followed by a line consisting of just a single dot (.). Each header goes on its own line and has the syntax HeaderName: HeaderValue. At the very least, you should have the headers "From", "To", and "Subject" because this is what email clients use to display the sender, recipients, and subject of an email. For example, I'm going to type the following:

From: <address@website.com>
To: <mike.angstadt@gmail.com>
Subject: My first SMTP email!

Dear Mike,
This is my first SMTP email.
.

Then, the SMTP server sends the email! You can enter more emails if you like or you can terminate the connection by sending the QUIT command.

The entire SMTP conversation.

Now, open up your email account and you should see a new email! However, it will likely be considered spam because the host in the "from" address does not match who it was really sent from. For example, nothing's stopping me from entering "barack.obama@whitehouse.gov" as the sender. But, obviously, it's not really from the President of the United States, so it would likely be marked as spam. So check your spam folder if you don't see it in your inbox.

Sunday, March 4, 2012

Properties File Wrapper Class

If you're a Java programmer, you know that a properties file is a text file that contains a series of key/value pairs and is often used to store the configuration settings of an application. Each key/value pair resides on its own line. The key comes first, followed by an equals sign, followed by the value. The convention is to organize the key/value pairs into a hierarchy by giving the keys "package-like" names. For example, if I want to store the username, password, and email address of an admin user, I might prepend all of the key names with "admin.", naming the keys "admin.username", "admin.password", and "admin.email". Property files in Java are read using the Properties class.

admin.username=jdoe
admin.password=secret
admin.email=jdoe@company.com
log.file=/home/user/logs/myapp.txt
state.AZ=Arizona
state.TX=Texas
state.MD=Maryland
colors=red,yellow,blue

One technique I like to use when reading properties files in Java is to create a wrapper class whose sole purpose is to read the data from the properties file. A method is created in this class for every key/value pair in the properties file. An advantage to this is that, if the programmer needs to access a property in multiple places throughout the application, the key name (a hard-coded String), need not be duplicated (and potentially misspelled) because it is centralized inside the wrapper class. The wrapper class can also perform extra manipulations on the values in order to "unmarshal" them into more programmer-friendly data structures (for example, converting a file path into a File object or a string of comma-delimited values into a List object).

As an example, let's create a properties wrapper class out of the properties file example shown above.

import java.util.*;
import java.io.*;

public class AppProperties {
  private final Properties props;

  public AppPropeties(Reader reader) throws IOException {
    props = new Properties();
    props.load(reader);
  }

  public String getAdminUsername(){
    return props.getProperty("admin.username");
  }

  public String getAdminPassword(){
    return props.getProperty("admin.password");
  }

  public String getAdminEmail(){
    return props.getProperty("admin.email");
  }

  public File getLogFile(){
    String value = props.getProperty("log.file");
    return (value == null) ? null : new File(value);
  }

  public String getStateName(String abbr){
    return props.getProperty("state." + abbr);
  }

  public List<String> getColors(){
    String value = props.getProperty("colors");
    if (value == null){
      return null;
    }
    String values[] = value.split(",");
    return Arrays.asList(values);
  }
}

The constructor takes a Reader object. This makes the class more flexible and easier to unit test, as it is not limited to reading the property data from a file (for example, a StringReader could be passed into it for unit testing purposes).

The "admin.*" properties each have their own method. For example, to retrieve the "admin.username" field, the getAdminUsername() method is called.

The "log.file" property is converted to a File object because this is what this value represents--a path to a file.

The "getStateName()" method for the "state.*" properties is more dynamic. It takes the state abbreviation as an argument and uses that to construct the key name. For example, if "TX" is passed into this method, the "state.TX" property will be accessed and "Texas" will be returned. Methods like this can be used if you need to retrieve property values based on input from the user.

Lastly, the getColors() method retrieves the value of the "colors" property, which is a comma-delimited string. It then parses the values out of this string and returns a List object.

Using a properties wrapper class like this can really neaten up your codebase. I've used this design pattern in multiple projects and have been happy with the results.