Add contacts, reply/forward, pagination, HTML toggle, Docker Compose for VPS
Co-authored-by: Junie <junie@jetbrains.com>
This commit is contained in:
+14
-3
@@ -1,5 +1,16 @@
|
||||
FROM eclipse-temurin:21-jdk-alpine
|
||||
# Stage 1: Build
|
||||
FROM eclipse-temurin:21-jdk-alpine AS build
|
||||
WORKDIR /app
|
||||
COPY build/libs/*.jar app.jar
|
||||
EXPOSE 8080
|
||||
COPY build.gradle settings.gradle gradlew ./
|
||||
COPY gradle gradle
|
||||
COPY src src
|
||||
RUN chmod +x gradlew
|
||||
RUN ./gradlew bootJar --no-daemon
|
||||
|
||||
# Stage 2: Run
|
||||
FROM eclipse-temurin:21-jre-alpine
|
||||
WORKDIR /app
|
||||
COPY --from=build /app/build/libs/*.jar app.jar
|
||||
RUN mkdir -p /app/attachments /app/dkim-keys
|
||||
EXPOSE 8080 3025
|
||||
ENTRYPOINT ["java", "-jar", "app.jar"]
|
||||
|
||||
@@ -276,4 +276,72 @@ public class MailController {
|
||||
Mono.just(org.springframework.http.ResponseEntity.badRequest().body(Map.of("error", e.getMessage()))))
|
||||
);
|
||||
}
|
||||
|
||||
// --- Contacts ---
|
||||
|
||||
@GetMapping("/contacts")
|
||||
public Flux<Object> getContacts(Mono<Authentication> authenticationMono) {
|
||||
return authenticationMono.flatMapMany(auth ->
|
||||
userService.findByEmail(auth.getName())
|
||||
.flatMapMany(user -> mailService.getContacts(user.getId()))
|
||||
);
|
||||
}
|
||||
|
||||
@PostMapping("/contacts")
|
||||
public Mono<Object> addContact(
|
||||
Mono<Authentication> authenticationMono,
|
||||
@RequestBody Mono<Map<String, String>> bodyMono) {
|
||||
return authenticationMono.zipWith(bodyMono)
|
||||
.flatMap(pair -> {
|
||||
String email = pair.getT1().getName();
|
||||
Map<String, String> body = pair.getT2();
|
||||
return userService.findByEmail(email)
|
||||
.flatMap(user -> mailService.addContact(
|
||||
user.getId(),
|
||||
body.get("name"),
|
||||
body.get("email"),
|
||||
body.get("phone"),
|
||||
body.get("company")
|
||||
));
|
||||
})
|
||||
.map(contact -> (Object) org.springframework.http.ResponseEntity.status(HttpStatus.CREATED).body(contact))
|
||||
.onErrorResume(IllegalArgumentException.class, e ->
|
||||
Mono.just((Object) org.springframework.http.ResponseEntity.badRequest().body(Map.of("error", e.getMessage()))));
|
||||
}
|
||||
|
||||
@PutMapping("/contacts/{id}")
|
||||
public Mono<Object> updateContact(
|
||||
@PathVariable Long id,
|
||||
Mono<Authentication> authenticationMono,
|
||||
@RequestBody Mono<Map<String, String>> bodyMono) {
|
||||
return authenticationMono.zipWith(bodyMono)
|
||||
.flatMap(pair -> {
|
||||
String email = pair.getT1().getName();
|
||||
Map<String, String> body = pair.getT2();
|
||||
return userService.findByEmail(email)
|
||||
.flatMap(user -> mailService.updateContact(
|
||||
id, user.getId(),
|
||||
body.get("name"),
|
||||
body.get("email"),
|
||||
body.get("phone"),
|
||||
body.get("company")
|
||||
));
|
||||
})
|
||||
.map(contact -> (Object) org.springframework.http.ResponseEntity.ok().body(contact))
|
||||
.onErrorResume(IllegalArgumentException.class, e ->
|
||||
Mono.just((Object) org.springframework.http.ResponseEntity.badRequest().body(Map.of("error", e.getMessage()))));
|
||||
}
|
||||
|
||||
@DeleteMapping("/contacts/{id}")
|
||||
public Mono<?> deleteContact(
|
||||
@PathVariable Long id,
|
||||
Mono<Authentication> authenticationMono) {
|
||||
return authenticationMono.flatMap(auth ->
|
||||
userService.findByEmail(auth.getName())
|
||||
.flatMap(user -> mailService.deleteContact(id, user.getId())
|
||||
.then(Mono.just(org.springframework.http.ResponseEntity.ok(Map.of("message", "Contact deleted")))))
|
||||
.onErrorResume(IllegalArgumentException.class, e ->
|
||||
Mono.just(org.springframework.http.ResponseEntity.badRequest().body(Map.of("error", e.getMessage()))))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user