feat: search for an email address simultaneously in to, cc and bcc #304

This commit is contained in:
rustmailer
2026-06-25 02:36:24 +08:00
parent 8542ba0d28
commit cad447275f
21 changed files with 72 additions and 4 deletions
+4
View File
@@ -43,6 +43,10 @@ pub struct EmailSearchFilter {
pub to: Option<String>,
pub cc: Option<String>,
pub bcc: Option<String>,
/// Matches if the address appears in `to`, `cc`, or `bcc` (OR semantics).
pub any_recipient: Option<String>,
/// Matches if the address appears in `from`, `to`, `cc`, or `bcc` (OR semantics).
pub any_participant: Option<String>,
pub since: Option<i64>,
pub before: Option<i64>,
/// Lower bound (inclusive) on the IMAP server INTERNALDATE timestamp.
+28
View File
@@ -461,6 +461,34 @@ impl IndexManager {
}
}
// any_recipient: OR across to, cc, bcc
if let Some(ref v) = filter.any_recipient {
let mut recipient_queries: Vec<(Occur, Box<dyn Query>)> = Vec::new();
for field in [f.f_to_text, f.f_cc_text, f.f_bcc_text] {
let query_parser = QueryParser::for_index(&self.index, vec![field]);
if let Ok(q) = query_parser.parse_query(v) {
recipient_queries.push((Occur::Should, q));
}
}
if !recipient_queries.is_empty() {
subqueries.push((Occur::Must, Box::new(BooleanQuery::new(recipient_queries))));
}
}
// any_participant: OR across from, to, cc, bcc
if let Some(ref v) = filter.any_participant {
let mut participant_queries: Vec<(Occur, Box<dyn Query>)> = Vec::new();
for field in [f.f_from_text, f.f_to_text, f.f_cc_text, f.f_bcc_text] {
let query_parser = QueryParser::for_index(&self.index, vec![field]);
if let Ok(q) = query_parser.parse_query(v) {
participant_queries.push((Occur::Should, q));
}
}
if !participant_queries.is_empty() {
subqueries.push((Occur::Must, Box::new(BooleanQuery::new(participant_queries))));
}
}
if let Some(has) = filter.has_attachment {
let lower: Bound<Term>;
let upper: Bound<Term>;
+4 -4
View File
@@ -30,13 +30,13 @@ import {
CommandGroup,
CommandInput,
CommandItem,
CommandList,
} from "@/components/ui/command"
import { ScrollArea } from "@/components/ui/scroll-area"
export function MailFilterPopover() {
const { t } = useTranslation()
const { filter, setFilter } = useSearchContext()
const fields = ['from', 'to', 'cc', 'bcc'] as const
const fields = ['from', 'to', 'cc', 'bcc', 'any_recipient', 'any_participant'] as const
const activeCount = fields.filter(k => !!filter[k]).length
@@ -196,7 +196,7 @@ function ContactSelectorField({
value={searchTerm}
onValueChange={setSearchTerm}
/>
<CommandList className="max-h-[360px]">
<ScrollArea className="h-[360px]">
{isLoading && (
<div className="p-4 text-xs text-center opacity-50">{t('search_contacts.loading')}</div>
)}
@@ -227,7 +227,7 @@ function ContactSelectorField({
</div>
)}
</CommandGroup>
</CommandList>
</ScrollArea>
</Command>
</PopoverContent>
</Popover>
+2
View File
@@ -1001,6 +1001,8 @@
"advanced": "متقدم",
"advancedFilters": "فلاتر متقدمة",
"any": "الكل",
"any_participant": "أي طرف في المراسلة",
"any_recipient": "أي مستلم",
"attachmentName": "اسم المرفق",
"attachmentsSize": "المرفقات والحجم",
"bcc": "نسخة مخفية",
+2
View File
@@ -1001,6 +1001,8 @@
"advanced": "Avanceret",
"advancedFilters": "Avancerede filtre",
"any": "Alle",
"any_participant": "Enhver korrespondent",
"any_recipient": "Enhver modtager",
"attachmentName": "Vedhæftningsfilnavn",
"attachmentsSize": "Vedhæftninger & Størrelse",
"bcc": "Blindkopi (BCC)",
+2
View File
@@ -1001,6 +1001,8 @@
"advanced": "Erweitert",
"advancedFilters": "Erweiterte Filter",
"any": "Beliebig",
"any_participant": "Beliebiger Beteiligter",
"any_recipient": "Beliebiger Empfänger",
"attachmentName": "Anhangsname",
"attachmentsSize": "Anhänge & Größe",
"bcc": "BCC",
+2
View File
@@ -1002,6 +1002,8 @@
"advanced": "Advanced",
"advancedFilters": "Advanced Filters",
"any": "Any",
"any_participant": "Any correspondent",
"any_recipient": "Any recipient",
"attachmentName": "Attachment Name",
"attachmentsSize": "Attachments & Size",
"bcc": "BCC",
+2
View File
@@ -1001,6 +1001,8 @@
"advanced": "Avanzado",
"advancedFilters": "Filtros avanzados",
"any": "Cualquiera",
"any_participant": "Cualquier participante",
"any_recipient": "Cualquier destinatario",
"attachmentName": "Nombre del adjunto",
"attachmentsSize": "Adjuntos y tamaño",
"bcc": "CCO",
+2
View File
@@ -1001,6 +1001,8 @@
"advanced": "Tarkennettu",
"advancedFilters": "Tarkennetut suodattimet",
"any": "Kaikki",
"any_participant": "Kuka tahansa osallistuja",
"any_recipient": "Kuka tahansa vastaanottaja",
"attachmentName": "Liitteen nimi",
"attachmentsSize": "Liitteet ja koko",
"bcc": "Piilokopio",
+2
View File
@@ -1001,6 +1001,8 @@
"advanced": "Avancé",
"advancedFilters": "Filtres Avancés",
"any": "Toutes",
"any_participant": "N'importe quel correspondant",
"any_recipient": "N'importe quel destinataire",
"attachmentName": "Nom de la Pièce Jointe",
"attachmentsSize": "Pièces Jointes et Taille",
"bcc": "Cci",
+2
View File
@@ -1001,6 +1001,8 @@
"advanced": "Avanzato",
"advancedFilters": "Filtri Avanzati",
"any": "Qualsiasi",
"any_participant": "Qualsiasi partecipante",
"any_recipient": "Qualsiasi destinatario",
"attachmentName": "Nome Allegato",
"attachmentsSize": "Allegati e Dimensione",
"bcc": "BCC",
+2
View File
@@ -1001,6 +1001,8 @@
"advanced": "高度な設定",
"advancedFilters": "高度なフィルター",
"any": "指定なし",
"any_participant": "すべての関係者",
"any_recipient": "すべての受信者",
"attachmentName": "添付ファイル名",
"attachmentsSize": "添付ファイルとサイズ",
"bcc": "BCC(ブラインド写し)",
+2
View File
@@ -1001,6 +1001,8 @@
"advanced": "고급",
"advancedFilters": "고급 필터",
"any": "전체",
"any_participant": "모든 관련자",
"any_recipient": "모든 수신자",
"attachmentName": "첨부 파일 이름",
"attachmentsSize": "첨부 파일 및 크기",
"bcc": "숨은 참조",
+2
View File
@@ -1001,6 +1001,8 @@
"advanced": "Geavanceerd",
"advancedFilters": "Geavanceerde Filters",
"any": "Alle",
"any_participant": "Elke correspondent",
"any_recipient": "Elke ontvanger",
"attachmentName": "Naam Bijlage",
"attachmentsSize": "Bijlagen & Grootte",
"bcc": "BCC",
+2
View File
@@ -1001,6 +1001,8 @@
"advanced": "Avansert",
"advancedFilters": "Avanserte filtre",
"any": "Alle",
"any_participant": "Enhver korrespondent",
"any_recipient": "Enhver mottaker",
"attachmentName": "Vedleggsnavn",
"attachmentsSize": "Vedlegg og størrelse",
"bcc": "Blindkopi (BCC)",
+2
View File
@@ -1001,6 +1001,8 @@
"advanced": "Zaawansowane",
"advancedFilters": "Zaawansowane filtry",
"any": "Dowolny",
"any_participant": "Dowolny uczestnik",
"any_recipient": "Dowolny odbiorca",
"attachmentName": "Nazwa załącznika",
"attachmentsSize": "Załączniki & Rozmiar",
"bcc": "UDW",
+2
View File
@@ -1001,6 +1001,8 @@
"advanced": "Avançado",
"advancedFilters": "Filtros Avançados",
"any": "Qualquer",
"any_participant": "Qualquer correspondente",
"any_recipient": "Qualquer destinatario",
"attachmentName": "Nome do Anexo",
"attachmentsSize": "Anexos e Tamanho",
"bcc": "BCC",
+2
View File
@@ -1001,6 +1001,8 @@
"advanced": "Дополнительно",
"advancedFilters": "Расширенные фильтры",
"any": "Любой",
"any_participant": "Любой участник переписки",
"any_recipient": "Любой получатель",
"attachmentName": "Имя вложения",
"attachmentsSize": "Вложения и Размер",
"bcc": "Скрытая копия",
+2
View File
@@ -1001,6 +1001,8 @@
"advanced": "Avancerat",
"advancedFilters": "Avancerade filter",
"any": "Alla",
"any_participant": "Valfri korrespondent",
"any_recipient": "Valfri mottagare",
"attachmentName": "Filnamn på bilaga",
"attachmentsSize": "Bilagor & storlek",
"bcc": "Hemlig kopia (BCC)",
+2
View File
@@ -1001,6 +1001,8 @@
"advanced": "進階",
"advancedFilters": "進階篩選",
"any": "不限",
"any_participant": "任意關聯人",
"any_recipient": "任意收件人",
"attachmentName": "附件名稱",
"attachmentsSize": "附件與大小",
"bcc": "密件副本 (BCC)",
+2
View File
@@ -1001,6 +1001,8 @@
"advanced": "高级",
"advancedFilters": "高级筛选",
"any": "不限",
"any_participant": "任意关联人",
"any_recipient": "任意收件人",
"attachmentName": "附件名称",
"attachmentsSize": "附件和大小",
"bcc": "密送",