diff --git a/src/plainui/forms.py b/src/plainui/forms.py
index 4a391b34aa214908fa1dc405efcac6b62d0dbf4d..a8b8013b43d27a0b47abf604543c59513b2006d4 100644
--- a/src/plainui/forms.py
+++ b/src/plainui/forms.py
@@ -253,5 +253,6 @@ class ReportForm(forms.Form):
             message=body,
         )
 
+
 class EditMailForm(forms.Form):
     email = forms.EmailField()
diff --git a/src/plainui/jinja2/plainui/profile.html b/src/plainui/jinja2/plainui/profile.html
index c8337f6fdc9c7dccfe5804f7b9a9e6099fbe4f2d..cbb264dec6f3840a65cac36c98f679944947faf8 100644
--- a/src/plainui/jinja2/plainui/profile.html
+++ b/src/plainui/jinja2/plainui/profile.html
@@ -22,10 +22,10 @@
             <dt>{{ _("email") }}</dt>
             <dd>
                 <div>
-                <form class="form-inline">
+                <form class="form-inline" method="POST" action="{{ url('plainui:userprofile-edit-mail', conf_slug=conf.slug) }}">
                     {{ csrf_input }}
                     <label class="sr-only" for="emailInput">eMail</label>
-                    <input class="form-control mb-2 mr-sm-2" id="emailInput" placeholder="mail@some.where" type="email" name="email" value="{{ user.communication_channels.filter(channel='mail', is_verified=True).first().address or "" }}">
+                    <input class="form-control mb-2 mr-sm-2" id="emailInput" placeholder="(optional)" type="email" name="email" value="{{ user.communication_channels.filter(channel='mail', is_verified=True).first().address or "" }}">
                     <button type="submit" class="btn btn-primary mb-2">{{ _("save") }}</button>
                 </form>
                 </div>
diff --git a/src/plainui/urls.py b/src/plainui/urls.py
index d496fe3fe090d9e8a9e0369ae62bd11a614ebb50..cadde64b50bfcb694845895cc90c305c488b9aa1 100644
--- a/src/plainui/urls.py
+++ b/src/plainui/urls.py
@@ -16,6 +16,7 @@ urlpatterns = [
     path('<slug:conf_slug>/reset/done/', views.PasswordResetCompleteView.as_view(), name='password_reset_complete'),
     path('<slug:conf_slug>/logout', views.LogoutView.as_view(), name='logout'),
     path('<slug:conf_slug>/me', views.ProfileView.as_view(), name='userprofile'),
+    path('<slug:conf_slug>/me/mail/update', views.EditMailView.as_view(), name='userprofile-edit-mail'),
     path('<slug:conf_slug>/redeem_token', views.RedeemTokenView.as_view(), name='redeem_token'),
     path('<slug:conf_slug>/redeem_token_add', views.RedeemTokenAddToUserView.as_view(), name='redeem_token_add_to_user'),
     path('<slug:conf_slug>/redeem_token_create', views.RedeemTokenUserCreateView.as_view(), name='redeem_token_create_user'),
diff --git a/src/plainui/views.py b/src/plainui/views.py
index 121d34925f4650a45a77078ffa0d45012b2bdb63..566ad2ae02206091269d47eb023f18c1c7ab4926 100644
--- a/src/plainui/views.py
+++ b/src/plainui/views.py
@@ -24,7 +24,8 @@ from django.views.generic.edit import FormView, UpdateView
 from core import integrations
 from core.forms import PasswordResetForm
 from core.models import Assembly, AssemblyLikeCount, Badge, Conference, ConferenceMember, ConferenceMemberTicket, ConferenceTag, \
-        ConferenceTrack, DirectMessage, Event, EventAttachment, EventLikeCount, EventParticipant, PlatformUser, Room, RoomLink, StaticPage, TagItem, UserBadge
+        ConferenceTrack, DirectMessage, Event, EventAttachment, EventLikeCount, EventParticipant, PlatformUser, Room, RoomLink, \
+        StaticPage, TagItem, UserBadge, UserCommunicationChannel
 from core.models.ticket import TicketValidationError
 from core.search import search
 from core.utils import render_markdown
@@ -405,6 +406,40 @@ class ProfileView(ConferenceRequiredMixin, UpdateView):
         return resp
 
 
+class EditMailView(ConferenceRequiredMixin, FormView):
+    form_class = EditMailForm
+    template_name = 'plainui/profile.html'
+
+    require_login = True
+    require_conference_member = True
+
+    def get(self, request, *args, **kwargs):
+        return redirect(reverse('plainui:redeem_token', kwargs={'conf_slug': self.conf.slug}))
+
+    def get_context_data(self, *args, **kwargs):
+        context = super().get_context_data(**kwargs)
+        context['conf'] = self.conf
+        context['hide_header'] = True
+        return context
+
+    def form_valid(self, form: EditMailForm):
+        # We don't verify mails (yet)
+        # TODO: error handling
+        #       verification
+        mail_channel, created = UserCommunicationChannel.objects.update_or_create(
+            channel = UserCommunicationChannel.Channel.MAIL,
+            is_verified = True,
+            user = self.request.user
+        )
+        mail_channel.address = form.cleaned_data['email']
+        mail_channel.save()
+        messages.success(self.request, gettext("eMail changed."))
+        return redirect(reverse('plainui:userprofile', kwargs={'conf_slug': self.conf.slug}))
+
+    def get_success_url(self):
+        return redirect(reverse('plainui:userprofile', kwargs={'conf_slug': self.conf.slug}))
+
+
 class RedeemTokenView(ConferenceRequiredMixin, TemplateView):
     template_name = 'plainui/redeem_token.html'
     require_login = False