diff --git a/api/views.py b/api/views.py
index 0a4bd72..b382cf0 100644
--- a/api/views.py
+++ b/api/views.py
@@ -18,7 +18,8 @@ from django.views.decorators.http import require_http_methods
from user_manager.models import UserAcl, AuthenticationToken
from vpn_invite.models import InviteSettings, PeerInvite
-from wgwadmlibrary.tools import user_allowed_peers, user_has_access_to_peer, get_peer_invite_data, create_peer_invite
+from wgwadmlibrary.tools import user_allowed_peers, user_has_access_to_peer, get_peer_invite_data, create_peer_invite, \
+ send_email
from wireguard.models import WebadminSettings, Peer, PeerStatus, WireGuardInstance
@@ -334,9 +335,11 @@ def api_peer_invite(request):
data['invite_data'] = get_peer_invite_data(peer_invite, invite_settings)
if request.GET.get('action') == 'email':
- data['status'] = 'success'
- data['message'] = 'Email sent'
- return JsonResponse(data)
+ data['status'], data['message'] = send_email(request.GET.get('address'), data['invite_data']['email_subject'], data['invite_data']['email_body'])
+ if data['status'] == 'success':
+ return JsonResponse(data)
+ else:
+ return JsonResponse(data, status=400)
else:
if request.GET.get('action') == 'email':
data['status'] = 'error'
diff --git a/templates/wireguard/wireguard_peer_list.html b/templates/wireguard/wireguard_peer_list.html
index a5c0097..cba7607 100644
--- a/templates/wireguard/wireguard_peer_list.html
+++ b/templates/wireguard/wireguard_peer_list.html
@@ -653,11 +653,18 @@
$("#invitePassword").html("Access Password: " + inviteData.password + " (Share this password via a separate secure channel)");
$("#inviteExpiration").text(new Date(inviteData.expiration).toLocaleString());
} else {
- $("#inviteMessage").html("
" + response.message + "
");
+ $("#inviteMessage").html("" + (response.message || "Unknown error") + "
");
}
},
error: function(xhr, status, error) {
- $("#inviteMessage").html("Error creating invite: " + error + "
");
+ var message = "Error creating invite.";
+ try {
+ var resp = xhr.responseJSON;
+ message = resp && resp.message ? resp.message : xhr.statusText;
+ } catch(err) {
+ message = xhr.statusText;
+ }
+ $("#inviteMessage").html("" + message + "
");
}
});
});
@@ -718,7 +725,7 @@
});
// Handler for sending invite via Email
- $("#sendInviteEmailButton").on("click", function(e) {
+ $("#sendInviteEmailButton").on("click", function(e, textStatus, xhr) {
e.preventDefault();
var contact = $("#inviteContactInput").val().trim();
if(!isValidEmail(contact)) {
@@ -732,15 +739,30 @@
data: { invite: inviteData.uuid, action: 'email', address: contact },
type: 'GET',
dataType: 'json',
- success: function(response) {
+ success: function(response, textStatus, xhr) {
+ var message = response.message;
+ if (!message) {
+ message = xhr.statusText;
+ }
if(response.status === "success") {
- $("#inviteMessage").html("Email sent successfully.
");
+ $("#inviteMessage").html("" + message + "
");
} else {
- $("#inviteMessage").html("" + response.message + "
");
+ $("#inviteMessage").html("" + message + "
");
}
},
error: function(xhr, status, error) {
- $("#inviteMessage").html("Error sending email: " + error + "
");
+ var message = "Error sending email.";
+ try {
+ var resp = xhr.responseJSON;
+ if (resp && resp.message) {
+ message = resp.message;
+ } else {
+ message = xhr.statusText;
+ }
+ } catch(err) {
+ message = xhr.statusText;
+ }
+ $("#inviteMessage").html("" + message + "
");
}
});
} else {
@@ -764,13 +786,24 @@
$("#inviteText").text(inviteData.text_body);
$("#invitePassword").html("Access Password: " + inviteData.password + " (Share this password via a separate secure channel)");
$("#inviteExpiration").text(new Date(inviteData.expiration).toLocaleString());
- $("#inviteMessage").html("Invite refreshed successfully.
");
+ $("#inviteMessage").html("" + (response.message || xhr.statusText) + "
");
} else {
- $("#inviteMessage").html("" + response.message + "
");
+ $("#inviteMessage").html("" + (response.message || "Error refreshing invite.") + "
");
}
},
error: function(xhr, status, error) {
- $("#inviteMessage").html("Error refreshing invite: " + error + "
");
+ var message = "Error refreshing invite.";
+ try {
+ var resp = xhr.responseJSON;
+ if (resp && resp.message) {
+ message = resp.message;
+ } else {
+ message = xhr.statusText;
+ }
+ } catch(err) {
+ message = xhr.statusText;
+ }
+ $("#inviteMessage").html("" + message + "
");
}
});
} else {
diff --git a/wgwadmlibrary/tools.py b/wgwadmlibrary/tools.py
index 24ebf1c..c8146b4 100644
--- a/wgwadmlibrary/tools.py
+++ b/wgwadmlibrary/tools.py
@@ -1,15 +1,20 @@
import ipaddress
import random
import re
+import smtplib
import subprocess
from datetime import timedelta
+from email.mime.text import MIMEText
+from django.core.exceptions import ValidationError
+from django.core.validators import validate_email
from django.db.models import Max
from django.utils import timezone
from user_manager.models import UserAcl
from vpn_invite.models import PeerInvite, InviteSettings
from wireguard.models import Peer, WireGuardInstance
+from wireguard_tools.models import EmailSettings
def user_has_access_to_instance(user_acl: UserAcl, instance: WireGuardInstance):
@@ -169,3 +174,42 @@ def create_peer_invite(peer: Peer, invite_settings: InviteSettings):
peer=peer, invite_password=password[:32], invite_expiration=timezone.now() + timedelta(minutes=invite_settings.invite_expiration)
)
return peer_invite
+
+
+def send_email(destination, subject, body):
+ success = 'error'
+ message = ''
+ try:
+ validate_email(destination)
+ except ValidationError:
+ return 'error', 'Invalid email address.'
+
+ email_settings = EmailSettings.objects.filter(name='email_settings', enabled=True).first()
+ if not email_settings:
+ message = 'Email settings not configured.'
+ return success, message
+
+ try:
+ msg = MIMEText(body, 'plain')
+ msg['Subject'] = subject
+ msg['From'] = email_settings.smtp_from_address
+ msg['To'] = destination
+
+ if email_settings.smtp_encryption.lower() == 'ssl':
+ server = smtplib.SMTP_SSL(email_settings.smtp_host, email_settings.smtp_port)
+ else:
+ server = smtplib.SMTP(email_settings.smtp_host, email_settings.smtp_port)
+ server.starttls()
+
+ if email_settings.smtp_username and email_settings.smtp_password:
+ server.login(email_settings.smtp_username, email_settings.smtp_password)
+
+ server.sendmail(email_settings.smtp_from_address, destination, msg.as_string())
+ server.quit()
+ success = 'success'
+ message = 'Email sent successfully.'
+ except Exception as e:
+ success = 'error'
+ message = f'Error sending email: {str(e)}'
+
+ return success, message