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

protocols-handlers.mddocs/

0

# Protocols and Handlers

1

2

Protocol definitions for creating Mail extensions including message decoders, encoders, security handlers, action handlers, and content blockers. This module defines the interfaces that Mail extensions must implement to provide custom functionality.

3

4

## Capabilities

5

6

### MEExtension Protocol

7

8

Base protocol for Mail extensions. All Mail extensions should conform to this protocol.

9

10

```python { .api }

11

# Protocol: MEExtension

12

def handlerForMessageActions(self):

13

"""

14

Return a handler for message actions.

15

16

Returns:

17

Handler object conforming to MEMessageActionHandler protocol, or None

18

"""

19

20

def handlerForMessageSecurity(self):

21

"""

22

Return a handler for message security operations.

23

24

Returns:

25

Handler object conforming to MEMessageSecurityHandler protocol, or None

26

"""

27

28

def handlerForContentBlocker(self):

29

"""

30

Return a handler for content blocking.

31

32

Returns:

33

Handler object conforming to MEContentBlocker protocol, or None

34

"""

35

36

def handlerForComposeSession_(self, session):

37

"""

38

Return a handler for compose sessions.

39

40

Args:

41

session: MEComposeSession instance

42

43

Returns:

44

Handler object conforming to MEComposeSessionHandler protocol, or None

45

"""

46

```

47

48

### MEMessageDecoder Protocol

49

50

Protocol for decoding messages. Extensions implementing this protocol can provide custom message decoding functionality.

51

52

```python { .api }

53

# Protocol: MEMessageDecoder

54

def decodedMessageForMessageData_(self, messageData):

55

"""

56

Decode message data and return a decoded message.

57

58

Args:

59

messageData: NSData containing the raw message data

60

61

Returns:

62

MEDecodedMessage: Decoded message object, or None if decoding failed

63

"""

64

```

65

66

### MEMessageEncoder Protocol

67

68

Protocol for encoding messages. Extensions implementing this protocol can provide custom message encoding functionality.

69

70

```python { .api }

71

# Protocol: MEMessageEncoder

72

def getEncodingStatusForMessage_composeContext_completionHandler_(

73

self, message, composeContext, completionHandler

74

):

75

"""

76

Get encoding status for a message.

77

78

Args:

79

message: The message to get encoding status for

80

composeContext: MEComposeContext with compose information

81

completionHandler: Completion handler: (MEOutgoingMessageEncodingStatus) -> None

82

"""

83

84

def encodeMessage_composeContext_completionHandler_(

85

self, message, composeContext, completionHandler

86

):

87

"""

88

Encode a message for sending.

89

90

Args:

91

message: The message to encode

92

composeContext: MEComposeContext with compose information

93

completionHandler: Completion handler: (MEMessageEncodingResult) -> None

94

"""

95

```

96

97

### MEMessageSecurityHandler Protocol

98

99

Protocol for handling message security operations. Extensions implementing this protocol can provide custom security functionality.

100

101

```python { .api }

102

# Protocol: MEMessageSecurityHandler

103

def extensionViewControllerForMessageContext_(self, messageContext):

104

"""

105

Return a view controller for the message context.

106

107

Args:

108

messageContext: Context information for the message

109

110

Returns:

111

UIViewController: View controller for displaying security information

112

"""

113

114

def extensionViewControllerForMessageSigners_(self, messageSigners):

115

"""

116

Return a view controller for message signers.

117

118

Args:

119

messageSigners: List of MEMessageSigner objects

120

121

Returns:

122

UIViewController: View controller for displaying signer information

123

"""

124

125

def primaryActionClickedForMessageContext_completionHandler_(

126

self, messageContext, completionHandler

127

):

128

"""

129

Handle primary action click for a message.

130

131

Args:

132

messageContext: Context information for the message

133

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

134

"""

135

```

136

137

### MEMessageActionHandler Protocol

138

139

Protocol for handling message actions. Extensions implementing this protocol can provide custom message action functionality.

140

141

```python { .api }

142

# Protocol: MEMessageActionHandler

143

def decideActionForMessage_completionHandler_(self, message, completionHandler):

144

"""

145

Decide what action to take for a message.

146

147

Args:

148

message: MEMessage object to make a decision about

149

completionHandler: Completion handler: (MEMessageActionDecision) -> None

150

"""

151

```

152

153

### MEContentBlocker Protocol

154

155

Protocol for content blocking functionality. Extensions implementing this protocol can provide content filtering capabilities.

156

157

```python { .api }

158

# Protocol: MEContentBlocker

159

def contentRulesJSON(self):

160

"""

161

Return JSON string containing content blocking rules.

162

163

Returns:

164

str: JSON string with content blocking rules in Safari Content Blocker format

165

"""

166

```

167

168

### MEComposeSessionHandler Protocol

169

170

Protocol for handling compose session events and operations. Extensions implementing this protocol can customize the compose experience.

171

172

```python { .api }

173

# Protocol: MEComposeSessionHandler

174

def mailComposeSessionDidBegin_(self, session):

175

"""

176

Called when a compose session begins.

177

178

Args:

179

session: MEComposeSession that began

180

"""

181

182

def mailComposeSessionDidEnd_(self, session):

183

"""

184

Called when a compose session ends.

185

186

Args:

187

session: MEComposeSession that ended

188

"""

189

190

def viewControllerForSession_(self, session):

191

"""

192

Return a view controller for the compose session.

193

194

Args:

195

session: MEComposeSession instance

196

197

Returns:

198

UIViewController: View controller for the compose session

199

"""

200

201

def session_annotateAddressesWithCompletionHandler_(self, session, completionHandler):

202

"""

203

Annotate addresses in a compose session.

204

205

Args:

206

session: MEComposeSession instance

207

completionHandler: Completion handler: (List[MEAddressAnnotation]) -> None

208

"""

209

210

def session_canSendMessageWithCompletionHandler_(self, session, completionHandler):

211

"""

212

Check if a message can be sent in the session.

213

214

Args:

215

session: MEComposeSession instance

216

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

217

"""

218

219

def additionalHeadersForSession_(self, session):

220

"""

221

Provide additional headers for the session.

222

223

Args:

224

session: MEComposeSession instance

225

226

Returns:

227

dict: Dictionary of additional headers, or None

228

"""

229

230

def requiredHeaders(self):

231

"""

232

Return required headers for compose sessions.

233

234

Returns:

235

List[str]: List of required header names, or None

236

"""

237

```

238

239

## Usage Examples

240

241

### Implementing a Message Decoder

242

243

```python

244

import MailKit

245

from Foundation import NSObject

246

247

class CustomMessageDecoder(NSObject):

248

"""Custom message decoder implementation."""

249

250

def decodedMessageForMessageData_(self, messageData):

251

"""Decode custom message format."""

252

try:

253

# Decode the message data

254

# This is where you would implement your custom decoding logic

255

decoded_data = self.decode_custom_format(messageData)

256

257

# Create security information

258

security_info = MailKit.MEMessageSecurityInformation.alloc().initWithSigners_isEncrypted_signingError_encryptionError_(

259

signers=[],

260

isEncrypted=False,

261

signingError=None,

262

encryptionError=None

263

)

264

265

# Create decoded message

266

decoded_message = MailKit.MEDecodedMessage.alloc().initWithData_securityInformation_context_(

267

data=decoded_data,

268

securityInformation=security_info,

269

context=None

270

)

271

272

return decoded_message

273

except Exception as e:

274

print(f"Failed to decode message: {e}")

275

return None

276

277

def decode_custom_format(self, data):

278

"""Implement your custom decoding logic here."""

279

# Placeholder for custom decoding

280

return data

281

```

282

283

### Implementing a Message Action Handler

284

285

```python

286

import MailKit

287

from Foundation import NSObject

288

289

class CustomActionHandler(NSObject):

290

"""Custom message action handler implementation."""

291

292

def decideActionForMessage_completionHandler_(self, message, completionHandler):

293

"""Decide action based on message analysis."""

294

try:

295

# Analyze message to determine action

296

action_decision = self.analyze_message_for_action(message)

297

298

# Call completion handler with decision

299

completionHandler(action_decision)

300

except Exception as e:

301

print(f"Failed to decide action: {e}")

302

completionHandler(None)

303

304

def analyze_message_for_action(self, message):

305

"""Analyze message and return action decision."""

306

# Placeholder for message analysis logic

307

# Return appropriate MEMessageActionDecision

308

return None

309

```

310

311

### Implementing a Content Blocker

312

313

```python

314

import MailKit

315

from Foundation import NSObject

316

import json

317

318

class CustomContentBlocker(NSObject):

319

"""Custom content blocker implementation."""

320

321

def contentRulesJSON(self):

322

"""Return content blocking rules in JSON format."""

323

try:

324

# Define content blocking rules

325

rules = [

326

{

327

"trigger": {

328

"url-filter": ".*tracking.*",

329

"resource-type": ["image"]

330

},

331

"action": {

332

"type": "block"

333

}

334

},

335

{

336

"trigger": {

337

"url-filter": ".*analytics.*"

338

},

339

"action": {

340

"type": "block"

341

}

342

}

343

]

344

345

return json.dumps(rules)

346

except Exception as e:

347

print(f"Failed to generate content rules: {e}")

348

return "[]"

349

```

350

351

### Implementing a Compose Session Handler

352

353

```python

354

import MailKit

355

from Foundation import NSObject

356

357

class CustomComposeSessionHandler(NSObject):

358

"""Custom compose session handler implementation."""

359

360

def mailComposeSessionDidBegin_(self, session):

361

"""Handle compose session beginning."""

362

print("Compose session began")

363

# Perform any initialization needed for the session

364

365

def mailComposeSessionDidEnd_(self, session):

366

"""Handle compose session ending."""

367

print("Compose session ended")

368

# Perform any cleanup needed

369

370

def viewControllerForSession_(self, session):

371

"""Return custom view controller for session."""

372

# Return a custom view controller if needed

373

return None

374

375

def session_annotateAddressesWithCompletionHandler_(self, session, completionHandler):

376

"""Annotate addresses in the session."""

377

try:

378

# Create address annotations

379

annotations = self.create_address_annotations(session)

380

completionHandler(annotations)

381

except Exception as e:

382

print(f"Failed to annotate addresses: {e}")

383

completionHandler([])

384

385

def session_canSendMessageWithCompletionHandler_(self, session, completionHandler):

386

"""Check if message can be sent."""

387

try:

388

# Validate message for sending

389

can_send = self.validate_message_for_sending(session)

390

if can_send:

391

completionHandler(None) # No error means can send

392

else:

393

# Create error for why message cannot be sent

394

error = self.create_validation_error()

395

completionHandler(error)

396

except Exception as e:

397

print(f"Failed to validate message: {e}")

398

completionHandler(e)

399

400

def additionalHeadersForSession_(self, session):

401

"""Provide additional headers."""

402

return {

403

"X-Custom-Extension": "CustomMailExtension",

404

"X-Version": "1.0"

405

}

406

407

def requiredHeaders(self):

408

"""Return required headers."""

409

return ["Subject", "To"]

410

411

def create_address_annotations(self, session):

412

"""Create address annotations for the session."""

413

# Placeholder for annotation creation logic

414

return []

415

416

def validate_message_for_sending(self, session):

417

"""Validate if message can be sent."""

418

# Placeholder for validation logic

419

return True

420

421

def create_validation_error(self):

422

"""Create validation error."""

423

# Placeholder for error creation

424

return None

425

```

426

427

### Implementing a Complete Extension

428

429

```python

430

import MailKit

431

from Foundation import NSObject

432

433

class CompleteMailExtension(NSObject):

434

"""Complete Mail extension implementing multiple protocols."""

435

436

def __init__(self):

437

super().__init__()

438

self.action_handler = CustomActionHandler.alloc().init()

439

self.security_handler = CustomSecurityHandler.alloc().init()

440

self.content_blocker = CustomContentBlocker.alloc().init()

441

442

# MEExtension protocol methods

443

def handlerForMessageActions(self):

444

"""Return message action handler."""

445

return self.action_handler

446

447

def handlerForMessageSecurity(self):

448

"""Return message security handler."""

449

return self.security_handler

450

451

def handlerForContentBlocker(self):

452

"""Return content blocker handler."""

453

return self.content_blocker

454

455

def handlerForComposeSession_(self, session):

456

"""Return compose session handler."""

457

return CustomComposeSessionHandler.alloc().init()

458

459

# Usage in extension main

460

# extension = CompleteMailExtension.alloc().init()

461

```