Add contacts, reply/forward, pagination, HTML toggle, Docker Compose for VPS

Co-authored-by: Junie <junie@jetbrains.com>
This commit is contained in:
2026-11-05 01:28:24 +01:00
co-authored by Junie
parent 0339413d6e
commit a23a020138
14 changed files with 570 additions and 12 deletions
@@ -1,6 +1,7 @@
package com.mailserver.service;
import com.mailserver.domain.Attachment;
import com.mailserver.domain.Contact;
import com.mailserver.domain.Folder;
import com.mailserver.domain.Message;
import com.mailserver.domain.User;
@@ -8,6 +9,7 @@ import com.mailserver.dto.AttachmentResponse;
import com.mailserver.dto.MessageResponse;
import com.mailserver.dto.SendRequest;
import com.mailserver.repository.AttachmentRepository;
import com.mailserver.repository.ContactRepository;
import com.mailserver.repository.FolderRepository;
import com.mailserver.repository.MessageRepository;
import com.mailserver.repository.UserRepository;
@@ -46,6 +48,7 @@ public class MailService {
private final FolderRepository folderRepository;
private final UserRepository userRepository;
private final AttachmentRepository attachmentRepository;
private final ContactRepository contactRepository;
private final SpamFilterService spamFilterService;
private final DkimService dkimService;
@@ -60,12 +63,14 @@ public class MailService {
public MailService(MessageRepository messageRepository, FolderRepository folderRepository,
UserRepository userRepository, AttachmentRepository attachmentRepository,
ContactRepository contactRepository,
SpamFilterService spamFilterService,
DkimService dkimService) {
this.messageRepository = messageRepository;
this.folderRepository = folderRepository;
this.userRepository = userRepository;
this.attachmentRepository = attachmentRepository;
this.contactRepository = contactRepository;
this.spamFilterService = spamFilterService;
this.dkimService = dkimService;
}
@@ -381,4 +386,49 @@ public class MailService {
return send.then(readResponse);
}
// --- Contacts ---
public Flux<Contact> getContacts(Long userId) {
return contactRepository.findByUserId(userId);
}
public Mono<Contact> addContact(Long userId, String name, String email, String phone, String company) {
if (email == null || email.trim().isEmpty()) {
return Mono.error(new IllegalArgumentException("Email is required"));
}
Contact contact = new Contact();
contact.setUserId(userId);
contact.setName(name != null ? name : "");
contact.setEmail(email.trim());
contact.setPhone(phone != null ? phone : "");
contact.setCompany(company != null ? company : "");
return contactRepository.save(contact);
}
public Mono<Contact> updateContact(Long id, Long userId, String name, String email, String phone, String company) {
return contactRepository.findById(id)
.switchIfEmpty(Mono.error(new IllegalArgumentException("Contact not found")))
.flatMap(contact -> {
if (!contact.getUserId().equals(userId)) {
return Mono.error(new IllegalArgumentException("Not your contact"));
}
if (name != null) contact.setName(name);
if (email != null) contact.setEmail(email.trim());
if (phone != null) contact.setPhone(phone);
if (company != null) contact.setCompany(company);
return contactRepository.save(contact);
});
}
public Mono<Void> deleteContact(Long id, Long userId) {
return contactRepository.findById(id)
.switchIfEmpty(Mono.error(new IllegalArgumentException("Contact not found")))
.flatMap(contact -> {
if (!contact.getUserId().equals(userId)) {
return Mono.error(new IllegalArgumentException("Not your contact"));
}
return contactRepository.delete(contact);
});
}
}