2014-09-29 14:45:51 +00:00
|
|
|
import copy
|
2015-04-03 10:14:45 +00:00
|
|
|
from urllib.parse import parse_qs
|
2014-09-29 14:45:51 +00:00
|
|
|
|
2014-08-22 15:31:44 +00:00
|
|
|
from django import forms
|
2015-10-07 11:44:30 +00:00
|
|
|
from django.contrib import admin, messages
|
|
|
|
from django.core.urlresolvers import reverse
|
2015-04-24 11:39:20 +00:00
|
|
|
from django.db.models import F, Value as V
|
|
|
|
from django.db.models.functions import Concat
|
2015-10-07 11:44:30 +00:00
|
|
|
from django.utils.safestring import mark_safe
|
2014-08-22 15:31:44 +00:00
|
|
|
from django.utils.translation import ugettext_lazy as _
|
|
|
|
|
2014-10-06 14:57:02 +00:00
|
|
|
from orchestra.admin import ExtendedModelAdmin, ChangePasswordAdminMixin
|
2015-05-09 17:08:45 +00:00
|
|
|
from orchestra.admin.actions import disable
|
2014-09-26 15:05:20 +00:00
|
|
|
from orchestra.admin.utils import admin_link, change_url
|
2015-07-21 10:44:32 +00:00
|
|
|
from orchestra.contrib.accounts.actions import list_accounts
|
2015-04-05 10:46:24 +00:00
|
|
|
from orchestra.contrib.accounts.admin import SelectAccountAdminMixin
|
|
|
|
from orchestra.contrib.accounts.filters import IsActiveListFilter
|
2014-08-22 15:31:44 +00:00
|
|
|
|
2014-11-27 19:17:26 +00:00
|
|
|
from . import settings
|
2015-05-05 19:42:55 +00:00
|
|
|
from .actions import SendMailboxEmail, SendAddressEmail
|
2014-08-22 15:31:44 +00:00
|
|
|
from .filters import HasMailboxListFilter, HasForwardListFilter, HasAddressListFilter
|
2014-10-09 17:04:12 +00:00
|
|
|
from .forms import MailboxCreationForm, MailboxChangeForm, AddressForm
|
2014-08-22 15:31:44 +00:00
|
|
|
from .models import Mailbox, Address, Autoresponse
|
2015-04-28 16:07:16 +00:00
|
|
|
from .widgets import OpenCustomFilteringOnSelect
|
2014-08-22 15:31:44 +00:00
|
|
|
|
|
|
|
|
|
|
|
class AutoresponseInline(admin.StackedInline):
|
|
|
|
model = Autoresponse
|
|
|
|
verbose_name_plural = _("autoresponse")
|
|
|
|
|
|
|
|
def formfield_for_dbfield(self, db_field, **kwargs):
|
|
|
|
if db_field.name == 'subject':
|
|
|
|
kwargs['widget'] = forms.TextInput(attrs={'size':'118'})
|
|
|
|
return super(AutoresponseInline, self).formfield_for_dbfield(db_field, **kwargs)
|
|
|
|
|
|
|
|
|
2014-10-21 15:29:36 +00:00
|
|
|
class MailboxAdmin(ChangePasswordAdminMixin, SelectAccountAdminMixin, ExtendedModelAdmin):
|
2014-08-22 15:31:44 +00:00
|
|
|
list_display = (
|
2015-04-29 21:35:56 +00:00
|
|
|
'name', 'account_link', 'display_filtering', 'display_addresses', 'display_active',
|
2014-08-22 15:31:44 +00:00
|
|
|
)
|
2015-03-26 16:00:30 +00:00
|
|
|
list_filter = (IsActiveListFilter, HasAddressListFilter, 'filtering')
|
2015-06-22 14:14:16 +00:00
|
|
|
search_fields = (
|
|
|
|
'account__username', 'account__short_name', 'account__full_name', 'name',
|
|
|
|
'addresses__name', 'addresses__domain__name',
|
|
|
|
)
|
2014-08-22 15:31:44 +00:00
|
|
|
add_fieldsets = (
|
|
|
|
(None, {
|
2014-10-21 15:29:36 +00:00
|
|
|
'fields': ('account_link', 'name', 'password1', 'password2', 'filtering'),
|
2014-08-22 15:31:44 +00:00
|
|
|
}),
|
2014-10-09 17:04:12 +00:00
|
|
|
(_("Custom filtering"), {
|
2014-09-29 14:45:51 +00:00
|
|
|
'classes': ('collapse',),
|
|
|
|
'fields': ('custom_filtering',),
|
2014-08-22 15:31:44 +00:00
|
|
|
}),
|
2014-10-21 15:29:36 +00:00
|
|
|
(_("Addresses"), {
|
|
|
|
'fields': ('addresses',)
|
|
|
|
}),
|
2014-08-22 15:31:44 +00:00
|
|
|
)
|
|
|
|
fieldsets = (
|
|
|
|
(None, {
|
2014-10-09 17:04:12 +00:00
|
|
|
'fields': ('name', 'password', 'is_active', 'account_link', 'filtering'),
|
2014-08-22 15:31:44 +00:00
|
|
|
}),
|
2014-10-09 17:04:12 +00:00
|
|
|
(_("Custom filtering"), {
|
2014-09-29 14:45:51 +00:00
|
|
|
'classes': ('collapse',),
|
|
|
|
'fields': ('custom_filtering',),
|
2014-08-22 15:31:44 +00:00
|
|
|
}),
|
|
|
|
(_("Addresses"), {
|
2014-10-21 15:29:36 +00:00
|
|
|
'fields': ('addresses',)
|
2014-08-22 15:31:44 +00:00
|
|
|
}),
|
|
|
|
)
|
2014-10-21 15:29:36 +00:00
|
|
|
readonly_fields = ('account_link', 'display_addresses')
|
2014-10-06 14:57:02 +00:00
|
|
|
change_readonly_fields = ('name',)
|
|
|
|
add_form = MailboxCreationForm
|
2014-10-09 17:04:12 +00:00
|
|
|
form = MailboxChangeForm
|
2014-11-20 16:48:50 +00:00
|
|
|
list_prefetch_related = ('addresses__domain',)
|
2015-07-21 10:44:32 +00:00
|
|
|
actions = (disable, list_accounts)
|
2015-05-09 17:08:45 +00:00
|
|
|
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
|
|
super(MailboxAdmin, self).__init__(*args, **kwargs)
|
|
|
|
if settings.MAILBOXES_LOCAL_ADDRESS_DOMAIN:
|
|
|
|
type(self).actions = self.actions + (SendMailboxEmail(),)
|
2014-08-22 15:31:44 +00:00
|
|
|
|
|
|
|
def display_addresses(self, mailbox):
|
|
|
|
addresses = []
|
|
|
|
for addr in mailbox.addresses.all():
|
2014-09-18 15:07:39 +00:00
|
|
|
url = change_url(addr)
|
2014-08-22 15:31:44 +00:00
|
|
|
addresses.append('<a href="%s">%s</a>' % (url, addr.email))
|
|
|
|
return '<br>'.join(addresses)
|
|
|
|
display_addresses.short_description = _("Addresses")
|
|
|
|
display_addresses.allow_tags = True
|
|
|
|
|
2015-04-29 21:35:56 +00:00
|
|
|
def display_filtering(self, mailbox):
|
|
|
|
""" becacuse of allow_tags = True """
|
|
|
|
return mailbox.get_filtering_display()
|
|
|
|
display_filtering.short_description = _("Filtering")
|
|
|
|
display_filtering.admin_order_field = 'filtering'
|
|
|
|
display_filtering.allow_tags = True
|
|
|
|
|
2015-04-28 16:07:16 +00:00
|
|
|
def formfield_for_dbfield(self, db_field, **kwargs):
|
|
|
|
if db_field.name == 'filtering':
|
|
|
|
kwargs['widget'] = OpenCustomFilteringOnSelect()
|
|
|
|
return super(MailboxAdmin, self).formfield_for_dbfield(db_field, **kwargs)
|
|
|
|
|
2014-09-29 14:45:51 +00:00
|
|
|
def get_fieldsets(self, request, obj=None):
|
2015-03-26 16:00:30 +00:00
|
|
|
fieldsets = super(MailboxAdmin, self).get_fieldsets(request, obj)
|
2014-10-09 17:04:12 +00:00
|
|
|
if obj and obj.filtering == obj.CUSTOM:
|
2014-10-23 15:38:46 +00:00
|
|
|
# not collapsed filtering when exists
|
2014-09-29 14:45:51 +00:00
|
|
|
fieldsets = copy.deepcopy(fieldsets)
|
2015-04-28 16:07:16 +00:00
|
|
|
fieldsets[1][1]['classes'] = fieldsets[0][1]['fields'] + ('collapse', 'open',)
|
2014-10-23 15:38:46 +00:00
|
|
|
elif '_to_field' in parse_qs(request.META['QUERY_STRING']):
|
|
|
|
# remove address from popup
|
|
|
|
fieldsets = list(copy.deepcopy(fieldsets))
|
|
|
|
fieldsets.pop(-1)
|
2014-09-29 14:45:51 +00:00
|
|
|
return fieldsets
|
|
|
|
|
2014-10-21 15:29:36 +00:00
|
|
|
def get_form(self, *args, **kwargs):
|
|
|
|
form = super(MailboxAdmin, self).get_form(*args, **kwargs)
|
|
|
|
form.modeladmin = self
|
|
|
|
return form
|
|
|
|
|
2015-06-22 14:14:16 +00:00
|
|
|
def get_search_results(self, request, queryset, search_term):
|
|
|
|
# Remove local domain from the search term if present (implicit local addreç)
|
|
|
|
search_term = search_term.replace('@'+settings.MAILBOXES_LOCAL_DOMAIN, '')
|
|
|
|
# Split address name from domain in order to support address searching
|
|
|
|
search_term = search_term.replace('@', ' ')
|
|
|
|
return super(MailboxAdmin, self).get_search_results(request, queryset, search_term)
|
|
|
|
|
2015-10-07 11:44:30 +00:00
|
|
|
def render_change_form(self, request, context, *args, **kwargs):
|
|
|
|
# Check if there exists an unrelated local Address for this mbox
|
|
|
|
local_domain = settings.MAILBOXES_LOCAL_DOMAIN
|
|
|
|
obj = kwargs['obj']
|
|
|
|
if local_domain and obj.name:
|
|
|
|
non_mbox_addresses = Address.objects.exclude(mailboxes__name=obj.name).exclude(
|
|
|
|
forward__regex=r'.*(^|\s)+%s($|\s)+.*' % obj.name)
|
|
|
|
try:
|
|
|
|
addr = non_mbox_addresses.get(name=obj.name, domain__name=local_domain)
|
|
|
|
except Address.DoesNotExist:
|
|
|
|
pass
|
|
|
|
else:
|
|
|
|
url = reverse('admin:mailboxes_address_change', args=(addr.pk,))
|
|
|
|
msg = _("Address <a href='{url}'>{addr}</a> clashes with this mailbox "
|
|
|
|
"local address. Consider adding this mailbox to the address.").format(
|
|
|
|
url=url, addr=addr)
|
|
|
|
self.message_user(request, mark_safe(msg), level=messages.WARNING)
|
|
|
|
return super(MailboxAdmin, self).render_change_form(request, context, *args, **kwargs)
|
|
|
|
|
2014-10-21 15:29:36 +00:00
|
|
|
def save_model(self, request, obj, form, change):
|
2015-10-07 11:44:30 +00:00
|
|
|
""" save hacky mailbox.addresses and local domain clashing """
|
2014-10-21 15:29:36 +00:00
|
|
|
super(MailboxAdmin, self).save_model(request, obj, form, change)
|
|
|
|
obj.addresses = form.cleaned_data['addresses']
|
2014-08-22 15:31:44 +00:00
|
|
|
|
|
|
|
|
|
|
|
class AddressAdmin(SelectAccountAdminMixin, ExtendedModelAdmin):
|
|
|
|
list_display = (
|
2015-04-24 11:39:20 +00:00
|
|
|
'display_email', 'account_link', 'domain_link', 'display_mailboxes', 'display_forward',
|
2014-08-22 15:31:44 +00:00
|
|
|
)
|
|
|
|
list_filter = (HasMailboxListFilter, HasForwardListFilter)
|
2015-04-07 15:14:49 +00:00
|
|
|
fields = ('account_link', 'email_link', 'mailboxes', 'forward')
|
|
|
|
add_fields = ('account_link', ('name', 'domain'), 'mailboxes', 'forward')
|
2015-05-20 18:21:21 +00:00
|
|
|
# inlines = [AutoresponseInline]
|
2015-04-24 14:03:42 +00:00
|
|
|
search_fields = ('forward', 'mailboxes__name', 'account__username', 'computed_email')
|
2014-08-22 15:31:44 +00:00
|
|
|
readonly_fields = ('account_link', 'domain_link', 'email_link')
|
2015-05-05 19:42:55 +00:00
|
|
|
actions = (SendAddressEmail(),)
|
2014-08-22 15:31:44 +00:00
|
|
|
filter_by_account_fields = ('domain', 'mailboxes')
|
|
|
|
filter_horizontal = ['mailboxes']
|
2014-10-06 14:57:02 +00:00
|
|
|
form = AddressForm
|
2014-11-20 16:48:50 +00:00
|
|
|
list_prefetch_related = ('mailboxes', 'domain')
|
2014-08-22 15:31:44 +00:00
|
|
|
|
|
|
|
domain_link = admin_link('domain', order='domain__name')
|
|
|
|
|
2015-04-24 11:39:20 +00:00
|
|
|
def display_email(self, address):
|
|
|
|
return address.computed_email
|
|
|
|
display_email.short_description = _("Email")
|
|
|
|
display_email.admin_order_field = 'computed_email'
|
|
|
|
|
2014-08-22 15:31:44 +00:00
|
|
|
def email_link(self, address):
|
|
|
|
link = self.domain_link(address)
|
|
|
|
return "%s@%s" % (address.name, link)
|
|
|
|
email_link.short_description = _("Email")
|
|
|
|
email_link.allow_tags = True
|
|
|
|
|
|
|
|
def display_mailboxes(self, address):
|
|
|
|
boxes = []
|
|
|
|
for mailbox in address.mailboxes.all():
|
2014-09-18 15:07:39 +00:00
|
|
|
url = change_url(mailbox)
|
2014-08-22 15:31:44 +00:00
|
|
|
boxes.append('<a href="%s">%s</a>' % (url, mailbox.name))
|
|
|
|
return '<br>'.join(boxes)
|
|
|
|
display_mailboxes.short_description = _("Mailboxes")
|
|
|
|
display_mailboxes.allow_tags = True
|
|
|
|
|
|
|
|
def display_forward(self, address):
|
|
|
|
values = [ dest for dest in address.forward.split() ]
|
|
|
|
return '<br>'.join(values)
|
|
|
|
display_forward.short_description = _("Forward")
|
|
|
|
display_forward.allow_tags = True
|
2015-04-24 14:03:42 +00:00
|
|
|
display_forward.admin_order_field = 'forward'
|
2014-08-22 15:31:44 +00:00
|
|
|
|
|
|
|
def formfield_for_dbfield(self, db_field, **kwargs):
|
|
|
|
if db_field.name == 'forward':
|
|
|
|
kwargs['widget'] = forms.TextInput(attrs={'size':'118'})
|
|
|
|
return super(AddressAdmin, self).formfield_for_dbfield(db_field, **kwargs)
|
|
|
|
|
2014-10-21 15:29:36 +00:00
|
|
|
def get_fields(self, request, obj=None):
|
|
|
|
""" Remove mailboxes field when creating address from a popup i.e. from mailbox add form """
|
2015-03-26 16:00:30 +00:00
|
|
|
fields = super(AddressAdmin, self).get_fields(request, obj)
|
2014-10-21 15:29:36 +00:00
|
|
|
if '_to_field' in parse_qs(request.META['QUERY_STRING']):
|
|
|
|
# Add address popup
|
|
|
|
fields = list(fields)
|
|
|
|
fields.remove('mailboxes')
|
|
|
|
return fields
|
2015-04-24 11:39:20 +00:00
|
|
|
|
|
|
|
def get_queryset(self, request):
|
|
|
|
qs = super(AddressAdmin, self).get_queryset(request)
|
|
|
|
return qs.annotate(computed_email=Concat(F('name'), V('@'), F('domain__name')))
|
2014-08-22 15:31:44 +00:00
|
|
|
|
|
|
|
|
|
|
|
admin.site.register(Mailbox, MailboxAdmin)
|
|
|
|
admin.site.register(Address, AddressAdmin)
|