Sending Mail via the Web
Last month, we looked at a simple CGI program (read-mail.pl) that allows us to view our e-mail from within a web browser. This program takes advantage of the fact that most e-mail today is delivered to a “post office” server, from which it is downloaded by a user's mail-reading program. Mail clients use the POP3 protocol to retrieve messages from a post office server, which means our program can retrieve a user's mail by connecting to a server and retrieving one or more messages.
read-mail.pl is good enough for basic purposes, in that it makes it possible to retrieve mail from any web browser in the world. However, while it makes it possible to read e-mail messages, it does not provide any mail-sending capabilities. True, many web browsers include such a capability—but many, such as Netscape Navigator, do not.
This month, then, we will take a look at how to send mail via the web. Between read-mail.pl (from last month) and send-mail.pl (in this article), we will have a simple, integrated mail system that allows users to perform all rudimentary tasks from any web browser.
Sending mail based on the contents of an HTML form was one of the first uses to which CGI programs were put, back in 1993 when CGI and HTML forms first arrived on the scene. As we will see, sending e-mail is not particularly difficult from within a CGI program. However, we will look at issues related to security as well as what we would need to do to turn these simple programs into a full-fledged Hotmail competitor.
Sending e-mail from within a program is normally quite straightforward, particularly if you are using Perl. You open a pipe to a mail-sending program, and send it the headers and data for the message you want to send. For instance, here is a simple program that sends a short “hello, world” message to my address, email@example.com:
#!/usr/bin/perl -w use strict; use diagnostics; my $mailprog = '/usr/lib/sendmail'; my $recipient = 'firstname.lastname@example.org'; open (MAIL, "|$mailprog $recipient") die "Cannot open $mailprog: $! "; print MAIL "From: nobody\n"; print MAIL "To: $recipient\n"; print "\n"; print MAIL "Hello there!\n"; close MAIL;
There are several things to notice about this program. First of all, we set $mailprog to “/usr/lib/sendmail”, the default name and location of the mail transfer agent (MTA) on Linux systems. If your copy of sendmail is in another location or if you are using a program other than sendmail, you will need to change the value of $mailprog.
Similarly, mail is sent to a single address, what is defined in $recipient. We will discuss the issue of recipients later, when we look at the issue of program security. Keep in mind that restricting the number of recipients to which the program will send e-mail reduces the possibility that your program will be turned into a mail gateway by spammers or others interested in sending anonymous mail.
We open a connection to $mailprog using Perl's open function, which allows us to write to a program's standard input (STDIN) by treating the program name as a file name, and by prefacing the program's name with a | character. Anything we print or write to that file handle will be treated as if it were sent to the program's STDIN. Any output from the program is ignored.
Finally, notice how we insert a new line character between the final header and the message body. As with HTTP, SMTP (the “simple mail transfer protocol” used for most mail transfer on the Internet) requires a blank line between the header and any data. This allows the receiving program to identify which lines are headers and which are in the body.
Those of us who have been sending mail from within Perl programs were delighted when the Mail::Sendmail module, written by Milivoj Ivkovic, was released to CPAN (the Comprehensive Perl Archive Network, based at http://www.cpan.org/). This module provides a portable method for sending mail from within a Perl program, but also provides a layer of abstraction between your program and the underlying mail system.
It is important to understand how the mail-sending mechanism works on your computer, particularly when it comes time to debug problems with sending or receiving e-mail. However, being able to send mail with three or four lines of Perl from a package maintained and updated independently of your program makes it possible to write shorter, more reliable programs. I have begun using Mail::Sendmail in all of my programs that send e-mail, and I suggest you do so as well, unless you have good reason to stick with the old system described above. One possible reason not to use Mail::Sendmail is if your program will be installed on a system without this package and on which you could not expect it to be installed. Given the ease with which packages can be downloaded and installed from CPAN, however, this should not deter you in a serious way.
The Mail::Sendmail module, like all other modules, must be imported at the top of any program that uses it with a use statement:
If you have not installed the module, or if it is not installed in one of the directories named in @INC (the path through which Perl searches when importing modules), Perl will fail with a fatal error.
After Mail::Sendmail is imported, sending a message becomes a two-step process. In the first stage, define a hash in which the keys are the headers and contents of the message. Specify the message body with the Message (or Body or Text) key. For example:
my %mail = (To => $recipient, From => $sender, Message => "Hello, there!");
You can then send the mail using the statement:
sendmail %mail;The sendmail function is imported into the current name space automatically with the use Mail::Sendmail instruction. Mail::Sendmail defines many other functions as well, but none of these are imported into the default name space unless you explicitly request it.
As you can see, the above code is significantly shorter and easier to understand than what we did first. The fact that it is more portable and easier to maintain are nice additional benefits.
Getting Started with DevOps - Including New Data on IT Performance from Puppet Labs 2015 State of DevOps Report
August 27, 2015
12:00 PM CDT
DevOps represents a profound change from the way most IT departments have traditionally worked: from siloed teams and high-anxiety releases to everyone collaborating on uneventful and more frequent releases of higher-quality code. It doesn't matter how large or small an organization is, or even whether it's historically slow moving or risk averse — there are ways to adopt DevOps sanely, and get measurable results in just weeks.
Free to Linux Journal readers.Register Now!
- August 2015 Issue of Linux Journal: Programming
- Hacking a Safe with Bash
- Django Models and Migrations
- Secure Server Deployments in Hostile Territory, Part II
- Huge Package Overhaul for Debian and Ubuntu
- The Controversy Behind Canonical's Intellectual Property Policy
- Shashlik - a Tasty New Android Simulator
- KDE Reveals Plasma Mobile
- Embed Linux in Monitoring and Control Systems
- General Relativity in Python