net-imap 0.1.1 → 0.2.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,106 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "errors"
4
+
5
+ module Net
6
+ class IMAP < Protocol
7
+
8
+ # Decode a string from modified UTF-7 format to UTF-8.
9
+ #
10
+ # UTF-7 is a 7-bit encoding of Unicode [UTF7]. IMAP uses a
11
+ # slightly modified version of this to encode mailbox names
12
+ # containing non-ASCII characters; see [IMAP] section 5.1.3.
13
+ #
14
+ # Net::IMAP does _not_ automatically encode and decode
15
+ # mailbox names to and from UTF-7.
16
+ def self.decode_utf7(s)
17
+ return s.gsub(/&([^-]+)?-/n) {
18
+ if $1
19
+ ($1.tr(",", "/") + "===").unpack1("m").encode(Encoding::UTF_8, Encoding::UTF_16BE)
20
+ else
21
+ "&"
22
+ end
23
+ }
24
+ end
25
+
26
+ # Encode a string from UTF-8 format to modified UTF-7.
27
+ def self.encode_utf7(s)
28
+ return s.gsub(/(&)|[^\x20-\x7e]+/) {
29
+ if $1
30
+ "&-"
31
+ else
32
+ base64 = [$&.encode(Encoding::UTF_16BE)].pack("m0")
33
+ "&" + base64.delete("=").tr("/", ",") + "-"
34
+ end
35
+ }.force_encoding("ASCII-8BIT")
36
+ end
37
+
38
+ # Formats +time+ as an IMAP-style date.
39
+ def self.format_date(time)
40
+ return time.strftime('%d-%b-%Y')
41
+ end
42
+
43
+ # Formats +time+ as an IMAP-style date-time.
44
+ def self.format_datetime(time)
45
+ return time.strftime('%d-%b-%Y %H:%M %z')
46
+ end
47
+
48
+ # Common validators of number and nz_number types
49
+ module NumValidator # :nodoc
50
+ module_function
51
+
52
+ # Check is passed argument valid 'number' in RFC 3501 terminology
53
+ def valid_number?(num)
54
+ # [RFC 3501]
55
+ # number = 1*DIGIT
56
+ # ; Unsigned 32-bit integer
57
+ # ; (0 <= n < 4,294,967,296)
58
+ num >= 0 && num < 4294967296
59
+ end
60
+
61
+ # Check is passed argument valid 'nz_number' in RFC 3501 terminology
62
+ def valid_nz_number?(num)
63
+ # [RFC 3501]
64
+ # nz-number = digit-nz *DIGIT
65
+ # ; Non-zero unsigned 32-bit integer
66
+ # ; (0 < n < 4,294,967,296)
67
+ num != 0 && valid_number?(num)
68
+ end
69
+
70
+ # Check is passed argument valid 'mod_sequence_value' in RFC 4551 terminology
71
+ def valid_mod_sequence_value?(num)
72
+ # mod-sequence-value = 1*DIGIT
73
+ # ; Positive unsigned 64-bit integer
74
+ # ; (mod-sequence)
75
+ # ; (1 <= n < 18,446,744,073,709,551,615)
76
+ num >= 1 && num < 18446744073709551615
77
+ end
78
+
79
+ # Ensure argument is 'number' or raise DataFormatError
80
+ def ensure_number(num)
81
+ return if valid_number?(num)
82
+
83
+ msg = "number must be unsigned 32-bit integer: #{num}"
84
+ raise DataFormatError, msg
85
+ end
86
+
87
+ # Ensure argument is 'nz_number' or raise DataFormatError
88
+ def ensure_nz_number(num)
89
+ return if valid_nz_number?(num)
90
+
91
+ msg = "nz_number must be non-zero unsigned 32-bit integer: #{num}"
92
+ raise DataFormatError, msg
93
+ end
94
+
95
+ # Ensure argument is 'mod_sequence_value' or raise DataFormatError
96
+ def ensure_mod_sequence_value(num)
97
+ return if valid_mod_sequence_value?(num)
98
+
99
+ msg = "mod_sequence_value must be unsigned 64-bit integer: #{num}"
100
+ raise DataFormatError, msg
101
+ end
102
+
103
+ end
104
+
105
+ end
106
+ end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Net
4
+ class IMAP < Protocol
5
+
6
+ # Superclass of IMAP errors.
7
+ class Error < StandardError
8
+ end
9
+
10
+ # Error raised when data is in the incorrect format.
11
+ class DataFormatError < Error
12
+ end
13
+
14
+ # Error raised when a response from the server is non-parseable.
15
+ class ResponseParseError < Error
16
+ end
17
+
18
+ # Superclass of all errors used to encapsulate "fail" responses
19
+ # from the server.
20
+ class ResponseError < Error
21
+
22
+ # The response that caused this error
23
+ attr_accessor :response
24
+
25
+ def initialize(response)
26
+ @response = response
27
+
28
+ super @response.data.text
29
+ end
30
+
31
+ end
32
+
33
+ # Error raised upon a "NO" response from the server, indicating
34
+ # that the client command could not be completed successfully.
35
+ class NoResponseError < ResponseError
36
+ end
37
+
38
+ # Error raised upon a "BAD" response from the server, indicating
39
+ # that the client command violated the IMAP protocol, or an internal
40
+ # server failure has occurred.
41
+ class BadResponseError < ResponseError
42
+ end
43
+
44
+ # Error raised upon a "BYE" response from the server, indicating
45
+ # that the client is not being allowed to login, or has been timed
46
+ # out due to inactivity.
47
+ class ByeResponseError < ResponseError
48
+ end
49
+
50
+ # Error raised upon an unknown response from the server.
51
+ class UnknownResponseError < ResponseError
52
+ end
53
+
54
+ RESPONSE_ERRORS = Hash.new(ResponseError)
55
+ RESPONSE_ERRORS["NO"] = NoResponseError
56
+ RESPONSE_ERRORS["BAD"] = BadResponseError
57
+
58
+ end
59
+ end
@@ -0,0 +1,234 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Net
4
+ class IMAP < Protocol
5
+
6
+ # -------------------------------------------------------------------------
7
+ # :section: Message Flags: system flags
8
+ #
9
+ # A message has a list of zero or more named tokens, known as "flags",
10
+ # associated with it. A flag is set by its addition to this list and is
11
+ # cleared by its removal. There are two types of flags in IMAP4rev2: system
12
+ # flags and keywords. A flag of either type can be permanent or
13
+ # session-only.
14
+ #
15
+ # A "system flag" is a message flag name that is predefined in the IMAP
16
+ # specification and begins with "\". +Net::IMAP+ returns all system flags
17
+ # as symbols, without the "\" prefix.
18
+ #
19
+ # The descriptions here were copied from the IMAP4rev2 specification:
20
+ # [RFC-9051 § 2.3.2](https://www.rfc-editor.org/rfc/rfc9051.html#section-2.3.2)
21
+ #
22
+ # See [RFC-3501 § 2.3.2](https://www.rfc-editor.org/rfc/rfc3501.html#section-2.3.2)
23
+ # for a description of the flags message attribute and system flag semantics
24
+ # in IMAP4rev1.
25
+ # -------------------------------------------------------------------------
26
+
27
+ # Flag indicating a message has been read.
28
+ SEEN = :Seen
29
+
30
+ # Flag indicating a message has been answered.
31
+ ANSWERED = :Answered
32
+
33
+ # A message flag indicating a message has been flagged for special or urgent
34
+ # attention.
35
+ #
36
+ # Also a mailbox special use attribute, which indicates that this mailbox
37
+ # presents all messages marked in some way as "important". When this
38
+ # special use is supported, it is likely to represent a virtual mailbox
39
+ # collecting messages (from other mailboxes) that are marked with the
40
+ # "\Flagged" message flag.
41
+ FLAGGED = :Flagged
42
+
43
+ # Flag indicating a message has been marked for deletion. This
44
+ # will occur when the mailbox is closed or expunged.
45
+ DELETED = :Deleted
46
+
47
+ # Flag indicating a message is only a draft or work-in-progress version.
48
+ DRAFT = :Draft
49
+
50
+ # Flag indicating that the message is "recent," meaning that this
51
+ # session is the first session in which the client has been notified
52
+ # of this message.
53
+ #
54
+ # This flag was defined by
55
+ # IMAP4rev1 [RFC-3501](https://www.rfc-editor.org/rfc/rfc3501.html),
56
+ # and has been deprecated by
57
+ # IMAP4rev2 [RFC-9051](https://www.rfc-editor.org/rfc/rfc9051.html).
58
+ RECENT = :Recent
59
+
60
+ # -------------------------------------------------------------------------
61
+ # :section: Mailbox Name Attributes, Base attributes
62
+ # Mailbox name attributes will be returned in LIST responses. Base
63
+ # attributes must be returned according to the server's capabilities.
64
+ #
65
+ # IMAP4 specifies that all mailbox name attributes, including future
66
+ # extensions, begin with "\". +Net::IMAP+ returns all mailbox attributes as
67
+ # symbols, without the "\" prefix.
68
+ #
69
+ # The descriptions here were copied from the IMAP4rev2 specification:
70
+ # [RFC9051 § 7.3.1](https://www.rfc-editor.org/rfc/rfc9051.html#section-7.3.1).
71
+ #
72
+ # Other mailbox name attributes can be found in the [IANA IMAP Mailbox Name
73
+ # Attributes registry](https://www.iana.org/assignments/imap-mailbox-name-attributes/imap-mailbox-name-attributes.xhtml)].
74
+ # -------------------------------------------------------------------------
75
+
76
+ # The "\NonExistent" attribute indicates that a mailbox name does not refer
77
+ # to an existing mailbox. Note that this attribute is not meaningful by
78
+ # itself, as mailbox names that match the canonical LIST pattern but don't
79
+ # exist must not be returned unless one of the two conditions listed below
80
+ # is also satisfied:
81
+ #
82
+ # 1. The mailbox name also satisfies the selection criteria (for example,
83
+ # it is subscribed and the "SUBSCRIBED" selection option has been
84
+ # specified).
85
+ #
86
+ # 2. "RECURSIVEMATCH" has been specified, and the mailbox name has at least
87
+ # one descendant mailbox name that does not match the LIST pattern and
88
+ # does match the selection criteria.
89
+ #
90
+ # In practice, this means that the "\NonExistent" attribute is usually
91
+ # returned with one or more of "\Subscribed", "\Remote", "\HasChildren", or
92
+ # the CHILDINFO extended data item.
93
+ #
94
+ # The client must treat the presence of the \NonExistent attribute as if the
95
+ # \NoSelect attribute was also sent by the server
96
+ NONEXISTENT = :NonExistent
97
+
98
+ # Mailbox attribute indicating it is not possible for any child levels of
99
+ # hierarchy to exist under this name; no child levels exist now and none can
100
+ # be created in the future children.
101
+ #
102
+ # The client must treat the presence of the \NoInferiors attribute as if the
103
+ # \HasNoChildren attribute was also sent by the server
104
+ NOINFERIORS = :Noinferiors
105
+
106
+ # Mailbox attribute indicating it is not possible to use this name as a
107
+ # selectable mailbox.
108
+ NOSELECT = :Noselect
109
+
110
+ # The presence of this attribute indicates that the mailbox has child
111
+ # mailboxes. A server SHOULD NOT set this attribute if there are child
112
+ # mailboxes and the user does not have permission to access any of them. In
113
+ # this case, \HasNoChildren SHOULD be used. In many cases, however, a server
114
+ # may not be able to efficiently compute whether a user has access to any
115
+ # child mailboxes. Note that even though the \HasChildren attribute for a
116
+ # mailbox must be correct at the time of processing the mailbox, a client
117
+ # must be prepared to deal with a situation when a mailbox is marked with
118
+ # the \HasChildren attribute, but no child mailbox appears in the response
119
+ # to the LIST command. This might happen, for example, due to child
120
+ # mailboxes being deleted or made inaccessible to the user (using access
121
+ # control) by another client before the server is able to list them.
122
+ #
123
+ # It is an error for the server to return both a \HasChildren and a
124
+ # \HasNoChildren attribute in the same LIST response. A client that
125
+ # encounters a LIST response with both \HasChildren and \HasNoChildren
126
+ # attributes present should act as if both are absent in the LIST response.
127
+ HAS_CHILDREN = :HasChildren
128
+
129
+ # The presence of this attribute indicates that the mailbox has NO child
130
+ # mailboxes that are accessible to the currently authenticated user.
131
+ #
132
+ # It is an error for the server to return both a \HasChildren and a
133
+ # \HasNoChildren attribute in the same LIST response. A client that
134
+ # encounters a LIST response with both \HasChildren and \HasNoChildren
135
+ # attributes present should act as if both are absent in the LIST response.
136
+ #
137
+ # Note: the \HasNoChildren attribute should not be confused with the
138
+ # \NoInferiors attribute, which indicates that no child mailboxes exist now
139
+ # and none can be created in the future.
140
+ HAS_NO_CHILDREN = :HasNoChildren
141
+
142
+ # The mailbox has been marked "interesting" by the server; the mailbox
143
+ # probably contains messages that have been added since the last time the
144
+ # mailbox was selected.
145
+ #
146
+ # If it is not feasible for the server to determine whether or not the
147
+ # mailbox is "interesting", the server SHOULD NOT send either \Marked or
148
+ # \Unmarked. The server MUST NOT send more than one of \Marked, \Unmarked,
149
+ # and \Noselect for a single mailbox, and it MAY send none of these.
150
+ MARKED = :Marked
151
+
152
+ # The mailbox does not contain any additional messages since the last time
153
+ # the mailbox was selected.
154
+ #
155
+ # If it is not feasible for the server to determine whether or not the
156
+ # mailbox is "interesting", the server SHOULD NOT send either \Marked or
157
+ # \Unmarked. The server MUST NOT send more than one of \Marked, \Unmarked,
158
+ # and \Noselect for a single mailbox, and it MAY send none of these.
159
+ UNMARKED = :Unmarked
160
+
161
+ # The mailbox name was subscribed to using the SUBSCRIBE command.
162
+ SUBSCRIBED = :Subscribed
163
+
164
+ # The mailbox is a remote mailbox.
165
+ REMOTE = :Remove
166
+
167
+ # -------------------------------------------------------------------------
168
+ # :section: Mailbox Name Attributes, Special Use
169
+ # Mailbox name attributes will be returned in LIST responses. In addition
170
+ # to the base mailbox name attributes defined above, an IMAP server MAY also
171
+ # include any or all of the following attributes that denote "role" (or
172
+ # "special-use") of a mailbox. These attributes are included along with base
173
+ # attributes defined above. A given mailbox may have none, one, or more than
174
+ # one of these attributes. In some cases, a special use is advice to a
175
+ # client about what to put in that mailbox. In other cases, it's advice to a
176
+ # client about what to expect to find there.
177
+ #
178
+ # IMAP4 specifies that all mailbox name attributes, including future
179
+ # extensions, begin with "\". +Net::IMAP+ returns all mailbox attributes as
180
+ # symbols, without the "\" prefix.
181
+ #
182
+ # The descriptions here were copied from the IMAP4rev2 specification:
183
+ # [RFC-9051 § 7.3.1](https://www.rfc-editor.org/rfc/rfc9051.html#section-7.3.1).
184
+ #
185
+ # Other mailbox name attributes can be found in the [IANA IMAP Mailbox Name
186
+ # Attributes registry](https://www.iana.org/assignments/imap-mailbox-name-attributes/imap-mailbox-name-attributes.xhtml)].
187
+ # -------------------------------------------------------------------------
188
+
189
+ # Mailbox attribute indicating that this mailbox presents all messages in
190
+ # the user's message store. Implementations MAY omit some messages, such as,
191
+ # perhaps, those in \Trash and \Junk. When this special use is supported, it
192
+ # is almost certain to represent a virtual mailbox
193
+ ALL = :All
194
+
195
+ # Mailbox attribute indicating that this mailbox is used to archive
196
+ # messages. The meaning of an "archival" mailbox is server dependent;
197
+ # typically, it will be used to get messages out of the inbox, or otherwise
198
+ # keep them out of the user's way, while still making them accessible
199
+ ARCHIVE = :Archive
200
+
201
+ # Mailbox attribute indicating that this mailbox is used to hold draft
202
+ # messages -- typically, messages that are being composed but have not yet
203
+ # been sent. In some server implementations, this might be a virtual
204
+ # mailbox, containing messages from other mailboxes that are marked with the
205
+ # "\Draft" message flag. Alternatively, this might just be advice that a
206
+ # client put drafts here
207
+ DRAFTS = :Drafts
208
+
209
+ # FLAGGED is defined with the system flags section.
210
+
211
+ # Mailbox attribute indicating that this mailbox is where messages deemed to
212
+ # be junk mail are held. Some server implementations might put messages here
213
+ # automatically. Alternatively, this might just be advice to a client-side
214
+ # spam filter.
215
+ JUNK = :Junk
216
+
217
+ # Mailbox attribute indicating that this mailbox is used to hold copies of
218
+ # messages that have been sent. Some server implementations might put
219
+ # messages here automatically. Alternatively, this might just be advice that
220
+ # a client save sent messages here.
221
+ SENT = :Sent
222
+
223
+ # Mailbox attribute indicating that this mailbox is used to hold messages
224
+ # that have been deleted or marked for deletion. In some server
225
+ # implementations, this might be a virtual mailbox, containing messages from
226
+ # other mailboxes that are marked with the "\Deleted" message flag.
227
+ # Alternatively, this might just be advice that a client that chooses not to
228
+ # use the IMAP "\Deleted" model should use as its trash location. In server
229
+ # implementations that strictly expect the IMAP "\Deleted" model, this
230
+ # special use is likely not to be supported.
231
+ TRASH = :Trash
232
+
233
+ end
234
+ end