prevent duplicate mails
authorHeiko Schlittermann (JUMPER) <hs@schlittermann.de>
Thu, 07 Jul 2011 09:42:53 +0200
changeset 18 c250bcee5857
parent 17 bf0ff90e2cf5 (current diff)
parent 16 116d3f91248d (diff)
child 19 b286d4293f77
prevent duplicate mails
index.cgi
templates/html.confirmation.done.tpl
templates/html.confirmed.tpl
templates/html.form-ack.tpl
templates/html.form.done.tpl
templates/html.invitation.done.tpl
templates/html.invitation.tpl
templates/mail.form-ack.tpl
templates/mail.form.done.tpl
--- a/index.cgi	Wed Jul 06 10:03:18 2011 +0200
+++ b/index.cgi	Thu Jul 07 09:42:53 2011 +0200
@@ -24,6 +24,20 @@
 sub page;
 sub mail;
 
+sub _encrypt {
+    my $_ = encrypt(shift);
+    s/\+/-/g;
+    s/\//_/g;
+    return $_;
+}
+
+sub _decrypt {
+    my $_ = shift;
+    s/_/\//g;
+    s/-/+/g;
+    return decrypt($_);
+}
+
 
 delete @ENV{grep /PATH$/ => keys %ENV};
 $ENV{PATH} = "/usr/bin:/usr/sbin:/bin:/sbin";
@@ -40,6 +54,7 @@
     OPT => [qw[tel]]
 );
 
+
 my %ttconfig = (
     INCLUDE_PATH => "templates",
     VARIABLES => {
@@ -58,14 +73,32 @@
 	print redirect(basename($ENV{SCRIPT_NAME}));
     }
 
+    # ACCESS
+    if (!path_info()) {
+        do_invite();
+	exit 0;
+    }
 
-    # ACCESS
-    # Here we generate a link URL (sent via Mail) containing the
-    # encrypted current timestamp. Accessing the form is only possible
-    # using this link. Note: These links may not be unique!
-    if (!path_info()) {
-	do_invite();
-	exit 0;
+    # /done.<uuid>/ filled forms etc
+    # /done/
+    if (path_info() =~ /^\/?done(?:\.(?<uuid>.*?))?\/(?<step>.*)$/) {
+	my %x = %+;
+	if ($x{step} ~~ [qw(invitation form confirmation)]) {	
+	    eval {
+		page("html.$x{step}.done.tpl", {
+		    done => {
+			map({ ($_, _decrypt(param($_))) } param()),
+		    },
+		    uuid => UUID->new($x{uuid}, map { @$_ } values %FIELDS),
+		});
+		exit 0;
+	    };
+	    die $@ if $@;
+	    if ($@) {
+		page("html.denied.tpl");
+		exit 0;
+	    }
+	}
     }
 
     # /show/(…)
@@ -79,10 +112,12 @@
     }
 
     # /user.<uuid>
-    if (path_info() =~ /^\/?user\.(.*)$/) {
+    if (path_info() =~ /^\/?user\.(.*)(?:\/(.*))?$/) {
 	my $uuid = $1;
 
-	my $confirmed = param("confirm") eq "yes";   
+	if (param("confirm")) {
+
+	my $confirmed = param("confirm") eq "yes" ? 1 : 0;   
 	my %data = confirm($uuid => $confirmed);
 
 	if ($data{error}) {
@@ -95,21 +130,20 @@
 	    confirmed => $confirmed,
 	});
 
-	page("html.confirmed.tpl", {
-	    confirmed => $confirmed,
-	    error => delete $data{error},
-	    value => \%data});
+	print redirect("$SELF/done.$uuid/confirmation?"
+	    . "confirmed=" . _encrypt($confirmed));
+
 	exit 0;
+	}
+
     }
 
     # /tmp.<uuid>
     if (path_info() =~ /^\/?tmp\.(.*)$/) {
 	my $_ = $1;
-	s/_/\//g;
-	s/-/+/g;
 
 	eval {
-	    my $time = decrypt($_) or die "DECRYPTION ERROR";
+	    my $time = _decrypt($_) or die "DECRYPTION ERROR";
 	    $time =~ /^\d+$/ or die "FORMAT ERROR";
 	    time() - $time < (60 * $EXPIRATION) or die "EXPIRED";
 	}; if ($@) {
@@ -154,34 +188,33 @@
 		$warn{$_} = join " ", @{$warn{$_}};
 	    }
 
-	    if (!%warn) {
-		my %r = insert(%value);
-
-		mail("mail.form-ack.tpl", {
-		    to => $value{email},
-		    url => {
-			yes => "$SELF/user.$r{uuid}?confirm=yes",
-			no  => "$SELF/user.$r{uuid}?confirm=no",
+	    if (%warn) {
+		page("html.form.tpl", {
+		    warn => %warn ? \%warn : undef,
+		    value => {
+			givenname => scalar param("givenname"),
+			surname => scalar param("surname"),
+			email => scalar param("email"),
 		    }
 		});
-
-		page("html.form-ack.tpl", {
-		    value => \%value,
-		    created => $r{created},
-		    uuid => $r{uuid},
-		});
 		exit 0;
 	    }
+
+	    my %r = insert(%value);
+
+	    mail("mail.form.done.tpl", {
+		to => $value{email},
+		url => {
+		    yes => "$SELF/user.$r{uuid}?confirm=yes",
+		    no  => "$SELF/user.$r{uuid}?confirm=no",
+		}
+	    });
+
+	    print redirect("$SELF/done.$r{uuid}/form");
+	    exit 0;
 	}
 
-	page("html.form.tpl", {
-	    warn => %warn ? \%warn : undef,
-	    value => {
-		givenname => scalar param("givenname"),
-		surname => scalar param("surname"),
-		email => scalar param("email"),
-	    },
-	} );
+	page("html.form.tpl");
 	exit 0;
     }
 
@@ -205,16 +238,16 @@
 	    my $created = $r->{created};
 	    $DBH->rollback;
 	    return (uuid => $uuid,
-	            created => $r->{created});
+	            exists => $created);
 	}
+
 	local $" = ", ";
 	$sth = $DBH->prepare("INSERT INTO db (@{$FIELDS{MAN}}, @{$FIELDS{OPT}}, uuid, created)
 		VALUES(?, ?, ?, ?, ?, datetime('now'))");
 	$sth->execute(@value{@{$FIELDS{MAN}}, @{$FIELDS{OPT}}}, $uuid);
     $DBH->commit;
 
-    return (uuid => $uuid,
-	    timestamp => undef);
+    return (uuid => $uuid);
 }
 
 sub confirm($$) {
@@ -266,9 +299,7 @@
 		$warn{email} = "INVALID";
 	    }
 	    else {
-		my $xxx = encrypt(time);
-		$xxx =~ s/\+/-/g;
-		$xxx =~ s/\//_/g;
+		my $xxx = _encrypt(time);
 
 		mail("mail.invitation.tpl", {
 		    to   => scalar(param("email")),
@@ -276,7 +307,10 @@
 
 		$sent = param("email");
 	    }
+	    print redirect("$SELF/done/invitation?email=" . _encrypt($sent));
+	    exit 0;
 	}
+	
 	page("html.invitation.tpl", {
 	    sent => $sent,
 	    warn => %warn ? \%warn : undef,
@@ -302,3 +336,28 @@
 	or die "SENDMAIL: $!\n";
 }
 
+{ package UUID;
+  use strict;
+  use warnings;
+
+  sub new {
+    my $self = bless {} => shift;
+    $self->{uuid} = shift;
+    $self->{fields} = [@_];
+    my $sth = $DBH->prepare("SELECT "
+	. join(", " => @{$self->{fields}})
+	. " FROM db WHERE uuid = ?");
+    $sth->execute($self->{uuid});
+    $self->{r} = $sth->fetchrow_hashref;
+    $sth->finish;
+    return undef if not $self->{r};
+    return $self;
+  }
+
+  sub AUTOLOAD {
+    my $self = shift;
+    my ($f) = ($UUID::AUTOLOAD =~ /.*::(.*)/);
+    return $self->{r}{$f};
+  }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/html.confirmation.done.tpl	Thu Jul 07 09:42:53 2011 +0200
@@ -0,0 +1,35 @@
+[%PROCESS "defaults"%]
+[%INCLUDE "html.head"%]
+
+[%IF done.confirmed%]
+
+    Danke, <em>jetzt</em> ist die Anmeldung vollständig. Folgende Daten
+    haben wir von Dir gespeichert:
+
+    <p>
+    <table>
+    <tr><td>Vorname:</td><td>[%uuid.givenname%]</td></tr>
+    <tr><td>Name:</td>   <td>[%uuid.surname%]</td></tr>
+    <tr><td>Mail:</td>   <td>[%uuid.email%]</td></tr>
+    [%IF uuid.tel%]
+    <tr><td>Telefon:</td><td>[%uuid.tel%]</td></tr>
+    [%END%]
+    </table>
+
+    <p>
+    Hier nochmal die <a href="[%SELF%]/show/info">Veranstaltungsinfo</a>,
+    die Bankdaten stehen auch dort. Vergiss bitte nicht die Bezahlung.
+
+[%ELSE%]
+	
+Danke, Deine Daten wurden wieder gelöscht.
+
+[%END%]
+
+<p>
+Solltest Du weitere Fragen haben, kontaktiere bitte 
+[%CONTACT.name%] per
+<a href="mailto:[%CONTACT.mail%]">Mail</a>
+oder telefonisch: [%CONTACT.tel%].
+
+[%INCLUDE "html.foot"%]
--- a/templates/html.confirmed.tpl	Wed Jul 06 10:03:18 2011 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
-[%PROCESS "defaults"%]
-[%INCLUDE "html.head"%]
-
-[%IF error%]
-
-    <div class="warn">
-    Leider konnte die An- oder Abmeldung nicht bestätigt werden. Bitte überprüfe den
-    verwendeten Link.
-    </div>
-
-[%ELSIF confirmed%]
-
-    Danke, <em>jetzt</em> ist die Anmeldung vollständig. Folgende Daten
-    haben wir von Dir gespeichert:
-
-    <p>
-    <table>
-    <tr><td>Vorname:</td><td>[%value.givenname%]</td></tr>
-    <tr><td>Name:</td>   <td>[%value.surname%]</td></tr>
-    <tr><td>Mail:</td>   <td>[%value.email%]</td></tr>
-    [%IF value.tel%]
-    <tr><td>Telefon:</td><td>[%value.tel%]</td></tr>
-    [%END%]
-    </table>
-
-    <p>
-    Hier nochmal die <a href="[%SELF%]/show/info">Veranstaltungsinfo</a>.
-
-[%ELSE%]
-	
-Danke, Deine Daten wurden wieder gelöscht.
-
-[%END%]
-
-<p>
-Solltest Du weitere Fragen haben, kontaktiere bitte 
-[%CONTACT.name%] per
-<a href="mailto:[%CONTACT.mail%]">Mail</a>
-oder telefonisch: [%CONTACT.tel%].
-
-[%INCLUDE "html.foot"%]
--- a/templates/html.form-ack.tpl	Wed Jul 06 10:03:18 2011 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,37 +0,0 @@
-[%INCLUDE "html.head"%]
-[%USE date%]
-
-[%IF timestamp %]
-
-    Deine Daten stehen bereits in unserer Datenbank. Wir haben Dir den 
-    Link zur Bestätigung noch einmal an die hinterlegte
-    Mailadresse (<u>[%value.email%]</u>) geschickt.
-
-    (Zeitstempel der Eintragung: [%date.format(timestamp, locale = "de_DE")%])
-
-[%ELSE%]
-
-    <p>
-    Vielen Dank für Deine Anmeldung.
-    Um die verwendete Mailadresse zu überprüfen, 
-    erhälst Du jetzt per Mail an [%value.email%] einen
-    Link, mit dem Du Deine Anmeldung bitte bestätigst. Vorher
-    geht hier gar nichts.
-
-    <p>
-    Folgende Daten haben wir jetzt gespeichert:
-
-    <table>
-    <tr><td>Vorname:</td><td>[%value.givenname%]</td></tr>
-    <tr><td>Name:</td>	 <td>[%value.surname%]</td></tr>
-    <tr><td>Mail:</td>	 <td>[%value.email%]</td></tr>
-    [%IF value.tel %]
-    <tr><td>Telefon:</td><td>[%value.tel%]</td></tr>
-    [%END%]
-    </table>
-
-    <em>Noch</em> bist Du nicht vollständig angemeldet!
-
-[%END%]
-
-[%INCLUDE "html.foot"%]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/html.form.done.tpl	Thu Jul 07 09:42:53 2011 +0200
@@ -0,0 +1,35 @@
+[%INCLUDE "html.head"%]
+[%USE date%]
+
+[%IF exists %]
+
+    Deine Daten stehen bereits in unserer Datenbank. 
+    (Zeitstempel der Eintragung: 
+    [%date.format(done.exists, locale = "de_DE")%])
+
+[%ELSE%]
+
+    <p>
+    Vielen Dank für Deine Anmeldung.
+    Um die verwendete Mailadresse zu überprüfen, 
+    erhälst Du jetzt per Mail an [%done.email%] einen
+    Link, mit dem Du Deine Anmeldung bitte bestätigst. Vorher
+    geht hier gar nichts.
+
+    <p>
+    Folgende Daten haben wir jetzt gespeichert:
+
+    <table>
+    <tr><td>Vorname:</td><td>[%uuid.givenname%]</td></tr>
+    <tr><td>Name:</td>	 <td>[%uuid.surname%]</td></tr>
+    <tr><td>Mail:</td>	 <td>[%uuid.email%]</td></tr>
+    [%IF uuid.tel %]
+    <tr><td>Telefon:</td><td>[%uuid.tel%]</td></tr>
+    [%END%]
+    </table>
+
+    <em>Noch</em> bist Du nicht vollständig angemeldet!
+
+[%END%]
+
+[%INCLUDE "html.foot"%]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/html.invitation.done.tpl	Thu Jul 07 09:42:53 2011 +0200
@@ -0,0 +1,16 @@
+[%PROCESS "defaults" %]
+[%INCLUDE "html.head"%]
+
+    <p>
+    Vielen Dank. 
+    
+    <p>
+    Eine Mail mit einem Anmeldelink wurde an Deine
+    Mailadresse <u>[%done.email%]</u> geschickt. Absender der Mail ist <a
+    href="mailto:[%CONTACT.mail%]">[%CONTACT.name%]</a> und die Betreffzeile beginnt mit
+    <u>[%SUBJECT%]</u> Der Link ist für die nächsten [%expires%] Minuten
+    gültig. Deine Adresse wurde von uns nicht gespeichert.
+
+
+
+[%INCLUDE "html.foot"%]
--- a/templates/html.invitation.tpl	Wed Jul 06 10:03:18 2011 +0200
+++ b/templates/html.invitation.tpl	Thu Jul 07 09:42:53 2011 +0200
@@ -1,8 +1,6 @@
 [%PROCESS "defaults" %]
 [%INCLUDE "html.head"%]
 
-[%IF !sent%]
-
     <h1>Anmeldung</h1>
 
     Schön, daß Du Dich zum <a
@@ -30,18 +28,5 @@
 	<input type="submit" name="submit" value="Los">
     </form>
 
-[%ELSE%]
-
-    <p>
-    Vielen Dank. 
-    
-    <p>
-    Eine Mail mit einem Anmeldelink wurde an Deine
-    Mailadresse <u>[%sent%]</u> geschickt. Absender der Mail ist <a
-    href="mailto:[%CONTACT.mail%]">[%CONTACT.name%]</a> und die Betreffzeile beginnt mit
-    <u>[%SUBJECT%]</u> Der Link ist für die nächsten [%expires%] Minuten
-    gültig. Deine Adresse wurde von uns nicht gespeichert.
-
-[%END%]
 
 [%INCLUDE "html.foot"%]
--- a/templates/mail.form-ack.tpl	Wed Jul 06 10:03:18 2011 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,18 +0,0 @@
-[%PROCESS "defaults"-%]
-From: "[%CONTACT.name%]" <[%CONTACT.mail%]>
-To: [%to%]
-Subject: [%SUBJECT%] Bitte bestaetige Deine Anmeldung
-[%INCLUDE "mail.head"-%]
-
-Bitte bestätige Deine Anmeldung. Dazu mußt Du folgenden Link in Deinem
-Browser öffnen:
-
-[%url.yes%]
-
-Wenn alles nur ein Irrtum war, dann kannst Du Deine Daten wieder
-AUSTRAGEN und wir vergessen Deine Anmeldung. Hier ist der Link zum
-AUSTRAGEN:
-
-[%url.no%]
-
-[%INCLUDE "mail.foot"%]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/mail.form.done.tpl	Thu Jul 07 09:42:53 2011 +0200
@@ -0,0 +1,18 @@
+[%PROCESS "defaults"-%]
+From: "[%CONTACT.name%]" <[%CONTACT.mail%]>
+To: [%to%]
+Subject: [%SUBJECT%] Bitte best=?utf-8?Q?=C3=A4?=tige Deine Anmeldung
+[%INCLUDE "mail.head"-%]
+
+Bitte bestätige Deine Anmeldung. Dazu mußt Du folgenden Link in Deinem
+Browser öffnen:
+
+[%url.yes%]
+
+Wenn alles nur ein Irrtum war, dann kannst Du Deine Daten wieder
+AUSTRAGEN und wir vergessen Deine Anmeldung. Hier ist der Link zum
+AUSTRAGEN:
+
+[%url.no%]
+
+[%INCLUDE "mail.foot"%]