Skip to main content

sieve/runtime/
handler.rs

1/*
2 * SPDX-FileCopyrightText: 2020 Stalwart Labs Ltd <hello@stalw.art>
3 *
4 * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
5 */
6
7use crate::{
8    Context, Envelope, ExternalId, Importance, MatchAs, Sieve,
9    compiler::grammar::actions::action_redirect::{ByTime, Notify, Ret},
10    runtime::{RuntimeError, Variable},
11};
12
13#[derive(Debug, Clone, PartialEq, Eq)]
14pub enum Reply<T> {
15    Ready(T),
16    Pending,
17    Error(RuntimeError),
18}
19
20#[derive(Debug, Clone, Copy, PartialEq, Eq)]
21pub enum Status {
22    Finished,
23    Pending,
24}
25
26#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
27pub enum Script<'a> {
28    Personal(&'a str),
29    Global(&'a str),
30}
31
32#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
33pub enum Mailbox<'a> {
34    Name(&'a str),
35    Id(&'a str),
36}
37
38#[derive(Debug, Clone, PartialEq, Eq)]
39pub enum Recipient<'a> {
40    Address(&'a str),
41    List(&'a str),
42    Group(Vec<&'a str>),
43}
44
45#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
46pub enum MessageSource {
47    Redirect,
48    Vacation,
49    Notification,
50}
51
52#[derive(Debug, PartialEq, Eq)]
53pub enum Action<'a> {
54    Keep {
55        flags: &'a [&'a str],
56        message_id: usize,
57    },
58    Discard,
59    Reject {
60        extended: bool,
61        reason: &'a str,
62    },
63    FileInto {
64        folder: &'a str,
65        flags: &'a [&'a str],
66        mailbox_id: Option<&'a str>,
67        special_use: Option<&'a str>,
68        create: bool,
69        message_id: usize,
70    },
71    SendMessage {
72        source: MessageSource,
73        recipient: Recipient<'a>,
74        notify: Notify,
75        return_of_content: Ret,
76        by_time: ByTime<i64>,
77        message_id: usize,
78    },
79    Notify {
80        from: Option<&'a str>,
81        importance: Importance,
82        options: &'a [&'a str],
83        message: &'a str,
84        method: &'a str,
85    },
86    SetEnvelope {
87        envelope: Envelope,
88        value: &'a str,
89    },
90    CreatedMessage {
91        message_id: usize,
92        message: Vec<u8>,
93    },
94}
95
96#[derive(Debug, Clone)]
97pub enum Input<'x> {
98    Bool(bool),
99    Value(Variable<'x>),
100    Script(Option<&'x Sieve<'x>>),
101    Continue,
102}
103
104impl From<bool> for Input<'_> {
105    fn from(value: bool) -> Self {
106        Input::Bool(value)
107    }
108}
109
110impl<'x> From<Variable<'x>> for Input<'x> {
111    fn from(value: Variable<'x>) -> Self {
112        Input::Value(value)
113    }
114}
115
116impl<'x> From<Option<&'x Sieve<'x>>> for Input<'x> {
117    fn from(value: Option<&'x Sieve<'x>>) -> Self {
118        Input::Script(value)
119    }
120}
121
122impl<'x> From<&'x Sieve<'x>> for Input<'x> {
123    fn from(value: &'x Sieve<'x>) -> Self {
124        Input::Script(Some(value))
125    }
126}
127
128impl<T> From<T> for Reply<T> {
129    fn from(value: T) -> Self {
130        Reply::Ready(value)
131    }
132}
133
134impl<'a> Script<'a> {
135    pub fn name(&self) -> &'a str {
136        match self {
137            Script::Personal(name) | Script::Global(name) => name,
138        }
139    }
140
141    pub fn is_global(&self) -> bool {
142        matches!(self, Script::Global(_))
143    }
144}
145
146impl std::fmt::Display for Script<'_> {
147    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
148        f.write_str(self.name())
149    }
150}
151
152#[allow(unused_variables)]
153pub trait Handler<'x> {
154    fn include_script(
155        &mut self,
156        ctx: &Context<'x>,
157        name: Script<'_>,
158        optional: bool,
159    ) -> Reply<Option<&'x Sieve<'x>>> {
160        Reply::Ready(None)
161    }
162
163    fn mailbox_exists(
164        &mut self,
165        ctx: &Context<'x>,
166        mailboxes: &[Mailbox<'_>],
167        special_use: &[&str],
168    ) -> Reply<bool> {
169        Reply::Ready(false)
170    }
171
172    fn list_contains(
173        &mut self,
174        ctx: &Context<'x>,
175        lists: &[&str],
176        values: &[&str],
177        match_as: MatchAs,
178    ) -> Reply<bool> {
179        Reply::Ready(false)
180    }
181
182    fn duplicate_id(
183        &mut self,
184        ctx: &Context<'x>,
185        id: &str,
186        expiry: u64,
187        last: bool,
188    ) -> Reply<bool> {
189        Reply::Ready(false)
190    }
191
192    fn function(
193        &mut self,
194        ctx: &Context<'x>,
195        id: ExternalId,
196        arguments: &[Variable<'x>],
197    ) -> Reply<Variable<'x>> {
198        Reply::Ready(Variable::default())
199    }
200
201    fn action(&mut self, ctx: &Context<'x>, action: Action<'x>) -> Reply<()> {
202        Reply::Ready(())
203    }
204}