diff --git a/scipost/constants.py b/scipost/constants.py
index aa19e9b476d151d4400e2a14037b60c24b4a17b9..3f8ef98b446e7553635d2424c16d040dc986c2ea 100644
--- a/scipost/constants.py
+++ b/scipost/constants.py
@@ -124,6 +124,7 @@ subject_areas_dict = {}
 for k in subject_areas_raw_dict.keys():
     subject_areas_dict.update(dict(subject_areas_raw_dict[k]))
 
+CONTRIBUTOR_NEWLY_REGISTERED = 0
 CONTRIBUTOR_NORMAL = 1
 CONTRIBUTOR_STATUS = (
     # status determine the type of Contributor:
@@ -135,7 +136,7 @@ CONTRIBUTOR_STATUS = (
     # -2: other account already exists for this person
     # -3: barred from SciPost (abusive behaviour)
     # -4: disabled account (deceased)
-    (0, 'newly registered'),
+    (CONTRIBUTOR_NEWLY_REGISTERED, 'newly registered'),
     (CONTRIBUTOR_NORMAL, 'normal user'),
     (-1, 'not a professional scientist'),
     (-2, 'other account already exists'),
diff --git a/scipost/forms.py b/scipost/forms.py
index 21c68fe51c5aa3a94289857a942539a620b7757d..61677101d231d2acdf4d79f1666a498d3c53fc68 100644
--- a/scipost/forms.py
+++ b/scipost/forms.py
@@ -4,6 +4,7 @@ from django.contrib.auth.models import User, Group
 from django.contrib.auth.password_validation import validate_password
 from django.core.exceptions import ValidationError
 from django.core.urlresolvers import reverse_lazy
+from django.utils import timezone
 from django.utils.http import is_safe_url
 
 from django_countries import countries
@@ -133,6 +134,41 @@ class DraftInvitationForm(forms.ModelForm):
                   'cited_in_submission', 'cited_in_publication'
                   ]
 
+    def __init__(self, *args, **kwargs):
+        '''
+        This form has a required keyword argument `current_user` which is used for validation of
+        the form fields.
+        '''
+        self.current_user = kwargs.pop('current_user')
+        super().__init__(*args, **kwargs)
+
+    def clean_email(self):
+        email = self.cleaned_data['email']
+        if self.instance.id:
+            return email
+
+        if RegistrationInvitation.objects.filter(email=email).exists():
+            self.add_error('email', 'This email address has already been used for an invitation')
+        elif DraftInvitation.objects.filter(email=email).exists():
+            self.add_error('email', ('This email address has already been'
+                                     ' used for a draft invitation'))
+        elif User.objects.filter(email=email).exists():
+            self.add_error('email', 'This email address is already associated to a Contributor')
+
+        return email
+
+    def clean_invitation_type(self):
+        invitation_type = self.cleaned_data['invitation_type']
+        if invitation_type == 'F' and not self.current_user.has_perm('scipost.can_invite_Fellows'):
+            self.add_error('invitation_type', ('You do not have the authorization'
+                                               ' to send a Fellow-type invitation.'
+                                               ' Consider Contributor, or cited (sub/pub).'))
+        if invitation_type == 'R':
+            self.add_error('invitation_type', ('Referee-type invitations must be made'
+                                               'by the Editor-in-charge at the relevant'
+                                               ' Submission\'s Editorial Page.'))
+        return invitation_type
+
 
 class RegistrationInvitationForm(forms.ModelForm):
     cited_in_submission = AutoCompleteSelectField('submissions_lookup', required=False)
@@ -147,12 +183,17 @@ class RegistrationInvitationForm(forms.ModelForm):
                   ]
 
     def __init__(self, *args, **kwargs):
+        '''
+        This form has a required keyword argument `current_user` which is used for validation of
+        the form fields.
+        '''
+        self.current_user = kwargs.pop('current_user')
         if kwargs.get('initial', {}).get('cited_in_submission', False):
             kwargs['initial']['cited_in_submission'] = kwargs['initial']['cited_in_submission'].id
         if kwargs.get('initial', {}).get('cited_in_publication', False):
             kwargs['initial']['cited_in_publication'] = kwargs['initial']['cited_in_publication'].id
 
-        super(RegistrationInvitationForm, self).__init__(*args, **kwargs)
+        super().__init__(*args, **kwargs)
         self.fields['personal_message'].widget.attrs.update(
             {'placeholder': ('NOTE: a personal phrase or two.'
                              ' The bulk of the text will be auto-generated.')})
@@ -161,6 +202,27 @@ class RegistrationInvitationForm(forms.ModelForm):
             queryset=Publication.objects.all().order_by('-publication_date'),
             required=False)
 
+    def clean_email(self):
+        email = self.cleaned_data['email']
+        if RegistrationInvitation.objects.filter(email=email).exists():
+            self.add_error('email', 'This email address has already been used for an invitation')
+        elif User.objects.filter(email=email).exists():
+            self.add_error('email', 'This email address is already associated to a Contributor')
+
+        return email
+
+    def clean_invitation_type(self):
+        invitation_type = self.cleaned_data['invitation_type']
+        if invitation_type == 'F' and not self.current_user.has_perm('scipost.can_invite_Fellows'):
+            self.add_error('invitation_type', ('You do not have the authorization'
+                                               ' to send a Fellow-type invitation.'
+                                               ' Consider Contributor, or cited (sub/pub).'))
+        if invitation_type == 'R':
+            self.add_error('invitation_type', ('Referee-type invitations must be made by the'
+                                               ' Editor-in-charge at the relevant Submission'
+                                               '\'s Editorial Page. '))
+        return invitation_type
+
 
 class ModifyPersonalMessageForm(forms.Form):
     personal_message = forms.CharField(widget=forms.Textarea())
@@ -314,10 +376,21 @@ class UnavailabilityPeriodForm(forms.ModelForm):
         fields = ['start', 'end']
 
     def __init__(self, *args, **kwargs):
-        super(UnavailabilityPeriodForm, self).__init__(*args, **kwargs)
+        super().__init__(*args, **kwargs)
         self.fields['start'].widget.attrs.update({'placeholder': 'YYYY-MM-DD'})
         self.fields['end'].widget.attrs.update({'placeholder': 'YYYY-MM-DD'})
 
+    def clean_end(self):
+        now = timezone.now()
+        start = self.cleaned_data['start']
+        end = self.cleaned_data['end']
+        if start > end:
+            self.add_error('end', 'The start date you have entered is later than the end date.')
+
+        if end < now.date():
+            self.add_error('end', 'You have entered an end date in the past.')
+        return end
+
 
 class RemarkForm(forms.Form):
     remark = forms.CharField(widget=forms.Textarea(), label='')
diff --git a/scipost/management/commands/add_groups_and_permissions.py b/scipost/management/commands/add_groups_and_permissions.py
index 5dc95ea7613d475ba31725e485d11e650878639b..ef95e885debea981eff40c8f073b9cd336ad6148 100644
--- a/scipost/management/commands/add_groups_and_permissions.py
+++ b/scipost/management/commands/add_groups_and_permissions.py
@@ -61,6 +61,10 @@ class Command(BaseCommand):
             codename='can_invite_Fellows',
             name='Can invite Fellows',
             content_type=content_type)
+        can_resend_registration_requests, created = Permission.objects.get_or_create(
+            codename='can_resend_registration_requests',
+            name='Can resend registration activation emails',
+            content_type=content_type)
 
         # Communications
         can_email_group_members, created = Permission.objects.get_or_create(
@@ -189,6 +193,7 @@ class Command(BaseCommand):
             can_manage_registration_invitations,
             can_email_group_members,
             can_email_particulars,
+            can_resend_registration_requests,
             can_vet_registration_requests,
             can_vet_commentary_requests,
             can_vet_thesislink_requests,
diff --git a/scipost/managers.py b/scipost/managers.py
index 518ca5aaf34d411d1ab3cde65c4a5023b9a7b1df..cd9344ef5b99d97a7825d57016b24e9b6638e260 100644
--- a/scipost/managers.py
+++ b/scipost/managers.py
@@ -3,7 +3,7 @@ import datetime
 from django.db import models
 from django.db.models import Q
 
-from .constants import CONTRIBUTOR_NORMAL
+from .constants import CONTRIBUTOR_NORMAL, CONTRIBUTOR_NEWLY_REGISTERED
 
 
 class FellowManager(models.Manager):
@@ -20,3 +20,6 @@ class FellowManager(models.Manager):
 class ContributorManager(models.Manager):
     def active(self):
         return self.filter(user__is_active=True, status=CONTRIBUTOR_NORMAL)
+
+    def awaiting_validation(self):
+        return self.filter(user__is_active=False, status=CONTRIBUTOR_NEWLY_REGISTERED)
diff --git a/scipost/migrations/0056_auto_20170619_2049.py b/scipost/migrations/0056_auto_20170619_2049.py
new file mode 100644
index 0000000000000000000000000000000000000000..fff00ef763559a8050171f9ee584cd5d851d1ed7
--- /dev/null
+++ b/scipost/migrations/0056_auto_20170619_2049.py
@@ -0,0 +1,30 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.10.3 on 2017-06-19 18:49
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('scipost', '0055_auto_20170519_0937'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='draftinvitation',
+            name='date_drafted',
+            field=models.DateTimeField(auto_now_add=True),
+        ),
+        migrations.AlterField(
+            model_name='draftinvitation',
+            name='first_name',
+            field=models.CharField(max_length=30),
+        ),
+        migrations.AlterField(
+            model_name='draftinvitation',
+            name='last_name',
+            field=models.CharField(max_length=30),
+        ),
+    ]
diff --git a/scipost/models.py b/scipost/models.py
index dd2bc50535f6bef22f63975dbebd01b167c19593..8c477ff6b07f1aea1fa6b5628f7bb7f9066e3636 100644
--- a/scipost/models.py
+++ b/scipost/models.py
@@ -103,7 +103,6 @@ class Contributor(models.Model):
         salt = self.user.username.encode('utf8')
         self.activation_key = hashlib.sha1(salt+salt).hexdigest()
         self.key_expires = datetime.datetime.now() + datetime.timedelta(days=2)
-        self.save()
 
     def discipline_as_string(self):
         # Redundant, to be removed in future
@@ -161,7 +160,7 @@ class Contributor(models.Model):
 
 
 class UnavailabilityPeriod(models.Model):
-    contributor = models.ForeignKey(Contributor, on_delete=models.CASCADE)
+    contributor = models.ForeignKey('scipost.Contributor', on_delete=models.CASCADE)
     start = models.DateField()
     end = models.DateField()
 
@@ -205,8 +204,8 @@ class DraftInvitation(models.Model):
     Draft of an invitation, filled in by an officer.
     """
     title = models.CharField(max_length=4, choices=TITLE_CHOICES)
-    first_name = models.CharField(max_length=30, default='')
-    last_name = models.CharField(max_length=30, default='')
+    first_name = models.CharField(max_length=30)
+    last_name = models.CharField(max_length=30)
     email = models.EmailField()
     invitation_type = models.CharField(max_length=2, choices=INVITATION_TYPE,
                                        default=INVITATION_CONTRIBUTOR)
@@ -216,10 +215,9 @@ class DraftInvitation(models.Model):
     cited_in_publication = models.ForeignKey('journals.Publication',
                                              on_delete=models.CASCADE,
                                              blank=True, null=True)
-    drafted_by = models.ForeignKey(Contributor,
-                                   on_delete=models.CASCADE,
+    drafted_by = models.ForeignKey('scipost.Contributor', on_delete=models.CASCADE,
                                    blank=True, null=True)
-    date_drafted = models.DateTimeField(default=timezone.now)
+    date_drafted = models.DateTimeField(auto_now_add=True)
     processed = models.BooleanField(default=False)
 
     def __str__(self):
diff --git a/scipost/templates/scipost/edit_draft_reg_inv.html b/scipost/templates/scipost/edit_draft_reg_inv.html
index 14a601fcce56ce0a207a5f8fa1d1e500ac24a2b1..f6fd6afe34f7e90492f7e502306e8cc1e280bc1f 100644
--- a/scipost/templates/scipost/edit_draft_reg_inv.html
+++ b/scipost/templates/scipost/edit_draft_reg_inv.html
@@ -36,10 +36,7 @@ $(document).ready(function(){
 <div class="row">
     <div class="col-12">
         <h1 class="highlight">Edit a draft registration invitation</h1>
-        {% if errormessage %}
-            <h3 class="text-danger">{{ errormessage }}</h3>
-        {% endif %}
-        <form action="{% url 'scipost:edit_draft_reg_inv' draft_id=draft.id %}" method="post">
+        <form action="{% url 'scipost:edit_draft_reg_inv' draft_id=draft_inv_form.instance.id %}" method="post">
             {% csrf_token %}
             {{draft_inv_form.media}}
             {{draft_inv_form|bootstrap}}
diff --git a/scipost/templates/scipost/personal_page.html b/scipost/templates/scipost/personal_page.html
index 883f8dcdfa54f0006aa954ec0574c7fa7cf2763b..32fcb4a45dd902f6925bd7211eb46b5be3e1cece 100644
--- a/scipost/templates/scipost/personal_page.html
+++ b/scipost/templates/scipost/personal_page.html
@@ -158,16 +158,23 @@
                 </div>
                 <div class="col-md-4 offset-md-1">
                     {% if unavailabilities %}
-                        <h3>Your unavailability periods in our records (YYYY-DD-MM):</h3>
-                        <table class="availabilities">
+                        <h3>Your unavailability periods in our records</h3>
+                        <p class="text-muted">(YYYY-DD-MM)</p>
+                        <table class="table">
                             <tr>
                                 <th>Start</th>
-                                <th>End</th>
+                                <th colspan="2">End</th>
                             </tr>
                         {% for unav in unavailabilities %}
                             <tr>
                                 <td>{{ unav.start }}</td>
                                 <td>{{ unav.end }}</td>
+                                <td>
+                                    <form action="{% url 'scipost:delete_unavailable_period' unav.id %}" method="post">
+                                        {% csrf_token %}
+                                        <input class="btn btn-danger" type="submit" value="Delete" />
+                                    </form>
+                                </td>
                             </tr>
                         {% endfor %}
                         </table>
@@ -198,7 +205,9 @@
                         <ul>
                             {% if perms.scipost.can_vet_registration_requests %}
                                 <li><a href="{% url 'scipost:vet_registration_requests' %}">Vet Registration requests</a> ({{ nr_reg_to_vet }})</li>
-                                <li>Awaiting validation ({{ nr_reg_awaiting_validation }}) (no action necessary)</li>
+                            {% endif %}
+                            {% if perms.scipost.can_resend_registration_requests %}
+                                <li><a href="{% url 'scipost:registration_requests' %}">Awaiting validation</a> ({{ nr_reg_awaiting_validation }})</li>
                             {% endif %}
                             {% if perms.scipost.can_draft_registration_invitations %}
                                 <li><a href="{% url 'scipost:draft_registration_invitation' %}">Draft a Registration Invitation</a></li>
diff --git a/scipost/templates/scipost/registration_requests.html b/scipost/templates/scipost/registration_requests.html
new file mode 100644
index 0000000000000000000000000000000000000000..3402c5b1ec0c224feacfe77ba7b6b2162e1ed9d3
--- /dev/null
+++ b/scipost/templates/scipost/registration_requests.html
@@ -0,0 +1,67 @@
+{% extends 'scipost/_personal_page_base.html' %}
+
+{% block pagetitle %}: registration awaiting validation{% endblock pagetitle %}
+
+{% load bootstrap %}
+
+{% block breadcrumb_items %}
+    {{block.super}}
+    <span class="breadcrumb-item">Registration awaiting validation</span>
+{% endblock %}
+
+{% block content %}
+
+<div class="row">
+    <div class="col-12">
+        <h1 class="highlight">Registration awaiting validation</h1>
+        <p>
+            These Contributors did not yet activate their account. Sometimes, this link is never clicked on (email is either lost to spam, or not received).<br>
+            As per this page, you are able to send a reminder email to the as-yet-unconfirmed contributor.
+        </p>
+    </div>
+</div>
+
+<div class="row">
+    <div class="col-12">
+        <table class="table">
+            <thead>
+                <tr>
+                    <th>Name</th>
+                    <th>Email</th>
+                    <th>Date requested</th>
+                    <th>Key expires</th>
+                    <th>Actions</th>
+                </tr>
+            </thead>
+            <tbody>
+                {% for contributor in unactive_contributors %}
+                    <tr>
+                        <td>{{contributor.user.first_name}} {{contributor.user.last_name}}</td>
+                        <td>{{contributor.user.email}}</td>
+                        <td>{{contributor.user.date_joined|timesince}} ago</td>
+                        <td>
+                            {% if contributor.key_expires < now %}
+                                <span class="text-danger">Expired {{contributor.key_expires|timesince}} ago</span>
+                            {% else %}
+                                Expires in {{contributor.key_expires|timeuntil}}
+                            {% endif %}
+                        </td>
+                        <td>
+                            <form action="{% url 'scipost:registration_requests_reset' contributor.id %}" method="post">
+                                {% csrf_token %}
+                                <input type="submit" class="btn btn-warning" value="Reset and resend" />
+                            </form>
+                        </td>
+                    </tr>
+                {% empty %}
+                    <tr>
+                        <td colspan="5">All registrations have been activated.</td>
+                    </tr>
+                {% endfor %}
+            </tbody>
+        </table>
+    </div>
+</div>
+
+
+{% endblock content %}
diff --git a/scipost/templates/scipost/unavailability_period_form.html b/scipost/templates/scipost/unavailability_period_form.html
new file mode 100644
index 0000000000000000000000000000000000000000..fc4b11d94fad505d3e50293f9104bd09a166ad68
--- /dev/null
+++ b/scipost/templates/scipost/unavailability_period_form.html
@@ -0,0 +1,26 @@
+{% extends 'scipost/_personal_page_base.html' %}
+
+{% block breadcrumb_items %}
+    {{block.super}}
+    <span class="breadcrumb-item">Mark a period as unavailable</span>
+{% endblock %}
+
+{% load bootstrap %}
+
+{% block pagetitle %}: Mark a period as unavailable{% endblock pagetitle %}
+
+{% block content %}
+
+<div class="row">
+    <div class="col-lg-8 offset-lg-2">
+        <h1 class="highlight">Mark a period as unavailable</h1>
+
+        <form method="post">
+            {% csrf_token %}
+            {{form|bootstrap}}
+            <input type="submit" class="btn btn-secondary" value="Submit" />
+        </form>
+    </div>
+</div>
+
+{% endblock content %}
diff --git a/scipost/urls.py b/scipost/urls.py
index ac5f3ab49fd370739874923df4f9d863bb3268a0..8eaf7b40ed5126af0d0397149b1081e65ac4c964 100644
--- a/scipost/urls.py
+++ b/scipost/urls.py
@@ -84,6 +84,9 @@ urlpatterns = [
         views.vet_registration_requests, name='vet_registration_requests'),
     url(r'^vet_registration_request_ack/(?P<contributor_id>[0-9]+)$',
         views.vet_registration_request_ack, name='vet_registration_request_ack'),
+    url(r'^registration_requests$', views.registration_requests, name="registration_requests"),
+    url(r'^registration_requests/(?P<contributor_id>[0-9]+)/reset$',
+        views.registration_requests_reset, name="registration_requests_reset"),
     url(r'^registration_invitations/(?P<draft_id>[0-9]+)$',
         views.registration_invitations, name="registration_invitations_from_draft"),
     url(r'^registration_invitations$',
@@ -133,11 +136,13 @@ urlpatterns = [
     url(r'^update_personal_data$', views.update_personal_data, name='update_personal_data'),
 
     # Unavailabilities
-    url(r'^mark_unavailable_period$', views.mark_unavailable_period,
-        name='mark_unavailable_period'),
+    url(r'^unavailable_period$', views.mark_unavailable_period, name='mark_unavailable_period'),
+    url(r'^unavailable_period/(?P<period_id>[0-9]+)/delete$', views.delete_unavailable_period,
+        name='delete_unavailable_period'),
 
     # Contributor info
-    url(r'^contributor/(?P<contributor_id>[0-9]+)$', views.contributor_info, name="contributor_info"),
+    url(r'^contributor/(?P<contributor_id>[0-9]+)$', views.contributor_info,
+        name="contributor_info"),
 
     # Authorship claims
     url(r'^claim_authorships$', views.claim_authorships, name="claim_authorships"),
diff --git a/scipost/views.py b/scipost/views.py
index 793e442f16126d790ef3f314231df94731121af0..229123403a324cc62918110819e7349e0045dc0b 100644
--- a/scipost/views.py
+++ b/scipost/views.py
@@ -7,7 +7,6 @@ from django.contrib.auth import login, logout, update_session_auth_hash
 from django.contrib.auth.decorators import login_required
 from django.contrib.auth.models import Group
 from django.contrib.auth.views import password_reset, password_reset_confirm
-from django.core.exceptions import MultipleObjectsReturned, ObjectDoesNotExist
 from django.core import mail
 from django.core.mail import EmailMessage, EmailMultiAlternatives
 from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
@@ -15,6 +14,7 @@ from django.core.urlresolvers import reverse
 from django.db.models import Q
 from django.shortcuts import redirect
 from django.template import Context, Template
+from django.views.decorators.http import require_POST
 from django.views.generic.list import ListView
 
 from django.db.models import Prefetch
@@ -278,6 +278,7 @@ def request_new_activation_link(request, contributor_id, key):
     if request.GET.get('confirm', False):
         # Generate a new email activation key and link
         contributor.generate_key()
+        contributor.save()
         Utils.load({'contributor': contributor}, request)
         Utils.send_new_activation_link_email()
 
@@ -385,6 +386,38 @@ def vet_registration_request_ack(request, contributor_id):
     return redirect(reverse('scipost:vet_registration_requests'))
 
 
+@permission_required('scipost.can_resend_registration_requests', return_403=True)
+def registration_requests(request):
+    '''
+    List all inactive users. These are users that have filled the registration form,
+    but did not yet activate their account using the validation email.
+    '''
+    unactive_contributors = (Contributor.objects.awaiting_validation()
+                             .prefetch_related('user')
+                             .order_by('-key_expires'))
+    context = {
+        'unactive_contributors': unactive_contributors,
+        'now': timezone.now()
+    }
+    return render(request, 'scipost/registration_requests.html', context)
+
+
+@require_POST
+@permission_required('scipost.can_resend_registration_requests', return_403=True)
+def registration_requests_reset(request, contributor_id):
+    '''
+    Reset specific activation_key for Contributor and resend activation mail.
+    '''
+    contributor = get_object_or_404(Contributor.objects.awaiting_validation(), id=contributor_id)
+    contributor.generate_key()
+    contributor.save()
+    Utils.load({'contributor': contributor}, request)
+    Utils.send_new_activation_link_email()
+    messages.success(request, ('New key successfully generated and sent to <i>%s</i>'
+                               % contributor.user.email))
+    return redirect(reverse('scipost:registration_requests'))
+
+
 @permission_required('scipost.can_draft_registration_invitations', return_403=True)
 def draft_registration_invitation(request):
     """
@@ -392,36 +425,13 @@ def draft_registration_invitation(request):
     This is similar to the registration_invitations method,
     which is used to complete the invitation process.
     """
-    errormessage = ''
-    if request.method == 'POST':
-        draft_inv_form = DraftInvitationForm(request.POST)
-        Utils.load({'contributor': request.user.contributor, 'form': draft_inv_form})
-        if draft_inv_form.is_valid():
-            if Utils.email_already_invited():
-                errormessage = ('DUPLICATE ERROR: '
-                                'This email address has already been used for an invitation')
-            elif Utils.email_already_drafted():
-                errormessage = ('DUPLICATE ERROR: '
-                                'This email address has already been used for a draft invitation')
-            elif Utils.email_already_taken():
-                errormessage = ('DUPLICATE ERROR: '
-                                'This email address is already associated to a Contributor')
-            elif (draft_inv_form.cleaned_data['invitation_type'] == 'F'
-                  and not request.user.has_perm('scipost.can_invite_Fellows')):
-                errormessage = ('You do not have the authorization to send a Fellow-type '
-                                'invitation. Consider Contributor, or cited (sub/pub). ')
-            elif (draft_inv_form.cleaned_data['invitation_type'] == 'R'):
-                errormessage = ('Referee-type invitations must be made by the Editor-in-charge '
-                                'at the relevant Submission\'s Editorial Page. ')
-            else:
-                Utils.create_draft_invitation()
-                messages.success(request, 'Draft invitation saved.')
-                return redirect(reverse('scipost:draft_registration_invitation'))
-        else:
-            errormessage = 'The form was not filled validly.'
-
-    else:
-        draft_inv_form = DraftInvitationForm()
+    draft_inv_form = DraftInvitationForm(request.POST or None, current_user=request.user)
+    if draft_inv_form.is_valid():
+        invitation = draft_inv_form.save(commit=False)
+        invitation.drafted_by = request.user.contributor
+        invitation.save()
+        messages.success(request, 'Draft invitation saved.')
+        return redirect(reverse('scipost:draft_registration_invitation'))
 
     sent_reg_inv = RegistrationInvitation.objects.filter(responded=False, declined=False)
     sent_reg_inv_fellows = sent_reg_inv.filter(invitation_type='F').order_by('last_name')
@@ -445,7 +455,7 @@ def draft_registration_invitation(request):
     existing_drafts = DraftInvitation.objects.filter(processed=False).order_by('last_name')
 
     context = {
-        'draft_inv_form': draft_inv_form, 'errormessage': errormessage,
+        'draft_inv_form': draft_inv_form,
         'sent_reg_inv_fellows': sent_reg_inv_fellows,
         'sent_reg_inv_contrib': sent_reg_inv_contrib,
         'sent_reg_inv_ref': sent_reg_inv_ref,
@@ -466,23 +476,15 @@ def draft_registration_invitation(request):
 @permission_required('scipost.can_manage_registration_invitations', return_403=True)
 def edit_draft_reg_inv(request, draft_id):
     draft = get_object_or_404(DraftInvitation, id=draft_id)
-    errormessage = ''
-    if request.method == 'POST':
-        draft_inv_form = DraftInvitationForm(request.POST)
-        if draft_inv_form.is_valid():
-            draft.title = draft_inv_form.cleaned_data['title']
-            draft.first_name = draft_inv_form.cleaned_data['first_name']
-            draft.last_name = draft_inv_form.cleaned_data['last_name']
-            draft.email = draft_inv_form.cleaned_data['email']
-            draft.save()
-            return redirect(reverse('scipost:registration_invitations'))
-        else:
-            errormessage = 'The form is invalidly filled'
-    else:
-        draft_inv_form = DraftInvitationForm(instance=draft)
-    context = {'draft_inv_form': draft_inv_form,
-               'draft': draft,
-               'errormessage': errormessage, }
+
+    draft_inv_form = DraftInvitationForm(request.POST or None, current_user=request.user,
+                                         instance=draft)
+    if draft_inv_form.is_valid():
+        draft = draft_inv_form.save()
+        messages.success(request, 'Draft invitation saved.')
+        return redirect(reverse('scipost:registration_invitations'))
+
+    context = {'draft_inv_form': draft_inv_form}
     return render(request, 'scipost/edit_draft_reg_inv.html', context)
 
 
@@ -511,62 +513,38 @@ def map_draft_reg_inv_to_contributor(request, draft_id, contributor_id):
 def registration_invitations(request, draft_id=None):
     """ Overview and tools for administrators """
     # List invitations sent; send new ones
-    errormessage = ''
     associated_contributors = None
-    if request.method == 'POST':
-        # Send invitation from form information
-        reg_inv_form = RegistrationInvitationForm(request.POST)
-        Utils.load({'contributor': request.user.contributor, 'form': reg_inv_form})
-        if reg_inv_form.is_valid():
-            if Utils.email_already_invited():
-                errormessage = ('DUPLICATE ERROR: '
-                                'This email address has already been used for an invitation')
-            elif Utils.email_already_taken():
-                errormessage = ('DUPLICATE ERROR: '
-                                'This email address is already associated to a Contributor')
-            elif (reg_inv_form.cleaned_data['invitation_type'] == 'F'
-                  and not request.user.has_perm('scipost.can_invite_Fellows')):
-                errormessage = ('You do not have the authorization to send a Fellow-type '
-                                'invitation. Consider Contributor, or cited (sub/pub). ')
-            elif (reg_inv_form.cleaned_data['invitation_type'] == 'R'):
-                errormessage = ('Referee-type invitations must be made by the Editor-in-charge '
-                                'at the relevant Submission\'s Editorial Page. ')
-            else:
-                Utils.create_invitation()
-                Utils.send_registration_invitation_email()
-                try:
-                    draft = DraftInvitation.objects.get(
-                        email=reg_inv_form.cleaned_data['email'])
-                    draft.processed = True
-                    draft.save()
-                except ObjectDoesNotExist:
-                    pass
-                except MultipleObjectsReturned:
-                    # Delete the first invitation
-                    draft_to_delete = RegistrationInvitation.objects.filter(
-                        email=reg_inv_form.cleaned_data['email']).first()
-                    draft_to_delete.delete()
-                messages.success(request, 'Registration Invitation sent')
-                return redirect(reverse('scipost:registration_invitations'))
-        else:
-            errormessage = 'The form was not filled validly.'
+    initial = {}
+    if draft_id:
+        # Fill draft data if draft_id given
+        draft = get_object_or_404(DraftInvitation, id=draft_id)
+        associated_contributors = Contributor.objects.filter(
+            user__last_name__icontains=draft.last_name)
+        initial = {
+            'title': draft.title,
+            'first_name': draft.first_name,
+            'last_name': draft.last_name,
+            'email': draft.email,
+            'invitation_type': draft.invitation_type,
+            'cited_in_submission': draft.cited_in_submission,
+            'cited_in_publication': draft.cited_in_publication,
+        }
 
-    else:
-        initial = {}
-        if draft_id:
-            draft = get_object_or_404(DraftInvitation, id=draft_id)
-            associated_contributors = Contributor.objects.filter(
-                user__last_name__icontains=draft.last_name)
-            initial = {
-                'title': draft.title,
-                'first_name': draft.first_name,
-                'last_name': draft.last_name,
-                'email': draft.email,
-                'invitation_type': draft.invitation_type,
-                'cited_in_submission': draft.cited_in_submission,
-                'cited_in_publication': draft.cited_in_publication,
-            }
-        reg_inv_form = RegistrationInvitationForm(initial=initial)
+    # Send invitation from form information
+    reg_inv_form = RegistrationInvitationForm(request.POST or None, initial=initial,
+                                              current_user=request.user)
+    if reg_inv_form.is_valid():
+        invitation = reg_inv_form.save(commit=False)
+        invitation.invited_by = request.user.contributor
+        invitation.save()
+
+        Utils.load({'invitation': invitation})
+        Utils.send_registration_invitation_email()
+        (DraftInvitation.objects.filter(email=reg_inv_form.cleaned_data['email'])
+         .update(processed=True))
+
+        messages.success(request, 'Registration Invitation sent')
+        return redirect(reverse('scipost:registration_invitations'))
 
     sent_reg_inv = RegistrationInvitation.objects.filter(responded=False, declined=False)
     sent_reg_inv_fellows = sent_reg_inv.filter(invitation_type='F').order_by('last_name')
@@ -590,7 +568,7 @@ def registration_invitations(request, draft_id=None):
     existing_drafts = DraftInvitation.objects.filter(processed=False).order_by('last_name')
 
     context = {
-        'reg_inv_form': reg_inv_form, 'errormessage': errormessage,
+        'reg_inv_form': reg_inv_form,
         'sent_reg_inv_fellows': sent_reg_inv_fellows,
         'sent_reg_inv_contrib': sent_reg_inv_contrib,
         'sent_reg_inv_ref': sent_reg_inv_ref,
@@ -758,28 +736,34 @@ def logout_view(request):
     return redirect(reverse('scipost:index'))
 
 
+@login_required
 def mark_unavailable_period(request):
-    if request.method == 'POST':
-        unav_form = UnavailabilityPeriodForm(request.POST)
-        errormessage = None
-        if unav_form.is_valid():
-            now = timezone.now()
-            if unav_form.cleaned_data['start'] > unav_form.cleaned_data['end']:
-                errormessage = 'The start date you have entered is later than the end date.'
-            elif unav_form.cleaned_data['end'] < now.date():
-                errormessage = 'You have entered an end date in the past.'
-            if errormessage is not None:
-                return render(request, 'scipost/error.html',
-                              context={'errormessage': errormessage})
-            else:
-                unav = UnavailabilityPeriod(
-                    contributor=request.user.contributor,
-                    start=unav_form.cleaned_data['start'],
-                    end=unav_form.cleaned_data['end'])
-                unav.save()
-        else:
-            errormessage = 'Please enter valid dates (format: YYYY-MM-DD).'
-            return render(request, 'scipost/error.html', context={'errormessage': errormessage})
+    '''
+    Mark period unavailable for Contributor using this view.
+    '''
+    unav_form = UnavailabilityPeriodForm(request.POST or None)
+    if unav_form.is_valid():
+        unav = unav_form.save(commit=False)
+        unav.contributor = request.user.contributor
+        unav.save()
+        messages.success(request, 'Unavailability period registered')
+        return redirect('scipost:personal_page')
+
+    # Template acts as a backup in case the form is invalid.
+    context = {'form': unav_form}
+    return render(request, 'scipost/unavailability_period_form.html', context)
+
+
+@require_POST
+@login_required
+def delete_unavailable_period(request, period_id):
+    '''
+    Delete period unavailable registered.
+    '''
+    unav = get_object_or_404(UnavailabilityPeriod,
+                             contributor=request.user.contributor, id=int(period_id))
+    unav.delete()
+    messages.success(request, 'Unavailability period deleted')
     return redirect('scipost:personal_page')
 
 
@@ -807,9 +791,9 @@ def personal_page(request):
 
         # count the number of pending registration requests
         nr_reg_to_vet = Contributor.objects.filter(user__is_active=True, status=0).count()
-        nr_reg_awaiting_validation = Contributor.objects.filter(
-            user__is_active=False, key_expires__gte=now,
-            key_expires__lte=intwodays, status=0).count()
+        nr_reg_awaiting_validation = (Contributor.objects.awaiting_validation()
+                                    #   .filter(key_expires__gte=now, key_expires__lte=intwodays)
+                                      .count())
         nr_submissions_to_assign = Submission.objects.filter(status__in=['unassigned']).count()
         nr_recommendations_to_prepare_for_voting = EICRecommendation.objects.filter(
             submission__status__in=['voting_in_preparation']).count()