SMTP and other email realted settings

This commit is contained in:
IGNY8 VPS (Salman)
2026-01-08 06:45:30 +00:00
parent 3651ee9ed4
commit d4ecddba22
7 changed files with 499 additions and 5 deletions

View File

@@ -27,6 +27,7 @@ class EmailSettingsAdmin(Igny8ModelAdmin):
list_display = [
'from_email',
'from_name',
'email_provider',
'reply_to_email',
'send_welcome_emails',
'send_billing_emails',
@@ -35,9 +36,26 @@ class EmailSettingsAdmin(Igny8ModelAdmin):
readonly_fields = ['updated_at']
fieldsets = (
('Email Provider', {
'fields': ('email_provider',),
'description': 'Select the active email service provider. Configure SMTP settings below if using SMTP.',
}),
('SMTP Configuration', {
'fields': (
'smtp_host',
'smtp_port',
'smtp_username',
'smtp_password',
'smtp_use_tls',
'smtp_use_ssl',
'smtp_timeout',
),
'description': 'SMTP server settings. Required when email_provider is set to SMTP.',
'classes': ('collapse',),
}),
('Sender Configuration', {
'fields': ('from_email', 'from_name', 'reply_to_email'),
'description': 'Default sender settings. Email address must be verified in Resend.',
'description': 'Default sender settings. Email address must be verified in Resend (if using Resend) or configured in SMTP server.',
}),
('Company Branding', {
'fields': ('company_name', 'company_address', 'logo_url'),
@@ -65,6 +83,114 @@ class EmailSettingsAdmin(Igny8ModelAdmin):
}),
)
change_form_template = 'admin/system/emailsettings/change_form.html'
def get_urls(self):
"""Add custom URL for test email"""
urls = super().get_urls()
custom_urls = [
path(
'test-email/',
self.admin_site.admin_view(self.test_email_view),
name='system_emailsettings_test_email'
),
path(
'send-test-email/',
self.admin_site.admin_view(self.send_test_email),
name='system_emailsettings_send_test'
),
]
return custom_urls + urls
def test_email_view(self, request):
"""Show test email form"""
settings = EmailSettings.get_settings()
context = {
**self.admin_site.each_context(request),
'title': 'Send Test Email',
'settings': settings,
'opts': self.model._meta,
'default_from_email': settings.from_email,
'default_to_email': request.user.email,
}
return render(request, 'admin/system/emailsettings/test_email.html', context)
def send_test_email(self, request):
"""Send test email to verify configuration"""
if request.method != 'POST':
return JsonResponse({'error': 'POST required'}, status=405)
from django.utils import timezone
from igny8_core.business.billing.services.email_service import EmailService
to_email = request.POST.get('to_email', request.user.email)
subject = request.POST.get('subject', 'IGNY8 Test Email')
# Create fresh EmailService instance to pick up latest settings
service = EmailService()
settings = EmailSettings.get_settings()
test_html = f"""
<html>
<body style="font-family: Arial, sans-serif; padding: 20px;">
<h1 style="color: #6366f1;">IGNY8 Email Test</h1>
<p>This is a test email to verify your email configuration.</p>
<h3>Configuration Details:</h3>
<ul>
<li><strong>Provider:</strong> {settings.email_provider.upper()}</li>
<li><strong>From:</strong> {settings.from_name} &lt;{settings.from_email}&gt;</li>
<li><strong>Reply-To:</strong> {settings.reply_to_email}</li>
<li><strong>Sent At:</strong> {timezone.now().strftime('%Y-%m-%d %H:%M:%S UTC')}</li>
</ul>
<p style="color: #22c55e; font-weight: bold;">
✓ If you received this email, your email configuration is working correctly!
</p>
<hr style="margin: 20px 0; border: none; border-top: 1px solid #e5e7eb;">
<p style="font-size: 12px; color: #6b7280;">
This is an automated test email from IGNY8 Admin.
</p>
</body>
</html>
"""
try:
result = service.send_transactional(
to=to_email,
subject=subject,
html=test_html,
tags=['test', 'admin-test'],
)
if result.get('success'):
# Log the test email
EmailLog.objects.create(
message_id=result.get('id', ''),
to_email=to_email,
from_email=settings.from_email,
subject=subject,
template_name='admin_test',
status='sent',
provider=result.get('provider', settings.email_provider),
tags=['test', 'admin-test'],
)
messages.success(
request,
f'Test email sent successfully to {to_email} via {result.get("provider", "unknown").upper()}!'
)
else:
messages.error(request, f'Failed to send: {result.get("error", "Unknown error")}')
except Exception as e:
messages.error(request, f'Error sending test email: {str(e)}')
return redirect(reverse('admin:system_emailsettings_changelist'))
def has_add_permission(self, request):
"""Only allow one instance (singleton)"""
return not EmailSettings.objects.exists()

View File

@@ -16,6 +16,52 @@ class EmailSettings(models.Model):
These settings work alongside IntegrationProvider (resend) configuration.
"""
EMAIL_PROVIDER_CHOICES = [
('resend', 'Resend'),
('smtp', 'SMTP'),
]
# Email provider selection
email_provider = models.CharField(
max_length=20,
choices=EMAIL_PROVIDER_CHOICES,
default='resend',
help_text='Active email service provider'
)
# SMTP Configuration
smtp_host = models.CharField(
max_length=255,
blank=True,
help_text='SMTP server hostname (e.g., smtp.gmail.com)'
)
smtp_port = models.IntegerField(
default=587,
help_text='SMTP server port (587 for TLS, 465 for SSL, 25 for plain)'
)
smtp_username = models.CharField(
max_length=255,
blank=True,
help_text='SMTP authentication username'
)
smtp_password = models.CharField(
max_length=255,
blank=True,
help_text='SMTP authentication password'
)
smtp_use_tls = models.BooleanField(
default=True,
help_text='Use TLS encryption (recommended for port 587)'
)
smtp_use_ssl = models.BooleanField(
default=False,
help_text='Use SSL encryption (for port 465)'
)
smtp_timeout = models.IntegerField(
default=30,
help_text='SMTP connection timeout in seconds'
)
# Default sender settings
from_email = models.EmailField(
default='noreply@igny8.com',

View File

@@ -0,0 +1,53 @@
# Generated by Django 5.2.10 on 2026-01-08 06:40
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('system', '0020_add_email_models'),
]
operations = [
migrations.AddField(
model_name='emailsettings',
name='email_provider',
field=models.CharField(choices=[('resend', 'Resend'), ('smtp', 'SMTP')], default='resend', help_text='Active email service provider', max_length=20),
),
migrations.AddField(
model_name='emailsettings',
name='smtp_host',
field=models.CharField(blank=True, help_text='SMTP server hostname (e.g., smtp.gmail.com)', max_length=255),
),
migrations.AddField(
model_name='emailsettings',
name='smtp_password',
field=models.CharField(blank=True, help_text='SMTP authentication password', max_length=255),
),
migrations.AddField(
model_name='emailsettings',
name='smtp_port',
field=models.IntegerField(default=587, help_text='SMTP server port (587 for TLS, 465 for SSL, 25 for plain)'),
),
migrations.AddField(
model_name='emailsettings',
name='smtp_timeout',
field=models.IntegerField(default=30, help_text='SMTP connection timeout in seconds'),
),
migrations.AddField(
model_name='emailsettings',
name='smtp_use_ssl',
field=models.BooleanField(default=False, help_text='Use SSL encryption (for port 465)'),
),
migrations.AddField(
model_name='emailsettings',
name='smtp_use_tls',
field=models.BooleanField(default=True, help_text='Use TLS encryption (recommended for port 587)'),
),
migrations.AddField(
model_name='emailsettings',
name='smtp_username',
field=models.CharField(blank=True, help_text='SMTP authentication username', max_length=255),
),
]