extract-msg 0.48.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. extract_msg/__init__.py +71 -0
  2. extract_msg/__main__.py +115 -0
  3. extract_msg/_rtf/__init__.py +21 -0
  4. extract_msg/_rtf/create_doc.py +29 -0
  5. extract_msg/_rtf/inject_rtf.py +174 -0
  6. extract_msg/_rtf/token.py +35 -0
  7. extract_msg/_rtf/tokenize_rtf.py +253 -0
  8. extract_msg/attachments/__init__.py +144 -0
  9. extract_msg/attachments/attachment.py +188 -0
  10. extract_msg/attachments/attachment_base.py +730 -0
  11. extract_msg/attachments/broken_att.py +42 -0
  12. extract_msg/attachments/custom_att.py +173 -0
  13. extract_msg/attachments/custom_att_handler/__init__.py +80 -0
  14. extract_msg/attachments/custom_att_handler/custom_handler.py +134 -0
  15. extract_msg/attachments/custom_att_handler/lnk_obj_att.py +109 -0
  16. extract_msg/attachments/custom_att_handler/outlook_image_dib.py +141 -0
  17. extract_msg/attachments/emb_msg_att.py +134 -0
  18. extract_msg/attachments/signed_att.py +234 -0
  19. extract_msg/attachments/unsupported_att.py +40 -0
  20. extract_msg/attachments/web_att.py +74 -0
  21. extract_msg/constants/__init__.py +294 -0
  22. extract_msg/constants/ps.py +46 -0
  23. extract_msg/constants/re.py +42 -0
  24. extract_msg/constants/st.py +110 -0
  25. extract_msg/data/logging-config/logging-nt.json +64 -0
  26. extract_msg/data/logging-config/logging-posix.json +64 -0
  27. extract_msg/encoding/__init__.py +277 -0
  28. extract_msg/encoding/_dt/__init__.py +4 -0
  29. extract_msg/encoding/_dt/_mac_ce.py +8 -0
  30. extract_msg/encoding/_dt/_mac_cyrillic.py +8 -0
  31. extract_msg/encoding/_dt/_mac_greek.py +8 -0
  32. extract_msg/encoding/_dt/_mac_iceland.py +8 -0
  33. extract_msg/encoding/_dt/_mac_turkish.py +8 -0
  34. extract_msg/encoding/_dt/_win874_dec.py +8 -0
  35. extract_msg/encoding/_dt/_win950_dec.py +6 -0
  36. extract_msg/encoding/utils.py +329 -0
  37. extract_msg/enums.py +2067 -0
  38. extract_msg/exceptions.py +170 -0
  39. extract_msg/msg_classes/__init__.py +49 -0
  40. extract_msg/msg_classes/appointment.py +195 -0
  41. extract_msg/msg_classes/calendar.py +92 -0
  42. extract_msg/msg_classes/calendar_base.py +496 -0
  43. extract_msg/msg_classes/contact.py +1335 -0
  44. extract_msg/msg_classes/journal.py +131 -0
  45. extract_msg/msg_classes/meeting_cancellation.py +108 -0
  46. extract_msg/msg_classes/meeting_exception.py +55 -0
  47. extract_msg/msg_classes/meeting_forward.py +115 -0
  48. extract_msg/msg_classes/meeting_related.py +65 -0
  49. extract_msg/msg_classes/meeting_request.py +189 -0
  50. extract_msg/msg_classes/meeting_response.py +74 -0
  51. extract_msg/msg_classes/message.py +12 -0
  52. extract_msg/msg_classes/message_base.py +1382 -0
  53. extract_msg/msg_classes/message_signed.py +17 -0
  54. extract_msg/msg_classes/message_signed_base.py +168 -0
  55. extract_msg/msg_classes/msg.py +1172 -0
  56. extract_msg/msg_classes/post.py +53 -0
  57. extract_msg/msg_classes/sticky_note.py +67 -0
  58. extract_msg/msg_classes/task.py +363 -0
  59. extract_msg/msg_classes/task_request.py +86 -0
  60. extract_msg/null_date.py +34 -0
  61. extract_msg/ole_writer.py +1086 -0
  62. extract_msg/open_msg.py +204 -0
  63. extract_msg/properties/__init__.py +23 -0
  64. extract_msg/properties/named.py +481 -0
  65. extract_msg/properties/prop.py +506 -0
  66. extract_msg/properties/properties_store.py +476 -0
  67. extract_msg/py.typed +0 -0
  68. extract_msg/recipient.py +362 -0
  69. extract_msg/structures/__init__.py +34 -0
  70. extract_msg/structures/_helpers.py +345 -0
  71. extract_msg/structures/business_card.py +422 -0
  72. extract_msg/structures/cfoas.py +108 -0
  73. extract_msg/structures/contact_link_entry.py +51 -0
  74. extract_msg/structures/dev_mode_a.py +621 -0
  75. extract_msg/structures/dv_target_device.py +168 -0
  76. extract_msg/structures/entry_id.py +697 -0
  77. extract_msg/structures/misc_id.py +222 -0
  78. extract_msg/structures/mon_stream.py +55 -0
  79. extract_msg/structures/odt.py +74 -0
  80. extract_msg/structures/ole_pres.py +302 -0
  81. extract_msg/structures/ole_stream_struct.py +117 -0
  82. extract_msg/structures/recurrence_pattern.py +199 -0
  83. extract_msg/structures/report_tag.py +127 -0
  84. extract_msg/structures/system_time.py +158 -0
  85. extract_msg/structures/time_zone_definition.py +111 -0
  86. extract_msg/structures/time_zone_struct.py +102 -0
  87. extract_msg/structures/toc_entry.py +137 -0
  88. extract_msg/structures/tz_rule.py +148 -0
  89. extract_msg/utils.py +1270 -0
  90. extract_msg-0.48.2.dist-info/LICENSE.txt +674 -0
  91. extract_msg-0.48.2.dist-info/METADATA +321 -0
  92. extract_msg-0.48.2.dist-info/RECORD +95 -0
  93. extract_msg-0.48.2.dist-info/WHEEL +5 -0
  94. extract_msg-0.48.2.dist-info/entry_points.txt +2 -0
  95. extract_msg-0.48.2.dist-info/top_level.txt +1 -0
@@ -0,0 +1,117 @@
1
+ __all__ = [
2
+ 'OleStreamStruct',
3
+ ]
4
+
5
+
6
+ from typing import final, Optional
7
+
8
+ from ..constants import st
9
+ from ._helpers import BytesReader
10
+ from .mon_stream import MonikerStream
11
+
12
+
13
+ @final
14
+ class OleStreamStruct:
15
+ """
16
+ The OLEStream structure, as specified in [MS-OLEDS].
17
+
18
+ Specifically, this is *only* the version that is used for embedded objects.
19
+ As such, only some of the fields are ever present.
20
+ """
21
+
22
+ def __init__(self, data: Optional[bytes] = None):
23
+ """
24
+ :raises TypeError: The data given is not for an embedded object.
25
+ """
26
+ self.__rms = None
27
+ if not data:
28
+ self.__flags = 0
29
+ self.__linkUpdateOption = 0
30
+ return
31
+ reader = BytesReader(data)
32
+ # Assert the version.
33
+ reader.assertRead(b'\x01\x00\x00\x02', 'Ole stream had invalid version (expected {expected}, got {actual}).')
34
+ self.__flags = reader.readUnsignedInt()
35
+ if self.__flags & 1:
36
+ raise TypeError('Cannot parse an OLEStream structure for a linked object.')
37
+ self.__linkUpdateOption = reader.readUnsignedInt()
38
+ reader.assertNull(4, 'Ole stream reserved was not null (got {actual}).')
39
+ rmsSize = reader.readUnsignedInt()
40
+ if rmsSize > 0:
41
+ self.__rms = MonikerStream(reader.read(rmsSize - 4))
42
+
43
+ def __bytes__(self) -> bytes:
44
+ return self.toBytes()
45
+
46
+ def toBytes(self) -> bytes:
47
+ ret = b'\x01\x00\x00\x02'
48
+ ret += st.ST_LE_UI32.pack(self.__flags)
49
+ ret += st.ST_LE_UI32.pack(self.__linkUpdateOption)
50
+ ret += b'\x00\x00\x00\x00'
51
+ rmsBytes = b'' if self.__rms is None else bytes(self.__rms)
52
+ rmsLen = (len(rmsBytes) + 4) if rmsBytes else 0
53
+ ret += st.ST_LE_UI32.pack(rmsLen) + rmsBytes
54
+
55
+ return ret
56
+
57
+ @property
58
+ def flags(self) -> int:
59
+ """
60
+ The flags for the OLEStream.
61
+
62
+ The bit with mask ``0x00001000`` is an implementation-specific hint
63
+ supplied by the application or by a higher-level protocol that creates
64
+ the data structure. It MAY be ignored on processing. A server
65
+ implementation which does not ignore this bit MAY cache the storage
66
+ when the bit is set.
67
+
68
+ :raises ValueError: The property was set with a bit other than the
69
+ implementation specific bit set.
70
+ """
71
+ return self.__flags
72
+
73
+ @flags.setter
74
+ def flags(self, value: int) -> None:
75
+ if not isinstance(value, int):
76
+ raise TypeError(':property flags: MUST be an int.')
77
+ if value != 0 and value != 0x1000:
78
+ raise ValueError('Cannot set bits other than the implementation specific one.')
79
+
80
+ self.__flags = value
81
+
82
+ @property
83
+ def linkUpdateOption(self) -> int:
84
+ """
85
+ An implementation-specific hint.
86
+
87
+ This hint MAY be ignored. On Windows, this field contains values from
88
+ the OLEUPDATE enumeration.
89
+ """
90
+ return self.__linkUpdateOption
91
+
92
+ @linkUpdateOption.setter
93
+ def linkUpdateOption(self, value: int) -> None:
94
+ if not isinstance(value, int):
95
+ raise TypeError(':property linkUpdateOption: MUST be an int.')
96
+ if value < 0:
97
+ raise ValueError(':property linkUpdateOption: MUST be positive.')
98
+ if value > 0xFFFFFFFF:
99
+ raise ValueError(':property linkUpdateOption: MUST be less than 0x100000000.')
100
+
101
+ self.__linkUpdateOption = value
102
+
103
+ @property
104
+ def reservedMonikerStream(self) -> Optional[MonikerStream]:
105
+ """
106
+ A MonikerStream structure that can contain any arbitrary value.
107
+ """
108
+ return self.__rms
109
+
110
+ @reservedMonikerStream.setter
111
+ def reservedMonikerStream(self, data: Optional[MonikerStream]) -> None:
112
+ if data is not None and not isinstance(data, MonikerStream):
113
+ raise TypeError('Reserved moniker stream must be a MonikerStream instance or None.')
114
+
115
+ self.__rms = data
116
+
117
+
@@ -0,0 +1,199 @@
1
+ __all__ = [
2
+ 'RecurrencePattern',
3
+ ]
4
+
5
+
6
+ from typing import Any, Tuple
7
+
8
+ from ..enums import RecurCalendarType, RecurDOW, RecurEndType, RecurFrequency, RecurMonthNthWeek, RecurPatternType, RecurPatternTypeSpecificWeekday
9
+ from ._helpers import BytesReader
10
+
11
+
12
+ class RecurrencePattern:
13
+ """
14
+ A RecurrencePattern structure, as specified in [MS-OXOCAL].
15
+ """
16
+
17
+ def __init__(self, data: bytes):
18
+ self.__rawData = data
19
+ reader = BytesReader(data)
20
+ self.__readerVersion = reader.readUnsignedShort()
21
+ self.__writerVersion = reader.readUnsignedShort()
22
+ if not (self.__readerVersion == self.__writerVersion == 0x3004):
23
+ raise ValueError('Reader version or writer version was not set to 0x3004.')
24
+
25
+ self.__recurFrequency = RecurFrequency(reader.readUnsignedShort())
26
+ self.__patternType = RecurPatternType(reader.readUnsignedShort())
27
+ self.__calendarType = RecurCalendarType(reader.readUnsignedShort())
28
+ self.__firstDateTime = reader.readUnsignedInt()
29
+ self.__period = reader.readUnsignedInt()
30
+ self.__slidingFlag = reader.readUnsignedInt()
31
+ # This is just here to help shorten lines.
32
+ RPTSW = RecurPatternTypeSpecificWeekday
33
+ # This field changes depending on the recurrence type.
34
+ if self.__patternType == RecurPatternType.DAY:
35
+ self.__patternTypeSpecific = None
36
+ elif self.__patternType == RecurPatternType.WEEK:
37
+ self.__patternTypeSpecific = RPTSW(reader.readUnsignedInt())
38
+ elif self.__patternType in (RecurPatternType.MONTH_NTH, RecurPatternType.HJ_MONTH_NTH):
39
+ self.__patternTypeSpecific = reader.readUnsignedInt()
40
+ else:
41
+ self.__patternTypeSpecific = (RPTSW(reader.readUnsignedInt()),
42
+ RecurMonthNthWeek(reader.readUnsignedInt()))
43
+
44
+ self.__endType = RecurEndType.fromInt(reader.readUnsignedInt())
45
+ self.__occurrenceCount = reader.readUnsignedInt()
46
+ self.__firstDOW = RecurDOW(reader.readUnsignedInt())
47
+ deletedInstanceCount = reader.readUnsignedInt()
48
+ self.__deletedInstanceDates = tuple(reader.readUnsignedInt() for _ in range(deletedInstanceCount))
49
+ modifiedInstanceCount = reader.readUnsignedInt()
50
+ self.__modifiedInstanceDates = tuple(reader.readUnsignedInt() for _ in range(modifiedInstanceCount))
51
+ self.__startDate = reader.readUnsignedInt()
52
+ self.__endDate = reader.readUnsignedInt()
53
+
54
+ def __bytes__(self) -> bytes:
55
+ return self.toBytes()
56
+
57
+ def toBytes(self) -> bytes:
58
+ return self.__rawData
59
+
60
+ @property
61
+ def calendarType(self) -> RecurCalendarType:
62
+ """
63
+ The type of calendar that is used.
64
+ """
65
+ return self.__calendarType
66
+
67
+ @property
68
+ def deletedInstanceDates(self) -> Tuple[int, ...]:
69
+ """
70
+ A tuple of the dates (stored as number of minutes between midnight,
71
+ January 1, 1601, and midnight on the specified day in the timezone
72
+ specified in the calendar object), ordered from earliest to latest, of
73
+ either a deleted instance or a modified instance for this recurrence.
74
+ """
75
+ return self.__deletedInstanceDates
76
+
77
+ @property
78
+ def endDate(self) -> int:
79
+ """
80
+ An integer that specifies the ending date for the recurrence.
81
+
82
+ The value is the number of minutes between midnight, January 1, 1601,
83
+ and midnight of the date of the last occurrence. When the value of the
84
+ endType field is ``END_AFTER_N_OCCURRENCES``, this value is calculated
85
+ based on the number of occurrences. If the recurrence does not have an
86
+ end date, the value of the endDate field MUST be set to ``0x5AE980DF``.
87
+ """
88
+ return self.__endDate
89
+
90
+ @property
91
+ def endType(self) -> RecurEndType:
92
+ """
93
+ The ending type for the recurrence.
94
+ """
95
+ return self.__endType
96
+
97
+ @property
98
+ def firstDateTime(self) -> int:
99
+ """
100
+ The first ever dat, week, or month of a recurring series, dating back to
101
+ a reference date, which is January 1, 1601, for a Gregorian calendar.
102
+ """
103
+ return self.__firstDateTime
104
+
105
+ @property
106
+ def firstDayOfWeek(self) -> RecurDOW:
107
+ """
108
+ The day on which the calendar week begins.
109
+ """
110
+ return self.__firstDOW
111
+
112
+ @property
113
+ def modifiedInstanceDates(self) -> Tuple[int, ...]:
114
+ """
115
+ A tuple of the dates (stored as number of minutes between midnight,
116
+ January 1, 1601, and midnight on the specified day in the timezone
117
+ specified in the calendar object), ordered from earliest to latest, of
118
+ a modified instance.
119
+ """
120
+ return self.__modifiedInstanceDates
121
+
122
+ @property
123
+ def occurrenceCount(self) -> int:
124
+ """
125
+ Number of occurrences for a recurrence that ends after N occurrences.
126
+ """
127
+ return self.__occurrenceCount
128
+
129
+ @property
130
+ def patternType(self) -> RecurPatternType:
131
+ """
132
+ The type of recurrence pattern.
133
+ """
134
+ return self.__patternType
135
+
136
+ @property
137
+ def patternTypeSpecific(self) -> Any:
138
+ """
139
+ The specifics for the pattern type.
140
+
141
+ Return is different depending on what type of pattern is being used.
142
+
143
+ * RecurPatternType.DAY: No value is returned.
144
+ * RecurPatternType.WEEK: A set of RecurPatternTypeSpecificWeekday bits.
145
+ * RecurPatternType.MONTH: The day of the month on which the recurrence
146
+ falls.
147
+ * RecurPatternType.MONTH_NTH: A tuple containing information from
148
+ [MS-OXOCAL] PatternTypeSpecific MonthNth.
149
+ * RecurPatternType.MONTH_END: The day of the month on which the
150
+ recurrence falls.
151
+ * RecurPatternType.HJ_MONTH: The day of the month on which the
152
+ recurrence falls.
153
+ * RecurPatternType.HJ_MONTH_NTH: A tuple containing information from
154
+ [MS-OXOCAL] PatternTypeSpecific MonthNth.
155
+ * RecurPatternType.HJ_MONTH_END: The day of the month on which the
156
+ recurrence falls.
157
+ """
158
+ return self.__patternTypeSpecific
159
+
160
+ @property
161
+ def period(self) -> int:
162
+ """
163
+ An integer that specifies the interval at which the meeting pattern
164
+ specified in PatternTypeSpecific field repeats.
165
+
166
+ The Period value MUST be between 1 and the maximum recurrence interval,
167
+ which is 999 days for daily recurrences, 99 weeks for weekly
168
+ recurrences, and 99 months for monthly recurrences.
169
+ """
170
+ return self.__period
171
+
172
+ @property
173
+ def readerVersion(self) -> int:
174
+ return self.__readerVersion
175
+
176
+ @property
177
+ def recurFrequency(self) -> RecurFrequency:
178
+ """
179
+ The frequency of the recurring series.
180
+ """
181
+ return self.__recurFrequency
182
+
183
+ @property
184
+ def slidingFlag(self) -> int:
185
+ return self.__slidingFlag
186
+
187
+ @property
188
+ def startDate(self) -> int:
189
+ """
190
+ An integer that specifies the date of the first occurrence.
191
+
192
+ The value is the number of minutes between midnight, January 1, 1601,
193
+ and midnight of the date of the first occurrence.
194
+ """
195
+ return self.__startDate
196
+
197
+ @property
198
+ def writerVersion(self) -> int:
199
+ return self.__writerVersion
@@ -0,0 +1,127 @@
1
+ __all__ = [
2
+ 'ReportTag',
3
+ ]
4
+
5
+
6
+ from typing import Optional
7
+
8
+ from ._helpers import BytesReader
9
+ from .entry_id import EntryID, FolderEntryID, MessageEntryID, StoreObjectEntryID
10
+
11
+
12
+ class ReportTag:
13
+ """
14
+ A Report Tag structure, as defined in [MS-OXOMSG].
15
+ """
16
+
17
+ def __init__(self, data: bytes):
18
+ self.__rawData = data
19
+ reader = BytesReader(data)
20
+
21
+ self.__cookie = reader.assertRead(b'PCDFEB09\x00')
22
+
23
+ self.__version = reader.readUnsignedInt()
24
+ entrySize = reader.readInt()
25
+ if entrySize:
26
+ self.__storeEntryID = StoreObjectEntryID(reader.read(entrySize))
27
+ else:
28
+ self.__storeEntryID = None
29
+
30
+ entrySize = reader.readInt()
31
+ if entrySize:
32
+ self.__folderEntryID = FolderEntryID(reader.read(entrySize))
33
+ else:
34
+ self.__folderEntryID = None
35
+
36
+ entrySize = reader.readInt()
37
+ if entrySize:
38
+ self.__messageEntryID = MessageEntryID(reader.read(entrySize))
39
+ else:
40
+ self.__messageEntryID = None
41
+
42
+ entrySize = reader.readInt()
43
+ if entrySize:
44
+ self.__searchFolderEntryID = FolderEntryID(reader.read(entrySize))
45
+ else:
46
+ self.__searchFolderEntryID = None
47
+
48
+ entrySize = reader.readInt()
49
+ if entrySize:
50
+ self.__messageSearchKey = reader.read(entrySize)
51
+ else:
52
+ self.__messageSearchKey = None
53
+
54
+ entrySize = reader.readInt()
55
+ if entrySize:
56
+ self.__ansiText = reader.read(entrySize)
57
+ else:
58
+ self.__ansiText = None
59
+
60
+ def __bytes__(self) -> bytes:
61
+ return self.toBytes()
62
+
63
+ def toBytes(self) -> bytes:
64
+ return self.__rawData
65
+
66
+ @property
67
+ def ansiText(self) -> Optional[bytes]:
68
+ """
69
+ The subject of the original message.
70
+
71
+ Set to None if not present.
72
+ """
73
+ return self.__ansiText
74
+
75
+ @property
76
+ def cookie(self) -> bytes:
77
+ """
78
+ String used for validation.
79
+
80
+ Set to ``b'PCDFEB09\x00'``.
81
+ """
82
+ return self.__cookie
83
+
84
+ @property
85
+ def folderEntryID(self) -> Optional[EntryID]:
86
+ """
87
+ The EntryID of the folder than contains the original message.
88
+ """
89
+ return self.__folderEntryID
90
+
91
+ @property
92
+ def messageEntryID(self) -> Optional[EntryID]:
93
+ """
94
+ The EntryID of the original message.
95
+ """
96
+ return self.__messageEntryID
97
+
98
+ @property
99
+ def messageSearchKey(self) -> Optional[bytes]:
100
+ """
101
+ The search key of the original message.
102
+ """
103
+ return self.__messageSearchKey
104
+
105
+ @property
106
+ def searchFolderEntryID(self) -> Optional[EntryID]:
107
+ """
108
+ The EntryID of an alternate folder that contains the original message.
109
+ """
110
+ return self.__searchFolderEntryID
111
+
112
+ @property
113
+ def storeEntryID(self) -> Optional[EntryID]:
114
+ """
115
+ The EntryID of the mailbox that contains the original message.
116
+ """
117
+ return self.__storeEntryID
118
+
119
+ @property
120
+ def version(self) -> int:
121
+ """
122
+ The version used.
123
+
124
+ If SearchFolderEntryID is present, this MUST be ``0x00020001``,
125
+ otherwise it MUST be ``0x00010001``.
126
+ """
127
+ return self.__version
@@ -0,0 +1,158 @@
1
+ __all__ = [
2
+ 'SystemTime',
3
+ ]
4
+
5
+
6
+ from typing import Any, Optional
7
+
8
+ from .. import constants
9
+
10
+
11
+ class SystemTime:
12
+ """
13
+ A SYSTEMTIME struct, as defined in [MS-DTYP].
14
+ """
15
+ def __init__(self, data: Optional[bytes] = None):
16
+ data = data or (b'\x00' * 16)
17
+ self.unpack(data)
18
+
19
+ def __eq__(self, other: Any) -> bool:
20
+ return isinstance(other, SystemTime) and bytes(self) == bytes(other)
21
+
22
+ def __ne__(self, other: Any) -> bool:
23
+ return not self.__eq__(other)
24
+
25
+ def __bytes__(self) -> bytes:
26
+ return self.toBytes()
27
+
28
+ def toBytes(self) -> bytes:
29
+ """
30
+ Packs the current data into bytes.
31
+ """
32
+ return constants.st.ST_SYSTEMTIME.pack(self.__year,
33
+ self.__month,
34
+ self.__dayOfWeek,
35
+ self.__day,
36
+ self.__hour,
37
+ self.__minute,
38
+ self.__second,
39
+ self.__milliseconds)
40
+
41
+ def unpack(self, data: bytes) -> None:
42
+ """
43
+ Fills out the fields of this instance by unpacking the bytes.
44
+ """
45
+ unpacked = constants.st.ST_SYSTEMTIME.unpack(data)
46
+ self.__year = unpacked[0]
47
+ self.__month = unpacked[1]
48
+ self.__dayOfWeek = unpacked[2]
49
+ self.__day = unpacked[3]
50
+ self.__hour = unpacked[4]
51
+ self.__minute = unpacked[5]
52
+ self.__second = unpacked[6]
53
+ self.__milliseconds = unpacked[7]
54
+
55
+ @property
56
+ def day(self) -> int:
57
+ return self.__day
58
+
59
+ @day.setter
60
+ def day(self, value: int) -> None:
61
+ if value < 0:
62
+ raise ValueError('Day must be positive.')
63
+ if value > 0xFFFF:
64
+ raise ValueError('Day cannot be greater than 0xFFFF.')
65
+
66
+ self.__day = value
67
+
68
+ @property
69
+ def dayOfWeek(self) -> int:
70
+ return self.__dayOfWeek
71
+
72
+ @dayOfWeek.setter
73
+ def dayOfWeek(self, value: int) -> None:
74
+ if value < 0:
75
+ raise ValueError('Day of week must be positive.')
76
+ if value > 0xFFFF:
77
+ raise ValueError('Day of week cannot be greater than 0xFFFF.')
78
+
79
+ self.__dayOfWeek = value
80
+
81
+ @property
82
+ def hour(self) -> int:
83
+ return self.__hour
84
+
85
+ @hour.setter
86
+ def hour(self, value: int) -> None:
87
+ if value < 0:
88
+ raise ValueError('Hour must be positive.')
89
+ if value > 0xFFFF:
90
+ raise ValueError('Hour cannot be greater than 0xFFFF.')
91
+
92
+ self.__hour = value
93
+
94
+ @property
95
+ def milliseconds(self) -> int:
96
+ return self.__milliseconds
97
+
98
+ @milliseconds.setter
99
+ def milliseconds(self, value: int) -> None:
100
+ if value < 0:
101
+ raise ValueError('Milliseconds must be positive.')
102
+ if value > 0xFFFF:
103
+ raise ValueError('Milliseconds cannot be greater than 0xFFFF.')
104
+
105
+ self.__milliseconds = value
106
+
107
+ @property
108
+ def minute(self) -> int:
109
+ return self.__minute
110
+
111
+ @minute.setter
112
+ def minute(self, value: int) -> None:
113
+ if value < 0:
114
+ raise ValueError('Minute must be positive.')
115
+ if value > 0xFFFF:
116
+ raise ValueError('Minute cannot be greater than 0xFFFF.')
117
+
118
+ self.__minute = value
119
+
120
+ @property
121
+ def month(self) -> int:
122
+ return self.__month
123
+
124
+ @month.setter
125
+ def month(self, value: int) -> None:
126
+ if value < 0:
127
+ raise ValueError('Month must be positive.')
128
+ if value > 0xFFFF:
129
+ raise ValueError('Month cannot be greater than 0xFFFF.')
130
+
131
+ self.__month = value
132
+
133
+ @property
134
+ def second(self) -> int:
135
+ return self.__second
136
+
137
+ @second.setter
138
+ def second(self, value: int) -> None:
139
+ if value < 0:
140
+ raise ValueError('Second must be positive.')
141
+ if value > 0xFFFF:
142
+ raise ValueError('Second cannot be greater than 0xFFFF.')
143
+
144
+ self.__second = value
145
+
146
+ @property
147
+ def year(self) -> int:
148
+ return self.__year
149
+
150
+ @year.setter
151
+ def year(self, value: int) -> None:
152
+ if value < 0:
153
+ raise ValueError('Year must be positive.')
154
+ if value > 0xFFFF:
155
+ raise ValueError('Year cannot be greater than 0xFFFF.')
156
+
157
+ self.__year = value
158
+