feat(webmail,auth): leitor estilo Outlook, responder a todos, importantes e isolamento do admin de dominio
Webmail - Leitor de mensagem em componente proprio, com barra de comandos fixa, cabecalho compacto, faixa de imagens bloqueadas e chips de anexo. - Divisor arrastavel entre lista e leitor (mouse, setas, duplo clique), largura persistida e limites que preservam os dois paineis. - Destinatarios em chips (Para, Cc, Cco): aceita nomes com virgula, colagem de listas, validacao e bloqueio de envio com endereco invalido. - Responder a todos, sem o proprio endereco e sem repetidos; In-Reply-To e References nas respostas; prefixo Re:/Fwd: sem repeticao. - Marcar como importante (estrela, filtro, linha da lista) e enviar com alta importancia (Importance/X-Priority), com etiqueta no leitor. - Sanitizador: a regexp de URI customizada descartava todo atributo que nao fosse link (width, colspan, bgcolor...), o que desmontava tabelas de e-mail; imagens de fundo agora sao bloqueadas de forma reversivel. Protocols - POST /api/v1/mail/flagged (\Flagged) com bump de modseq para IMAP. - Renderizacao expoe message_id, in_reply_to e important. - Cabecalhos de resposta validados contra injecao. Auth - As views do admin de dominio eram globais: dashboard, fila de saida, DMARC, preflight e diagnostico mostravam dados de todos os dominios. Agora todas respeitam o escopo da sessao; super admin segue vendo tudo. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
b5baf33a63
commit
50a67531ba
30 files changed
+1810
-348
No files matched your search
@@ -4,6 +4,7 @@ import {
|
||||
badgeCount,
|
||||
messageCounts,
|
||||
filterMessages,
|
||||
applyFlagged,
|
||||
listHeaderCount,
|
||||
applySeen,
|
||||
type FolderSummary,
|
||||
@@ -80,16 +81,28 @@ describe("the number on a sidebar folder", () => {
|
||||
const messages: MessageSummary[] = [
|
||||
{ uid: 1, seen: false, has_attachments: true },
|
||||
{ uid: 2, seen: true, has_attachments: false },
|
||||
{ uid: 3, seen: false, has_attachments: false },
|
||||
{ uid: 3, seen: false, has_attachments: false, flagged: true },
|
||||
];
|
||||
|
||||
describe("important messages", () => {
|
||||
it("filters to the flagged ones", () => {
|
||||
expect(filterMessages(messages, "important").map((m) => m.uid)).toEqual([3]);
|
||||
});
|
||||
|
||||
it("sets and clears the flag on one row only", () => {
|
||||
const on = applyFlagged(messages, 1, true);
|
||||
expect(on.map((m) => !!m.flagged)).toEqual([true, false, true]);
|
||||
expect(applyFlagged(on, 1, false).map((m) => !!m.flagged)).toEqual([false, false, true]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("counting the loaded page", () => {
|
||||
it("counts what is on it by unread and by attachment", () => {
|
||||
expect(messageCounts(messages)).toEqual({ loaded: 3, unread: 2, withAttachments: 1 });
|
||||
expect(messageCounts(messages)).toEqual({ loaded: 3, unread: 2, withAttachments: 1, important: 1 });
|
||||
});
|
||||
|
||||
it("counts an empty page as zeros", () => {
|
||||
expect(messageCounts([])).toEqual({ loaded: 0, unread: 0, withAttachments: 0 });
|
||||
expect(messageCounts([])).toEqual({ loaded: 0, unread: 0, withAttachments: 0, important: 0 });
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in new issue
Block a user