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