forked from Enough-Software/enough_mail
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathresponse.dart
More file actions
277 lines (219 loc) · 7.21 KB
/
Copy pathresponse.dart
File metadata and controls
277 lines (219 loc) · 7.21 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
import '../../enough_mail.dart';
/// Status for command responses.
enum ResponseStatus {
/// The response completed successfully
ok,
/// The command is not supported
no,
/// The command is supported but the client send a wrong request
/// or is a wrong state
bad,
}
/// Base class for command responses.
class Response<T> {
/// The status, either OK or Failed
ResponseStatus? status;
/// The textual response details
String? details;
/// The result of the operation
T? result;
/// Returns `true` when the response status is OK
bool get isOkStatus => status == ResponseStatus.ok;
/// Returns `true` when the response status is not ok
bool get isFailedStatus => !isOkStatus;
}
/// A generic result that provide details about the success or failure
/// of the command.
class GenericImapResult {
/// A list of possible warnings
final List<ImapWarning> warnings = <ImapWarning>[];
/// Optional response code as text
String? responseCode;
/// Optional details as text
String? details;
/// Retrieves the APPENDUID details after an APPEND call,
/// compare https://tools.ietf.org/html/rfc4315
UidResponseCode? get responseCodeAppendUid =>
_parseUidResponseCode('APPENDUID');
/// Retrieves the COPYUID details after an COPY call,
/// compare https://tools.ietf.org/html/rfc4315
UidResponseCode? get responseCodeCopyUid => _parseUidResponseCode('COPYUID');
UidResponseCode? _parseUidResponseCode(String name) {
final responseCode = this.responseCode;
if (responseCode != null && responseCode.startsWith(name)) {
final uidParts = responseCode.substring(name.length + 1).split(' ');
if (uidParts.length == 3) {
if (uidParts[1].isEmpty || uidParts[2].isEmpty) {
return null;
}
return UidResponseCode(
int.parse(uidParts[0]),
MessageSequence.parse(uidParts[1], isUidSequence: true),
MessageSequence.parse(uidParts[2], isUidSequence: true),
);
} else if (uidParts.length == 2) {
if (uidParts[1].isEmpty) {
return null;
}
return UidResponseCode(
int.parse(uidParts[0]),
null,
MessageSequence.parse(uidParts[1], isUidSequence: true),
);
}
}
return null;
}
}
/// Result for FETCH operations
class FetchImapResult {
/// Creates a new fetch result
const FetchImapResult(
this.messages,
this.vanishedMessagesUidSequence, {
this.modifiedSequence,
});
/// Any messages that have been removed by other clients.
/// This is only given from QRESYNC compliant servers after having enabled
/// `QRESYNC` by the client.
/// Clients must NOT use these vanished sequence to update their
/// internal sequence IDs, because
/// they have happened earlier.
/// Compare https://tools.ietf.org/html/rfc7162 for details.
final MessageSequence? vanishedMessagesUidSequence;
/// The sequence of messages that have been modified
final MessageSequence? modifiedSequence;
/// The requested messages
final List<MimeMessage> messages;
/// Replaces matching messages
void replaceMatchingMessages(List<MimeMessage> newMessages) {
for (final mime in newMessages) {
final uid = mime.uid;
final sequenceId = mime.sequenceId;
if (uid != null) {
final index = messages.indexWhere((msg) => msg.uid == uid);
if (index != -1) {
messages[index] = mime;
}
} else if (sequenceId != null) {
final index =
messages.indexWhere((msg) => msg.sequenceId == sequenceId);
if (index != -1) {
messages[index] = mime;
}
}
}
}
}
/// Result for STORE and UID STORE operations
class StoreImapResult {
/// A list of messages that have been updated
List<MimeMessage>? changedMessages;
/// A list of IDs of messages that have been modified on the server side.
/// The IDs are sequence IDs for STORE and UIDs for UID STORE commands.
/// The modified IDs can only be returned when the unchangedSinceModSequence
/// parameter has been specified.
MessageSequence? modifiedMessageSequence;
}
/// Result for SEARCH and UID SEARCH operations
class SearchImapResult {
/// A list of message IDs
MessageSequence? matchingSequence;
/// The highest modification sequence in the searched messages
/// The modification sequence can only be returned when the `MODSEQ` search
/// criteria has been used and when the server supports the
/// `CONDSTORE` capability.
int? highestModSequence;
/// Identifies an extended search result
bool? isExtended;
/// Result tag
String? tag;
/// Minimum found message ID or UID
int? min;
/// Maximum found message ID or UID
int? max;
/// Matches count
int? count;
/// Range of the partial result returned
String? partialRange;
/// Is this a partial search response?
bool get isPartial {
final partialRange = this.partialRange;
return partialRange != null && partialRange.isNotEmpty;
}
}
/// Contains a UID response code
class UidResponseCode {
/// Creates a new response code
const UidResponseCode(
this.uidValidity,
this.originalSequence,
this.targetSequence,
);
/// The UID validity
final int uidValidity;
/// The optional original sequence
final MessageSequence? originalSequence;
/// The optional target sequence
final MessageSequence targetSequence;
}
/// Warnings can often be ignored but provide more insights in case of problems
/// They are given in untagged responses of the server.
class ImapWarning {
/// Creates a new warning instance
const ImapWarning(this.type, this.details);
/// Either 'BAD' or 'NO'
final String type;
/// The human readable error
final String details;
}
/// Result for QUOTA operations
class QuotaResult {
/// Creates a new quota result
const QuotaResult(this.rootName, this.resourceLimits);
/// The optional name of the root
final String? rootName;
/// The resource limits
final List<ResourceLimit> resourceLimits;
}
/// Result for QUOTAROOT operations
class QuotaRootResult {
/// Creates a new quota root result
QuotaRootResult(this.mailboxName, this.rootNames);
/// The name of the associated mailbox
final String mailboxName;
/// All names in this root
final List<String> rootNames;
/// The quota results
Map<String?, QuotaResult> quotaRoots = {};
}
/// Result for SORT and UID SORT operations
///
/// Copy of [SearchImapResult] class because SEARCH and SORT are equivalents
class SortImapResult {
/// A list of message IDs
MessageSequence? matchingSequence;
/// The highest modification sequence in the searched messages
///
/// The modification sequence can only be returned when the `MODSEQ` search
/// criteria has been used and when the server supports the
/// `CONDSTORE` capability.
int? highestModSequence;
/// Signals an extended sort result
bool? isExtended;
/// Result tag
String? tag;
/// Minimum found message ID or UID
int? min;
/// Maximum found message ID or UID
int? max;
/// Matches count
int? count;
/// Range of the partial result returned
String? partialRange;
/// Is this a partial response?
bool get isPartial {
final partialRange = this.partialRange;
return partialRange != null && partialRange.isNotEmpty;
}
}