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
+96
View File
@@ -0,0 +1,96 @@
import { Injectable, inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable, map } from 'rxjs';
import { Message, Folder, Attachment, SendRequest, BlacklistEntry, PageResponse } from '../models/mail.models';
@Injectable({
providedIn: 'root'
})
export class MailService {
private http = inject(HttpClient);
private apiUrl = 'http://localhost:8080/api';
// Папки
getFolders(): Observable<Folder[]> {
return this.http.get<Folder[]>(`${this.apiUrl}/folders`);
}
// Письма
getMessages(folderId: number, page: number = 0, size: number = 20): Observable<Message[]> {
return this.http.get<PageResponse<Message>>(`${this.apiUrl}/messages`, {
params: { folderId, page, size }
}).pipe(map(response => response.content));
}
getMessage(id: number): Observable<Message> {
return this.http.get<Message>(`${this.apiUrl}/messages/${id}`);
}
searchMessages(
folderId: number,
keyword?: string,
subject?: string,
body?: string,
sender?: string,
recipient?: string
): Observable<Message[]> {
const params: { [key: string]: string } = { folderId: folderId.toString() };
if (keyword) params['keyword'] = keyword;
if (subject) params['subject'] = subject;
if (body) params['body'] = body;
if (sender) params['sender'] = sender;
if (recipient) params['recipient'] = recipient;
return this.http.get<PageResponse<Message>>(`${this.apiUrl}/messages/search`, { params })
.pipe(map(response => response.content));
}
// Отправка
send(sendRequest: SendRequest): Observable<void> {
return this.http.post<void>(`${this.apiUrl}/send`, sendRequest);
}
// Статус
markAsRead(id: number): Observable<void> {
return this.http.put<void>(`${this.apiUrl}/messages/${id}/read`, null);
}
deleteMessage(id: number): Observable<void> {
return this.http.delete<void>(`${this.apiUrl}/messages/${id}`);
}
// Вложения
getAttachments(messageId: number): Observable<Attachment[]> {
return this.http.get<Attachment[]>(`${this.apiUrl}/messages/${messageId}/attachments`);
}
uploadAttachment(messageId: number, file: File): Observable<void> {
const formData = new FormData();
formData.append('file', file);
return this.http.post<void>(`${this.apiUrl}/messages/${messageId}/attachments`, formData);
}
downloadAttachment(attachmentId: number): Observable<Blob> {
return this.http.get<Blob>(`${this.apiUrl}/attachments/${attachmentId}/download`, {
responseType: 'blob' as 'json'
});
}
deleteAttachment(attachmentId: number): Observable<void> {
return this.http.delete<void>(`${this.apiUrl}/attachments/${attachmentId}`);
}
// Чёрный список
getBlacklist(): Observable<string[]> {
return this.http.get<string[]>(`${this.apiUrl}/spam/blacklist`);
}
addToBlacklist(entry: BlacklistEntry): Observable<void> {
return this.http.post<void>(`${this.apiUrl}/spam/blacklist`, entry);
}
removeFromBlacklist(senderEmail: string): Observable<void> {
return this.http.delete<void>(`${this.apiUrl}/spam/blacklist`, {
params: { senderEmail }
});
}
}