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:

There are many variations on this theme: for example,

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,

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);

ConfirmedOptIn (last edited 2007-09-05 09:00:27 by DaveEvans)