This page describes how to ensure that only "good" addresses, of people who actually want to receive your email, end up on your mailing lists.
How to safely add an address to the list
To protect yourself from being used to send unwanted mail, you should ensure that you only add addresses to your mailing lists after first verifying the address. The only safe way to verify an address for this purpose is as follows:
- Send a one-off email to the address in question, including some sort of code which will only be known to you and to the recipient.
- When the recipient receives the one-off email, they then confirm that they have received it, and that they consent to being added to your list, by proving to you that they know the code.
There are many variations on this theme: for example,
- The code could take the form of a web link back to your web server (which handles the mailing list),
- so to confirm, the recipient would click the link
- The code could be in the "Reply-To" header of the email, so to confirm, the recipient would reply to the email
To protect against accidental confirmation (e.g. by email "auto-reply" systems), using a web link is probably the better option (and, for most people, easier to implement).
Also,
The code could include the recipient's email address (e.g. http://www.yourcompany.com/subscribe?addr=bob@example.com&key=lijr6yohinj) in which case your web server would then have to verify the "key" part
The code could just be some opaque key (e.g. http://www.yourcompany.com/subscribe?key=lijr6yohinj) in which case your web server would have to verify the "key", including knowing to which address the key was sent
A specific example
This example uses a "secret" on your mailing list server, and a hash algorithm (in this case, SHA1) to generate the code sent to the recipient. It doesn't need the mailing list server to remember what codes have been sent.
The code below is written in Perl, but should give you the general idea for converting to other languages.
First, the "secret", which is just any old string of rubbish that nobody will know:
our $secret = "This is an example secret passphrase, make sure you change it!"
When someone requests that an address be added to the list:
my $address = 'bob@example.com'; # the recipient's address
my $expiry_time = time() + 86400 * 7; # the code will expire in 7 days' time
use Digest::SHA1 'sha1_hex';
my $code = sha1_hex("$address $expiry_time $secret");
use URI::Encode qw( uri_escape );
my $url = sprintf "http://www.yourcompany.com/confirm?addr=%s&exp=%d&code=%s",
uri_escape($addr), $expiry_time, $code;
my $email = <<EOF;
Hello,
Someone, probably you, has asked that <$address> be added to the
Widget Co monthly newsletter mailing list.
To confirm that you want to be added, click here:
$url
Otherwise, just ignore this message, and you will not be added to the list.
EOF
then send the message ($email) to the recipient ($address).
When someone visits the "confirm" web page:
use CGI 'param';
my $address = param("addr");
my $expiry_time = param("exp");
my $code_supplied = param("code");
use Digest::SHA1 'sha1_hex';
my $correct_code = sha1_hex("$address $expiry_time $secret");
$code_supplied eq $correct_code
or reject("Bad code, request rejected"); # trickery!
$expiry_time > time()
or reject("Code expired, request rejected"); # recipient took more than 7 days to confirm
# Accepted!
add_to_mailing_list($address);
send_welcome_message($address);
show_accepted_web_page($address);