From 1f29b33d3f71b8a40f5ae76bf20b95618b518654 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Wed, 18 May 2016 01:23:05 +0000 Subject: unsubscribe: get off mah lawn^H^H^Hist While public-inbox is intended primarily for archival, SMTP list subscriptions are still in use in most places and users are likely to want a good unsubscribe mechanism. HTTP (or HTTPS) links in the List-Unsubscribe header are often preferable since some users may use an incorrect email address for mailto: links. Thus, it is useful to provide an example which generates an HTTPS link for users to click on. The default .psgi requires a POST confirmation (as destructive actions with GET are considered bad practice). However, the "confirm" parameter may be disabled for a true "one-click" unsubscribe. The generated URLs are hopefully short enough and both shell and highlighting-friendly to reduce copy+paste errors. --- examples/unsubscribe.psgi | 68 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 examples/unsubscribe.psgi (limited to 'examples/unsubscribe.psgi') diff --git a/examples/unsubscribe.psgi b/examples/unsubscribe.psgi new file mode 100644 index 00000000..82e186b1 --- /dev/null +++ b/examples/unsubscribe.psgi @@ -0,0 +1,68 @@ +#!/usr/bin/perl -w +# Copyright (C) 2016 all contributors +# License: GPL-3.0+ +# This should not require any other PublicInbox code, but may use +# PublicInbox::Config if ~/.public-inbox/config exists or +# PI_CONFIG is pointed to an appropriate location +use strict; +use Plack::Builder; +use PublicInbox::Unsubscribe; +my $app = PublicInbox::Unsubscribe->new( + pi_config => eval { # optional, for pointing out archives + require PublicInbox::Config; + # uses ~/.public-inbox/config by default, + # can override with PI_CONFIG or here since + # I run this .psgi as the mlmmj user while the + # public-inbox-mda code which actually writes to + # the archives runs as a different user. + PublicInbox::Config->new('/home/pi/.public-inbox/config') + }, + code_url => 'git://80x24.org/public-inbox.git', # change if you fork + owner_email => 'BOFH@example.com', + confirm => 1, + + # First 8 bytes is for the key, next 8 bytes is for the IV + # using Blowfish. We want as short URLs as possible to avoid + # copy+paste errors + # umask 077 && dd if=/dev/urandom bs=16 count=1 of=.unsubscribe.key + key_file => '/home/mlmmj/.unsubscribe.key', + + # this runs as whatever user has perms to run /usr/bin/mlmmj-unsub + # users of other mailing lists. Returns '' on success. + unsubscribe => sub { + my ($user_addr, $list_addr) = @_; + + # map list_addr to mlmmj spool, I use: + # /home/mlmmj/spool/$LIST here + my ($list, $domain) = split('@', $list_addr, 2); + my $spool = "/home/mlmmj/spool/$list"; + + return "Invalid list: $list" unless -d $spool; + + # -c to send a confirmation email, -s is important + # in case a user is click-happy and clicks twice. + my @cmd = (qw(/usr/bin/mlmmj-unsub -c -s), + '-L', $spool, '-a', $user_addr); + + # we don't know which version they're subscribed to, + # try both non-digest and digest + my $normal = system(@cmd); + my $digest = system(@cmd, '-d'); + + # success if either succeeds: + return '' if ($normal == 0 || $digest == 0); + + # missing executable or FS error, + # otherwise -s always succeeds, right? + return 'Unknown error, contact admin'; + }, +); + +builder { + mount '/u' => builder { + eval { enable 'Deflater' }; # optional + eval { enable 'ReverseProxy' }; # optional + enable 'Head'; + sub { $app->call(@_) }; + }; +}; -- cgit v1.2.3-24-ge0c7