diff --git a/helios/forms.py b/helios/forms.py
index de3f435c926dc11760e917961c03969f75c20ae3..21cff19c54965daf73600d2f969166688e99a5c8 100644
--- a/helios/forms.py
+++ b/helios/forms.py
@@ -25,4 +25,5 @@ class ElectionTimesForm(forms.Form):
 class EmailVotersForm(forms.Form):
   subject = forms.CharField(max_length=80)
   body = forms.CharField(max_length=2000, widget=forms.Textarea)
-
+  suppress_election_links = forms.BooleanField(label = "Suppress links?", required=False)
+  send_to = forms.ChoiceField(label="Send To", choices= [('all', 'all voters'), ('voted', 'voters who have cast a ballot'), ('not-voted', 'voters who have not yet cast a ballot')])
diff --git a/helios/tasks.py b/helios/tasks.py
index c0f189a21733f98f5629f3acb16b94553bb109e1..461150f96992ab226f202193b9f5cc444e53e0d2 100644
--- a/helios/tasks.py
+++ b/helios/tasks.py
@@ -36,9 +36,22 @@ def cast_vote_verify_and_store(cast_vote_id, status_update_message=None, **kwarg
         logger.error("Failed to verify and store %d" % cast_vote_id)
     
 @task()
-def voters_email(election_id, subject_template, body_template, extra_vars={}):
+def voters_email(election_id, subject_template, body_template, extra_vars={},
+                 voter_constraints_include=None, voter_constraints_exclude=None):
+    """
+    voter_constraints_include are conditions on including voters
+    voter_constraints_exclude are conditions on excluding voters
+    """
     election = Election.objects.get(id = election_id)
-    for voter in election.voter_set.all():
+
+    # select the right list of voters
+    voters = election.voter_set.all()
+    if voter_constraints_include:
+        voters = voters.filter(**voter_constraints_include)
+    if voter_constraints_exclude:
+        voters = voters.exclude(**voter_constraints_exclude)
+
+    for voter in voters:
         single_voter_email.delay(voter.uuid, subject_template, body_template, extra_vars)
 
 @task()
diff --git a/helios/templates/email/vote_body.txt b/helios/templates/email/vote_body.txt
index 4e2afd3eb5b6f26b990247c4de4426d2ed346430..7672da0dc2c703c53b4f09580251deea950cd89c 100644
--- a/helios/templates/email/vote_body.txt
+++ b/helios/templates/email/vote_body.txt
@@ -10,7 +10,7 @@ Your password: {{voter.user.info.password}}
 {% else %}
 Log in with your {{voter.voter_type}} account.
 {% endifequal %}{% if voter.vote_hash %}
-We have a vote recorded for you already, with smart tracker:
+We have recorded your vote with smart tracker:
 
   {{voter.vote_hash}}
 
diff --git a/helios/templates/email/vote_body_nolinks.txt b/helios/templates/email/vote_body_nolinks.txt
new file mode 100644
index 0000000000000000000000000000000000000000..43500ac230ad509c7fd8e9c75d670ff427b9083e
--- /dev/null
+++ b/helios/templates/email/vote_body_nolinks.txt
@@ -0,0 +1,6 @@
+Dear {{voter.name}},
+
+{{custom_message|safe}}
+
+--
+Helios
diff --git a/helios/views.py b/helios/views.py
index b26b17132d3cabf0ae66c1f556d3764c43eefd2b..e486fa32ee4d2150ca6e9146bac6f787670dc0fb 100644
--- a/helios/views.py
+++ b/helios/views.py
@@ -943,7 +943,7 @@ def voters_email(request, election):
   voter = Voter.get_by_election_and_voter_id(election, voter_id)
   
   if request.method == "GET":
-    email_form = forms.EmailVotersForm({'subject': 'Vote in %s' % election.name, 'body':' '})
+    email_form = forms.EmailVotersForm(initial={'subject': 'Vote in %s' % election.name})
   else:
     email_form = forms.EmailVotersForm(request.POST)
     
@@ -952,6 +952,9 @@ def voters_email(request, election):
       # the client knows to submit only once with a specific voter_id
       subject_template = 'email/vote_subject.txt'
       body_template = 'email/vote_body.txt'
+
+      if email_form.cleaned_data['suppress_election_links']:
+        body_template = 'email/vote_body_nolinks.txt'
       
       extra_vars = {
         'custom_subject' : email_form.cleaned_data['subject'],
@@ -960,11 +963,21 @@ def voters_email(request, election):
         'election' : election
         }
         
+      voter_constraints_include = None
+      voter_constraints_exclude = None
+
+      # exclude those who have not voted
+      if email_form.cleaned_data['send_to'] == 'voted':
+        voter_constraints_exclude = {'vote_hash' : None}
+
+      # include only those who have not voted
+      if email_form.cleaned_data['send_to'] == 'not-voted':
+        voter_constraints_include = {'vote_hash': None}
 
       if voter:
         tasks.single_voter_email.delay(voter_uuid = voter.uuid, subject_template = subject_template, body_template = body_template, extra_vars = extra_vars)
       else:
-        tasks.voters_email.delay(election_id = election.id, subject_template = subject_template, body_template = body_template, extra_vars = extra_vars)
+        tasks.voters_email.delay(election_id = election.id, subject_template = subject_template, body_template = body_template, extra_vars = extra_vars, voter_constraints_include = voter_constraints_include, voter_constraints_exclude = voter_constraints_exclude)
 
       # this batch process is all async, so we can return a nice note
       return HttpResponseRedirect(reverse(one_election_view, args=[election.uuid]))