262 lines
8.4 KiB
Python
262 lines
8.4 KiB
Python
from rest_framework import serializers
|
|
from django.contrib.auth import get_user_model
|
|
from .models import (
|
|
Email, EmailFolder, EmailAttachment, EmailThread, EmailTemplate,
|
|
EmailSignature, EmailRule, EmailSearch
|
|
)
|
|
|
|
User = get_user_model()
|
|
|
|
|
|
class EmailFolderSerializer(serializers.ModelSerializer):
|
|
"""Serializer for email folders."""
|
|
|
|
email_count = serializers.SerializerMethodField()
|
|
unread_count = serializers.SerializerMethodField()
|
|
|
|
class Meta:
|
|
model = EmailFolder
|
|
fields = '__all__'
|
|
read_only_fields = ('user', 'created_at', 'updated_at')
|
|
|
|
def get_email_count(self, obj):
|
|
return obj.emails.count()
|
|
|
|
def get_unread_count(self, obj):
|
|
return obj.emails.filter(is_read=False).count()
|
|
|
|
|
|
class EmailAttachmentSerializer(serializers.ModelSerializer):
|
|
"""Serializer for email attachments."""
|
|
|
|
class Meta:
|
|
model = EmailAttachment
|
|
fields = '__all__'
|
|
read_only_fields = ('created_at',)
|
|
|
|
|
|
class EmailSerializer(serializers.ModelSerializer):
|
|
"""Serializer for emails."""
|
|
|
|
attachments = EmailAttachmentSerializer(many=True, read_only=True)
|
|
folder_name = serializers.CharField(source='folder.name', read_only=True)
|
|
from_name = serializers.SerializerMethodField()
|
|
recipients = serializers.SerializerMethodField()
|
|
thread_count = serializers.SerializerMethodField()
|
|
|
|
class Meta:
|
|
model = Email
|
|
fields = '__all__'
|
|
read_only_fields = ('uuid', 'user', 'message_id', 'created_at', 'updated_at')
|
|
|
|
def get_from_name(self, obj):
|
|
# Try to get name from contacts or use email
|
|
return obj.from_email
|
|
|
|
def get_recipients(self, obj):
|
|
return {
|
|
'to': obj.to_emails,
|
|
'cc': obj.cc_emails,
|
|
'bcc': obj.bcc_emails,
|
|
}
|
|
|
|
def get_thread_count(self, obj):
|
|
return obj.threads.count()
|
|
|
|
|
|
class EmailCreateSerializer(serializers.ModelSerializer):
|
|
"""Serializer for creating emails."""
|
|
|
|
attachments = serializers.ListField(
|
|
child=serializers.FileField(),
|
|
required=False,
|
|
write_only=True
|
|
)
|
|
|
|
class Meta:
|
|
model = Email
|
|
fields = (
|
|
'subject', 'to_emails', 'cc_emails', 'bcc_emails', 'reply_to',
|
|
'body_text', 'body_html', 'priority', 'folder', 'attachments'
|
|
)
|
|
|
|
def validate_to_emails(self, value):
|
|
if not value:
|
|
raise serializers.ValidationError("At least one recipient is required.")
|
|
return value
|
|
|
|
def create(self, validated_data):
|
|
attachments_data = validated_data.pop('attachments', [])
|
|
user = self.context['request'].user
|
|
|
|
# Set from_email to user's email
|
|
validated_data['from_email'] = user.email
|
|
|
|
# Create email
|
|
email = Email.objects.create(user=user, **validated_data)
|
|
|
|
# Handle attachments
|
|
for attachment_file in attachments_data:
|
|
EmailAttachment.objects.create(
|
|
email=email,
|
|
filename=attachment_file.name,
|
|
content_type=attachment_file.content_type,
|
|
size=attachment_file.size,
|
|
file=attachment_file
|
|
)
|
|
|
|
return email
|
|
|
|
|
|
class EmailReplySerializer(serializers.ModelSerializer):
|
|
"""Serializer for replying to emails."""
|
|
|
|
original_email = serializers.PrimaryKeyRelatedField(queryset=Email.objects.all())
|
|
|
|
class Meta:
|
|
model = Email
|
|
fields = ('original_email', 'subject', 'body_text', 'body_html', 'priority')
|
|
|
|
def create(self, validated_data):
|
|
original_email = validated_data.pop('original_email')
|
|
user = self.context['request'].user
|
|
|
|
# Set reply headers
|
|
validated_data.update({
|
|
'user': user,
|
|
'from_email': user.email,
|
|
'to_emails': [original_email.from_email],
|
|
'in_reply_to': original_email.message_id,
|
|
'references': f"{original_email.references} {original_email.message_id}".strip(),
|
|
'folder': EmailFolder.objects.get(user=user, folder_type='sent'),
|
|
})
|
|
|
|
# Add "Re: " prefix if not already present
|
|
subject = validated_data.get('subject', '')
|
|
if not subject.startswith('Re: '):
|
|
validated_data['subject'] = f"Re: {subject}"
|
|
|
|
return Email.objects.create(**validated_data)
|
|
|
|
|
|
class EmailForwardSerializer(serializers.ModelSerializer):
|
|
"""Serializer for forwarding emails."""
|
|
|
|
original_email = serializers.PrimaryKeyRelatedField(queryset=Email.objects.all())
|
|
|
|
class Meta:
|
|
model = Email
|
|
fields = ('original_email', 'to_emails', 'cc_emails', 'bcc_emails', 'subject', 'body_text', 'body_html', 'priority')
|
|
|
|
def create(self, validated_data):
|
|
original_email = validated_data.pop('original_email')
|
|
user = self.context['request'].user
|
|
|
|
# Set forward headers
|
|
validated_data.update({
|
|
'user': user,
|
|
'from_email': user.email,
|
|
'in_reply_to': original_email.message_id,
|
|
'folder': EmailFolder.objects.get(user=user, folder_type='sent'),
|
|
})
|
|
|
|
# Add "Fwd: " prefix if not already present
|
|
subject = validated_data.get('subject', '')
|
|
if not subject.startswith('Fwd: '):
|
|
validated_data['subject'] = f"Fwd: {subject}"
|
|
|
|
# Add original email content
|
|
original_content = f"\n\n--- Forwarded message ---\nFrom: {original_email.from_email}\nDate: {original_email.sent_at}\nSubject: {original_email.subject}\n\n{original_email.body_text}"
|
|
validated_data['body_text'] += original_content
|
|
|
|
return Email.objects.create(**validated_data)
|
|
|
|
|
|
class EmailThreadSerializer(serializers.ModelSerializer):
|
|
"""Serializer for email threads."""
|
|
|
|
emails = EmailSerializer(many=True, read_only=True)
|
|
email_count = serializers.SerializerMethodField()
|
|
|
|
class Meta:
|
|
model = EmailThread
|
|
fields = '__all__'
|
|
|
|
def get_email_count(self, obj):
|
|
return obj.emails.count()
|
|
|
|
|
|
class EmailTemplateSerializer(serializers.ModelSerializer):
|
|
"""Serializer for email templates."""
|
|
|
|
class Meta:
|
|
model = EmailTemplate
|
|
fields = '__all__'
|
|
read_only_fields = ('user', 'created_at', 'updated_at')
|
|
|
|
|
|
class EmailSignatureSerializer(serializers.ModelSerializer):
|
|
"""Serializer for email signatures."""
|
|
|
|
class Meta:
|
|
model = EmailSignature
|
|
fields = '__all__'
|
|
read_only_fields = ('user', 'created_at', 'updated_at')
|
|
|
|
|
|
class EmailRuleSerializer(serializers.ModelSerializer):
|
|
"""Serializer for email rules."""
|
|
|
|
class Meta:
|
|
model = EmailRule
|
|
fields = '__all__'
|
|
read_only_fields = ('user', 'created_at', 'updated_at')
|
|
|
|
|
|
class EmailSearchSerializer(serializers.ModelSerializer):
|
|
"""Serializer for email searches."""
|
|
|
|
class Meta:
|
|
model = EmailSearch
|
|
fields = '__all__'
|
|
read_only_fields = ('user', 'created_at')
|
|
|
|
|
|
class EmailBulkActionSerializer(serializers.Serializer):
|
|
"""Serializer for bulk email actions."""
|
|
|
|
ACTION_CHOICES = [
|
|
('mark_read', 'Mark as read'),
|
|
('mark_unread', 'Mark as unread'),
|
|
('mark_starred', 'Mark as starred'),
|
|
('mark_unstarred', 'Mark as unstarred'),
|
|
('mark_important', 'Mark as important'),
|
|
('mark_unimportant', 'Mark as unimportant'),
|
|
('move_to_folder', 'Move to folder'),
|
|
('delete', 'Delete'),
|
|
]
|
|
|
|
email_ids = serializers.ListField(
|
|
child=serializers.IntegerField(),
|
|
min_length=1
|
|
)
|
|
action = serializers.ChoiceField(choices=ACTION_CHOICES)
|
|
folder_id = serializers.IntegerField(required=False)
|
|
|
|
def validate_email_ids(self, value):
|
|
user = self.context['request'].user
|
|
# Verify all emails belong to the user
|
|
email_count = Email.objects.filter(id__in=value, user=user).count()
|
|
if email_count != len(value):
|
|
raise serializers.ValidationError("Some emails don't exist or don't belong to you.")
|
|
return value
|
|
|
|
def validate(self, attrs):
|
|
action = attrs.get('action')
|
|
folder_id = attrs.get('folder_id')
|
|
|
|
if action == 'move_to_folder' and not folder_id:
|
|
raise serializers.ValidationError("folder_id is required for move_to_folder action.")
|
|
|
|
return attrs
|