MAPIUtils   F
last analyzed

Complexity

Total Complexity 130

Size/Duplication

Total Lines 702
Duplicated Lines 0 %

Importance

Changes 5
Bugs 2 Features 0
Metric Value
eloc 317
c 5
b 2
f 0
dl 0
loc 702
rs 2
wmc 130

17 Methods

Rating   Name   Duplication   Size   Complexity  
A GetContactPicRestriction() 0 7 1
A GetEmailRestriction() 0 8 1
A GetCalendarRestriction() 0 96 1
A GetSearchRestriction() 0 50 1
A GetEmailAddressRestriction() 0 29 1
B IsMessageSharedAndPrivate() 0 19 7
A IsInEmailSyncInterval() 0 12 3
A readPropStream() 0 24 5
A GetError() 0 10 5
A IsUnicodeStore() 0 5 3
B GetFolderTypeFromContainerClass() 0 21 7
F GetNativeBodyType() 0 92 54
B ParseSmime() 0 50 8
A GetSubfoldersForType() 0 8 2
B IsInCalendarSyncInterval() 0 35 11
A GetFolderTypeRestriction() 0 7 1
D GetContainerClassFromFolderType() 0 38 19

How to fix   Complexity   

Complex Class

Complex classes like MAPIUtils often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use MAPIUtils, and based on these observations, apply Extract Interface, too.

1
<?php
2
/*
3
 * SPDX-License-Identifier: AGPL-3.0-only
4
 * SPDX-FileCopyrightText: Copyright 2007-2013,2016 Zarafa Deutschland GmbH
5
 * SPDX-FileCopyrightText: Copyright 2020-2024 grommunio GmbH
6
 */
7
8
/**
9
 * MAPI utility functions.
10
 */
11
class MAPIUtils {
12
	/**
13
	 * Create a MAPI restriction to use within an email folder which will
14
	 * return all messages since since $timestamp.
15
	 *
16
	 * @param long $timestamp Timestamp since when to include messages
0 ignored issues
show
Bug introduced by
The type long was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
17
	 *
18
	 * @return array
19
	 */
20
	public static function GetEmailRestriction($timestamp) {
21
		// ATTENTION: ON CHANGING THIS RESTRICTION, MAPIUtils::IsInEmailSyncInterval() also needs to be changed
22
		return [
23
			RES_PROPERTY,
0 ignored issues
show
Bug introduced by
The constant RES_PROPERTY was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
24
			[
25
				RELOP => RELOP_GE,
0 ignored issues
show
Bug introduced by
The constant RELOP was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
Bug introduced by
The constant RELOP_GE was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
26
				ULPROPTAG => PR_MESSAGE_DELIVERY_TIME,
0 ignored issues
show
Bug introduced by
The constant PR_MESSAGE_DELIVERY_TIME was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
Bug introduced by
The constant ULPROPTAG was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
27
				VALUE => $timestamp,
0 ignored issues
show
Bug introduced by
The constant VALUE was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
28
			],
29
		];
30
	}
31
32
	/**
33
	 * Create a MAPI restriction to use in the calendar which will
34
	 * return all future calendar items, plus those since $timestamp.
35
	 *
36
	 * @param MAPIStore $store     the MAPI store
0 ignored issues
show
Bug introduced by
The type MAPIStore was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
37
	 * @param long      $timestamp Timestamp since when to include messages
38
	 *
39
	 * @return array
40
	 */
41
	// TODO getting named properties
42
	public static function GetCalendarRestriction($store, $timestamp) {
43
		// This is our viewing window
44
		$start = $timestamp;
45
		$end = 0x7FFFFFFF; // infinite end
46
47
		$props = MAPIMapping::GetAppointmentProperties();
48
		$props = getPropIdsFromStrings($store, $props);
0 ignored issues
show
Bug introduced by
The function getPropIdsFromStrings was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

48
		$props = /** @scrutinizer ignore-call */ getPropIdsFromStrings($store, $props);
Loading history...
49
50
		// ATTENTION: ON CHANGING THIS RESTRICTION, MAPIUtils::IsInCalendarSyncInterval() also needs to be changed
51
		return [
52
			RES_OR,
0 ignored issues
show
Bug introduced by
The constant RES_OR was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
53
			[
54
				// OR
55
				// item.end > window.start && item.start < window.end
56
				[
57
					RES_AND,
0 ignored issues
show
Bug introduced by
The constant RES_AND was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
58
					[
59
						[
60
							RES_PROPERTY,
0 ignored issues
show
Bug introduced by
The constant RES_PROPERTY was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
61
							[
62
								RELOP => RELOP_LE,
0 ignored issues
show
Bug introduced by
The constant RELOP_LE was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
Bug introduced by
The constant RELOP was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
63
								ULPROPTAG => $props["starttime"],
0 ignored issues
show
Bug introduced by
The constant ULPROPTAG was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
64
								VALUE => $end,
0 ignored issues
show
Bug introduced by
The constant VALUE was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
65
							],
66
						],
67
						[
68
							RES_PROPERTY,
69
							[
70
								RELOP => RELOP_GE,
0 ignored issues
show
Bug introduced by
The constant RELOP_GE was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
71
								ULPROPTAG => $props["endtime"],
72
								VALUE => $start,
73
							],
74
						],
75
					],
76
				],
77
				// OR
78
				[
79
					RES_OR,
80
					[
81
						// OR
82
						// (EXIST(recurrence_enddate_property) && item[isRecurring] == true && recurrence_enddate_property >= start)
83
						[
84
							RES_AND,
85
							[
86
								[
87
									RES_EXIST,
0 ignored issues
show
Bug introduced by
The constant RES_EXIST was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
88
									[ULPROPTAG => $props["recurrenceend"],
89
									],
90
								],
91
								[
92
									RES_PROPERTY,
93
									[
94
										RELOP => RELOP_EQ,
0 ignored issues
show
Bug introduced by
The constant RELOP_EQ was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
95
										ULPROPTAG => $props["isrecurring"],
96
										VALUE => true,
97
									],
98
								],
99
								[
100
									RES_PROPERTY,
101
									[
102
										RELOP => RELOP_GE,
103
										ULPROPTAG => $props["recurrenceend"],
104
										VALUE => $start,
105
									],
106
								],
107
							],
108
						],
109
						// OR
110
						// (!EXIST(recurrence_enddate_property) && item[isRecurring] == true && item[start] <= end)
111
						[
112
							RES_AND,
113
							[
114
								[
115
									RES_NOT,
0 ignored issues
show
Bug introduced by
The constant RES_NOT was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
116
									[
117
										[
118
											RES_EXIST,
119
											[ULPROPTAG => $props["recurrenceend"],
120
											],
121
										],
122
									],
123
								],
124
								[
125
									RES_PROPERTY,
126
									[
127
										RELOP => RELOP_LE,
128
										ULPROPTAG => $props["starttime"],
129
										VALUE => $end,
130
									],
131
								],
132
								[
133
									RES_PROPERTY,
134
									[
135
										RELOP => RELOP_EQ,
136
										ULPROPTAG => $props["isrecurring"],
137
										VALUE => true,
138
									],
139
								],
140
							],
141
						],
142
					],
143
				], // EXISTS OR
144
			],
145
		];        // global OR
146
	}
147
148
	/**
149
	 * Create a MAPI restriction in order to check if a contact has a picture.
150
	 *
151
	 * @return array
152
	 */
153
	public static function GetContactPicRestriction() {
154
		return [
155
			RES_PROPERTY,
0 ignored issues
show
Bug introduced by
The constant RES_PROPERTY was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
156
			[
157
				RELOP => RELOP_EQ,
0 ignored issues
show
Bug introduced by
The constant RELOP_EQ was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
Bug introduced by
The constant RELOP was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
158
				ULPROPTAG => mapi_prop_tag(PT_BOOLEAN, 0x7FFF),
0 ignored issues
show
Bug introduced by
The constant PT_BOOLEAN was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
Bug introduced by
The constant ULPROPTAG was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
159
				VALUE => true,
0 ignored issues
show
Bug introduced by
The constant VALUE was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
160
			],
161
		];
162
	}
163
164
	/**
165
	 * Create a MAPI restriction for search.
166
	 *
167
	 * @param string $query
168
	 *
169
	 * @return array
170
	 */
171
	public static function GetSearchRestriction($query) {
172
		return [
173
			RES_AND,
0 ignored issues
show
Bug introduced by
The constant RES_AND was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
174
			[
175
				[
176
					RES_OR,
0 ignored issues
show
Bug introduced by
The constant RES_OR was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
177
					[
178
						[
179
							RES_CONTENT,
0 ignored issues
show
Bug introduced by
The constant RES_CONTENT was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
180
							[
181
								FUZZYLEVEL => FL_SUBSTRING | FL_IGNORECASE,
0 ignored issues
show
Bug introduced by
The constant FUZZYLEVEL was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
Bug introduced by
The constant FL_SUBSTRING was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
Bug introduced by
The constant FL_IGNORECASE was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
182
								ULPROPTAG => PR_DISPLAY_NAME,
0 ignored issues
show
Bug introduced by
The constant PR_DISPLAY_NAME was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
Bug introduced by
The constant ULPROPTAG was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
183
								VALUE => $query,
0 ignored issues
show
Bug introduced by
The constant VALUE was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
184
							],
185
						],
186
						[
187
							RES_CONTENT,
188
							[
189
								FUZZYLEVEL => FL_SUBSTRING | FL_IGNORECASE,
190
								ULPROPTAG => PR_ACCOUNT,
0 ignored issues
show
Bug introduced by
The constant PR_ACCOUNT was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
191
								VALUE => $query,
192
							],
193
						],
194
						[
195
							RES_CONTENT,
196
							[
197
								FUZZYLEVEL => FL_SUBSTRING | FL_IGNORECASE,
198
								ULPROPTAG => PR_SMTP_ADDRESS,
0 ignored issues
show
Bug introduced by
The constant PR_SMTP_ADDRESS was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
199
								VALUE => $query,
200
							],
201
						],
202
					], // RES_OR
203
				],
204
				[
205
					RES_OR,
206
					[
207
						[
208
							RES_PROPERTY,
0 ignored issues
show
Bug introduced by
The constant RES_PROPERTY was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
209
							[
210
								RELOP => RELOP_EQ,
0 ignored issues
show
Bug introduced by
The constant RELOP_EQ was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
Bug introduced by
The constant RELOP was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
211
								ULPROPTAG => PR_OBJECT_TYPE,
0 ignored issues
show
Bug introduced by
The constant PR_OBJECT_TYPE was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
212
								VALUE => MAPI_MAILUSER,
0 ignored issues
show
Bug introduced by
The constant MAPI_MAILUSER was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
213
							],
214
						],
215
						[
216
							RES_PROPERTY,
217
							[
218
								RELOP => RELOP_EQ,
219
								ULPROPTAG => PR_OBJECT_TYPE,
220
								VALUE => MAPI_DISTLIST,
0 ignored issues
show
Bug introduced by
The constant MAPI_DISTLIST was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
221
							],
222
						],
223
					],
224
				], // RES_OR
225
			], // RES_AND
226
		];
227
	}
228
229
	/**
230
	 * Create a MAPI restriction for a certain email address.
231
	 *
232
	 * @param MAPIStore $store the MAPI store
233
	 * @param mixed     $email
234
	 *
235
	 * @return array
236
	 */
237
	public static function GetEmailAddressRestriction($store, $email) {
238
		$props = MAPIMapping::GetContactProperties();
239
		$props = getPropIdsFromStrings($store, $props);
0 ignored issues
show
Bug introduced by
The function getPropIdsFromStrings was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

239
		$props = /** @scrutinizer ignore-call */ getPropIdsFromStrings($store, $props);
Loading history...
240
241
		return [
242
			RES_OR,
0 ignored issues
show
Bug introduced by
The constant RES_OR was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
243
			[
244
				[
245
					RES_PROPERTY,
0 ignored issues
show
Bug introduced by
The constant RES_PROPERTY was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
246
					[
247
						RELOP => RELOP_EQ,
0 ignored issues
show
Bug introduced by
The constant RELOP_EQ was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
Bug introduced by
The constant RELOP was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
248
						ULPROPTAG => $props['emailaddress1'],
0 ignored issues
show
Bug introduced by
The constant ULPROPTAG was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
249
						VALUE => [$props['emailaddress1'] => $email],
0 ignored issues
show
Bug introduced by
The constant VALUE was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
250
					],
251
				],
252
				[
253
					RES_PROPERTY,
254
					[
255
						RELOP => RELOP_EQ,
256
						ULPROPTAG => $props['emailaddress2'],
257
						VALUE => [$props['emailaddress2'] => $email],
258
					],
259
				],
260
				[
261
					RES_PROPERTY,
262
					[
263
						RELOP => RELOP_EQ,
264
						ULPROPTAG => $props['emailaddress3'],
265
						VALUE => [$props['emailaddress3'] => $email],
266
					],
267
				],
268
			],
269
		];
270
	}
271
272
	/**
273
	 * Create a MAPI restriction for a certain folder type.
274
	 *
275
	 * @param string $foldertype folder type for restriction
276
	 *
277
	 * @return array
278
	 */
279
	public static function GetFolderTypeRestriction($foldertype) {
280
		return [
281
			RES_PROPERTY,
0 ignored issues
show
Bug introduced by
The constant RES_PROPERTY was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
282
			[
283
				RELOP => RELOP_EQ,
0 ignored issues
show
Bug introduced by
The constant RELOP_EQ was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
Bug introduced by
The constant RELOP was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
284
				ULPROPTAG => PR_CONTAINER_CLASS,
0 ignored issues
show
Bug introduced by
The constant PR_CONTAINER_CLASS was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
Bug introduced by
The constant ULPROPTAG was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
285
				VALUE => [PR_CONTAINER_CLASS => $foldertype],
0 ignored issues
show
Bug introduced by
The constant VALUE was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
286
			],
287
		];
288
	}
289
290
	/**
291
	 * Returns subfolders of given type for a folder or false if there are none.
292
	 *
293
	 * @param MAPIFolder $folder
0 ignored issues
show
Bug introduced by
The type MAPIFolder was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
294
	 * @param string     $type
295
	 *
296
	 * @return bool|MAPITable
0 ignored issues
show
Bug introduced by
The type MAPITable was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
297
	 */
298
	public static function GetSubfoldersForType($folder, $type) {
299
		$subfolders = mapi_folder_gethierarchytable($folder, CONVENIENT_DEPTH);
0 ignored issues
show
Bug introduced by
The constant CONVENIENT_DEPTH was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
300
		mapi_table_restrict($subfolders, MAPIUtils::GetFolderTypeRestriction($type));
301
		if (mapi_table_getrowcount($subfolders) > 0) {
302
			return mapi_table_queryallrows($subfolders, [PR_ENTRYID]);
303
		}
304
305
		return false;
306
	}
307
308
	/**
309
	 * Checks if mapimessage is inside the synchronization interval
310
	 * also defined by MAPIUtils::GetEmailRestriction().
311
	 *
312
	 * @param MAPIStore   $store       mapi store
313
	 * @param MAPIMessage $mapimessage the mapi message to be checked
0 ignored issues
show
Bug introduced by
The type MAPIMessage was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
314
	 * @param long        $timestamp   the lower time limit
315
	 *
316
	 * @return bool
317
	 */
318
	public static function IsInEmailSyncInterval($store, $mapimessage, $timestamp) {
319
		$p = mapi_getprops($mapimessage, [PR_MESSAGE_DELIVERY_TIME]);
0 ignored issues
show
Bug introduced by
The constant PR_MESSAGE_DELIVERY_TIME was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
320
321
		if (isset($p[PR_MESSAGE_DELIVERY_TIME]) && $p[PR_MESSAGE_DELIVERY_TIME] >= $timestamp) {
322
			SLog::Write(LOGLEVEL_DEBUG, "MAPIUtils->IsInEmailSyncInterval: Message is in the synchronization interval");
323
324
			return true;
325
		}
326
327
		SLog::Write(LOGLEVEL_WARN, "MAPIUtils->IsInEmailSyncInterval: Message is OUTSIDE the synchronization interval");
328
329
		return false;
330
	}
331
332
	/**
333
	 * Checks if mapimessage is inside the synchronization interval
334
	 * also defined by MAPIUtils::GetCalendarRestriction().
335
	 *
336
	 * @param MAPIStore   $store       mapi store
337
	 * @param MAPIMessage $mapimessage the mapi message to be checked
338
	 * @param long        $timestamp   the lower time limit
339
	 *
340
	 * @return bool
341
	 */
342
	public static function IsInCalendarSyncInterval($store, $mapimessage, $timestamp) {
343
		// This is our viewing window
344
		$start = $timestamp;
345
		$end = 0x7FFFFFFF; // infinite end
346
347
		$props = MAPIMapping::GetAppointmentProperties();
348
		$props = getPropIdsFromStrings($store, $props);
0 ignored issues
show
Bug introduced by
The function getPropIdsFromStrings was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

348
		$props = /** @scrutinizer ignore-call */ getPropIdsFromStrings($store, $props);
Loading history...
349
350
		$p = mapi_getprops($mapimessage, [$props["starttime"], $props["endtime"], $props["recurrenceend"], $props["isrecurring"], $props["recurrenceend"]]);
351
352
		if (
353
			(
354
				isset($p[$props["endtime"]], $p[$props["starttime"]]) &&
355
				// item.end > window.start && item.start < window.end
356
				$p[$props["endtime"]] > $start && $p[$props["starttime"]] < $end
357
			) ||
358
			(
359
				isset($p[$props["isrecurring"]], $p[$props["recurrenceend"]]) &&
360
					// (EXIST(recurrence_enddate_property) && item[isRecurring] == true && recurrence_enddate_property >= start)
361
					$p[$props["isrecurring"]] == true && $p[$props["recurrenceend"]] >= $start
362
			) ||
363
			(
364
				isset($p[$props["isrecurring"]], $p[$props["starttime"]]) &&
365
					// (!EXIST(recurrence_enddate_property) && item[isRecurring] == true && item[start] <= end)
366
					!isset($p[$props["recurrenceend"]]) && $p[$props["isrecurring"]] == true && $p[$props["starttime"]] <= $end
367
			)
368
		) {
369
			SLog::Write(LOGLEVEL_DEBUG, "MAPIUtils->IsInCalendarSyncInterval: Message is in the synchronization interval");
370
371
			return true;
372
		}
373
374
		SLog::Write(LOGLEVEL_WARN, "MAPIUtils->IsInCalendarSyncInterval: Message is OUTSIDE the synchronization interval");
375
376
		return false;
377
	}
378
379
	/**
380
	 * Checks if mapimessage is in a shared folder and private.
381
	 *
382
	 * @param string      $folderid    binary folderid of the message
383
	 * @param MAPIMessage $mapimessage the mapi message to be checked
384
	 *
385
	 * @return bool
386
	 */
387
	public static function IsMessageSharedAndPrivate($folderid, $mapimessage) {
388
		$sensitivity = mapi_getprops($mapimessage, [PR_SENSITIVITY]);
0 ignored issues
show
Bug introduced by
The constant PR_SENSITIVITY was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
389
		if (isset($sensitivity[PR_SENSITIVITY]) && $sensitivity[PR_SENSITIVITY] >= SENSITIVITY_PRIVATE) {
0 ignored issues
show
Bug introduced by
The constant SENSITIVITY_PRIVATE was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
390
			$hexFolderid = bin2hex($folderid);
391
			$shortId = GSync::GetDeviceManager()->GetFolderIdForBackendId($hexFolderid);
392
			if (Utils::GetFolderOriginFromId($shortId) == DeviceManager::FLD_ORIGIN_IMPERSONATED) {
393
				SLog::Write(LOGLEVEL_DEBUG, sprintf("MAPIUtils->IsMessageSharedAndPrivate(): Message is in impersonated store '%s' and marked as private", GSync::GetBackend()->GetImpersonatedUser()));
394
395
				return true;
396
			}
397
			$sharedUser = GSync::GetAdditionalSyncFolderStore($hexFolderid);
398
			if (Utils::GetFolderOriginFromId($shortId) != DeviceManager::FLD_ORIGIN_USER && $sharedUser != false && $sharedUser != 'SYSTEM') {
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing $sharedUser of type string to the boolean false. If you are specifically checking for a non-empty string, consider using the more explicit !== '' instead.
Loading history...
399
				SLog::Write(LOGLEVEL_DEBUG, sprintf("MAPIUtils->IsMessageSharedAndPrivate(): Message is in shared store '%s' and marked as private", $sharedUser));
400
401
				return true;
402
			}
403
		}
404
405
		return false;
406
	}
407
408
	/**
409
	 * Reads data of large properties from a stream.
410
	 *
411
	 * @param MAPIMessage $message
412
	 * @param long        $prop
413
	 *
414
	 * @return string
415
	 */
416
	public static function readPropStream($message, $prop) {
417
		$stream = mapi_openproperty($message, $prop, IID_IStream, 0, 0);
0 ignored issues
show
Bug introduced by
The constant IID_IStream was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
418
		$ret = mapi_last_hresult();
419
		if ($ret == MAPI_E_NOT_FOUND) {
0 ignored issues
show
Bug introduced by
The constant MAPI_E_NOT_FOUND was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
420
			SLog::Write(LOGLEVEL_DEBUG, sprintf("MAPIUtils->readPropStream: property 0x%08X not found. It is either empty or not set. It will be ignored.", $prop));
421
422
			return "";
423
		}
424
		if ($ret) {
425
			SLog::Write(LOGLEVEL_ERROR, sprintf("MAPIUtils->readPropStream error opening stream: 0x%08X", $ret));
426
427
			return "";
428
		}
429
		$data = "";
0 ignored issues
show
Unused Code introduced by
The assignment to $data is dead and can be removed.
Loading history...
430
		$string = "";
431
		while (1) {
432
			$data = mapi_stream_read($stream, 1024);
433
			if (strlen($data) == 0) {
434
				break;
435
			}
436
			$string .= $data;
437
		}
438
439
		return $string;
440
	}
441
442
	/**
443
	 * Checks if a store supports properties containing unicode characters.
444
	 *
445
	 * @param MAPIStore $store
446
	 */
447
	public static function IsUnicodeStore($store) {
448
		$supportmask = mapi_getprops($store, [PR_STORE_SUPPORT_MASK]);
0 ignored issues
show
Bug introduced by
The constant PR_STORE_SUPPORT_MASK was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
449
		if (isset($supportmask[PR_STORE_SUPPORT_MASK]) && ($supportmask[PR_STORE_SUPPORT_MASK] & STORE_UNICODE_OK)) {
0 ignored issues
show
Bug introduced by
The constant STORE_UNICODE_OK was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
450
			SLog::Write(LOGLEVEL_DEBUG, "Store supports properties containing Unicode characters.");
451
			define('STORE_INTERNET_CPID', INTERNET_CPID_UTF8);
452
		}
453
	}
454
455
	/**
456
	 * Returns the MAPI PR_CONTAINER_CLASS string for an ActiveSync Foldertype.
457
	 *
458
	 * @param int $foldertype
459
	 *
460
	 * @return string
461
	 */
462
	public static function GetContainerClassFromFolderType($foldertype) {
463
		switch ($foldertype) {
464
			case SYNC_FOLDER_TYPE_TASK:
465
			case SYNC_FOLDER_TYPE_USER_TASK:
466
				return "IPF.Task";
467
				break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
468
469
			case SYNC_FOLDER_TYPE_APPOINTMENT:
470
			case SYNC_FOLDER_TYPE_USER_APPOINTMENT:
471
				return "IPF.Appointment";
472
				break;
473
474
			case SYNC_FOLDER_TYPE_CONTACT:
475
			case SYNC_FOLDER_TYPE_USER_CONTACT:
476
				return "IPF.Contact";
477
				break;
478
479
			case SYNC_FOLDER_TYPE_NOTE:
480
			case SYNC_FOLDER_TYPE_USER_NOTE:
481
				return "IPF.StickyNote";
482
				break;
483
484
			case SYNC_FOLDER_TYPE_JOURNAL:
485
			case SYNC_FOLDER_TYPE_USER_JOURNAL:
486
				return "IPF.Journal";
487
				break;
488
489
			case SYNC_FOLDER_TYPE_INBOX:
490
			case SYNC_FOLDER_TYPE_DRAFTS:
491
			case SYNC_FOLDER_TYPE_WASTEBASKET:
492
			case SYNC_FOLDER_TYPE_SENTMAIL:
493
			case SYNC_FOLDER_TYPE_OUTBOX:
494
			case SYNC_FOLDER_TYPE_USER_MAIL:
495
			case SYNC_FOLDER_TYPE_OTHER:
496
			case SYNC_FOLDER_TYPE_UNKNOWN:
497
			default:
498
				return "IPF.Note";
499
				break;
500
		}
501
	}
502
503
	/**
504
	 * Returns the ActiveSync (USER) Foldertype from MAPI PR_CONTAINER_CLASS.
505
	 *
506
	 * @param mixed $class
507
	 *
508
	 * @return int
509
	 */
510
	public static function GetFolderTypeFromContainerClass($class) {
511
		if ($class == "IPF.Note") {
512
			return SYNC_FOLDER_TYPE_USER_MAIL;
513
		}
514
		if ($class == "IPF.Task") {
515
			return SYNC_FOLDER_TYPE_USER_TASK;
516
		}
517
		if ($class == "IPF.Appointment") {
518
			return SYNC_FOLDER_TYPE_USER_APPOINTMENT;
519
		}
520
		if ($class == "IPF.Contact") {
521
			return SYNC_FOLDER_TYPE_USER_CONTACT;
522
		}
523
		if ($class == "IPF.StickyNote") {
524
			return SYNC_FOLDER_TYPE_USER_NOTE;
525
		}
526
		if ($class == "IPF.Journal") {
527
			return SYNC_FOLDER_TYPE_USER_JOURNAL;
528
		}
529
530
		return SYNC_FOLDER_TYPE_OTHER;
531
	}
532
533
	/**
534
	 * Calculates the native body type of a message using available properties. Refer to oxbbody.
535
	 *
536
	 * @param array $messageprops
537
	 *
538
	 * @return int
539
	 */
540
	public static function GetNativeBodyType($messageprops) {
541
		// check if the properties are set and get the error code if needed
542
		if (!isset($messageprops[PR_BODY])) {
0 ignored issues
show
Bug introduced by
The constant PR_BODY was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
543
			$messageprops[PR_BODY] = self::GetError(PR_BODY, $messageprops);
544
		}
545
		if (!isset($messageprops[PR_RTF_COMPRESSED])) {
0 ignored issues
show
Bug introduced by
The constant PR_RTF_COMPRESSED was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
546
			$messageprops[PR_RTF_COMPRESSED] = self::GetError(PR_RTF_COMPRESSED, $messageprops);
547
		}
548
		if (!isset($messageprops[PR_HTML])) {
0 ignored issues
show
Bug introduced by
The constant PR_HTML was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
549
			$messageprops[PR_HTML] = self::GetError(PR_HTML, $messageprops);
550
		}
551
		if (!isset($messageprops[PR_RTF_IN_SYNC])) {
0 ignored issues
show
Bug introduced by
The constant PR_RTF_IN_SYNC was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
552
			$messageprops[PR_RTF_IN_SYNC] = self::GetError(PR_RTF_IN_SYNC, $messageprops);
553
		}
554
555
		if ( // 1
556
			($messageprops[PR_BODY] == MAPI_E_NOT_FOUND) &&
0 ignored issues
show
Bug introduced by
The constant MAPI_E_NOT_FOUND was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
557
			($messageprops[PR_RTF_COMPRESSED] == MAPI_E_NOT_FOUND) &&
558
			($messageprops[PR_HTML] == MAPI_E_NOT_FOUND)) {
559
			return SYNC_BODYPREFERENCE_PLAIN;
560
		}
561
		if ( // 2
562
			($messageprops[PR_BODY] == MAPI_E_NOT_ENOUGH_MEMORY) &&
0 ignored issues
show
Bug introduced by
The constant MAPI_E_NOT_ENOUGH_MEMORY was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
563
			($messageprops[PR_RTF_COMPRESSED] == MAPI_E_NOT_FOUND) &&
564
			($messageprops[PR_HTML] == MAPI_E_NOT_FOUND)) {
565
			return SYNC_BODYPREFERENCE_PLAIN;
566
		}
567
		if ( // 3
568
			($messageprops[PR_BODY] == MAPI_E_NOT_ENOUGH_MEMORY) &&
569
			($messageprops[PR_RTF_COMPRESSED] == MAPI_E_NOT_ENOUGH_MEMORY) &&
570
			($messageprops[PR_HTML] == MAPI_E_NOT_FOUND)) {
571
			return SYNC_BODYPREFERENCE_PLAIN;
572
		}
573
		if ( // 4
574
			($messageprops[PR_BODY] == MAPI_E_NOT_ENOUGH_MEMORY) &&
575
			($messageprops[PR_RTF_COMPRESSED] == MAPI_E_NOT_ENOUGH_MEMORY) &&
576
			($messageprops[PR_HTML] == MAPI_E_NOT_ENOUGH_MEMORY) &&
577
			$messageprops[PR_RTF_IN_SYNC]) {
578
			return SYNC_BODYPREFERENCE_PLAIN;
579
		}
580
		if ( // 5
581
			($messageprops[PR_BODY] == MAPI_E_NOT_ENOUGH_MEMORY) &&
582
			($messageprops[PR_RTF_COMPRESSED] == MAPI_E_NOT_ENOUGH_MEMORY) &&
583
			($messageprops[PR_HTML] == MAPI_E_NOT_ENOUGH_MEMORY) &&
584
			(!$messageprops[PR_RTF_IN_SYNC])) {
585
			return SYNC_BODYPREFERENCE_HTML;
586
		}
587
		if ( // 6
588
			($messageprops[PR_RTF_COMPRESSED] != MAPI_E_NOT_FOUND || $messageprops[PR_RTF_COMPRESSED] == MAPI_E_NOT_ENOUGH_MEMORY) &&
589
			($messageprops[PR_HTML] != MAPI_E_NOT_FOUND || $messageprops[PR_HTML] == MAPI_E_NOT_ENOUGH_MEMORY) &&
590
			$messageprops[PR_RTF_IN_SYNC]) {
591
			return SYNC_BODYPREFERENCE_PLAIN;
592
		}
593
		if ( // 7
594
			($messageprops[PR_RTF_COMPRESSED] != MAPI_E_NOT_FOUND || $messageprops[PR_RTF_COMPRESSED] == MAPI_E_NOT_ENOUGH_MEMORY) &&
595
			($messageprops[PR_HTML] != MAPI_E_NOT_FOUND || $messageprops[PR_HTML] == MAPI_E_NOT_ENOUGH_MEMORY) &&
596
			(!$messageprops[PR_RTF_IN_SYNC])) {
597
			return SYNC_BODYPREFERENCE_HTML;
598
		}
599
		if ( // 8
600
			($messageprops[PR_BODY] != MAPI_E_NOT_FOUND || $messageprops[PR_BODY] == MAPI_E_NOT_ENOUGH_MEMORY) &&
601
			($messageprops[PR_RTF_COMPRESSED] != MAPI_E_NOT_FOUND || $messageprops[PR_RTF_COMPRESSED] == MAPI_E_NOT_ENOUGH_MEMORY) &&
602
			$messageprops[PR_RTF_IN_SYNC]) {
603
			return SYNC_BODYPREFERENCE_PLAIN;
604
		}
605
		if ( // 9.1
606
			($messageprops[PR_BODY] != MAPI_E_NOT_FOUND || $messageprops[PR_BODY] == MAPI_E_NOT_ENOUGH_MEMORY) &&
607
			($messageprops[PR_RTF_COMPRESSED] != MAPI_E_NOT_FOUND || $messageprops[PR_RTF_COMPRESSED] == MAPI_E_NOT_ENOUGH_MEMORY) &&
608
			(!$messageprops[PR_RTF_IN_SYNC])) {
609
			return SYNC_BODYPREFERENCE_PLAIN;
610
		}
611
		if ( // 9.2
612
			($messageprops[PR_RTF_COMPRESSED] != MAPI_E_NOT_FOUND || $messageprops[PR_RTF_COMPRESSED] == MAPI_E_NOT_ENOUGH_MEMORY) &&
613
			($messageprops[PR_BODY] == MAPI_E_NOT_FOUND) &&
614
			($messageprops[PR_HTML] == MAPI_E_NOT_FOUND)) {
615
			return SYNC_BODYPREFERENCE_PLAIN;
616
		}
617
		if ( // 9.3
618
			($messageprops[PR_BODY] != MAPI_E_NOT_FOUND || $messageprops[PR_BODY] == MAPI_E_NOT_ENOUGH_MEMORY) &&
619
			($messageprops[PR_RTF_COMPRESSED] == MAPI_E_NOT_FOUND) &&
620
			($messageprops[PR_HTML] == MAPI_E_NOT_FOUND)) {
621
			return SYNC_BODYPREFERENCE_PLAIN;
622
		}
623
		if ( // 9.4
624
			($messageprops[PR_HTML] != MAPI_E_NOT_FOUND || $messageprops[PR_HTML] == MAPI_E_NOT_ENOUGH_MEMORY) &&
625
			($messageprops[PR_BODY] == MAPI_E_NOT_FOUND) &&
626
			($messageprops[PR_RTF_COMPRESSED] == MAPI_E_NOT_FOUND)) {
627
			return SYNC_BODYPREFERENCE_HTML;
628
		}
629
630
		// 10
631
		return SYNC_BODYPREFERENCE_PLAIN;
632
	}
633
634
	/**
635
	 * Returns the error code for a given property.
636
	 * Helper for MAPIUtils::GetNativeBodyType() function but also used in other places.
637
	 *
638
	 * @param int   $tag
639
	 * @param array $messageprops
640
	 *
641
	 * @return int (MAPI_ERROR_CODE)
642
	 */
643
	public static function GetError($tag, $messageprops) {
644
		$prBodyError = mapi_prop_tag(PT_ERROR, mapi_prop_id($tag));
0 ignored issues
show
Bug introduced by
The constant PT_ERROR was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
645
		if (isset($messageprops[$prBodyError]) && mapi_is_error($messageprops[$prBodyError])) {
646
			if ($messageprops[$prBodyError] == MAPI_E_NOT_ENOUGH_MEMORY_32BIT ||
647
					$messageprops[$prBodyError] == MAPI_E_NOT_ENOUGH_MEMORY_64BIT) {
648
				return MAPI_E_NOT_ENOUGH_MEMORY;
0 ignored issues
show
Bug introduced by
The constant MAPI_E_NOT_ENOUGH_MEMORY was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
649
			}
650
		}
651
652
		return MAPI_E_NOT_FOUND;
0 ignored issues
show
Bug introduced by
The constant MAPI_E_NOT_FOUND was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
653
	}
654
655
	/**
656
	 * Function will be used to decode smime messages and convert it to normal messages.
657
	 *
658
	 * @param MAPISession    $session
0 ignored issues
show
Bug introduced by
The type MAPISession was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
659
	 * @param MAPIStore      $store
660
	 * @param MAPIAdressBook $addressBook
0 ignored issues
show
Bug introduced by
The type MAPIAdressBook was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
661
	 * @param mixed          $mapimessage
662
	 */
663
	public static function ParseSmime($session, $store, $addressBook, &$mapimessage) {
664
		$props = mapi_getprops($mapimessage, [
665
			PR_MESSAGE_CLASS,
0 ignored issues
show
Bug introduced by
The constant PR_MESSAGE_CLASS was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
666
			PR_SUBJECT,
0 ignored issues
show
Bug introduced by
The constant PR_SUBJECT was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
667
			PR_MESSAGE_DELIVERY_TIME,
0 ignored issues
show
Bug introduced by
The constant PR_MESSAGE_DELIVERY_TIME was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
668
			PR_SENT_REPRESENTING_NAME,
0 ignored issues
show
Bug introduced by
The constant PR_SENT_REPRESENTING_NAME was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
669
			PR_SENT_REPRESENTING_ENTRYID,
0 ignored issues
show
Bug introduced by
The constant PR_SENT_REPRESENTING_ENTRYID was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
670
			PR_SENT_REPRESENTING_SEARCH_KEY,
0 ignored issues
show
Bug introduced by
The constant PR_SENT_REPRESENTING_SEARCH_KEY was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
671
			PR_SENT_REPRESENTING_EMAIL_ADDRESS,
0 ignored issues
show
Bug introduced by
The constant PR_SENT_REPRESENTING_EMAIL_ADDRESS was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
672
			PR_SENT_REPRESENTING_SMTP_ADDRESS,
0 ignored issues
show
Bug introduced by
The constant PR_SENT_REPRESENTING_SMTP_ADDRESS was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
673
			PR_SENT_REPRESENTING_ADDRTYPE,
0 ignored issues
show
Bug introduced by
The constant PR_SENT_REPRESENTING_ADDRTYPE was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
674
			PR_CLIENT_SUBMIT_TIME,
0 ignored issues
show
Bug introduced by
The constant PR_CLIENT_SUBMIT_TIME was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
675
			PR_MESSAGE_FLAGS,
0 ignored issues
show
Bug introduced by
The constant PR_MESSAGE_FLAGS was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
676
		]);
677
		$read = $props[PR_MESSAGE_FLAGS] & MSGFLAG_READ;
0 ignored issues
show
Bug introduced by
The constant MSGFLAG_READ was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
678
679
		if (isset($props[PR_MESSAGE_CLASS]) && stripos($props[PR_MESSAGE_CLASS], 'IPM.Note.SMIME.MultipartSigned') !== false) {
680
			// this is a signed message. decode it.
681
			$attachTable = mapi_message_getattachmenttable($mapimessage);
682
			$rows = mapi_table_queryallrows($attachTable, [PR_ATTACH_MIME_TAG, PR_ATTACH_NUM]);
0 ignored issues
show
Bug introduced by
The constant PR_ATTACH_NUM was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
Bug introduced by
The constant PR_ATTACH_MIME_TAG was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
683
			$attnum = false;
684
685
			foreach ($rows as $row) {
686
				if (isset($row[PR_ATTACH_MIME_TAG]) && $row[PR_ATTACH_MIME_TAG] == 'multipart/signed') {
687
					$attnum = $row[PR_ATTACH_NUM];
688
				}
689
			}
690
691
			if ($attnum !== false) {
692
				$att = mapi_message_openattach($mapimessage, $attnum);
693
				$data = mapi_openproperty($att, PR_ATTACH_DATA_BIN);
0 ignored issues
show
Bug introduced by
The constant PR_ATTACH_DATA_BIN was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
694
				mapi_message_deleteattach($mapimessage, $attnum);
695
				mapi_inetmapi_imtomapi($session, $store, $addressBook, $mapimessage, $data, ["parse_smime_signed" => 1]);
696
				SLog::Write(LOGLEVEL_DEBUG, "Convert a smime signed message to a normal message.");
697
			}
698
			$mprops = mapi_getprops($mapimessage, [PR_MESSAGE_FLAGS]);
699
			// Workaround for issue 13
700
			mapi_setprops($mapimessage, [
701
				PR_MESSAGE_CLASS => 'IPM.Note.SMIME.MultipartSigned',
702
				PR_SUBJECT => $props[PR_SUBJECT],
703
				PR_MESSAGE_DELIVERY_TIME => $props[PR_MESSAGE_DELIVERY_TIME],
704
				PR_SENT_REPRESENTING_NAME => $props[PR_SENT_REPRESENTING_NAME],
705
				PR_SENT_REPRESENTING_ENTRYID => $props[PR_SENT_REPRESENTING_ENTRYID],
706
				PR_SENT_REPRESENTING_SEARCH_KEY => $props[PR_SENT_REPRESENTING_SEARCH_KEY],
707
				PR_SENT_REPRESENTING_EMAIL_ADDRESS => $props[PR_SENT_REPRESENTING_EMAIL_ADDRESS] ?? '',
708
				PR_SENT_REPRESENTING_SMTP_ADDRESS => $props[PR_SENT_REPRESENTING_SMTP_ADDRESS] ?? '',
709
				PR_SENT_REPRESENTING_ADDRTYPE => $props[PR_SENT_REPRESENTING_ADDRTYPE] ?? 'SMTP',
710
				PR_CLIENT_SUBMIT_TIME => $props[PR_CLIENT_SUBMIT_TIME] ?? time(),
711
				// mark the message as read if the main message has read flag
712
				PR_MESSAGE_FLAGS => $read ? $mprops[PR_MESSAGE_FLAGS] | MSGFLAG_READ : $mprops[PR_MESSAGE_FLAGS],
713
			]);
714
		}
715
		// TODO check if we need to do this for encrypted (and signed?) message as well
716
	}
717
}
718