Initial commit: mail-server with WebFlux backend and Angular v22 Synthwave frontend

Co-authored-by: Junie <junie@jetbrains.com>
This commit is contained in:
2026-11-05 01:07:29 +01:00
co-authored by Junie
commit 0339413d6e
78 changed files with 6808 additions and 0 deletions
@@ -0,0 +1,9 @@
package com.mailserver.repository;
import com.mailserver.domain.Attachment;
import org.springframework.data.r2dbc.repository.R2dbcRepository;
import reactor.core.publisher.Flux;
public interface AttachmentRepository extends R2dbcRepository<Attachment, Long> {
Flux<Attachment> findByMessageId(Long messageId);
}
@@ -0,0 +1,19 @@
package com.mailserver.repository;
import com.mailserver.domain.BlacklistEntry;
import org.springframework.data.r2dbc.repository.Query;
import org.springframework.data.r2dbc.repository.R2dbcRepository;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
public interface BlacklistRepository extends R2dbcRepository<BlacklistEntry, Long> {
Flux<BlacklistEntry> findByUserId(Long userId);
Mono<BlacklistEntry> findByUserIdAndSenderEmail(Long userId, String senderEmail);
@Query("SELECT COUNT(*) > 0 FROM blacklist WHERE user_id = :#{#userId} AND LOWER(sender_email) = LOWER(:#{#senderEmail})")
Mono<Boolean> isBlacklisted(Long userId, String senderEmail);
Mono<Void> deleteByUserIdAndSenderEmail(Long userId, String senderEmail);
}
@@ -0,0 +1,11 @@
package com.mailserver.repository;
import com.mailserver.domain.Contact;
import org.springframework.data.r2dbc.repository.R2dbcRepository;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
public interface ContactRepository extends R2dbcRepository<Contact, Long> {
Flux<Contact> findByUserId(Long userId);
Mono<Contact> findByUserIdAndEmail(Long userId, String email);
}
@@ -0,0 +1,12 @@
package com.mailserver.repository;
import com.mailserver.domain.Folder;
import org.springframework.data.r2dbc.repository.Query;
import org.springframework.data.r2dbc.repository.R2dbcRepository;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
public interface FolderRepository extends R2dbcRepository<Folder, Long> {
Flux<Folder> findByUserId(Long userId);
Mono<Folder> findByUserIdAndName(Long userId, String name);
}
@@ -0,0 +1,38 @@
package com.mailserver.repository;
import com.mailserver.domain.Message;
import org.springframework.data.domain.Pageable;
import org.springframework.data.r2dbc.repository.Query;
import org.springframework.data.r2dbc.repository.R2dbcRepository;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
public interface MessageRepository extends R2dbcRepository<Message, Long> {
@Query("SELECT * FROM messages WHERE folder_id = :#{#folderId} ORDER BY received_at DESC")
Flux<Message> findByFolderId(Long folderId, Pageable pageable);
@Query("SELECT COUNT(*) FROM messages WHERE folder_id = :#{#folderId} AND is_read = false")
Mono<Long> countUnreadByFolderId(Long folderId);
@Query("SELECT * FROM messages WHERE folder_id = :#{#folderId} AND is_read = false ORDER BY received_at DESC")
Flux<Message> findUnreadByFolderId(Long folderId, Pageable pageable);
@Query("SELECT * FROM messages WHERE folder_id = :#{#folderId} AND " +
"(LOWER(subject) LIKE '%' || LOWER(:#{#keyword}) || '%' OR " +
"LOWER(sender_email) LIKE '%' || LOWER(:#{#keyword}) || '%' OR " +
"LOWER(sender_name) LIKE '%' || LOWER(:#{#keyword}) || '%' OR " +
"LOWER(body) LIKE '%' || LOWER(:#{#keyword}) || '%') " +
"ORDER BY received_at DESC")
Flux<Message> searchInFolder(Long folderId, String keyword, Pageable pageable);
@Query("SELECT * FROM messages WHERE folder_id = :#{#folderId} AND (" +
"(:#{#subject} IS NULL OR LOWER(subject) LIKE '%' || LOWER(:#{#subject}) || '%') AND " +
"(:#{#body} IS NULL OR LOWER(body) LIKE '%' || LOWER(:#{#body}) || '%') AND " +
"(:#{#sender} IS NULL OR LOWER(sender_email) LIKE '%' || LOWER(:#{#sender}) || '%' OR " +
"LOWER(sender_name) LIKE '%' || LOWER(:#{#sender}) || '%') AND " +
"(:#{#recipient} IS NULL OR LOWER(recipient_email) LIKE '%' || LOWER(:#{#recipient}) || '%')) " +
"ORDER BY received_at DESC")
Flux<Message> searchWithFilters(Long folderId, String subject, String body,
String sender, String recipient, Pageable pageable);
}
@@ -0,0 +1,10 @@
package com.mailserver.repository;
import com.mailserver.domain.User;
import org.springframework.data.r2dbc.repository.R2dbcRepository;
import reactor.core.publisher.Mono;
public interface UserRepository extends R2dbcRepository<User, Long> {
Mono<User> findByEmail(String email);
Mono<Boolean> existsByEmail(String email);
}