imap_client/tasks/tasks/
append.rs1use imap_next::imap_types::{
2 command::CommandBody,
3 datetime::DateTime,
4 extensions::binary::LiteralOrLiteral8,
5 flag::Flag,
6 mailbox::Mailbox,
7 response::{Data, StatusBody, StatusKind},
8};
9use tracing::warn;
10
11use super::TaskError;
12use crate::tasks::Task;
13
14#[derive(Clone, Debug)]
15pub struct AppendTask {
16 mailbox: Mailbox<'static>,
17 flags: Vec<Flag<'static>>,
18 date: Option<DateTime>,
19 message: LiteralOrLiteral8<'static>,
20 output: Option<u32>,
21}
22
23impl AppendTask {
24 pub fn new(mailbox: Mailbox<'static>, message: LiteralOrLiteral8<'static>) -> Self {
25 Self {
26 mailbox,
27 flags: Default::default(),
28 date: Default::default(),
29 message,
30 output: Default::default(),
31 }
32 }
33
34 pub fn set_flags(&mut self, flags: Vec<Flag<'static>>) {
35 self.flags = flags;
36 }
37
38 pub fn add_flag(&mut self, flag: Flag<'static>) {
39 self.flags.push(flag);
40 }
41
42 pub fn with_flags(mut self, flags: Vec<Flag<'static>>) -> Self {
43 self.set_flags(flags);
44 self
45 }
46
47 pub fn with_flag(mut self, flag: Flag<'static>) -> Self {
48 self.add_flag(flag);
49 self
50 }
51
52 pub fn set_date(&mut self, date: DateTime) {
53 self.date = Some(date);
54 }
55
56 pub fn with_date(mut self, date: DateTime) -> Self {
57 self.set_date(date);
58 self
59 }
60}
61
62impl Task for AppendTask {
63 type Output = Result<Option<u32>, TaskError>;
64
65 fn command_body(&self) -> CommandBody<'static> {
66 CommandBody::Append {
67 mailbox: self.mailbox.clone(),
68 flags: self.flags.clone(),
69 date: self.date.clone(),
70 message: self.message.clone(),
71 }
72 }
73
74 fn process_data(&mut self, data: Data<'static>) -> Option<Data<'static>> {
75 if let Data::Exists(seq) = data {
78 if self.output.is_some() {
79 warn!("received duplicate APPEND EXISTS data");
80 }
81 self.output = Some(seq);
82 None
83 } else {
84 Some(data)
85 }
86 }
87
88 fn process_tagged(self, status_body: StatusBody<'static>) -> Self::Output {
89 match status_body.kind {
90 StatusKind::Ok => Ok(self.output),
91 StatusKind::No => Err(TaskError::UnexpectedNoResponse(status_body)),
92 StatusKind::Bad => Err(TaskError::UnexpectedBadResponse(status_body)),
93 }
94 }
95}
96
97#[derive(Clone, Debug, Default)]
104pub struct PostAppendNoOpTask {
105 output: Option<u32>,
106}
107
108impl PostAppendNoOpTask {
109 pub fn new() -> Self {
110 Default::default()
111 }
112}
113
114impl Task for PostAppendNoOpTask {
115 type Output = Result<Option<u32>, TaskError>;
116
117 fn command_body(&self) -> CommandBody<'static> {
118 CommandBody::Noop
119 }
120
121 fn process_data(&mut self, data: Data<'static>) -> Option<Data<'static>> {
122 if let Data::Exists(seq) = data {
123 self.output = Some(seq);
124 None
125 } else {
126 Some(data)
127 }
128 }
129
130 fn process_tagged(self, status_body: StatusBody<'static>) -> Self::Output {
131 match status_body.kind {
132 StatusKind::Ok => Ok(self.output),
133 StatusKind::No => Err(TaskError::UnexpectedNoResponse(status_body)),
134 StatusKind::Bad => Err(TaskError::UnexpectedBadResponse(status_body)),
135 }
136 }
137}
138
139#[derive(Clone, Debug, Default)]
146pub struct PostAppendCheckTask {
147 output: Option<u32>,
148}
149
150impl PostAppendCheckTask {
151 pub fn new() -> Self {
152 Default::default()
153 }
154}
155
156impl Task for PostAppendCheckTask {
157 type Output = Result<Option<u32>, TaskError>;
158
159 fn command_body(&self) -> CommandBody<'static> {
160 CommandBody::Check
161 }
162
163 fn process_data(&mut self, data: Data<'static>) -> Option<Data<'static>> {
164 if let Data::Exists(seq) = data {
165 self.output = Some(seq);
166 None
167 } else {
168 Some(data)
169 }
170 }
171
172 fn process_tagged(self, status_body: StatusBody<'static>) -> Self::Output {
173 match status_body.kind {
174 StatusKind::Ok => Ok(self.output),
175 StatusKind::No => Err(TaskError::UnexpectedNoResponse(status_body)),
176 StatusKind::Bad => Err(TaskError::UnexpectedBadResponse(status_body)),
177 }
178 }
179}