continuous-integration/drone/pr Build is passing
- V7: users.is_shared, mailbox_access (MEMBER от админа/Jambotron, ATTACHED по паролю ящика), messages.answered_by
- /api/mailboxes: мои ящики с непрочитанными, сессия другого ящика (JWT с claim by), подключить по паролю
(LoginGuard), убрать из меню
- общий ящик: без своего входа (веб/SMTP/IMAP), участники открывают; «прочитано» общее; ответ из веба → answered_by
- SMTP/IMAP: ящик*логин + пароль логина (как master user в Dovecot)
- открытый чужой ящик (общий, подключённый, OPEN админа): профиль и пароль не меняются (403)
- админ: создать shared, участники ящика (PUT /{id}/members); служебное API: PUT /shared/{address};
выключение аккаунта убирает и из общих ящиков
- UI: MAILBOXES в левом меню (переключение, ⊕ подключить, × убрать), shared/участники в настройках,
«Answered by» у письма
- 88 тестов; живой прогон на Postgres 17 (апгрейд V6→V7 на данных), скриншоты UI
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
53 lines
1.6 KiB
Java
53 lines
1.6 KiB
Java
package com.mailserver.dto;
|
|
|
|
import jakarta.validation.constraints.NotBlank;
|
|
import jakarta.validation.constraints.Size;
|
|
|
|
/**
|
|
* "Send" from the web client. {@code to} and {@code cc}: one or more addresses separated by commas, semicolons or
|
|
* spaces. {@code draftId}: the draft being sent — its attachments go with the message, the draft is removed.
|
|
*/
|
|
public class SendRequest {
|
|
|
|
@NotBlank
|
|
@Size(max = 5000)
|
|
private String to;
|
|
|
|
@Size(max = 5000)
|
|
private String cc;
|
|
|
|
@Size(max = 1000)
|
|
private String subject;
|
|
|
|
@Size(max = 1_000_000)
|
|
private String body;
|
|
|
|
private boolean html = false;
|
|
|
|
private Long draftId;
|
|
|
|
/** The message this one answers (web client «Reply»): marked answered, by whom. */
|
|
private Long replyToId;
|
|
|
|
public Long getReplyToId() { return replyToId; }
|
|
public void setReplyToId(Long replyToId) { this.replyToId = replyToId; }
|
|
|
|
public String getTo() { return to; }
|
|
public void setTo(String to) { this.to = to; }
|
|
|
|
public String getCc() { return cc; }
|
|
public void setCc(String cc) { this.cc = cc; }
|
|
|
|
public String getSubject() { return subject == null ? "" : subject; }
|
|
public void setSubject(String subject) { this.subject = subject; }
|
|
|
|
public String getBody() { return body == null ? "" : body; }
|
|
public void setBody(String body) { this.body = body; }
|
|
|
|
public boolean isHtml() { return html; }
|
|
public void setHtml(boolean html) { this.html = html; }
|
|
|
|
public Long getDraftId() { return draftId; }
|
|
public void setDraftId(Long draftId) { this.draftId = draftId; }
|
|
}
|