diff --git a/helios/templates/castvote.html b/helios/templates/castvote.html
index 42e7894b1179423c9b319f48a97e7bb33ec53c67..18edfc951f271594e71b732fcb703785f6861585 100644
--- a/helios/templates/castvote.html
+++ b/helios/templates/castvote.html
@@ -4,7 +4,15 @@
 {% block content %}
 <h2 class="title">Cast Vote {{cast_vote.vote_tinyhash}}</h2>
 cast in <a href="{% url helios.views.one_election_view election.uuid %}">{{election.name}}</a><br />
-by {{voter.name}}
+Fingerprint: <tt>{{cast_vote.vote_hash}}</tt><br />
+by <b><u>{{voter.name}}</u></b>
+<br /><br />
+<a href="#" onclick="$('#castvote_content').slideToggle(250); return false;">details</a><br /><br />
+<div style="display:none;" id="castvote_content">
+<textarea cols="100" rows="10">
+{{vote_content}}
+</textarea>
+</div>
 <br /><br />
 
 
diff --git a/helios/tests.py b/helios/tests.py
index 7dbd3a931b7a1fc4b0e0ebca6549ddc940e6fb1a..d742458f86856df9818fdc6827b7ed08c7c2a119 100644
--- a/helios/tests.py
+++ b/helios/tests.py
@@ -15,6 +15,7 @@ import utils
 from django.db import IntegrityError, transaction
 from django.test.client import Client
 from django.test import TestCase
+from django.utils.html import escape as html_escape
 
 from django.core import mail
 from django.core.files import File
@@ -472,6 +473,16 @@ class ElectionBlackboxTests(TestCase):
                 "status_update" : False})
         self.assertRedirects(response, "%s/helios/elections/%s/cast_done" % (settings.URL_HOST, election_id))
 
+        # at this point an email should have gone out to the user
+        # at position num_messages after, since that was the len() before we cast this ballot
+        email_message = mail.outbox[num_messages_after]
+        url = re.search('http://[^/]+(/[^ \n]*)', email_message.body).group(1)
+
+        # check that we can get at that URL
+        response = self.client.get(url)
+        self.assertContains(response, ballot.hash)
+        self.assertContains(response, html_escape(encrypted_vote))
+
         # encrypted tally
         response = self.client.post("/helios/elections/%s/compute_tally" % election_id, {
                 "csrf_token" : self.client.session['csrf_token']                
diff --git a/helios/views.py b/helios/views.py
index 37796cdb8102b0b52e254c264fb15068d04c9531..286e7c8c4d08d7b428d8446e8bdf91a9beafde7d 100644
--- a/helios/views.py
+++ b/helios/views.py
@@ -51,6 +51,9 @@ from django.conf import settings
 def get_election_url(election):
   return settings.URL_HOST + reverse(election_shortcut, args=[election.short_name])  
 
+def get_castvote_url(cast_vote):
+  return settings.URL_HOST + reverse(castvote_shortcut, args=[cast_vote.vote_tinyhash])
+
 # simple static views
 def home(request):
   user = get_user(request)
@@ -139,7 +142,7 @@ def castvote_shortcut(request, vote_tinyhash):
     raise Http404
 
   # FIXME: consider privacy of election
-  return render_template(request, 'castvote', {'cast_vote' : cast_vote, 'voter': cast_vote.voter, 'election': cast_vote.voter.election})
+  return render_template(request, 'castvote', {'cast_vote' : cast_vote, 'vote_content': cast_vote.vote.toJSON(), 'voter': cast_vote.voter, 'election': cast_vote.voter.election})
 
 @trustee_check
 def trustee_keygenerator(request, election, trustee):
diff --git a/server_ui/glue.py b/server_ui/glue.py
index 7d87d63fb5bffd588edec250dc67a2f04480e2fb..bcb0995e16e53fe7d95facd436dca11cbcb7b6ee 100644
--- a/server_ui/glue.py
+++ b/server_ui/glue.py
@@ -19,10 +19,10 @@ You have successfully cast a vote in
 
   %s
   
-Your ballot tracking number is:
+Your ballot is archived at:
 
   %s
-""" % (election.name, cast_vote.vote_hash)
+""" % (election.name, helios.views.get_castvote_url(cast_vote))
   
   if election.use_voter_aliases:
     body += """