diff --git a/invitations/admin.py b/invitations/admin.py
index 1aaf18857234d0c5917d1297687ebcf0df990a60..a2012f98edee74417477674d8bf2c17a310ec307 100644
--- a/invitations/admin.py
+++ b/invitations/admin.py
@@ -1,6 +1,6 @@
 from django.contrib import admin
 
-from .models import RegistrationInvitation
+from .models import RegistrationInvitation, CitationNotification
 
 
 class RegistrationInvitationAdmin(admin.ModelAdmin):
@@ -11,3 +11,14 @@ class RegistrationInvitationAdmin(admin.ModelAdmin):
 
 
 admin.site.register(RegistrationInvitation, RegistrationInvitationAdmin)
+
+
+class CitationNotificationAdmin(admin.ModelAdmin):
+    date_hierarchy = 'date_sent'
+    search_fields = ['invitation__first_name', 'invitation__last_name',
+                     'contributor__first_name', 'contributor__last_name']
+    list_display = ['__str__', 'created_by', 'date_sent', 'processed']
+    list_filter = ['processed']
+
+
+admin.site.register(CitationNotification, CitationNotificationAdmin)
diff --git a/invitations/constants.py b/invitations/constants.py
index b1f0598fa1a9815846075f7e5e33714b0c421df5..9de09698378d2332d28ad699f7fdb06c5257be46 100644
--- a/invitations/constants.py
+++ b/invitations/constants.py
@@ -1,8 +1,9 @@
-STATUS_DRAFT, STATUS_SENT = ('draft', 'sent')
+STATUS_DRAFT, STATUS_SENT, STATUS_SENT_AND_EDITED = ('draft', 'sent', 'edited')
 STATUS_DECLINED, STATUS_REGISTERED = ('declined', 'register')
 REGISTATION_INVITATION_STATUSES = (
     (STATUS_DRAFT, 'Draft'),
     (STATUS_SENT, 'Sent'),
+    (STATUS_SENT_AND_EDITED, 'Sent and edited'),
     (STATUS_DECLINED, 'Declined'),
     (STATUS_REGISTERED, 'Registered'),
 )
diff --git a/invitations/forms.py b/invitations/forms.py
index ee5a24a7df9ab474bd3d30f2fa515d8fb720e962..a6afd6c4d66495e8db44ab6e9b99fcc9cfdcf9a8 100644
--- a/invitations/forms.py
+++ b/invitations/forms.py
@@ -1,13 +1,130 @@
 from django import forms
+from django.contrib import messages
 
-from .models import RegistrationInvitation
+from journals.models import Publication
+from scipost.models import Contributor
+from submissions.models import Submission
 
-from ajax_select.fields import AutoCompleteSelectMultipleField
+from . import constants
+from .models import RegistrationInvitation, CitationNotification
+from .utils import Utils
 
+from ajax_select.fields import AutoCompleteSelectField, AutoCompleteSelectMultipleField
 
-class RegistrationInvitationForm(forms.ModelForm):
-    cited_in_submission = AutoCompleteSelectMultipleField('submissions_lookup', required=False)
-    cited_in_publication = AutoCompleteSelectMultipleField('publication_lookup', required=False)
+
+class AcceptRequestMixin:
+    def __init__(self, *args, **kwargs):
+        self.request = kwargs.pop('request')
+        super().__init__(*args, **kwargs)
+
+
+class RegistrationInvitationFilterForm(forms.Form):
+    last_name = forms.CharField()
+
+    def search(self, qs):
+        last_name = self.cleaned_data.get('last_name')
+        return qs.filter(last_name__icontains=last_name)
+
+
+class ContributorSearchForm(forms.Form):
+    last_name = forms.CharField()
+
+    def search(self):
+        last_name = self.cleaned_data.get('last_name')
+
+        if last_name:
+            contributors = Contributor.objects.filter(user__last_name__icontains=last_name)
+            invitations = RegistrationInvitation.objects.filter(last_name__icontains=last_name)
+            return contributors, invitations
+        return Contributor.objects.none(), RegistrationInvitation.objects.none()
+
+
+class CitationNotificationForm(AcceptRequestMixin, forms.ModelForm):
+    submission = AutoCompleteSelectField('submissions_lookup', required=False)
+    publication = AutoCompleteSelectField('publication_lookup', required=False)
+
+    class Meta:
+        model = CitationNotification
+        fields = (
+            'contributor',
+            'submission',
+            'publication')
+
+    def __init__(self, *args, **kwargs):
+        contributors = kwargs.pop('contributors')
+        super().__init__(*args, **kwargs)
+        if contributors:
+            self.fields['contributor'].queryset = contributors
+            self.fields['contributor'].empty_label = None
+        else:
+            self.fields['contributor'].queryset = Contributor.objects.none()
+
+    def save(self, *args, **kwargs):
+        if not hasattr(self.instance, 'created_by'):
+            self.instance.created_by = self.request.user
+        return super().save(*args, **kwargs)
+
+
+class CitationNotificationProcessForm(AcceptRequestMixin, forms.ModelForm):
+    class Meta:
+        model = CitationNotification
+        fields = ()
+
+    def get_all_notifications(self):
+        return self.instance.related_notifications().unprocessed()
+
+    def save(self, *args, **kwargs):
+        if kwargs.get('commit', True):
+            self.get_all_notifications().update(processed=True)
+
+            contributor = self.get_all_notifications().filter(contributor__isnull=False)[0]
+            send_mail = (contributor and contributor.accepts_SciPost_emails) or not contributor
+            if send_mail:
+                Utils.load({'notifications': self.get_all_notifications()})
+                Utils.citation_notifications_email()
+        return super().save(*args, **kwargs)
+
+
+class RegistrationInvitationAddCitationForm(AcceptRequestMixin, forms.ModelForm):
+    cited_in_submissions = AutoCompleteSelectMultipleField('submissions_lookup', required=False)
+    cited_in_publications = AutoCompleteSelectMultipleField('publication_lookup', required=False)
+
+    class Meta:
+        model = RegistrationInvitation
+        fields = ()
+
+    def save(self, *args, **kwargs):
+        if kwargs.get('commit', True):
+            updated = 0
+            # Save the Submission notifications
+            submissions = Submission.objects.filter(
+                id__in=self.cleaned_data['cited_in_submissions'])
+            for submission in submissions:
+                __, _updated = CitationNotification.objects.get_or_create(
+                    invitation=self.instance,
+                    submission=submission,
+                    defaults={'created_by': self.request.user})
+                updated += 1 if _updated else 0
+
+            # Save the Publication notifications
+            publications = Publication.objects.filter(
+                id__in=self.cleaned_data['cited_in_publications'])
+            for publication in publications:
+                __, _updated = CitationNotification.objects.get_or_create(
+                    invitation=self.instance,
+                    publication=publication,
+                    defaults={'created_by': self.request.user})
+                updated += 1 if _updated else 0
+            if updated > 0:
+                self.instance.status = constants.STATUS_SENT_AND_EDITED
+                self.instance.save()
+            messages.success(self.request, '{} Citation Notification(s) added.'.format(updated))
+        return self.instance
+
+
+class RegistrationInvitationForm(AcceptRequestMixin, forms.ModelForm):
+    cited_in_submissions = AutoCompleteSelectMultipleField('submissions_lookup', required=False)
+    cited_in_publications = AutoCompleteSelectMultipleField('publication_lookup', required=False)
 
     class Meta:
         model = RegistrationInvitation
@@ -17,12 +134,20 @@ class RegistrationInvitationForm(forms.ModelForm):
             'last_name',
             'email',
             'message_style',
-            'personal_message',
-            'cited_in_submission',
-            'cited_in_publication')
+            'personal_message')
 
     def __init__(self, *args, **kwargs):
-        self.request = kwargs.pop('request')
+        # Find Submissions/Publications related to the invitation and fill the autocomplete fields
+        initial = kwargs.get('initial', {})
+        invitation = kwargs.get('instance', None)
+        if invitation:
+            submission_ids = invitation.citation_notifications.for_submissions().values_list(
+                'submission_id', flat=True)
+            publication_ids = invitation.citation_notifications.for_publications().values_list(
+                'publication_id', flat=True)
+            initial['cited_in_submissions'] = Submission.objects.filter(id__in=submission_ids)
+            initial['cited_in_publications'] = Publication.objects.filter(id__in=publication_ids)
+        kwargs['initial'] = initial
         super().__init__(*args, **kwargs)
         if not self.request.user.has_perm('scipost.can_manage_registration_invitations'):
             del self.fields['message_style']
@@ -31,18 +156,76 @@ class RegistrationInvitationForm(forms.ModelForm):
     def save(self, *args, **kwargs):
         if not hasattr(self.instance, 'created_by'):
             self.instance.created_by = self.request.user
+        invitation = super().save(*args, **kwargs)
+        if kwargs.get('commit', True):
+            # Save the Submission notifications
+            submissions = Submission.objects.filter(
+                id__in=self.cleaned_data['cited_in_submissions'])
+            for submission in submissions:
+                CitationNotification.objects.get_or_create(
+                    invitation=self.instance,
+                    submission=submission,
+                    defaults={
+                        'created_by': self.instance.created_by
+                    })
+
+            # Save the Publication notifications
+            publications = Publication.objects.filter(
+                id__in=self.cleaned_data['cited_in_publications'])
+            for publication in publications:
+                CitationNotification.objects.get_or_create(
+                    invitation=self.instance,
+                    publication=publication,
+                    defaults={
+                        'created_by': self.instance.created_by
+                    })
+        return invitation
+
+
+class RegistrationInvitationReminderForm(AcceptRequestMixin, forms.ModelForm):
+    class Meta:
+        model = RegistrationInvitation
+        fields = ()
+
+    def save(self, *args, **kwargs):
+        if kwargs.get('commit', True):
+            self.instance.mail_sent()
         return super().save(*args, **kwargs)
 
 
-class RegistrationInvitationReminderForm(forms.ModelForm):
+class RegistrationInvitationMapToContributorForm(AcceptRequestMixin, forms.ModelForm):
+    contributor = None
+
     class Meta:
         model = RegistrationInvitation
         fields = ()
 
-    def __init__(self, *args, **kwargs):
-        self.request = kwargs.pop('request')
-        super().__init__(*args, **kwargs)
+    def clean(self, *args, **kwargs):
+        try:
+            self.contributor = Contributor.objects.get(
+                id=self.request.resolver_match.kwargs['contributor_id'])
+        except Contributor.DoesNotExist:
+            self.add_error(None, 'Contributor does not exist.')
+        return {}
+
+    def get_contributor(self):
+        if not self.contributor:
+            self.clean()
+        return self.contributor
 
     def save(self, *args, **kwargs):
-        self.mail_sent()
-        return super().save(*args, **kwargs)
+        if kwargs.get('commit', True):
+            self.instance.citation_notifications.update(contributor=self.contributor)
+            self.instance.delete()
+        return self.instance
+
+
+class RegistrationInvitationMarkForm(AcceptRequestMixin, forms.ModelForm):
+    class Meta:
+        model = RegistrationInvitation
+        fields = ()
+
+    def save(self, *args, **kwargs):
+        if kwargs.get('commit', True):
+            self.instance.mail_sent()
+        return self.instance
diff --git a/invitations/managers.py b/invitations/managers.py
index 7954565fa5953e74a8ed36e4faa42d870ba27c15..0f931c825b6bb142d9f1964b367ce0f6046d3040 100644
--- a/invitations/managers.py
+++ b/invitations/managers.py
@@ -16,8 +16,27 @@ class RegistrationInvitationQuerySet(models.QuerySet):
     def drafts(self):
         return self.filter(status=constants.STATUS_DRAFT)
 
-    def pending_response(self):
-        return self.filter(status=constants.STATUS_SENT)
+    def sent(self):
+        return self.filter(status__in=[constants.STATUS_SENT, constants.STATUS_SENT_AND_EDITED])
+
+    def no_response(self):
+        return self.filter(status__in=[constants.STATUS_SENT,
+                                       constants.STATUS_DRAFT,
+                                       constants.STATUS_SENT_AND_EDITED])
 
     def invited_by(self, user):
         return self.filter(invited_by=user)
+
+
+class CitationNotificationQuerySet(models.QuerySet):
+    def for_submissions(self):
+        return self.filter(submission__isnull=False)
+
+    def for_publications(self):
+        return self.filter(publication__isnull=False)
+
+    def unprocessed(self):
+        return self.filter(processed=False)
+
+    def processed(self):
+        return self.filter(processed=False)
diff --git a/invitations/migrations/0007_auto_20180218_1200.py b/invitations/migrations/0007_auto_20180218_1200.py
new file mode 100644
index 0000000000000000000000000000000000000000..223d8fbb57806086568323a1fe6e2f72f653ddce
--- /dev/null
+++ b/invitations/migrations/0007_auto_20180218_1200.py
@@ -0,0 +1,35 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.4 on 2018-02-18 11:00
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('journals', '0013_auto_20180216_0850'),
+        ('submissions', '0008_auto_20180127_2208'),
+        ('invitations', '0006_auto_20180217_1600'),
+    ]
+
+    operations = [
+        migrations.RemoveField(
+            model_name='registrationinvitation',
+            name='cited_in_publication',
+        ),
+        migrations.RemoveField(
+            model_name='registrationinvitation',
+            name='cited_in_submission',
+        ),
+        migrations.AddField(
+            model_name='registrationinvitation',
+            name='cited_in_publications',
+            field=models.ManyToManyField(blank=True, related_name='_registrationinvitation_cited_in_publications_+', to='journals.Publication'),
+        ),
+        migrations.AddField(
+            model_name='registrationinvitation',
+            name='cited_in_submissions',
+            field=models.ManyToManyField(blank=True, related_name='_registrationinvitation_cited_in_submissions_+', to='submissions.Submission'),
+        ),
+    ]
diff --git a/invitations/migrations/0008_auto_20180218_1305.py b/invitations/migrations/0008_auto_20180218_1305.py
new file mode 100644
index 0000000000000000000000000000000000000000..d74f26c02b7c9411230ea18f421b156c4bfb4104
--- /dev/null
+++ b/invitations/migrations/0008_auto_20180218_1305.py
@@ -0,0 +1,45 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.4 on 2018-02-18 12:05
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('submissions', '0008_auto_20180127_2208'),
+        ('journals', '0013_auto_20180216_0850'),
+        ('scipost', '0004_auto_20180212_1932'),
+        ('invitations', '0007_auto_20180218_1200'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='CitationNotification',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('processed', models.BooleanField(default=False)),
+                ('cited_in_publication', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='+', to='journals.Publication')),
+                ('cited_in_submission', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='+', to='submissions.Submission')),
+                ('contributor', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='+', to='scipost.Contributor')),
+            ],
+            options={
+                'default_related_name': 'citation_notifications',
+            },
+        ),
+        migrations.RemoveField(
+            model_name='registrationinvitation',
+            name='cited_in_publications',
+        ),
+        migrations.RemoveField(
+            model_name='registrationinvitation',
+            name='cited_in_submissions',
+        ),
+        migrations.AddField(
+            model_name='citationnotification',
+            name='invitation',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='citation_notifications', to='invitations.RegistrationInvitation'),
+        ),
+    ]
diff --git a/invitations/migrations/0009_auto_20180218_1556.py b/invitations/migrations/0009_auto_20180218_1556.py
new file mode 100644
index 0000000000000000000000000000000000000000..a755f03d264593dc8191ba51b3293aa5c196dc3d
--- /dev/null
+++ b/invitations/migrations/0009_auto_20180218_1556.py
@@ -0,0 +1,32 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.4 on 2018-02-18 14:56
+from __future__ import unicode_literals
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('scipost', '0005_auto_20180218_1556'),
+        ('submissions', '0008_auto_20180127_2208'),
+        ('journals', '0013_auto_20180216_0850'),
+        ('invitations', '0008_auto_20180218_1305'),
+    ]
+
+    operations = [
+        migrations.RenameField(
+            model_name='citationnotification',
+            old_name='cited_in_publication',
+            new_name='publication',
+        ),
+        migrations.RenameField(
+            model_name='citationnotification',
+            old_name='cited_in_submission',
+            new_name='submission',
+        ),
+        migrations.AlterUniqueTogether(
+            name='citationnotification',
+            unique_together=set([('contributor', 'publication'), ('invitation', 'publication'), ('invitation', 'submission'), ('contributor', 'submission')]),
+        ),
+    ]
diff --git a/invitations/migrations/0010_auto_20180218_1613.py b/invitations/migrations/0010_auto_20180218_1613.py
new file mode 100644
index 0000000000000000000000000000000000000000..b002ed903b52c1e9422bbb2f04404376c1c2a665
--- /dev/null
+++ b/invitations/migrations/0010_auto_20180218_1613.py
@@ -0,0 +1,46 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.4 on 2018-02-18 15:13
+from __future__ import unicode_literals
+
+from django.conf import settings
+from django.db import migrations, models
+import django.db.models.deletion
+import django.utils.timezone
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+        ('invitations', '0009_auto_20180218_1556'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='citationnotification',
+            name='created',
+            field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now),
+            preserve_default=False,
+        ),
+        migrations.AddField(
+            model_name='citationnotification',
+            name='created_by',
+            field=models.ForeignKey(default=2, on_delete=django.db.models.deletion.CASCADE, related_name='notifications_created', to=settings.AUTH_USER_MODEL),
+            preserve_default=False,
+        ),
+        migrations.AddField(
+            model_name='citationnotification',
+            name='date_sent',
+            field=models.DateTimeField(blank=True, null=True),
+        ),
+        migrations.AddField(
+            model_name='citationnotification',
+            name='modified',
+            field=models.DateTimeField(auto_now=True),
+        ),
+        migrations.AlterField(
+            model_name='citationnotification',
+            name='invitation',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='citation_notifications', to='invitations.RegistrationInvitation'),
+        ),
+    ]
diff --git a/invitations/mixins.py b/invitations/mixins.py
index 1e996e16d24c1119f1bf651937749f58c40496be..4b23a2f302e3f4ad7ff65cf4439b59844b79c33b 100644
--- a/invitations/mixins.py
+++ b/invitations/mixins.py
@@ -2,22 +2,40 @@ from django.db import transaction
 from django.contrib import messages
 from django.contrib.auth.mixins import LoginRequiredMixin, PermissionRequiredMixin
 
+from .utils import Utils
 
-class RegistrationInvitationFormMixin(LoginRequiredMixin, PermissionRequiredMixin):
+
+class RequestArgumentMixin:
+    """
+    Use the WSGIRequest as an argument in the form.
+    """
     def get_form_kwargs(self):
         kwargs = super().get_form_kwargs()
         kwargs['request'] = self.request
         return kwargs
 
+
+class PermissionsMixin(LoginRequiredMixin, PermissionRequiredMixin):
+    pass
+
+
+class SaveAndSendFormMixin:
+    """
+    Use the Save or Save and Send option to send the mail out after form is valid.
+    """
     @transaction.atomic
     def form_valid(self, form):
         response = super().form_valid(form)
         send_mail = self.request.POST.get('save', '') == 'save_and_send'
         if send_mail:
+            # Confirm permissions for user
             send_mail = self.request.user.has_perm('scipost.can_manage_registration_invitations')
+        model_name = self.object._meta.verbose_name
         if send_mail:
             self.object.mail_sent()
-            messages.success(self.request, 'Registration Invitation updated and sent')
+            Utils.load({model_name: self.object})
+            getattr(Utils, self.utils_email_method)()
+            messages.success(self.request, '{} updated and sent'.format(model_name))
         else:
-            messages.success(self.request, 'Registration Invitation updated')
+            messages.success(self.request, '{} updated'.format(model_name))
         return response
diff --git a/invitations/models.py b/invitations/models.py
index 1c8dcf464256fbc3fbd23a72434f8d56ac3c6cce..cf8bc8cfdd390092821bec51ca39d0c3bf40761e 100644
--- a/invitations/models.py
+++ b/invitations/models.py
@@ -3,12 +3,12 @@ import hashlib
 import random
 import string
 
-from django.db import models
+from django.db import models, IntegrityError
 from django.conf import settings
 from django.utils import timezone
 
 from . import constants
-from .managers import RegistrationInvitationQuerySet
+from .managers import RegistrationInvitationQuerySet, CitationNotificationQuerySet
 
 from scipost.constants import TITLE_CHOICES
 
@@ -35,10 +35,10 @@ class RegistrationInvitation(models.Model):
     # Related to objects
     invitation_type = models.CharField(max_length=2, choices=constants.INVITATION_TYPE,
                                        default=constants.INVITATION_CONTRIBUTOR)
-    cited_in_submission = models.ManyToManyField('submissions.Submission',
-                                                 blank=True, related_name='+')
-    cited_in_publication = models.ManyToManyField('journals.Publication',
-                                                  blank=True, related_name='+')
+    # cited_in_submissions = models.ManyToManyField('submissions.Submission',
+    #                                               blank=True, related_name='+')
+    # cited_in_publications = models.ManyToManyField('journals.Publication',
+    #                                                blank=True, related_name='+')
 
     # Response keys
     invitation_key = models.CharField(max_length=40, unique=True)
@@ -88,5 +88,77 @@ class RegistrationInvitation(models.Model):
             self.date_sent_first = timezone.now()
         self.date_sent_last = timezone.now()
         self.invited_by = user or self.created_by
-        self.times_sent = self.times_sent + 1
+        self.times_sent += 1
+        self.citation_notifications.update(processed=True)
         self.save()
+
+
+class CitationNotification(models.Model):
+    invitation = models.ForeignKey('invitations.RegistrationInvitation',
+                                   on_delete=models.SET_NULL,
+                                   null=True, blank=True)
+    contributor = models.ForeignKey('scipost.Contributor',
+                                    on_delete=models.CASCADE,
+                                    null=True, blank=True,
+                                    related_name='+')
+
+    # Content
+    submission = models.ForeignKey('submissions.Submission', null=True, blank=True,
+                                   related_name='+')
+    publication = models.ForeignKey('journals.Publication', null=True, blank=True,
+                                    related_name='+')
+    processed = models.BooleanField(default=False)
+
+    # Meta info
+    created_by = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='notifications_created')
+    date_sent = models.DateTimeField(null=True, blank=True)
+    created = models.DateTimeField(auto_now_add=True)
+    modified = models.DateTimeField(auto_now=True)
+
+    objects = CitationNotificationQuerySet.as_manager()
+
+    class Meta:
+        default_related_name = 'citation_notifications'
+        unique_together = (
+            ('invitation', 'submission'),
+            ('invitation', 'publication'),
+            ('contributor', 'submission'),
+            ('contributor', 'publication'),
+        )
+
+    def __str__(self):
+        _str = 'Citation for '
+        if self.invitation:
+            _str += ' Invitation ({} {})'.format(
+                self.invitation.first_name,
+                self.invitation.last_name,
+            )
+        elif self.contributor:
+            _str += ' Contributor ({})'.format(self.contributor)
+
+        _str += ' on '
+        if self.submission:
+            _str += 'Submission ({})'.format(self.submission.arxiv_identifier_w_vn_nr)
+        elif self.publication:
+            _str += 'Publication ({})'.format(self.publication.doi_label)
+        return _str
+
+    def save(self, *args, **kwargs):
+        if not self.submission and not self.publication:
+            raise IntegrityError(('CitationNotification needs to be related to either a '
+                                  'Submission or Publication object.'))
+        return super().save(*args, **kwargs)
+
+    def mail_sent(self):
+        """
+        Update instance fields as if a new citation notification mail has been sent out.
+        """
+        self.processed = True
+        if not self.date_sent:
+            # Don't overwrite by accident...
+            self.date_sent = timezone.now()
+        self.save()
+
+    def related_notifications(self):
+        return CitationNotification.objects.filter(
+            models.Q(contributor=self.contributor) | models.Q(invitation=self.invitation))
diff --git a/invitations/templates/invitations/citationnotification_form.html b/invitations/templates/invitations/citationnotification_form.html
new file mode 100644
index 0000000000000000000000000000000000000000..49d8c3eed57363ad33725729142db774d0a808fe
--- /dev/null
+++ b/invitations/templates/invitations/citationnotification_form.html
@@ -0,0 +1,39 @@
+{% extends 'scipost/_personal_page_base.html' %}
+
+{% block pagetitle %}: Process Citation Notification{% endblock pagetitle %}
+
+{% load bootstrap %}
+
+{% block breadcrumb_items %}
+    {{block.super}}
+    <a href="{% url 'invitations:list' %}" class="breadcrumb-item">Registration Invitations</a>
+    <a href="{% url 'invitations:citation_notification_list' %}" class="breadcrumb-item">Citation Notifications</a>
+    <span class="breadcrumb-item">Process</span>
+{% endblock %}
+
+{% block content %}
+
+<div class="row">
+    <div class="col-12">
+        <h1 class="highlight">Process Citation Notification</h1>
+
+        <h3>All related unprocessed Citation Notifications</h3>
+        {% for related_notification in form.get_all_notifications %}
+            {% include 'partials/invitations/citationnotification_summary.html' with notification=related_notification %}
+            <br>
+        {% endfor %}
+    </div>
+</div>
+
+<div class="row">
+    <div class="col-12">
+        <form method="post">
+            {% csrf_token %}
+            {{ form|bootstrap }}
+            <input type="submit" class="btn btn-primary" name="save" value="Process all notifications">
+        </form>
+
+    </div>
+</div>
+
+{% endblock %}
diff --git a/invitations/templates/invitations/citationnotification_list.html b/invitations/templates/invitations/citationnotification_list.html
new file mode 100644
index 0000000000000000000000000000000000000000..c24a4abb6a3851fd9883ff60f8592c481a1d8da6
--- /dev/null
+++ b/invitations/templates/invitations/citationnotification_list.html
@@ -0,0 +1,25 @@
+{% extends 'scipost/_personal_page_base.html' %}
+
+{% load bootstrap %}
+
+{% block pagetitle %}: Unprocessed Citation Notifications{% endblock pagetitle %}
+
+{% block breadcrumb_items %}
+    {{block.super}}
+    <a href="{% url 'invitations:list' %}" class="breadcrumb-item">Registration Invitations</a>
+    <span class="breadcrumb-item">Unprocessed Citation Notifications</span>
+{% endblock %}
+
+{% block content %}
+
+<h1 class="highlight">Unprocessed Citation Notifications</h1>
+<a href="{% url 'invitations:list' %}">Back to Registration Invitations</a>
+
+<div class="row">
+    <div class="col-12">
+        <br>
+        {% include 'partials/invitations/citationnotification_table.html' with notifications=object_list %}
+    </div>
+</div>
+
+{% endblock %}
diff --git a/invitations/templates/invitations/registrationinvitation_confirm_delete.html b/invitations/templates/invitations/registrationinvitation_confirm_delete.html
index 989547dc85e2604a5db881a6f862d914fb976279..c65958c8547340e2b5dc9f79d564c029eb5e5166 100644
--- a/invitations/templates/invitations/registrationinvitation_confirm_delete.html
+++ b/invitations/templates/invitations/registrationinvitation_confirm_delete.html
@@ -14,12 +14,7 @@
     <div class="col-12">
         <h1 class="highlight">Delete Registration Invitation {{ object.id }}</h1>
         <p>Are you sure you want to delete the Registration Invitation?</p>
-
-        <p>
-            Name: <strong>{{ object.first_name }} {{ object.last_name }}</strong>
-            <br>
-            Email: <strong>{{ object.email }}</strong>
-        </p>
+        {% include 'partials/invitations/registrationinvitation_summary.html' with invitation=object %}
 
         <form method="post">
             {% csrf_token %}
diff --git a/invitations/templates/invitations/registrationinvitation_form.html b/invitations/templates/invitations/registrationinvitation_form.html
index a552c0d0b9658a6943647e24d1b37059c2947bc2..878ad6087d05b52a539f6ff611d3958c1d5b61b5 100644
--- a/invitations/templates/invitations/registrationinvitation_form.html
+++ b/invitations/templates/invitations/registrationinvitation_form.html
@@ -1,6 +1,6 @@
 {% extends 'scipost/_personal_page_base.html' %}
 
-{% block pagetitle %}: {% if object %}Edit{% else %}New{% endif %} Registration Invitation{% endblock pagetitle %}
+{% block pagetitle %}: Edit Registration Invitation{% endblock pagetitle %}
 
 {% load scipost_extras %}
 {% load bootstrap %}
@@ -8,28 +8,24 @@
 {% block breadcrumb_items %}
     {{block.super}}
     <a href="{% url 'invitations:list' %}" class="breadcrumb-item">Registration Invitations</a>
-    <span class="breadcrumb-item">{% if object %}Edit{% else %}New{% endif %}</span>
+    <span class="breadcrumb-item">Edit</span>
 {% endblock %}
 
 {% block content %}
 
 <div class="row">
     <div class="col-12">
-        <h1 class="highlight">{% if object %}Registration Invitation {{ object.id }}{% else %}New Registration Invitation{% endif %}</h1>
-    </div>
-</div>
+        <h1 class="highlight">Registration Invitation {{ object.id }}</h1>
 
-<div class="row">
-    <div class="col-12">
         <form method="post">
             {% csrf_token %}
             {{ form|bootstrap }}
-            <button type="submit" class="btn btn-primary" name="save" value="save">{% if object %}Update{% else %}Create{% endif %}</button>
+            <button type="submit" class="btn btn-primary" name="save" value="save">Save</button>
+            <button type="submit" class="ml-2 btn btn-primary" name="save" value="save_and_create">Save and create new</button>
             {% if perms.scipost.can_manage_registration_invitations %}
-                <button type="submit" class="ml-2 btn btn-primary" name="save" value="save_and_send">{% if object %}Update{% else %}Create{% endif %} and send</button>
+                <button type="submit" class="ml-2 btn btn-secondary" name="save" value="save_and_send">Save and send mail</button>
             {% endif %}
         </form>
-
     </div>
 </div>
 
diff --git a/invitations/templates/invitations/registrationinvitation_form_add_citation.html b/invitations/templates/invitations/registrationinvitation_form_add_citation.html
new file mode 100644
index 0000000000000000000000000000000000000000..af960d23a5b97ac8823e1b3d2b7b169d71296ccb
--- /dev/null
+++ b/invitations/templates/invitations/registrationinvitation_form_add_citation.html
@@ -0,0 +1,43 @@
+{% extends 'scipost/_personal_page_base.html' %}
+
+{% block pagetitle %}: Add Citation Notification{% endblock pagetitle %}
+
+{% load bootstrap %}
+
+{% block breadcrumb_items %}
+    {{block.super}}
+    <a href="{% url 'invitations:list' %}" class="breadcrumb-item">Registration Invitations</a>
+    <span class="breadcrumb-item">Add Citation Notification</span>
+{% endblock %}
+
+{% block content %}
+
+<div class="row">
+    <div class="col-12">
+        <h1 class="highlight">Add Citation Notification</h1>
+        <h3>Registration Invitation</h3>
+        {% include 'partials/invitations/registrationinvitation_summary.html' with invitation=object %}
+    </div>
+</div>
+
+<hr class="divider">
+
+<div class="row">
+    <div class="col-12">
+        <h3>Submission or Publication to add to the Registration Invitation</h3>
+        <br>
+        <form method="post">
+            {% csrf_token %}
+            {{ form|bootstrap }}
+            <input type="submit" class="btn btn-primary" value="Add">
+        </form>
+
+    </div>
+</div>
+
+{% endblock %}
+
+{% block footer_script %}
+    {{ block.super }}
+    {{ form.media }}
+{% endblock footer_script %}
diff --git a/invitations/templates/invitations/registrationinvitation_form_add_new.html b/invitations/templates/invitations/registrationinvitation_form_add_new.html
new file mode 100644
index 0000000000000000000000000000000000000000..b8e3129f0a33b705f2a5b24e6902f4713f8476f1
--- /dev/null
+++ b/invitations/templates/invitations/registrationinvitation_form_add_new.html
@@ -0,0 +1,81 @@
+{% extends 'scipost/_personal_page_base.html' %}
+
+{% block pagetitle %}: New Registration Invitation{% endblock pagetitle %}
+
+{% load scipost_extras %}
+{% load bootstrap %}
+
+{% block breadcrumb_items %}
+    {{block.super}}
+    <a href="{% url 'invitations:list' %}" class="breadcrumb-item">Registration Invitations</a>
+    <span class="breadcrumb-item">New</span>
+{% endblock %}
+
+{% block content %}
+
+<div class="row">
+    <div class="col-12">
+        <h1 class="highlight">New Registration Invitation</h1>
+
+        {% if contributor_search_form %}
+            <h3 class="mb-1">Search for existing Contributor</h3>
+            <form method="get">
+                {{ contributor_search_form|bootstrap }}
+                <input type="submit" class="btn btn-primary" value="Search">
+                {% if contributor_search_form.is_bound %}
+                    <a href="{% url 'invitations:new' %}" class="ml-2 btn btn-link">Cancel search</a>
+                {% endif %}
+            </form>
+
+            <hr class="divider">
+            {% if contributor_search_form.is_bound %}
+                {% if suggested_invitations %}
+                    <h3>Registration Invitations found</h3>
+                    <ul class="mb-2">
+                        {% for inv in suggested_invitations %}
+                            <li><a href="{% url 'invitations:add_citation' inv.id %}">Use Registration Invitation for {{ inv.first_name }} {{ inv.last_name }}</a></li>
+                        {% endfor %}
+                    </ul>
+                {% endif %}
+
+                <h3>Citation Notification</h3>
+                <br>
+            {% else %}
+                <h3 class="mb-1">...or write a new Registration Invitation</h3>
+            {% endif %}
+
+        {% endif %}
+
+        {% if contributor_search_form.is_bound %}
+            <form method="post">
+                {% csrf_token %}
+                {{ citation_form|bootstrap }}
+                <button type="submit" class="btn btn-primary" name="save" value="save">Save</button>
+                <button type="submit" class="ml-2 btn btn-primary" name="save" value="save_and_create">Save and create new</button>
+                {% if perms.scipost.can_manage_registration_invitations %}
+                    <button type="submit" class="ml-2 btn btn-secondary" name="save" value="save_and_send">Save and send mail</button>
+                {% endif %}
+            </form>
+
+            <br>
+            <a href="{% url 'invitations:new' %}">Cancel search here</a> to write a new Registration Invitation.
+        {% else %}
+            <form method="post">
+                {% csrf_token %}
+                {{ invitation_form|bootstrap }}
+                <button type="submit" class="btn btn-primary" name="save" value="save">Save</button>
+                <button type="submit" class="ml-2 btn btn-primary" name="save" value="save_and_create">Save and create new</button>
+                {% if perms.scipost.can_manage_registration_invitations %}
+                    <button type="submit" class="ml-2 btn btn-secondary" name="save" value="save_and_send">Save and send mail</button>
+                {% endif %}
+            </form>
+        {% endif %}
+    </div>
+</div>
+
+{% endblock %}
+
+{% block footer_script %}
+    {{ block.super }}
+    {{ invitation_form.media }}
+{% endblock footer_script %}
diff --git a/invitations/templates/invitations/registrationinvitation_form_map_to_contributor.html b/invitations/templates/invitations/registrationinvitation_form_map_to_contributor.html
new file mode 100644
index 0000000000000000000000000000000000000000..46b8e5fa11019753e665d7c263a9d52b0ce52824
--- /dev/null
+++ b/invitations/templates/invitations/registrationinvitation_form_map_to_contributor.html
@@ -0,0 +1,38 @@
+{% extends 'scipost/_personal_page_base.html' %}
+
+{% block pagetitle %}: Map Registration Invitation{% endblock pagetitle %}
+
+{% load bootstrap %}
+
+{% block breadcrumb_items %}
+    {{block.super}}
+    <a href="{% url 'invitations:list' %}" class="breadcrumb-item">Registration Invitations</a>
+    <span class="breadcrumb-item">Map to Contributor</span>
+{% endblock %}
+
+{% block content %}
+
+<div class="row">
+    <div class="col-12">
+        <h1 class="highlight">Map Registration Invitation to Contributor</h1>
+        <h3>Registration Invitation</h3>
+        {% include 'partials/invitations/registrationinvitation_summary.html' with invitation=object %}
+    </div>
+</div>
+
+<div class="row">
+    <div class="col-12">
+        <form method="post">
+            {% csrf_token %}
+            {{ form|bootstrap }}
+            <h3>Map to Contributor</h3>
+            {{ form.get_contributor.get_title_display }} {{ form.get_contributor.user.first_name }} {{ form.get_contributor.user.last_name }}
+            <br>
+            <br>
+            <input type="submit" class="btn btn-primary" name="save" value="Map to Contributor">
+        </form>
+
+    </div>
+</div>
+
+{% endblock %}
diff --git a/invitations/templates/invitations/registrationinvitation_form_mark_as.html b/invitations/templates/invitations/registrationinvitation_form_mark_as.html
new file mode 100644
index 0000000000000000000000000000000000000000..e288ceadd2fa9298764caa9efba8bf38a90421bf
--- /dev/null
+++ b/invitations/templates/invitations/registrationinvitation_form_mark_as.html
@@ -0,0 +1,33 @@
+{% extends 'scipost/_personal_page_base.html' %}
+
+{% block pagetitle %}: Mark Registration Invitation {{ request.resolver_match.kwargs.label }}{% endblock pagetitle %}
+
+{% load bootstrap %}
+
+{% block breadcrumb_items %}
+    {{block.super}}
+    <a href="{% url 'invitations:list' %}" class="breadcrumb-item">Registration Invitations</a>
+    <span class="breadcrumb-item">Mark {{ request.resolver_match.kwargs.label }}</span>
+{% endblock %}
+
+{% block content %}
+
+<div class="row">
+    <div class="col-12">
+        <h1 class="highlight">Mark Registration Invitation {{ request.resolver_match.kwargs.label }}</h1>
+        {% include 'partials/invitations/registrationinvitation_summary.html' with invitation=object %}
+    </div>
+</div>
+
+<div class="row">
+    <div class="col-12">
+        <form method="post">
+            {% csrf_token %}
+            {{ form|bootstrap }}
+            <button type="submit" class="btn btn-primary" name="save" value="save">Mark {{ request.resolver_match.kwargs.label }}</button>
+        </form>
+
+    </div>
+</div>
+
+{% endblock %}
diff --git a/invitations/templates/invitations/registrationinvitation_list.html b/invitations/templates/invitations/registrationinvitation_list.html
index 1b4be34a68c04c09eb6c02705bdba37771099c03..9ef7afeeaa17c0fda2f5ba2d806ae1866e807c97 100644
--- a/invitations/templates/invitations/registrationinvitation_list.html
+++ b/invitations/templates/invitations/registrationinvitation_list.html
@@ -1,5 +1,7 @@
 {% extends 'scipost/_personal_page_base.html' %}
 
+{% load bootstrap %}
+
 {% block pagetitle %}: Registration Invitations{% endblock pagetitle %}
 
 {% block breadcrumb_items %}
@@ -12,35 +14,47 @@
 <h1 class="highlight">Registration Invitations</h1>
 
 <div class="row">
-    <div class="col-md-8">
+    <div class="col-md-6">
         <h3>Actions</h3>
         <ul class="mb-0">
-            {% if perms.scipost.can_manage_registration_invitations %}
-                <li><a href="{% url 'invitations:cleanup' %}">Perform a cleanup</a></li>
-                <li><a href="{% url 'invitations:list_pending_invitations' %}">Show pending invitations</a></li>
-            {% endif %}
             {% if perms.scipost.can_create_registration_invitations %}
                 <li><a href="{% url 'invitations:new' %}">Create a new invitation</a></li>
             {% endif %}
+            {% if perms.scipost.can_manage_registration_invitations %}
+                <li><a href="{% url 'invitations:cleanup' %}">Perform a cleanup</a></li>
+                <li><a href="{% url 'invitations:citation_notification_list' %}">List unprocessed Citation Notifications</a></li>
+            {% endif %}
         </ul>
     </div>
-    <div class="col-md-4 text-right">
+    <div class="col-md-6 text-md-right">
         <h3>Quick stats</h3>
         Number in draft: {{ count_in_draft }}<br>
         Number pending response: {{ count_pending }}
+
+        {% if perms.scipost.can_create_registration_invitations %}
+            <br><br>
+            <a href="{% url 'invitations:new' %}" class="btn btn-primary">Create a new invitation</a>
+        {% endif %}
     </div>
 </div>
 
 <div class="row">
     <div class="col-12">
-        <h2 class="highlight">Invitations in draft</h2>
-        {% if perms.scipost.can_manage_registration_invitations %}
-            <a href="{% url 'invitations:list_pending_invitations' %}">Show pending invitations</a>
-            <br>
-        {% endif %}
-
+        <h2 class="highlight">Registration Invitations</h2>
+    </div>
+    <div class="col-md-6">
+        <form method="get">
+            {{ search_form|bootstrap }}
+            <input class="btn btn-primary" type="submit" value="Filter">
+            <a href="{% url 'invitations:list' %}" class="btn btn-link">Reset filter</a>
+        </form>
+    </div>
+    <div class="col-12">
         <br>
         {% include 'partials/invitations/registrationinvitation_table.html' with invitations=object_list %}
+        {% if search_form.is_bound %}
+            <a href="{% url 'invitations:list' %}" class="btn btn-link">Reset filter</a>
+        {% endif %}
     </div>
 </div>
 
diff --git a/invitations/templates/invitations/registrationinvitation_pending_list.html b/invitations/templates/invitations/registrationinvitation_pending_list.html
deleted file mode 100644
index 62a73082373777afc5c31a0095cc5b2738c44a58..0000000000000000000000000000000000000000
--- a/invitations/templates/invitations/registrationinvitation_pending_list.html
+++ /dev/null
@@ -1,45 +0,0 @@
-{% extends 'scipost/_personal_page_base.html' %}
-
-{% block pagetitle %}: Registration Invitations{% endblock pagetitle %}
-
-{% block breadcrumb_items %}
-    {{ block.super }}
-    <a href="{% url 'invitations:list' %}" class="breadcrumb-item">Registration Invitations</a>
-    <span class="breadcrumb-item">Pending response</span>
-{% endblock %}
-
-{% block content %}
-
-<h1 class="highlight">Registration Invitations</h1>
-<div class="row">
-    <div class="col-md-8">
-        <h3>Actions</h3>
-        <ul class="mb-0">
-            {% if perms.scipost.can_manage_registration_invitations %}
-                <li><a href="{% url 'invitations:cleanup' %}">Perform a cleanup</a></li>
-                <li><a href="{% url 'invitations:list' %}">Show drafted invitations</a></li>
-            {% endif %}
-            {% if perms.scipost.can_create_registration_invitations %}
-                <li><a href="{% url 'invitations:new' %}">Create a new invitation</a></li>
-            {% endif %}
-        </ul>
-    </div>
-    <div class="col-md-4 text-right">
-        <h3>Quick stats</h3>
-        Number in draft: {{ count_in_draft }}<br>
-        Number pending response: {{ count_pending }}
-    </div>
-</div>
-
-<div class="row">
-    <div class="col-12">
-        <h2 class="highlight">Invitations pending response</h2>
-        <a href="{% url 'invitations:list' %}">Show drafted invitations</a>
-
-        <br>
-        <br>
-        {% include 'partials/invitations/registrationinvitation_table.html' with invitations=object_list %}
-    </div>
-</div>
-
-{% endblock %}
diff --git a/invitations/templates/invitations/registrationinvitation_reminder_form.html b/invitations/templates/invitations/registrationinvitation_reminder_form.html
index 57a876fcb250af8c7646a7375fc5e7f10688cb05..c328668dc3dc632039fbaa7ddca64a6cbb37920f 100644
--- a/invitations/templates/invitations/registrationinvitation_reminder_form.html
+++ b/invitations/templates/invitations/registrationinvitation_reminder_form.html
@@ -8,7 +8,6 @@
 {% block breadcrumb_items %}
     {{block.super}}
     <a href="{% url 'invitations:list' %}" class="breadcrumb-item">Registration Invitations</a>
-    <a href="{% url 'invitations:list_pending_invitations' %}" class="breadcrumb-item">Pending response</a>
     <span class="breadcrumb-item">Send reminder</span>
 {% endblock %}
 
@@ -17,6 +16,7 @@
 <div class="row">
     <div class="col-12">
         <h1 class="highlight">Send reminder for Registration Invitation</h1>
+        {% include 'partials/invitations/registrationinvitation_summary.html' with invitation=object %}
     </div>
 </div>
 
diff --git a/invitations/templates/partials/invitations/citationnotification_summary.html b/invitations/templates/partials/invitations/citationnotification_summary.html
new file mode 100644
index 0000000000000000000000000000000000000000..9bf9479b994638c448280a61a05ec630df415f37
--- /dev/null
+++ b/invitations/templates/partials/invitations/citationnotification_summary.html
@@ -0,0 +1,42 @@
+<table class="registration_invitation notification">
+    <tr>
+        <th>Name</th>
+        <td>
+            {% if notification.contributor %}
+                {{ notification.contributor.get_title_display }} {{ notification.contributor.user.first_name }} {{ notification.contributor.user.last_name }}
+            {% elif notification.invitation %}
+                {{ notification.invitation.first_name }} {{ notification.invitation.last_name }}
+            {% endif %}
+        </td>
+    </tr>
+    <tr>
+        <th>Email</th>
+        <td>
+            {% if notification.contributor %}
+                {{ notification.contributor.user.email }}
+            {% elif notification.invitation %}
+                {{ notification.invitation.email }}
+            {% endif %}
+        </td>
+    </tr>
+    <tr>
+        <th>Status</th>
+        <td>{{ notification.processed|yesno:'Processed,Not processed' }}</td>
+    </tr>
+    <tr>
+        <th>Submission</th>
+        <td>{{ notification.submission|default:'-' }}</td>
+    </tr>
+    <tr>
+        <th>Publication</th>
+        <td>{{ notification.publication|default:'-' }}</td>
+    </tr>
+    <tr>
+        <th>Created</th>
+        <td>{{ notification.created }} (by {{ notification.created_by.first_name }} {{ notification.created_by.last_name }})</td>
+    </tr>
+    <tr>
+        <th>Date Sent</th>
+        <td>{{ notification.date_sent|default:'<em>Not sent yet</em>' }}</td>
+    </tr>
+</table>
diff --git a/invitations/templates/partials/invitations/citationnotification_table.html b/invitations/templates/partials/invitations/citationnotification_table.html
new file mode 100644
index 0000000000000000000000000000000000000000..d2e3a598eef7dc5a6ca86d547bb66e0b90cc0e54
--- /dev/null
+++ b/invitations/templates/partials/invitations/citationnotification_table.html
@@ -0,0 +1,49 @@
+<table class="table">
+    <thead>
+        <tr>
+            <th>Name</th>
+            <th>Email</th>
+            <th>Type</th>
+            <th>Cited in</th>
+            <th>Created by</th>
+            <th>Date created</th>
+            <th>Actions</th>
+        </tr>
+    </thead>
+    <tbody>
+        {% for notification in notifications %}
+          <tr>
+              <td>
+                  {% if notification.contributor %}
+                      {{ notification.contributor.user.first_name }} {{ notification.contributor.user.last_name }}
+                  {% elif notification.invitation %}
+                      {{ notification.invitation.first_name }} {{ notification.invitation.last_name }}
+                  {% endif %}
+              </td>
+              <td>
+                  {% if notification.contributor %}
+                      {{ notification.contributor.user.email }}
+                  {% elif notification.invitation %}
+                      {{ notification.invitation.email }}
+                  {% endif %}
+              </td>
+              <td>
+                  {% if notification.contributor %}For Contributor{% elif notification.invitation %}Registration Invitation{% else %}<span class="text-danger">Invalid</span>{% endif %}
+              </td>
+              <td>
+                  {% if notification.publication %}
+                    {{ notification.publication.citation }}
+                  {% endif %}
+                  {% if notification.submission %}
+                    {{ notification.submission.arxiv_identifier_w_vn_nr }}
+                  {% endif %}
+              </td>
+            <td>{{ notification.created_by.first_name }} {{ notification.created_by.last_name }}</td>
+            <td>{{ notification.created }}</td>
+            <td>
+                <a href="{% url 'invitations:citation_notification_process' notification.id %}">Process citation</a>
+            </td>
+        </tr>
+        {% endfor %}
+    </tbody>
+</table>
diff --git a/invitations/templates/partials/invitations/registrationinvitation_summary.html b/invitations/templates/partials/invitations/registrationinvitation_summary.html
new file mode 100644
index 0000000000000000000000000000000000000000..4ff47a7f113268c1816d49986cccc5bf33fe0ac6
--- /dev/null
+++ b/invitations/templates/partials/invitations/registrationinvitation_summary.html
@@ -0,0 +1,53 @@
+<table class="registration_invitation">
+    <tr>
+        <th>Name</th>
+        <td>{{ invitation.get_title_display }} {{ invitation.first_name }} {{ invitation.last_name }}</td>
+    </tr>
+    <tr>
+        <th>Email</th>
+        <td>{{ invitation.email }}</td>
+    </tr>
+    <tr>
+        <th>Status</th>
+        <td>{{ invitation.get_status_display }}</td>
+    </tr>
+
+    <tr>
+        <th>Submission(s)</th>
+        <td>
+            <ul class="pl-3 mb-0">
+                {% for citation in invitation.citation_notifications.for_submissions %}
+                    <li>{{ citation.submission }}</li>
+                {% empty %}
+                    <li><em>No submissions linked</em></li>
+                {% endfor %}
+            </ul>
+        </td>
+    </tr>
+    <tr>
+        <th>Publication(s)</th>
+        <td>
+            <ul class="pl-3 mb-0">
+                {% for citation in invitation.citation_notifications.for_publications %}
+                    <li>{{ citation.publication }}</li>
+                {% empty %}
+                    <li><em>No publications linked</em></li>
+                {% endfor %}
+            </ul>
+        </td>
+    </tr>
+    <tr>
+        <th>Created</th>
+        <td>{{ invitation.created }}</td>
+    </tr>
+    <tr>
+        <th>Times sent</th>
+        <td><strong>{{ invitation.times_sent }}</strong> time{{ invitation.times_sent|pluralize }}{% if invitation.times_sent %} (last time: {{ invitation.date_sent_last }}){% endif %}</td>
+    </tr>
+</table>
+
+{% if invitation.personal_message %}
+    <br>
+    <strong>Personal Message</strong>
+    <p>{{ invitation.personal_message|linebreaksbr }}</p>
+{% endif %}
diff --git a/invitations/templates/partials/invitations/registrationinvitation_table.html b/invitations/templates/partials/invitations/registrationinvitation_table.html
index 020ce0e8103e7bf5b98c5f6c8d9f48730f647e4f..ad2056ab8cafdeb8c0be6fd1629f51c5f7be55b5 100644
--- a/invitations/templates/partials/invitations/registrationinvitation_table.html
+++ b/invitations/templates/partials/invitations/registrationinvitation_table.html
@@ -3,55 +3,68 @@
 <table class="table">
     <thead>
         <tr>
-            <th>Last name</th>
-            <th>First name</th>
+            <th>Name</th>
             <th>Email</th>
-            <th>Date</th>
+            <th>Status</th>
             <th>Type</th>
             <th>Drafted by</th>
-            <th{% if perms.scipost.can_manage_registration_invitations %} colspan="2"{% endif %}>Actions</th>
+            <th>Date created</th>
+            <th>Times sent</th>
+            <th colspan="2">Actions</th>
         </tr>
     </thead>
     <tbody>
         {% for invitation in invitations %}
           <tr>
-            <td>{{ invitation.last_name }}</td>
-            <td>{{ invitation.first_name }}</td>
+            <td>{{ invitation.last_name }}, {{ invitation.first_name }}</td>
             <td>{{ invitation.email }}</td>
+            <td>{{ invitation.get_status_display }}</td>
+            <td>{{ invitation.get_invitation_type_display }}</td>
+            <td>{{ invitation.created_by.first_name }} {{ invitation.created_by.last_name }}</td>
+            <td>{{ invitation.created }}</td>
             <td>
-                {% if invitation.status == 'draft' %}
-                    {{ invitation.modified }}
+                {% if invitation.times_sent %}
+                    <strong>{{ invitation.times_sent }}</strong> time{{ invitation.times_sent|pluralize }}
+                    &middot; {{ invitation.date_sent_last|timesince }} ago
                 {% else %}
-                    {{ invitation.date_sent_last }}
+                    -
                 {% endif %}
             </td>
-            <td>{{ invitation.get_invitation_type_display }}</td>
-            <td>{{ invitation.created_by.user.first_name }} {{ invitation.created_by.user.last_name }}</td>
             {% if perms.scipost.can_manage_registration_invitations %}
                 <td>
-                    {% if invitation.status == 'draft' %}
-                        <a href="{% url 'invitations:update' invitation.id %}">Edit or send</a> &middot;
-                        <a href="{% url 'scipost:mark_draft_inv_as_processed' draft_id=invitation.id %}">Mark as send</a>
-                    {% elif invitation.status == 'sent' %}
-                        <a href="{% url 'invitations:send_reminder' invitation.id %}">Send reminder</a>
-                    {% endif %}
+                    <ul class="pl-3 mb-0">
+                        {% if invitation.status == 'draft' %}
+                            <li><a href="{% url 'invitations:update' invitation.id %}">Edit or send</a></li>
+                            <li><a href="{% url 'invitations:mark' invitation.id 'sent' %}">Mark as sent</a></li>
+                        {% elif invitation.status == 'sent' or invitation.status == 'edited' %}
+                            <li><a href="{% url 'invitations:send_reminder' invitation.id %}">Send reminder</a></li>
+                        {% endif %}
+                    </ul>
+                </td>
+                <td>
+                    <ul class="mb-0">
+                        {% for ac in invitation|associated_contributors %}
+                            <li>
+                                <a href="{% url 'invitations:map_to_contributor' pk=invitation.id contributor_id=ac.id %}">Map to {{ ac.user.first_name }} {{ ac.user.last_name }}</a>
+                            </li>
+                        {% endfor %}
+                        <li><a href="{% url 'invitations:add_citation' invitation.id %}">Add new Citation to Invitation</a></li>
+                    </ul>
+                </td>
+            {% else %}
+                <td colspan="2">
+                    <ul class="pl-3 mb-0">
+                        <li><a href="{% url 'invitations:add_citation' invitation.id %}">Add new Citation to Invitation</a></li>
+                        {% if invitation.status == 'draft' and invitation.created_by == request.user %}
+                            <li><a href="{% url 'invitations:update' invitation.id %}">Edit Invitation</a></li>
+                        {% endif %}
+                    </ul>
                 </td>
             {% endif %}
-            <td>
-                <ul class="mb-0">
-                    {% for ac in invitation|associated_contributors %}
-                        <li>
-                            <a href="{% url 'scipost:map_draft_reg_inv_to_contributor' draft_id=invitation.id contributor_id=ac.id %}">Map to {{ ac.user.first_name }} {{ ac.user.last_name }}</a>
-                        </li>
-                    {% empty %}
-                        <li>No associated contributors found.</li>
-                    {% endfor %}
-                </ul>
-            </td>
           </tr>
         {% empty %}
             <tr>
-                <td colspan="8">No Invitations found.</td>
+                <td colspan="9">No Invitations found.</td>
             </tr>
         {% endfor %}
     </tbody>
diff --git a/invitations/urls.py b/invitations/urls.py
index ee3e5a35d588fa37e60939efb57b5501a7b93319..d53b7ea3ef19fb78c221549ca4d81d78fedc8f33 100644
--- a/invitations/urls.py
+++ b/invitations/urls.py
@@ -4,11 +4,23 @@ from . import views
 
 urlpatterns = [
     url(r'^$', views.RegistrationInvitationsView.as_view(), name='list'),
-    url(r'^pending_invitations$', views.PendingRegistrationInvitationsView.as_view(),
-        name='list_pending_invitations'),
-    url(r'^new$', views.RegistrationInvitationsCreateView.as_view(), name='new'),
+    url(r'^new$', views.create_registration_invitation_or_citation, name='new'),
     url(r'^(?P<pk>[0-9]+)$', views.RegistrationInvitationsUpdateView.as_view(), name='update'),
-    url(r'^(?P<pk>[0-9]+)/delete$', views.RegistrationInvitationsDeleteView.as_view(), name='delete'),
-    url(r'^(?P<pk>[0-9]+)/send_reminder$', views.RegistrationInvitationsReminderView.as_view(), name='send_reminder'),
+    url(r'^(?P<pk>[0-9]+)/add_citation$', views.RegistrationInvitationsAddCitationView.as_view(),
+        name='add_citation'),
+    url(r'^(?P<pk>[0-9]+)/delete$', views.RegistrationInvitationsDeleteView.as_view(),
+        name='delete'),
+    url(r'^(?P<pk>[0-9]+)/mark/(?P<label>sent)$', views.RegistrationInvitationsMarkView.as_view(),
+        name='mark'),
+    url(r'^(?P<pk>[0-9]+)/map_to_contributor/(?P<contributor_id>[0-9]+)$',
+        views.RegistrationInvitationsMapToContributorView.as_view(),
+        name='map_to_contributor'),
+    url(r'^(?P<pk>[0-9]+)/send_reminder$', views.RegistrationInvitationsReminderView.as_view(),
+        name='send_reminder'),
     url(r'^cleanup$', views.cleanup, name='cleanup'),
+
+    url(r'^citations$', views.CitationNotificationsView.as_view(),
+        name='citation_notification_list'),
+    url(r'^citations/(?P<pk>[0-9]+)$', views.CitationNotificationsProcessView.as_view(),
+        name='citation_notification_process'),
 ]
diff --git a/invitations/utils.py b/invitations/utils.py
new file mode 100644
index 0000000000000000000000000000000000000000..4ba915726de3348db196f64b66607aff45c18fc6
--- /dev/null
+++ b/invitations/utils.py
@@ -0,0 +1,31 @@
+from common.utils import BaseMailUtil
+
+
+class Utils(BaseMailUtil):
+    mail_sender = 'invitations@scipost.org'
+    mail_sender_title = 'SciPost Invitation'
+
+    @classmethod
+    def invite_contributor_email(cls):
+        """
+        Send email to unregistered people inviting them to become a SciPost Contributor.
+        Requires context to contain 'registration_invitation' (RegistrationInvitation instance).
+        """
+        raise NotImplementedError('invite_contributor_email')
+
+    @classmethod
+    def invite_contributor_reminder_email(cls):
+        """
+        Send reminder(!) email to unregistered people inviting them to become a SciPost
+        Contributor.
+        Requires context to contain 'registration_invitation'(RegistrationInvitation instance).
+        """
+        raise NotImplementedError('invite_contributor_reminder_email')
+
+    @classmethod
+    def citation_notifications_email(cls):
+        """
+        Send email to a SciPost Contributor about a Citation Notification that's been created
+        for him/her. Requires context to contain 'notifications' (list of CitationNotifications).
+        """
+        raise NotImplementedError('citation_notifications_email')
diff --git a/invitations/views.py b/invitations/views.py
index 7dfe2214f3e428c474ec00b8ddbbbf944c02f73b..024172cfc6c6edb9b8166f7804faf3f81d2d0582 100644
--- a/invitations/views.py
+++ b/invitations/views.py
@@ -1,25 +1,35 @@
+from django.contrib import messages
 from django.contrib.auth.decorators import login_required, permission_required
-from django.contrib.auth.mixins import LoginRequiredMixin, PermissionRequiredMixin
-from django.shortcuts import render
-from django.urls import reverse_lazy
+from django.db import transaction
+from django.shortcuts import render, redirect
+from django.urls import reverse_lazy, reverse
 from django.views.generic.list import ListView
-from django.views.generic.edit import CreateView, UpdateView, DeleteView
+from django.views.generic.edit import UpdateView, DeleteView
 
-from .forms import RegistrationInvitationForm, RegistrationInvitationReminderForm
-from .mixins import RegistrationInvitationFormMixin
-from .models import RegistrationInvitation
+from .forms import RegistrationInvitationForm, RegistrationInvitationReminderForm,\
+    RegistrationInvitationMarkForm, RegistrationInvitationMapToContributorForm,\
+    CitationNotificationForm, ContributorSearchForm, RegistrationInvitationFilterForm,\
+    CitationNotificationProcessForm, RegistrationInvitationAddCitationForm
+from .mixins import RequestArgumentMixin, PermissionsMixin, SaveAndSendFormMixin
+from .models import RegistrationInvitation, CitationNotification
 
 from scipost.models import Contributor
+from mails.mixins import MailEditorMixin
 
 
-class RegistrationInvitationsView(LoginRequiredMixin, PermissionRequiredMixin, ListView):
+class RegistrationInvitationsView(PermissionsMixin, ListView):
     permission_required = 'scipost.can_create_registration_invitations'
-    queryset = RegistrationInvitation.objects.drafts()
+    queryset = RegistrationInvitation.objects.no_response()
 
     def get_context_data(self, **kwargs):
         context = super().get_context_data(**kwargs)
         context['count_in_draft'] = RegistrationInvitation.objects.drafts().count()
-        context['count_pending'] = RegistrationInvitation.objects.pending_response().count()
+        context['count_pending'] = RegistrationInvitation.objects.sent().count()
+        search_form = RegistrationInvitationFilterForm(self.request.GET or None)
+        if search_form.is_valid():
+            context['object_list'] = search_form.search(context['object_list'])
+        context['object_list'] = context['object_list'].order_by('status', 'last_name')
+        context['search_form'] = search_form
         return context
 
     def get_queryset(self, *args, **kwargs):
@@ -29,23 +39,78 @@ class RegistrationInvitationsView(LoginRequiredMixin, PermissionRequiredMixin, L
         return qs
 
 
-class PendingRegistrationInvitationsView(RegistrationInvitationsView):
+class CitationNotificationsView(PermissionsMixin, ListView):
     permission_required = 'scipost.can_manage_registration_invitations'
-    queryset = RegistrationInvitation.objects.pending_response()
-    template_name = 'invitations/registrationinvitation_pending_list.html'
+    queryset = CitationNotification.objects.unprocessed().prefetch_related(
+        'invitation', 'contributor', 'contributor__user')
 
 
-class RegistrationInvitationsCreateView(RegistrationInvitationFormMixin, CreateView):
-    permission_required = 'scipost.can_create_registration_invitations'
-    form_class = RegistrationInvitationForm
-    model = RegistrationInvitation
-    success_url = reverse_lazy('invitations:list')
+class CitationNotificationsProcessView(PermissionsMixin, RequestArgumentMixin, UpdateView):
+    permission_required = 'scipost.can_manage_registration_invitations'
+    form_class = CitationNotificationProcessForm
+    queryset = CitationNotification.objects.unprocessed()
+    success_url = reverse_lazy('invitations:citation_notification_list')
+
+
+@login_required
+@permission_required('scipost.can_create_registration_invitations', raise_exception=True)
+@transaction.atomic
+def create_registration_invitation_or_citation(request):
+    """
+    Create a new Registration Invitation or Citation Notification, depending whether
+    it is meant for an already existing Contributor or not.
+    """
+    contributors = []
+    suggested_invitations = []
+    contributor_search_form = ContributorSearchForm(request.GET or None)
+    if contributor_search_form.is_valid():
+        contributors, suggested_invitations = contributor_search_form.search()
+    citation_form = CitationNotificationForm(request.POST or None, contributors=contributors,
+                                             prefix='notification', request=request)
+
+    # New citation is related to a Contributor: CitationNotification
+    if citation_form.is_valid():
+        citation_form.save()
+        messages.success(request, 'New Citation Notification created')
+        if request.POST.get('save') == 'save_and_create':
+            return redirect('invitations:new')
+        return redirect('invitations:list')
+
+    # New citation is related to a Contributor: RegistationInvitation
+    invitation_form = RegistrationInvitationForm(request.POST or None, request=request,
+                                                 prefix='invitation')
+    if invitation_form.is_valid():
+        invitation_form.save()
+        messages.success(request, 'New Registration Invitation created')
+        if request.POST.get('save') == 'save_and_create':
+            return redirect('invitations:new')
+        return redirect('invitations:list')
+
+    context = {
+        'contributor_search_form': contributor_search_form,
+        'citation_form': citation_form,
+        'suggested_invitations': suggested_invitations,
+        'invitation_form': invitation_form,
+    }
+    return render(request, 'invitations/registrationinvitation_form_add_new.html', context)
 
 
-class RegistrationInvitationsUpdateView(RegistrationInvitationFormMixin, UpdateView):
+class RegistrationInvitationsUpdateView(RequestArgumentMixin, PermissionsMixin,
+                                        SaveAndSendFormMixin, MailEditorMixin, UpdateView):
     permission_required = 'scipost.can_create_registration_invitations'
     form_class = RegistrationInvitationForm
-    success_url = reverse_lazy('invitations:list')
+    utils_email_method = 'invite_contributor_email'
+    mail_code = 'registration_invitation'
+
+    def get_context_data(self, **kwargs):
+        context = super().get_context_data(**kwargs)
+        context['invitation_form'] = context['form']
+        return context
+
+    def get_success_url(self):
+        if self.request.POST.get('save') == 'save_and_create':
+            return reverse('invitations:new')
+        return reverse('invitations:list')
 
     def get_queryset(self, *args, **kwargs):
         qs = RegistrationInvitation.objects.drafts()
@@ -56,14 +121,42 @@ class RegistrationInvitationsUpdateView(RegistrationInvitationFormMixin, UpdateV
         return qs
 
 
-class RegistrationInvitationsReminderView(RegistrationInvitationFormMixin, UpdateView):
+class RegistrationInvitationsAddCitationView(RequestArgumentMixin, PermissionsMixin, UpdateView):
+    permission_required = 'scipost.can_create_registration_invitations'
+    form_class = RegistrationInvitationAddCitationForm
+    template_name = 'invitations/registrationinvitation_form_add_citation.html'
+    success_url = reverse_lazy('invitations:list')
+    queryset = RegistrationInvitation.objects.no_response()
+
+
+class RegistrationInvitationsMarkView(RequestArgumentMixin, PermissionsMixin, UpdateView):
     permission_required = 'scipost.can_manage_registration_invitations'
-    queryset = RegistrationInvitation.objects.pending_response()
+    queryset = RegistrationInvitation.objects.drafts()
+    form_class = RegistrationInvitationMarkForm
+    template_name = 'invitations/registrationinvitation_form_mark_as.html'
+    success_url = reverse_lazy('invitations:list')
+
+
+class RegistrationInvitationsMapToContributorView(RequestArgumentMixin, PermissionsMixin,
+                                                  UpdateView):
+    permission_required = 'scipost.can_manage_registration_invitations'
+    model = RegistrationInvitation
+    form_class = RegistrationInvitationMapToContributorForm
+    template_name = 'invitations/registrationinvitation_form_map_to_contributor.html'
+    success_url = reverse_lazy('invitations:list')
+
+
+class RegistrationInvitationsReminderView(RequestArgumentMixin, PermissionsMixin,
+                                          SaveAndSendFormMixin, UpdateView):
+    permission_required = 'scipost.can_manage_registration_invitations'
+    queryset = RegistrationInvitation.objects.sent()
+    success_url = reverse_lazy('invitations:list')
     form_class = RegistrationInvitationReminderForm
     template_name = 'invitations/registrationinvitation_reminder_form.html'
+    utils_email_method = 'invite_contributor_reminder_email'
 
 
-class RegistrationInvitationsDeleteView(LoginRequiredMixin, PermissionRequiredMixin, DeleteView):
+class RegistrationInvitationsDeleteView(PermissionsMixin, DeleteView):
     permission_required = 'scipost.can_manage_registration_invitations'
     model = RegistrationInvitation
     success_url = reverse_lazy('invitations:list')
@@ -77,8 +170,7 @@ def cleanup(request):
     database of registered Contributors. Flags overlaps.
     """
     contributor_email_list = Contributor.objects.values_list('user__email', flat=True)
-    invitations = RegistrationInvitation.objects.pending_response().filter(
-        email__in=contributor_email_list)
+    invitations = RegistrationInvitation.objects.sent().filter(email__in=contributor_email_list)
     context = {
         'invitations': invitations
     }
diff --git a/mails/forms.py b/mails/forms.py
index a34a5107cde3ba26cc27d88356ae10ecdb478637..4eee0da3e10758195dc264f19773d766af3a9773 100644
--- a/mails/forms.py
+++ b/mails/forms.py
@@ -20,33 +20,40 @@ class EmailTemplateForm(forms.Form):
     extra_recipient = forms.EmailField(label="Optional: bcc this email to", required=False)
     prefix = 'mail_form'
 
-    def __init__(self, *args, **kwargs):
+    def __init__(self, data, *args, **kwargs):
         self.mail_code = kwargs.pop('mail_code')
         self.mail_fields = None
+        # This is a pseudo-modelform; it does not take `instance` by default
+        instance = kwargs.pop('instance', None)
+
+        # This form shouldn't be is_bound==True is there is any non-relavant POST data given.
+        if '%s-subject' % self.prefix in data.keys():
+            data = {
+                '%s-subject' % self.prefix: data.get('%s-subject' % self.prefix),
+                '%s-text' % self.prefix: data.get('%s-text' % self.prefix),
+                '%s-extra_recipient' % self.prefix: data.get('%s-extra_recipient' % self.prefix),
+            }
+        else:
+            data = None
+        super().__init__(data, *args, **kwargs)
+
+        # Gather meta data
+        json_location = '%s/mails/templates/mail_templates/%s.json' % (settings.BASE_DIR,
+                                                                       self.mail_code)
+        self.mail_data = json.loads(open(json_location).read())
 
-        data = {}
-        if args[0]:
-            if args[0].get('subject'):
-                data['subject'] = args[0]['subject']
-            if args[0].get('text'):
-                data['text'] = args[0]['text']
-            if args[0].get('extra_recipient'):
-                data['extra_recipient'] = args[0]['extra_recipient']
-        super().__init__(data or None)
-
-        # Gather data
+        # Digest the templates
         mail_template = loader.get_template('mail_templates/%s.html' % self.mail_code)
+        if instance and self.mail_data.get('context_object'):
+            kwargs[self.mail_data['context_object']] = instance
         mail_template = mail_template.render(kwargs)
         # self.doc = html.fromstring(mail_template)
         # self.doc2 = self.doc.text_content()
         # print(self.doc2)
 
-        json_location = '%s/mails/templates/mail_templates/%s.json' % (settings.BASE_DIR,
-                                                                       self.mail_code)
-        self.mail_data = json.loads(open(json_location).read())
-
         # Object
         self.object = kwargs.get(self.mail_data.get('context_object', ''), None)
+        self.object = self.object or instance
         self.recipient = None
         if self.object:
             recipient = self.object
@@ -141,6 +148,8 @@ class EmailTemplateForm(forms.Form):
             reply_to=[self.mail_data.get('from_address', 'no-reply@scipost.org')])
         email.attach_alternative(self.mail_fields['html_message'], 'text/html')
         email.send(fail_silently=False)
+        if self.object and hasattr(self.object, 'mail_sent'):
+            self.object.mail_sent()
 
 
 class HiddenDataForm(forms.Form):
diff --git a/mails/mixins.py b/mails/mixins.py
new file mode 100644
index 0000000000000000000000000000000000000000..4d07529c8b5fd0e5c2bf4f24a9b418b5b7a6f6f1
--- /dev/null
+++ b/mails/mixins.py
@@ -0,0 +1,75 @@
+from .forms import EmailTemplateForm, HiddenDataForm
+
+
+class MailEditorMixin:
+    """
+    Use MailEditorMixin in edit CBVs to automatically implement the mail editor as
+    a post-form_valid hook.
+
+    The view must specify the `mail_code` variable.
+    """
+    object = None
+    mail_form = None
+
+    def __init__(self, *args, **kwargs):
+        if not self.mail_code:
+            raise AttributeError(self.__class__.__name__ + ' object has no attribute `mail_code`')
+        super().__init__(*args, **kwargs)
+
+    def get_template_names(self):
+        """
+        The mail editor form has its own template.
+        """
+        if self.mail_form and not self.mail_form.is_valid():
+            return ['mails/mail_form.html']
+        return super().get_template_names()
+
+    def post(self, request, *args, **kwargs):
+        """
+        Handle POST requests, but interpect the data if the mail form data isn't valid.
+        """
+        self.object = self.get_object()
+        form = self.get_form()
+        if form.is_valid():
+            self.mail_form = EmailTemplateForm(request.POST or None,
+                                               mail_code=self.mail_code,
+                                               instance=self.object)
+            if self.mail_form.is_valid():
+                return self.form_valid(form)
+
+            return self.render_to_response(
+                self.get_context_data(form=self.mail_form,
+                                      transfer_data_form=HiddenDataForm(form)))
+        else:
+            return self.form_invalid(form)
+
+    def form_valid(self, form):
+        """
+        If both the regular form and mailing form are valid, save the form and run the mail form.
+        """
+        self.mail_form.send()
+        return super().form_valid(form)
+
+
+    # def __init__(self, request, mail_code, **kwargs):
+    #     self.request = request
+    #     self.context = kwargs.get('context', {})
+    #     self.template_name = kwargs.get('template', 'mails/mail_form.html')
+    #     self.mail_form = EmailTemplateForm(request.POST or None, mail_code=mail_code, **kwargs)
+    #
+    # @property
+    # def recipients_string(self):
+    #     return ', '.join(getattr(self.mail_form, 'mail_fields', {}).get('recipients', ['']))
+    #
+    # def add_form(self, form):
+    #     self.context['transfer_data_form'] = HiddenDataForm(form)
+    #
+    # def is_valid(self):
+    #     return self.mail_form.is_valid()
+    #
+    # def send(self):
+    #     return self.mail_form.send()
+    #
+    # def return_render(self):
+    #     self.context['form'] = self.mail_form
+    #     return render(self.request, self.template_name, self.context)
diff --git a/mails/templates/mail_templates/registration_invitation.html b/mails/templates/mail_templates/registration_invitation.html
index 0202042a577c7c213ca9280752a95e17febd011b..4990434fcb7ff6172e336db008f2343eddff1b26 100644
--- a/mails/templates/mail_templates/registration_invitation.html
+++ b/mails/templates/mail_templates/registration_invitation.html
@@ -1,11 +1,3 @@
-{% if renew %}
-    Reminder: Invitation to SciPost
-    -------------------------------
-
-    <strong>Reminder: Invitation to SciPost</strong>
-    <br/>
-{% endif %}
-
 {% if invitation.invitation_type == 'F' %}
     <strong>RE: Invitation to join the Editorial College of SciPost</strong>
     <br>
diff --git a/mails/templates/mail_templates/registration_invitation.json b/mails/templates/mail_templates/registration_invitation.json
index 9941b614623cf8f70ca83bcfbf4f934307d93b3f..639804acfbc0fb392c5675b52a7a53fb42106189 100644
--- a/mails/templates/mail_templates/registration_invitation.json
+++ b/mails/templates/mail_templates/registration_invitation.json
@@ -1,7 +1,7 @@
 {
     "subject": "SciPost: invitation",
     "to_address": "email",
-    "bcc_to": "invited_by.user.email",
+    "bcc_to": "jscaux@scipost.org",
     "from_address_name": "J-S Caux",
     "from_address": "jscaux@scipost.org",
     "context_object": "invitation"
diff --git a/mails/templates/mails/mail_form.html b/mails/templates/mails/mail_form.html
index 651e840fe09cc5808caf604e33a0788b35faa701..4b4f9dd316e2268e89e46af6bad12d20ea79ded3 100644
--- a/mails/templates/mails/mail_form.html
+++ b/mails/templates/mails/mail_form.html
@@ -9,8 +9,6 @@
     <h1>Complete and send mail</h1>
     <h3 class="mb-4">You may edit the mail before sending it.</h3>
 
-    {{ transfer_data }}
-
     <form enctype="multipart/form-data" method="post">
         {% csrf_token %}
         {% if transfer_data_form %}{{ transfer_data_form }}{% endif %}
diff --git a/scipost/migrations/0005_auto_20180218_1556.py b/scipost/migrations/0005_auto_20180218_1556.py
new file mode 100644
index 0000000000000000000000000000000000000000..5ac3f68be6966a91551ed637d0e0bd7f91bce982
--- /dev/null
+++ b/scipost/migrations/0005_auto_20180218_1556.py
@@ -0,0 +1,25 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.4 on 2018-02-18 14:56
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('scipost', '0004_auto_20180212_1932'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='registrationinvitation',
+            name='first_name',
+            field=models.CharField(max_length=30),
+        ),
+        migrations.AlterField(
+            model_name='registrationinvitation',
+            name='last_name',
+            field=models.CharField(max_length=30),
+        ),
+    ]
diff --git a/scipost/static/scipost/assets/css/_buttons.scss b/scipost/static/scipost/assets/css/_buttons.scss
index 6abdc7c02b81ac4c4a9c4d8ce9cc82c87f0ef977..7a7b57a4ec67b3e60f7432b80d8e0bebc8b3362d 100644
--- a/scipost/static/scipost/assets/css/_buttons.scss
+++ b/scipost/static/scipost/assets/css/_buttons.scss
@@ -12,6 +12,10 @@
     }
 }
 
+.btn-link {
+    color: $scipost-lightblue;
+}
+
 .btn-secondary {
     color: $scipost-darkblue;
     background-color: $white;
diff --git a/scipost/static/scipost/assets/css/_form.scss b/scipost/static/scipost/assets/css/_form.scss
index e0182d0420dcb8d74eccf2521dc7e72103560f7e..27a45b99ee238df2992b68646487ce2b4e30a9ec 100644
--- a/scipost/static/scipost/assets/css/_form.scss
+++ b/scipost/static/scipost/assets/css/_form.scss
@@ -117,3 +117,24 @@ select.form-control {
     height: auto;
   }
 }
+
+
+// Autocomplete fields
+.results_on_deck {
+    .help-block {
+        color: #666;
+        font-style: italic;
+    }
+
+    > div {
+        background-color: $scipost-lightestblue;
+        padding: 2px 10px;
+        display: inline-block;
+        border-radius: 5px;
+
+        .ui-icon {
+            margin-top: 0;
+            margin-right: 3px;
+        }
+    }
+}
diff --git a/scipost/static/scipost/assets/css/_tables.scss b/scipost/static/scipost/assets/css/_tables.scss
index 8873b93c394e15c1ef958f4509818a1f193e5c59..7c3d0fdc6c1d930fd04287fd8b90807a6e4410b8 100644
--- a/scipost/static/scipost/assets/css/_tables.scss
+++ b/scipost/static/scipost/assets/css/_tables.scss
@@ -12,6 +12,8 @@
 }
 
 table.commentary td,
+table.registration_invitation td,
+table.registration_invitation th,
 table.submission td {
     padding: 0.1em 0.7em;