Source code for apps.mails.views

import math
import zipfile

from io import BytesIO
from urllib.parse import quote_plus

from django.core.urlresolvers import reverse
from django.db.models import Q
from django.shortcuts import redirect
from django.views.generic import TemplateView
from django.views.generic import View
from django.http import HttpResponse
from rest_framework import status

from apps.filters.models import FilterSet
from apps.mails.models import Message, MessagePart


[docs]class MailList(TemplateView): template_name = 'mails/list.html' sortable_columns = { 'from': 'sender_address', 'to': 'recipients_to', 'subject': 'subject', 'size': 'size', 'received': 'created_at', }
[docs] def get_context_data(self, **kwargs): # Search search = self.request.GET.get('q', False) if not search: search = None # Sort & Order sort = self.request.GET.get('sort', 'received') order = self.request.GET.get('order', 'desc') if not self.sortable_columns.get(sort, None): sort = 'received' order = 'desc' if not order == 'asc' and not order == 'desc': order = 'asc' sort_field = self.sortable_columns.get(sort) filterset = None if 'filter_id' in kwargs: try: filterset = FilterSet.objects.get(pk=kwargs['filter_id']) except: pass # Check if user has rights to access the filter set. if filterset and not filterset.is_global: if not self.request.user.is_authenticated() or not getattr(self.request.user, 'is_superuser', False) \ or not filterset.created_by_id != self.request.user.pk: filterset = None if not filterset: mails = Message.objects.all() else: mails = filterset.get_matches() # Apply order. mails = mails.order_by('{}{}'.format('-' if order == 'desc' else '', sort_field)) # Searching if search: mails = mails.filter( Q(subject__icontains=search) | Q(sender_name__icontains=search) | Q(sender_address__icontains=search) | Q(recipients_to__icontains=search) | Q(peer__icontains=search) | Q(size__icontains=search) | Q(source__icontains=search) ) # Pagination. total = mails.count() per_page = int(self.request.GET.get('max', 40)) page = int(self.request.GET.get('page', 1)) if type(per_page) is not int or per_page < 1 or per_page > 1000: per_page = 40 pages = int(math.ceil(total / per_page)) prev = True if page > 1 else False next = False if page >= pages else True display = list() if page <= 5 and pages >= 10: display = list(range(1, 11)) elif page <= 5 and pages < 10: display = list(range(1, pages)) elif page > 5 and pages >= (page + 4): display = list(range((page - 5), (page + 5))) elif page > 5 and pages >= page: display = list(range((page - 5), (pages + 1))) else: display = list(page) offset = (page - 1) * per_page limit = offset + per_page mails = mails[offset:limit] return { 'list': mails, 'sort': sort, 'order': order, 'pagination': { 'prev': prev, 'next': next, 'page': page, 'prev_page': page - 1, 'next_page': page + 1, 'rows': total, 'pages': pages, 'display': display }, 'search_text': '' if not search else search, 'actionbar': True }
[docs]class MailDownload(View):
[docs] def get(self, request, mail_ids): mail_ids = mail_ids.split(',') stream = BytesIO() zf = zipfile.ZipFile(stream, 'w') for idx in mail_ids: mail = Message.objects.get(pk=int(idx)) zf.writestr(zinfo_or_arcname='mail-{}.eml'.format(int(idx)), data=mail.eml) zf.close() resp = HttpResponse(stream.getvalue(), content_type='application/x-zip-compressed') resp['Content-Disposition'] = 'attachment; filename={}'.format('emails.zip') return resp
[docs]class MailPart(TemplateView): template_name = 'mails/part.html'
[docs] def get(self, request, mail_id, part_id, *args, **kwargs): try: message = Message.objects.get(pk=int(mail_id)) part = MessagePart.objects.get(pk=int(part_id), message_id=int(mail_id)) except: return redirect(reverse('mails:list')) return self.render_to_response(context={ 'part': part, 'message': message })
[docs]class MailPartBody(View): cant_display = [ 'multipart/alternative', 'multipart/mixed' ]
[docs] def get(self, request, mail_id, part_id, *args, **kwargs): response_type = kwargs.get('response_type') try: message = Message.objects.get(pk=int(mail_id)) part = MessagePart.objects.get(pk=int(part_id), message_id=int(mail_id)) except: return redirect(reverse('mails:list')) if part.is_attachment and response_type != 'download': return HttpResponse(content='', content_type='text/plain', status=status.HTTP_204_NO_CONTENT) if response_type == 'body': if part.type in self.cant_display: return HttpResponse(content='- this part can\'t be displayed! -', content_type='text/plain') return HttpResponse(content=part.body, content_type=part.type, charset=part.charset) elif response_type == 'source': return HttpResponse(content=part.body.decode(), content_type='text/plain') elif response_type == 'download': response = HttpResponse(part.body, content_type='application/octet-stream') filename = quote_plus(part.filename if part.filename else 'file.txt') response['Content-Disposition'] = 'attachment; filename="{}"'.format(filename) return response