<title>Configuring Systems To Use The Bulkmail Module</title>

<body>
<h1>Configuring Systems To Use The Bulkmail Module</h1>

<h2>Configure qmail servers</h2>

A set of qmail servers should be configured on multiple ports and/or hosts
in order to serve outgoing mail connections from an AOLserver running the bulkmail module.

<p>
[instructions here for configuring qmail to listen on N TCP ports]

<p>
[instructions should include what config files need to be set to
allow mail relaying, plus how to configure test mailers which deliver
all mail to a local filesystem]

</h2>Configuring qmail bounce handling for use with the
Bulkmail module</h2>

For each mailer host, qmail configuration files need to be
edited as follows:

<h3>Bounce handling for <FONT COLOR=GREEN>hostname.com</FONT> (i.e., away.com)</h3>

In <tt>/var/qmail/alias</tt> the following files need to be created
or modified:

<ul>
<li>
Create the file <tt>/var/qmail/alias/.qmail-<FONT COLOR=GREEN>hostname</FONT>-email-return-default</tt>
containing the line
<pre>
|touch "/web/<FONT COLOR=GREEN>hostname</FONT>/mail/bounce/$EXT4@`date +%Y%mm%dd%HH%MM%SS`"
</pre>

<p>
<li>Edit the file <tt>/var/qmail/control/rcpthosts</tt> to contain the line

<pre>
<FONT COLOR=GREEN>hostname.com</FONT>
</pre>
<p>

<li>Edit the file <tt>/var/qmail/control/virtualdomains</tt> to contain the line
<pre>
<FONT COLOR=GREEN>hostname.com</FONT>:alias-<FONT COLOR=GREEN>hostname</FONT>
</pre>

</ul>

Then in your AOLServer /web/<font color=green>hostname</font>/parameters/<font color=green>hostname</font>.ini file, set 
the following params in the <b><tt>bulkmail</tt></b> section.

<pre>
[ns/server/<FONT COLOR=GREEN>hostname</FONT>/acs/bulkmail]
; the template for the bounce (sender) address
BulkmailSenderAddress=email-return-$key_code@<FONT COLOR=GREEN>hostname.com</FONT>

; the template for the reply-to address
BulkmailReplyAddress=email-reply-$key_code@<FONT COLOR=GREEN>hostname.com</FONT>


</pre>

<h3>Restart the qmail send process</h3>
On the mailer host(s) restart the qmail process with a HUP signal.

<pre>
as root:
ps -ef | grep qmail-send | grep -v grep | perl -n -a -e 'print "kill -HUP $F[1]\n"' | bash

</pre>

 man -M /var/qmail/man dot-qmail

<pre>
p: You need to cd to /service, and then issue a '/usr/local/bin/svc -d <instance>' where instance is qmail, qmail2 or qmail3

</pre>

<h3>Automatic handling of unsubscribe requests</h3>

The VERP tags used in bounce handling on outgoing mail in the return-path can
also be used to do double duty in the reply-to address system, to make it easier
to handle unsubscribe requests generated by users hitting "reply" to the bulkmail
message they receive. The <code>email-reply-$key_code</code> above can be used to
trigger a script which runs on any mail to the address "email-reply-XXXXXX@<FONT COLOR=GREEN>hostname.com</FONT>".



An example unsubscribe perl script is shown below. 

The script below should be invoked via the following qmail alias file:

Create the file <tt>/var/qmail/alias/.qmail-<FONT COLOR=GREEN>hostname</FONT>-email-reply-default</tt>
containing the line
<pre>
|/web/yourserver/bin/unsubscribe-user.pl "$EXT4"
</pre>

This will ensure that the script gets passed the VERP code if there is one
that the message was generated with, which is the most reliable way to figure out
the user_id (and email address) the mail was sent to in the first place.
<p>


<pre>
#!/usr/local/bin/perl
#
# Unsubscribe the user or users in an email message from all newsletters
#
# hqm@ai.mit.edu
#
# If bulkmail VERP keycode arg is supplied, that user is unsubscribed, otherwise
# parses out the From header and unsubscribes the user from all newsletters
# (actually, removes them from any group of type 'newsletter').
#
# Args: (optional) bulkmail encoded VERP key containing user_id
# and raw message body on stdin

# Oracle access
$ENV{'ORACLE_HOME'} = "/ora8/m01/app/oracle/product/8.1.6";
$ENV{'LD_LIBRARY_PATH'} = "/ora8/m01/app/oracle/product/8.1.6/lib:/lib:/usr/lib";
$ENV{'ORACLE_BASE'} = "/ora8/m01/app/oracle";
$ENV{'ORACLE_SID'} = "ora8";

$VERP_code        = shift;

$mailer = "/var/qmail/bin/qmail-inject";

use DBI;
use Mail::Address;
require Mail::Send;

################################################################
# Global Definitions

# For sending email error message replies back to member
$mailer = "/usr/lib/sendmail";
$return_address = "webmaster\@hostname.com";
$maintainer = "webmaster\@hostname.com";
$an_system_url = "http://www.hostname.com";


$DEBUG = 1;
$debug_logfile = "/web/yourwebserver/log/unsubscribe.log"; 



if ($DEBUG) {
    open (LOG, "&gt;&gt;$debug_logfile");
    debug("================================================================\n");
    debug(`/bin/date`);
}


$db_datasrc = 'dbi:Oracle:';
$db_user = 'YOURDBUSER;
$db_passwd = 'YOURDBPASSWD';

#################################################################
## Snarf down incoming msg on STDIN
#################################################################

# extract From: header
while (&lt;&gt;) {
    $in_header =   1  .. /^$/;
    if ($in_header) {
	if (/^From:.*([\s&lt;]\S+\@\S+[&gt;\s])/ || /^Subject:.*([\s&lt;]\S+\@\S+[&gt;\s])/) {
	    $line = $1;
	    @from = Mail::Address-&gt;parse($line);
	    $from_address = $from[0]-&gt;address;
	    last;
	}
    }
}
    
debug("VERP code = $VERP_code\n");

# open the database connection
$dbh = DBI-&gt;connect($db_datasrc, $db_user, $db_passwd)
  || die "Couldn't connect to database";
$dbh-&gt;{AutoCommit} = 1;

if ($VERP_code eq "") {
    $user_id = get_user_id_from_email($from_address);
} else {
    $user_id = decode_verp_key($VERP_code);
}

debug("user id = $user_id\n");

if ($user_id ne "") {
    $real_email = get_email_from_user_id($user_id);
    $err = unsubscribe_user($user_id);
    debug("unsubscribing user_id $user_id, email=$real_email, err=$err\n");
    if ($err eq "") {
	send_email($real_email, $return_address,
		   "Unsubscribed $real_email from hostname.com newsletters",
		   "The account with email address $real_email has been unsubscribed from all newsletters on hostname.com.\n");
    } else {
	send_email($real_email, $return_address,
		   "Error unsubscribing from hostname.com newsletters",
		   "There was an error processing your unsubscribe request. Please contact webmaster\@hostname.com. It would be helpful to forward an original copy of the newsletter you are trying to unsubscribe from.

Thank you.
\n");
    }
}

# All done

$dbh-&gt;disconnect;
if ($DEBUG) { close LOG; }

sub debug () {
    my ($msg) = @_;
    print LOG $msg;
}

# Remove user from all newsletters
# args: user_id
sub unsubscribe_user () {
  my ($id) = @_;
  $query = "delete from user_group_map 
            where user_id = $id and
            group_id in (select group_id from user_groups where group_type = 'newsletter')";
  $sth= $dbh-&gt;prepare($query) || return $dbh-&gt;errstr;
  $sth-&gt;execute || return $dbh-&gt;errstr;
  $sth-&gt;finish;
  return;
}

# take an email addr, return a user_id
sub get_user_id_from_email () {
    my ($email) = @_;
    # SQL quotify
    ($QQemail = $email) =~ s/\'/''/g;
    $h = $dbh-&gt;prepare(qq[SELECT user_id FROM users
			  WHERE lower(email) = lower('$QQemail')]);
    if (!$h-&gt;execute()) {
	die "Unable to execute query in send_error_reply:\n" . $dbh-&gt;errstr;
    }
    $id = $h-&gt;fetchrow;
    $h-&gt;finish;
    return ($id);
}


sub get_email_from_user_id () {
    my ($id) = @_;
    $h = $dbh-&gt;prepare(qq[SELECT email FROM users
			  WHERE user_id = $id]);
    if (!$h-&gt;execute()) {
	die "Unable to execute query in send_error_reply:\n" . $dbh-&gt;errstr;
    }
    $email = $h-&gt;fetchrow;
    $h-&gt;finish;
    return ($email);
}




################################################################
# decode_verp_key(key)
#
# Decode the user_id from a bulkmail VERP key
#
#
################################################################
#  regexp -nocase {([0-9]+)A([0-9]+)B([0-9]+)} $user_content match bulkmail_id user_id time

sub decode_verp_key () {
  my ($key) = @_;
  my ($bulkmail_id,$user_id,$nstime);

# key was generated by /tcl/bulkmail-utils.tcl
  ($bulkmail_id, $user_id, $nstime) =
      ($key =~ /^(\d+)A(\d+)B(\d+)C(\d+)$/i);
  
  return ($user_id);
}


################################################################
# send_email (recipient, sender, subject, body)
################################################################

sub send_email () {
    my ($recipient, $sender, $subject, $body) = @_;
    open(MAIL, "|$mailer $recipient -f$sender") || die "Cannot open: '$mailer'\n";
    print MAIL "To: $recipient\nFrom: $sender\nSubject: $subject\n\n$body\n";
    close(MAIL);
}
</pre>