diff --git a/account_helper/admin.py b/account_helper/admin.py index 12de889..cbad20e 100644 --- a/account_helper/admin.py +++ b/account_helper/admin.py @@ -1,7 +1,5 @@ from django.contrib import admin -from .models import Realm, LdapGroupRDN, LdapUserRDN +from .models import Realm # Register your models here. admin.site.register(Realm) -admin.site.register(LdapGroupRDN) -admin.site.register(LdapUserRDN) diff --git a/account_helper/models.py b/account_helper/models.py index 45c3d80..19b906f 100644 --- a/account_helper/models.py +++ b/account_helper/models.py @@ -1,27 +1,13 @@ +from django.contrib.auth.models import Group from django.db import models -from django.contrib.auth.models import User, Group # Create your models here. class Realm(models.Model): name = models.CharField(max_length=200, unique=True) - email = models.EmailField(blank=True, null=True) + email = models.CharField(max_length=200) admin_group = models.ForeignKey(Group, models.PROTECT, blank=True, null=True) ldap_base_dn = models.CharField(max_length=400, unique=True) def __str__(self): return f'{self.name} - {self.ldap_base_dn}' - - -class LdapUserRDN(models.Model): - rdn = models.CharField(max_length=400, unique=True) - - def __str__(self): - return self.rdn - - -class LdapGroupRDN(models.Model): - rdn = models.CharField(max_length=400, unique=True) - - def __str__(self): - return self.rdn diff --git a/account_manager/forms.py b/account_manager/forms.py index 8f41573..d5519d8 100644 --- a/account_manager/forms.py +++ b/account_manager/forms.py @@ -1,4 +1,5 @@ from django import forms + from .models import LdapUser, LdapGroup @@ -29,7 +30,10 @@ class RealmUpdateForm(forms.Form): help_text='TODO', max_length=200) name = forms.CharField(label='Bereichsname', max_length=200) - email = forms.EmailField(label='E-Mail', required=False) admin_group = forms.ModelChoiceField(label='Admin Grouppe', help_text="Die Mitglieder dieser Gruppe darf den Bereich administieren", queryset=LdapGroup.objects.all()) + + +class EmailSettingsForm(forms.Form): + email = forms.EmailField(label='Eigene E-Mail Adresse') diff --git a/account_manager/main_views.py b/account_manager/main_views.py index c5c470d..beb4fd3 100644 --- a/account_manager/main_views.py +++ b/account_manager/main_views.py @@ -1,10 +1,15 @@ -from django.shortcuts import render, redirect -from .models import LdapGroup, LdapUser -from .forms import RealmAddForm, RealmUpdateForm -from account_helper.models import Realm -from django.contrib.auth.models import Group, User -from django.contrib.auth.decorators import login_required import re +from smtplib import SMTPAuthenticationError, SMTPConnectError, SMTPException +from socket import timeout + +from django.contrib.auth.decorators import login_required +from django.contrib.auth.models import Group, User +from django.shortcuts import render, redirect + +from account_helper.models import Realm +from account_manager.utils.mail_utils import realm_send_mail +from .forms import RealmAddForm, RealmUpdateForm, EmailSettingsForm +from .models import LdapGroup, LdapUser def is_realm_admin(view_func): @@ -62,15 +67,12 @@ def realm_update(request, realm_id): if request.user.is_superuser: realm_obj = Realm.objects.get(id=realm_id) data = {'id': realm_obj.id, 'ldap_base_dn': realm_obj.ldap_base_dn, 'name': realm_obj.name, - 'email': realm_obj.email, 'admin_group': realm_obj.admin_group} if request.method == 'POST': form = RealmUpdateForm(request.POST) if form.is_valid(): realm_obj.name = form.cleaned_data['name'] realm_obj.ldap_base_dn = form.cleaned_data['ldap_base_dn'] - realm_obj.email = form.cleaned_data['email'] - admin_ldap_group = form.cleaned_data['admin_group'] realm_obj.admin_group, _ = Group.objects.get_or_create(name=admin_ldap_group.name) realm_obj.save() @@ -107,3 +109,45 @@ def realm_delete(request, realm_id): def permission_denied(request): return render(request, 'permission_denied.jinja2', {}) + + +@login_required +@is_realm_admin +def realm_email_update(request, realm_id): + realm = Realm.objects.get(id=realm_id) + + if request.method == 'POST': + form = EmailSettingsForm(request.POST) + if form.is_valid(): + realm.email = form.cleaned_data['email'] + realm.save() + return redirect('realm-detail', realm.id) + else: + data = {} + if realm.email: + data = {'email': realm.email, } + form = EmailSettingsForm(initial=data) + return render(request, 'realm/realm_create_update_mail.jinja2', {'realm': realm, 'form': form}) + + +def realm_email_test(request, realm_id): + realm = Realm.objects.get(id=realm_id) + try: + realm_send_mail(realm, realm.email, f'{realm.name} Test Mail', + f'Du hast die Mail Konfiguration für {realm.name} erfolgreich abgeschlossen.') + except SMTPAuthenticationError as err: + return render(request, 'realm/realm_detailed.jinja2', + {'realm': realm, 'error': f'Mail konnte nicht versendet werden, Anmeldedaten inkorrekt.'}) + except SMTPConnectError as err: + return render(request, 'realm/realm_detailed.jinja2', + {'realm': realm, + 'error': f'Mail konnte nicht versendet werden. Verbindungsaufbau abgelehnt. Bitte überprüfen sie die Server Addresse und den Port'}) + except timeout as err: + return render(request, 'realm/realm_detailed.jinja2', + {'realm': realm, + 'error': f'Mail konnte nicht versendet werden. Zeitüberschreitung beim Verbindungsaufbau. Bitte überprüfen sie die Server Addresse und den Port'}) + except SMTPException: + return render(request, 'realm/realm_detailed.jinja2', + {'realm': realm, + 'error': f'Mail konnte nicht versendet werden. Bitte kontaktieren sie den Administrator'}) + return render(request, 'realm/realm_detailed.jinja2', {'realm': realm, 'notice': 'Test erfolgreich'}) diff --git a/account_manager/models.py b/account_manager/models.py index 72e82c1..7896be4 100644 --- a/account_manager/models.py +++ b/account_manager/models.py @@ -1,18 +1,17 @@ # Create your models here. -from ldapdb.models import fields as ldap_fields -from ldapdb.models.base import Model -from django.dispatch import receiver -from django.db.models.signals import post_save, pre_save +import re -from django.utils.encoding import force_bytes -from django.utils.http import urlsafe_base64_encode -from django.template.loader import render_to_string -from core.tokens import account_activation_token -from django.core.mail import EmailMessage from django.contrib.auth.models import User from django.contrib.auth.tokens import default_token_generator +from django.template.loader import render_to_string +from django.utils.encoding import force_bytes +from django.utils.http import urlsafe_base64_encode +from ldapdb.models import fields as ldap_fields +from ldapdb.models.base import Model + from core.settings import PASSWORD_RESET_TIMEOUT_DAYS -import re +from account_manager.utils.mail_utils import realm_send_mail +from multiprocessing import Process class LdapUser(Model): @@ -42,11 +41,9 @@ class LdapUser(Model): return self.full_name @staticmethod - def create_with_django_user_creation_and_welcome_mail(protocol, domain, username, email): - # current_site = get_current_site(request) + def create_with_django_user_creation_and_welcome_mail(realm, protocol, domain, username, email): ldap_user = LdapUser.objects.create(username=username, email=email, first_name=" ", last_name=" ") user, _ = User.objects.get_or_create(username=username, email=email) - # user.save() mail_subject = 'Activate your blog account.' message = render_to_string('registration/welcome_email.jinja2', { 'user': user, @@ -57,10 +54,9 @@ class LdapUser(Model): 'email': email, 'expiration_days': PASSWORD_RESET_TIMEOUT_DAYS }) - email = EmailMessage( - mail_subject, message, to=[user.email] - ) - email.send() + # TODO failure handling + p1 = Process(target=realm_send_mail, args=(realm, user.email, mail_subject, message)) + p1.start() return ldap_user @staticmethod diff --git a/account_manager/urls.py b/account_manager/urls.py index 1a38b92..2823391 100644 --- a/account_manager/urls.py +++ b/account_manager/urls.py @@ -1,4 +1,4 @@ -from django.urls import path, re_path +from django.urls import path import account_manager.views.group_views import account_manager.views.user_views @@ -10,6 +10,8 @@ urlpatterns = [ path('realm//', main_views.realm_detail, name='realm-detail'), path('realm//update/', main_views.realm_update, name='realm-update'), path('realm//delete/', main_views.realm_delete, name='realm-delete'), + path('realm//mail/', main_views.realm_email_update, name='realm-mail-add-update'), + path('realm//mail/test/', main_views.realm_email_test, name='realm-mail-test'), # Realm User path('realm//users/', account_manager.views.user_views.realm_user, name='realm-user-list'), diff --git a/account_manager/utils/__init__.py b/account_manager/utils/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/account_manager/utils/mail_utils.py b/account_manager/utils/mail_utils.py new file mode 100644 index 0000000..9c986e9 --- /dev/null +++ b/account_manager/utils/mail_utils.py @@ -0,0 +1,22 @@ +import logging + +from django.core.mail import get_connection, send_mail + +from core.settings import EMAIL_HOST, EMAIL_PORT, EMAIL_USE_SSL, EMAIL_USE_TLS + +logger = logging.getLogger(__name__) + + +def realm_send_mail(realm, to, subject, message): + logger.info('send mail') + connection = get_connection(host=EMAIL_HOST, + port=EMAIL_PORT, + username=realm.email, + use_ssl=EMAIL_USE_SSL, + use_tls=EMAIL_USE_TLS) + send_mail(subject=subject, + message=message, + from_email=realm.email, + recipient_list=[to, ], + connection=connection) + logger.info('mail sent') diff --git a/account_manager/views/user_views.py b/account_manager/views/user_views.py index b55ef47..5ef0bae 100644 --- a/account_manager/views/user_views.py +++ b/account_manager/views/user_views.py @@ -52,8 +52,11 @@ def user_add(request, realm_id): if request.is_secure(): protocol = 'https' LdapUser.base_dn = f'ou=people,{realm_obj.ldap_base_dn}' - LdapUser.create_with_django_user_creation_and_welcome_mail(protocol=protocol, domain=current_site.domain, - username=username, email=email) + LdapUser.create_with_django_user_creation_and_welcome_mail(realm=realm_obj, + protocol=protocol, + domain=current_site.domain, + username=username, + email=email) return redirect('realm-user-list', realm_id) # if a GET (or any other method) we'll create a blank form diff --git a/core/settings.py b/core/settings.py index 92dc1a6..edc0bea 100644 --- a/core/settings.py +++ b/core/settings.py @@ -173,10 +173,54 @@ AUTH_PROFILE_MODULE = 'account_manager.UserProfile' ######################################################################################################################## # EMAIL Config # ######################################################################################################################## -EMAIL_BACKEND = 'django.core.mail.backends.filebased.EmailBackend' -EMAIL_FILE_PATH = os.path.join(BASE_DIR, "sent_emails") -# EMAIL_HOST = 'smtp.gmail.com' -# EMAIL_PORT = 587 -# EMAIL_HOST_USER = 'info.mgserver3@gmail.com' -# EMAIL_HOST_PASSWORD = 'HaUTQh;tw6Z3"gZNK.UY' -# EMAIL_USE_TLS = True +# EMAIL_BACKEND = 'django.core.mail.backends.filebased.EmailBackend' +# EMAIL_FILE_PATH = os.path.join(BASE_DIR, "sent_emails") +EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' +EMAIL_TIMEOUT = 15 +EMAIL_HOST = 'smtp.uni-bamberg.de' +EMAIL_PORT = 587 +EMAIL_USE_TLS = False +EMAIL_USE_SSL = False + +######################################################################################################################## +# Logging Config # +######################################################################################################################## +LOGGING = { + 'version': 1, + 'disable_existing_loggers': False, + 'formatters': { + 'default': { + 'format': '%(asctime)s %(module)s [%(levelname)s]: %(message)s', + 'datefmt': '%Y-%m-%d %H:%M:%S', + } + }, + 'handlers': { + 'console': { + 'class': 'logging.StreamHandler', + 'formatter': 'default', + }, + 'file': { + 'class': 'logging.FileHandler', + 'filename': './logs/import_food.log', + 'formatter': 'default', + }, + 'mail_admins': { + 'level': 'ERROR', + 'class': 'django.utils.log.AdminEmailHandler', + }, + 'mail_admins_image_upload': { + 'level': 'INFO', + 'class': 'django.utils.log.AdminEmailHandler', + }, + }, + 'loggers': { + 'account_manager': { + 'handlers': ['console', 'file'], + 'level': 'INFO', + }, + 'account_helper': { + 'handlers': ['console', 'file'], + 'level': 'INFO', + }, + }, +} diff --git a/templates/realm/realm_create_update_mail.jinja2 b/templates/realm/realm_create_update_mail.jinja2 new file mode 100644 index 0000000..be207a4 --- /dev/null +++ b/templates/realm/realm_create_update_mail.jinja2 @@ -0,0 +1,11 @@ +{% extends 'realm/realm_detailed.jinja2' %} +{% block realm_form %} +

Email Account erstellen oder updaten

+ {% if form %} +
+ + {{ form.as_p()|safe }} + +
+ {% endif %} +{% endblock %} \ No newline at end of file diff --git a/templates/realm/realm_detailed.jinja2 b/templates/realm/realm_detailed.jinja2 index 6dbacd1..5527f51 100644 --- a/templates/realm/realm_detailed.jinja2 +++ b/templates/realm/realm_detailed.jinja2 @@ -2,15 +2,31 @@ {% block content %} Zurück zur Realmübersicht

Bereich {{ realm.name }}

+ {% if notice %} +

{{ notice }}

+ {% endif %} + {% if error %} +

{{ error }}

+ {% endif %}

Bereich Info

LDAP OU: {{ realm.ldap_base_dn }}

-

Email: {{ realm.email }}

+ {% if realm.email %} +

Email: {{ realm.email }}

+ {% else %} +

Noch ausstehend

+ {% endif %}

Admin Gruppe: {{ realm.admin_group }}

{% if request.user.is_superuser %} {% block realm_form %}

Bereichsinformationen anpassen

{% endblock %} {% endif %} +

+ E-Mail Einstellungen | + {% if realm.email %} + Test Mail + {% endif %} +

Nutzer hinzufügen

{% block user_content %} diff --git a/templates/registration/welcome_email.jinja2 b/templates/registration/welcome_email.jinja2 index ac866a1..5c07fd5 100644 --- a/templates/registration/welcome_email.jinja2 +++ b/templates/registration/welcome_email.jinja2 @@ -6,4 +6,5 @@

Über den folgenden Link kannst du deinen Account aktivieren: {{ protocol }}://{{ domain }}{{ url('ldap_password_reset_confirm', kwargs={'uidb64':uid, 'token':token}) }}

Der Link ist nur {{ expiration_days }} Tage gültig!

+

Und so erreichst du deinen Account: {{ protocol }}://{{ domain }}{{ url('login') }}