or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

compose-sessions.mdextension-management.mdindex.mdmessage-actions.mdmessage-classes.mdprotocols-handlers.mdsecurity-encryption.md

extension-management.mddocs/

0

# Extension Management

1

2

Extension manager for controlling Mail extensions, reloading content blockers, and managing visible messages. This module provides the core functionality for managing Mail extension lifecycle and operations.

3

4

## Capabilities

5

6

### MEExtensionManager

7

8

Manager for Mail extension operations and reloading. This is the primary class for controlling extension behavior and triggering system updates.

9

10

```python { .api }

11

class MEExtensionManager:

12

def reloadContentBlockerWithIdentifier_completionHandler_(

13

self,

14

identifier: str, # Content blocker identifier

15

completionHandler # Completion handler: (NSError or None) -> None

16

):

17

"""

18

Reload a content blocker with the specified identifier.

19

20

Args:

21

identifier: The unique identifier of the content blocker to reload

22

completionHandler: Completion handler called when reload completes,

23

receives an NSError if the operation failed, None on success

24

"""

25

26

def reloadVisibleMessagesWithCompletionHandler_(

27

self,

28

completionHandler # Completion handler: (NSError or None) -> None

29

):

30

"""

31

Reload all visible messages in the Mail application.

32

33

Args:

34

completionHandler: Completion handler called when reload completes,

35

receives an NSError if the operation failed, None on success

36

"""

37

```

38

39

### MEExtensionViewController

40

41

Base view controller class for Mail extensions. Provides the foundation for creating custom view controllers in Mail extensions.

42

43

```python { .api }

44

class MEExtensionViewController:

45

"""

46

Base view controller for Mail extensions.

47

48

This class provides the foundation for creating custom view controllers

49

that integrate with the Mail application interface.

50

51

Note: This class cannot be instantiated directly using init() or new().

52

Subclass this class to create custom extension view controllers.

53

"""

54

```

55

56

## Usage Examples

57

58

### Reloading Content Blockers

59

60

```python

61

import MailKit

62

63

# Reload a specific content blocker

64

def reload_content_blocker(extension_manager, blocker_id):

65

"""Reload a content blocker and handle the result."""

66

67

def completion_handler(error):

68

if error is None:

69

print(f"Successfully reloaded content blocker: {blocker_id}")

70

else:

71

print(f"Failed to reload content blocker {blocker_id}: {error}")

72

73

extension_manager.reloadContentBlockerWithIdentifier_completionHandler_(

74

identifier=blocker_id,

75

completionHandler=completion_handler

76

)

77

78

# Example usage

79

# extension_manager would be provided by the Mail framework

80

# reload_content_blocker(extension_manager, "com.example.mailblocker")

81

```

82

83

### Reloading Visible Messages

84

85

```python

86

import MailKit

87

88

# Reload all visible messages

89

def reload_visible_messages(extension_manager):

90

"""Reload all visible messages and handle the result."""

91

92

def completion_handler(error):

93

if error is None:

94

print("Successfully reloaded visible messages")

95

else:

96

print(f"Failed to reload visible messages: {error}")

97

98

extension_manager.reloadVisibleMessagesWithCompletionHandler_(

99

completionHandler=completion_handler

100

)

101

102

# Example usage

103

# extension_manager would be provided by the Mail framework

104

# reload_visible_messages(extension_manager)

105

```

106

107

### Extension Manager Utility Class

108

109

```python

110

import MailKit

111

112

class MailExtensionManager:

113

"""Utility class for managing Mail extension operations."""

114

115

def __init__(self, extension_manager):

116

"""

117

Initialize with a MEExtensionManager instance.

118

119

Args:

120

extension_manager: MEExtensionManager instance from the Mail framework

121

"""

122

self.extension_manager = extension_manager

123

self.reload_callbacks = {}

124

125

def reload_content_blocker_async(self, blocker_id, callback=None):

126

"""

127

Asynchronously reload a content blocker.

128

129

Args:

130

blocker_id: Identifier of the content blocker

131

callback: Optional callback function to call on completion

132

"""

133

def completion_handler(error):

134

success = error is None

135

if callback:

136

callback(blocker_id, success, error)

137

138

# Store result for later retrieval

139

self.reload_callbacks[blocker_id] = {

140

"success": success,

141

"error": error,

142

"timestamp": __import__("time").time()

143

}

144

145

self.extension_manager.reloadContentBlockerWithIdentifier_completionHandler_(

146

identifier=blocker_id,

147

completionHandler=completion_handler

148

)

149

150

def reload_visible_messages_async(self, callback=None):

151

"""

152

Asynchronously reload visible messages.

153

154

Args:

155

callback: Optional callback function to call on completion

156

"""

157

def completion_handler(error):

158

success = error is None

159

if callback:

160

callback(success, error)

161

162

self.extension_manager.reloadVisibleMessagesWithCompletionHandler_(

163

completionHandler=completion_handler

164

)

165

166

def get_last_reload_result(self, blocker_id):

167

"""

168

Get the result of the last reload operation for a content blocker.

169

170

Args:

171

blocker_id: Identifier of the content blocker

172

173

Returns:

174

dict: Result information or None if no reload has been performed

175

"""

176

return self.reload_callbacks.get(blocker_id)

177

178

# Example usage

179

# manager = MailExtensionManager(extension_manager_instance)

180

#

181

# def reload_callback(blocker_id, success, error):

182

# if success:

183

# print(f"Content blocker {blocker_id} reloaded successfully")

184

# else:

185

# print(f"Failed to reload content blocker {blocker_id}: {error}")

186

#

187

# manager.reload_content_blocker_async("com.example.blocker", reload_callback)

188

```

189

190

### Batch Content Blocker Operations

191

192

```python

193

import MailKit

194

195

class BatchExtensionManager:

196

"""Manager for batch extension operations."""

197

198

def __init__(self, extension_manager):

199

self.extension_manager = extension_manager

200

self.pending_operations = {}

201

202

def reload_multiple_content_blockers(self, blocker_ids, completion_callback=None):

203

"""

204

Reload multiple content blockers and track completion.

205

206

Args:

207

blocker_ids: List of content blocker identifiers

208

completion_callback: Called when all operations complete

209

"""

210

batch_id = f"batch_{__import__('time').time()}"

211

self.pending_operations[batch_id] = {

212

"total": len(blocker_ids),

213

"completed": 0,

214

"results": {},

215

"callback": completion_callback

216

}

217

218

def individual_completion(blocker_id, error):

219

batch_info = self.pending_operations[batch_id]

220

batch_info["completed"] += 1

221

batch_info["results"][blocker_id] = {

222

"success": error is None,

223

"error": error

224

}

225

226

# Check if batch is complete

227

if batch_info["completed"] == batch_info["total"]:

228

if batch_info["callback"]:

229

batch_info["callback"](batch_id, batch_info["results"])

230

# Clean up

231

del self.pending_operations[batch_id]

232

233

# Start all reload operations

234

for blocker_id in blocker_ids:

235

self.extension_manager.reloadContentBlockerWithIdentifier_completionHandler_(

236

identifier=blocker_id,

237

completionHandler=lambda error, bid=blocker_id: individual_completion(bid, error)

238

)

239

240

return batch_id

241

242

def get_batch_status(self, batch_id):

243

"""

244

Get the status of a batch operation.

245

246

Args:

247

batch_id: Batch operation identifier

248

249

Returns:

250

dict: Batch status information or None if not found

251

"""

252

return self.pending_operations.get(batch_id)

253

254

# Example usage

255

# batch_manager = BatchExtensionManager(extension_manager_instance)

256

#

257

# def batch_completion(batch_id, results):

258

# print(f"Batch {batch_id} completed:")

259

# for blocker_id, result in results.items():

260

# status = "SUCCESS" if result["success"] else "FAILED"

261

# print(f" {blocker_id}: {status}")

262

#

263

# blocker_list = ["com.example.blocker1", "com.example.blocker2", "com.example.blocker3"]

264

# batch_id = batch_manager.reload_multiple_content_blockers(blocker_list, batch_completion)

265

```

266

267

### Error Handling and Retry Logic

268

269

```python

270

import MailKit

271

import time

272

273

class RobustExtensionManager:

274

"""Extension manager with retry logic and error handling."""

275

276

def __init__(self, extension_manager, max_retries=3, retry_delay=1.0):

277

self.extension_manager = extension_manager

278

self.max_retries = max_retries

279

self.retry_delay = retry_delay

280

self.retry_attempts = {}

281

282

def reload_content_blocker_with_retry(self, blocker_id, final_callback=None):

283

"""

284

Reload content blocker with automatic retry on failure.

285

286

Args:

287

blocker_id: Content blocker identifier

288

final_callback: Callback called after all retries exhausted

289

"""

290

attempt_key = f"{blocker_id}_{time.time()}"

291

self.retry_attempts[attempt_key] = 0

292

293

def attempt_reload():

294

attempt_count = self.retry_attempts[attempt_key]

295

296

def completion_handler(error):

297

if error is None:

298

# Success - clean up and notify

299

if attempt_key in self.retry_attempts:

300

del self.retry_attempts[attempt_key]

301

if final_callback:

302

final_callback(blocker_id, True, None, attempt_count + 1)

303

else:

304

# Failure - check if we should retry

305

self.retry_attempts[attempt_key] += 1

306

current_attempt = self.retry_attempts[attempt_key]

307

308

if current_attempt < self.max_retries:

309

print(f"Retrying content blocker reload {blocker_id} (attempt {current_attempt + 1}/{self.max_retries})")

310

# Schedule retry after delay

311

__import__("threading").Timer(self.retry_delay, attempt_reload).start()

312

else:

313

# All retries exhausted

314

if attempt_key in self.retry_attempts:

315

del self.retry_attempts[attempt_key]

316

if final_callback:

317

final_callback(blocker_id, False, error, current_attempt)

318

319

self.extension_manager.reloadContentBlockerWithIdentifier_completionHandler_(

320

identifier=blocker_id,

321

completionHandler=completion_handler

322

)

323

324

# Start first attempt

325

attempt_reload()

326

327

# Example usage

328

# robust_manager = RobustExtensionManager(extension_manager_instance, max_retries=3, retry_delay=2.0)

329

#

330

# def final_callback(blocker_id, success, error, attempts):

331

# if success:

332

# print(f"Content blocker {blocker_id} reloaded successfully after {attempts} attempts")

333

# else:

334

# print(f"Failed to reload content blocker {blocker_id} after {attempts} attempts: {error}")

335

#

336

# robust_manager.reload_content_blocker_with_retry("com.example.blocker", final_callback)

337

```