UCSD Main WebsiteUCSD Jacobs SchoolDepartment of Computer Science and Engineering
spacer gif
spacer gif
CSE 223B
spacer gifspacer gif
spacer gif
spacer gifCourse Overview
spacer gifspacer gifStructure
spacer gifspacer gifGrading
spacer gifspacer gifUseful books
spacer gif
spacer gifspacer gifSchedule
spacer gif
spacer gifspacer gifReadings
spacer gif
spacer gifLabs
spacer gif   Lab 1
spacer gif   Lab 2
spacer gif   Lab 3
spacer gif
spacer gif
spacer gif
Search
spacer gifspacer gifspacer gif
Advanced search  arrows gif

spacer gif
spacer gifspacer gif
spacer gif
spacer gif
spacer gif
spacer gif
spacer gifspacer gifspacer gif
spacer gif Lab 1: Charlie on the MTA
Due: 12:30pm, Tuesday, January 15th, 2008

Preliminaries

Your task for this assignment is to write a simple Mail Transfer Agent (MTA). An MTA is a program that relays email messages between senders, receivers, and possibly other MTAs. MTAs are the servers that process email messages in the Internet, passing them from the sender's email client---or Mail User Agent (MUA)---and the receiver's mail delivery agent. By far the most common MTA in use on the Internet is the infamous sendmail program. Most of sendmail's notoriety comes from its incredible complexity and resulting never-ending discovery of security vulnerabilities. Don't despair; your MTA will be considerably simpler, although not necessarily any easier to debug!

The reason you're writing an MTA is not to build a replacement for sendmail (although the Internet could badly use one!), but rather to learn about how complex Internet servers are constructed. Initially, we'll start off simple with a single-threaded server that can only process one mail message at a time. It should be able to accept a mail message from a MUA, forward the message on to its destination, and then prepare to accept the next mail message. We'll fix this limitation as part of Lab 2.

Specification

Your MTA will use the Internet-standard Simple Mail Transfer Protocol (SMTP) to exchange mail messages. SMTP is documented in RFC 2821, but you'll only need to implement a small subset of the commands listed below. You will not need to handle local delivery of mail messages. Instead, your MTA will only forward email messages on to another MTA for actual delivery.

You are responsible for the following requirements:

  • Your MTA is able to properly receive a message from a well-behaved MUA like Netscape, Outlook Express, or Mozilla. This will require you to support the following SMTP commands: HELO, MAIL, DATA, RCPT, QUIT, and RSET.
  • You must support the use of dotted-quad IP addresses instead of domain names in both the HELO, MAIL, and RCPT commands.
  • You may not use the fork() system call.
  • You do not need to handle messages with more than 255 recipients.
  • You do not need to handle mail messages larger than 65535 bytes.
You do not need to bother with the following things. You should just ignore them as best you can.
  • You don't need to support local destinations or source-routed messages. If the argument to the RCPT TO: command is not of the form user@domain.name (where domain.name could also be a dotted-quad IP address), you should refuse to accept the message.
  • You don't need to queue messages that cannot be delivered. Any destination address that is unable to accept the message immediately (after trying all the MX options--see below) should be treated as a delivery failure, and an "undeliverable mail" notification should be returned to the sender immediately.
  • Any other SMTP commands like EXPN, VRFY, HELP, ETRN, NOOP, or VERB. You may simply return an error message if your MTA receives one of these commands.
  • ESMTP extensions. You do not need to recognize EHLO or any of the additional parameters to standard SMTP commands.
  • You do not need to implement the data transparency procedure described in Section 4.5.2 of the RFC. Basically, you can assume your MTA will never receive a message with a period as the first character of a line.
  • You should ignore all headers in the DATA portion of the message. Further, you do not need to implement any sort of loop detection.
If you are able to send a simple email message using your MTA, you're in good shape.

A sample mail transaction

SMTP is a simple client/server protocol that runs over TCP. A client (either an MUA or an MTA) opens a TCP connection to an MTA, identifies itself, specifies the recipients of the message, sends the contents of the message, and quits. The server processes the message and forwards it on to the destinations specified using the same procedure. You can play with a real, live MTA yourself. The UCSD campus has an MTA running on smtp.ucsd.edu.
% telnet smtp.ucsd.edu 25
This opens a TCP connection to port 25 (the well-known SMTP port) on smtp.ucsd.edu. You should see:
Trying 132.239.1.49...
Connected to smtp.ucsd.edu.
Escape character is '^]'.
220 smtp.ucsd.edu ESMTP Sendmail 8.13.6/8.13.6; Fri, 4 Jan 2008 10:48:43 -0800 (PST)
The first three lines are output from the telnet program. The last is the greeting sent by the MTA (Sendmail, surprise, surprise) at smtp.ucsd.edu. You can then identify yourself using the HELO command:
HELO dungeonsofdespair.com
and the MTA returns
250 smtp.ucsd.edu Hello fast.ucsd.edu [132.239.15.4], pleased to meet you
Where fast.ucsd.edu is the machine you're actually using. Pretty smart MTA, huh? So much for trying to fool it---at least at this stage. We can now ask it to deliver a message for us:
MAIL FROM:<223bstudent@ucsd.edu>
and it responds:
250 2.1.0 <223bstudent@ucsd.edu>... Sender ok
Now, we'll try sending ourselves a message:
RCPT TO:<223baccount@ucsd.edu>
You should obviously replace 223baccount@ucsd.edu with your own account name.
250 2.1.5 ... Recipient ok
Note that if you use an account not at UCSD, and you're connecting from a machine outside of UCSD, you'll get a message like:
550 5.7.1 ... Relaying denied
Seems UCSD doesn't want to be bothered with handling other people's mail. By now you're probably starting to understand why sendmail is so complicated. Luckily we're going to ignore all of these details in our MTA. Now, send your message:
DATA
This is a sample message.
.
Note that you must end your message with a . on a line by itself. The server responds with:
250 2.0.0 h33J23M4002993 Message accepted for delivery
Great. Now we can log off.
QUIT
221 2.0.0 smtp.ucsd.edu closing connection
Connection closed by foreign host.
If everything went well, you've now got mail! That's all there is to it. Of course, what happened behind the scenes is that smtp.ucsd.edu connected to the MTA at your mail server and repeated this whole process in an automated fashion. That server then moved the mail to your local mail spool. We're not going to worry about how that last step happens.

Building your MTA

The first thing you should do, if you're not already comfortable with sockets programming, is check out MIT's excellent Using TCP through Sockets tutorial.

We have provided an initial skeleton directory to get you started. It is available as /net/cluster/cse223b/labs/lab1.tgz on the course cluster machines. You should copy this file to your working directory. The following sequence of commands should extract the files and build the initial (useless) executable:

% tar xzf lab1.tgz
% cd lab1
% gmake
The tarball contains four files: domain.c, domain.h, Makefile, and mta.C. You'll find the first two files useful for looking up the destination MTA for messages you're trying to deliver (see the following section on mail exchangers). The Makefile, as the name implies, is a GNU makefile that builds the executable. (If you are trying to build on FreeBSD, you should follow the directions in the comments about how to edit the Makefile.) You shouldn't need to know anything about make to use it, but if you're curious, the documentation is on-line. The last file, mta.C, is the one you're going to use to write your MTA. Currently, it just accepts TCP connections, closes them, and waits for another. You can run the executable by typing:
% ./mta 2225
Where 2225 is the port you want it to listen on. In order not to conflict with the already running MTA (sendmail), you should run your MTA on a port other than 25 (larger than 1024). During testing you're likely to want to use something other than 2225 as well so it doesn't conflict with other students working on their projects.

Mail exchangers

When determining where to send messages to, it would be nice if you could just contact the destination directly. Unfortunately, many domains have mail exchangers that receive mail. This is especially important for you to know, as cs.ucsd.edu, the domain many of you use for your email accounts, is NOT usually handled by a machine called cs.ucsd.edu. Instead, there are six machines set up to handle mail for the cs.ucsd.edu domain. These are stored in so-called MX records in the DNS.

You can see for yourself using the dig command:

% dig mx cs.ucsd.edu

; <<>> DiG 9.2.4 <<>> mx cs.ucsd.edu
;; global options:  printcmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 33263
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 6, AUTHORITY: 4, ADDITIONAL: 12

;; QUESTION SECTION:
;cs.ucsd.edu.			IN	MX

;; ANSWER SECTION:
cs.ucsd.edu.		172800	IN	MX	666 spaminator.ucsd.edu.
cs.ucsd.edu.		172800	IN	MX	10 cse-inbound.ucsd.edu.
cs.ucsd.edu.		172800	IN	MX	15 cseghost.ucsd.edu.
cs.ucsd.edu.		172800	IN	MX	25 cse-inbound2.ucsd.edu.
cs.ucsd.edu.		172800	IN	MX	50 cs.ucsd.edu.
cs.ucsd.edu.		172800	IN	MX	75 inbound.ucsd.edu.

...
As you can see, spaminator, cse-inbound, cseghost, etc... are the machines that you should actually contact to send mail to a user at cs.ucsd.edu. Which one you choose is up to you, but it may be the case that one or more of them (spaminator, for example) isn't functioning when you try to send the message. In that case, you should try each entry in the list in turn.

Because MX processing is complicated business, we've provided some code for you, in domain.c, that will handle the difficult parts. getmxrr() will return an ordered list of machines that you can try to deliver mail to for a given domain. mta.C includes some sample code showing you how to use it.

Testing your MTA

The easiest way to test and debug your MTA is to use it interactively just as we did above. Of course, once your MTA accepts messages, you'll need to send them on. I'd suggest trying to send messages to yourself so you can see if it actually succeeds! You might find programs like Ethereal and Netcat (nc) useful to follow the communication between your MTA and others.

Once you think your MTA is working, you can hook it up to a real MUA and give it a whirl. The simplest way is to use your normal mail reader (Eudora, Netscape, Mozilla, Outlook Express, etc.) and just configure it to use your MTA rather than your default one.

For Mozilla, you can do this by going to Edit->Mail and Newsgroup Account Settings and selecting the Outgoing Server (SMTP) tab. Enter the name of the machine your MTA is running on (e.g., 7.cse223b.snoeren.usher.ucsdsys.net) and port 2225. Make sure you turn off SSL (Never) and uncheck the user name and password option.

Similar changes can be made to other mailers. I'll post them here if anyone wants to email me how to do this in your own mail reader.

Collaboration policy

All code for this assignment must be written individually. You are not allowed to look at anyone else's solutions or solutions to similar assignments you may find for courses at UCSD or other institutions. You may discuss the assignment with fellow students, but all code you submit must be either yours alone or code that was provided to you as part of the assignment.

Turnin procedure

The Makefile distributed in the lab tarball has the ability to tar up all of the files in your directory. One consequence of this is that you should make sure that all the files I need to compile your code are in this directory. You might take this opportunity to include a README file or somesuch giving me any instructions I might need about how to run your code, known bugs, etc., etc. Do not modify the Makefile to link in code outside of the working directory. When you're ready to submit your code, you can execute the following command:
% gmake turnin
which will create a file called user-turnin.tgz, where user is your user ID, and copy it to the submission directory. You might verify your tarball contains all the right things in the following fashion.
% mkdir tmp
% cd tmp
% tar xzf ../user-turnin.tgz
% make
If all goes well, you've submitted your assignment. You are free to resubmit at any time up to the deadline using the same mechanism. Only your most recent submission is saved.


spacer gif

spacer gif
spacer gifback to top ^
spacer gif
spacer gif
spacer gif
spacer gif
9500 Gilman Drive, La Jolla, CA 92093-0114
spacer gif
About CSE | CSE People | Faculty & Research | Graduate Education | Undergraduate Education
Department Administration | Contact CSE | Help | Search | Site map | Home
snoeren@cs.ucsd.edu
Official web page of the University of California, San Diego
Copyright © 2002 Regents of the University of California. All rights reserved.
spacer gif