Python bindings for Apple's MailKit framework, enabling developers to create mail extensions that integrate with macOS Mail applications
—
Email composition session handling including compose context, session handlers, and address annotation. This module provides functionality for managing email composition workflows and customizing the compose experience.
Manages email composition sessions. This is the primary class for working with compose sessions in Mail extensions.
class MEComposeSession:
"""
Manages an email composition session.
Note: This class cannot be instantiated directly using init() or new().
Instances are provided by the Mail framework when composition begins.
"""Provides context information for email composition including encryption/signing state. Contains information about the current state and requirements for message composition.
class MEComposeContext:
def isEncrypted(self) -> bool:
"""
Check if the compose context indicates encryption.
Returns:
bool: True if the context is encrypted
"""
def shouldEncrypt(self) -> bool:
"""
Check if the message should be encrypted.
Returns:
bool: True if the message should be encrypted
"""
def isSigned(self) -> bool:
"""
Check if the compose context indicates signing.
Returns:
bool: True if the context is signed
"""
def shouldSign(self) -> bool:
"""
Check if the message should be signed.
Returns:
bool: True if the message should be signed
"""Provides annotations for email addresses during composition. Used to add additional information or context to email addresses in the compose interface.
class MEAddressAnnotation:
"""
Provides annotations for email addresses.
Note: This class cannot be instantiated directly using init() or new().
Instances are created through the address annotation process.
"""Constants representing different compose user actions:
MEComposeUserActionNewMessage: int # = 1, Creating a new message
MEComposeUserActionReply: int # = 2, Replying to a message
MEComposeUserActionReplyAll: int # = 3, Replying to all recipients
MEComposeUserActionForward: int # = 4, Forwarding a message# Error domain
MEComposeSessionErrorDomain: str # Error domain for compose session errors
# Error codes
MEComposeSessionErrorCodeInvalidRecipients: int # = 0, Invalid recipients error
MEComposeSessionErrorCodeInvalidHeaders: int # = 1, Invalid headers error
MEComposeSessionErrorCodeInvalidBody: int # = 2, Invalid body errorType definition for compose session error codes:
MEComposeSessionErrorCode: type # Enum type for compose session error codesimport MailKit
# Check compose context security settings
def check_compose_security(compose_context):
"""Check and report on compose context security settings."""
# Check current encryption state
if compose_context.isEncrypted():
print("Compose context is currently encrypted")
# Check if encryption is recommended
if compose_context.shouldEncrypt():
print("Message should be encrypted")
else:
print("Encryption not required")
# Check current signing state
if compose_context.isSigned():
print("Compose context is currently signed")
# Check if signing is recommended
if compose_context.shouldSign():
print("Message should be signed")
else:
print("Signing not required")
# Example usage with a compose context
# compose_context would be provided by the Mail framework
# check_compose_security(compose_context)import MailKit
# Determine compose action type
def get_compose_action_description(action_type):
"""Get a description of the compose action type."""
if action_type == MailKit.MEComposeUserActionNewMessage:
return "Creating a new message"
elif action_type == MailKit.MEComposeUserActionReply:
return "Replying to a message"
elif action_type == MailKit.MEComposeUserActionReplyAll:
return "Replying to all recipients"
elif action_type == MailKit.MEComposeUserActionForward:
return "Forwarding a message"
else:
return f"Unknown compose action: {action_type}"
# Example usage
action = MailKit.MEComposeUserActionReply
description = get_compose_action_description(action)
print(description) # Output: "Replying to a message"import MailKit
# Handle compose session errors
def handle_compose_error(error_code):
"""Handle different types of compose session errors."""
if error_code == MailKit.MEComposeSessionErrorCodeInvalidRecipients:
return {
"error": "Invalid Recipients",
"description": "One or more recipients are invalid",
"suggestion": "Please check recipient email addresses"
}
elif error_code == MailKit.MEComposeSessionErrorCodeInvalidHeaders:
return {
"error": "Invalid Headers",
"description": "Message headers are invalid",
"suggestion": "Please check message headers and format"
}
elif error_code == MailKit.MEComposeSessionErrorCodeInvalidBody:
return {
"error": "Invalid Body",
"description": "Message body is invalid",
"suggestion": "Please check message content and formatting"
}
else:
return {
"error": "Unknown Error",
"description": f"Unknown error code: {error_code}",
"suggestion": "Please try again or contact support"
}
# Example usage
error_info = handle_compose_error(MailKit.MEComposeSessionErrorCodeInvalidRecipients)
print(f"Error: {error_info['error']} - {error_info['description']}")
print(f"Suggestion: {error_info['suggestion']}")import MailKit
# All available compose actions
compose_actions = {
"new_message": MailKit.MEComposeUserActionNewMessage,
"reply": MailKit.MEComposeUserActionReply,
"reply_all": MailKit.MEComposeUserActionReplyAll,
"forward": MailKit.MEComposeUserActionForward
}
# Function to get action name from value
def get_action_name(action_value):
for name, value in compose_actions.items():
if value == action_value:
return name
return "unknown"
# Function to validate compose action
def is_valid_compose_action(action_value):
return action_value in compose_actions.values()
# Example usage
action_name = get_action_name(MailKit.MEComposeUserActionForward)
print(f"Action: {action_name}") # Output: "Action: forward"
if is_valid_compose_action(MailKit.MEComposeUserActionReply):
print("Reply action is valid")import MailKit
# Comprehensive security analysis for compose context
def analyze_compose_security(compose_context):
"""Perform comprehensive security analysis of compose context."""
analysis = {
"current_state": {},
"recommendations": {},
"warnings": []
}
# Analyze current state
analysis["current_state"]["encrypted"] = compose_context.isEncrypted()
analysis["current_state"]["signed"] = compose_context.isSigned()
# Analyze recommendations
analysis["recommendations"]["should_encrypt"] = compose_context.shouldEncrypt()
analysis["recommendations"]["should_sign"] = compose_context.shouldSign()
# Generate warnings based on mismatches
if compose_context.shouldEncrypt() and not compose_context.isEncrypted():
analysis["warnings"].append("Encryption is recommended but not currently enabled")
if compose_context.shouldSign() and not compose_context.isSigned():
analysis["warnings"].append("Signing is recommended but not currently enabled")
# Generate security summary
security_level = "basic"
if analysis["current_state"]["encrypted"] and analysis["current_state"]["signed"]:
security_level = "high"
elif analysis["current_state"]["encrypted"] or analysis["current_state"]["signed"]:
security_level = "medium"
analysis["security_level"] = security_level
return analysis
# Example usage
# analysis = analyze_compose_security(compose_context)
# print(f"Security Level: {analysis['security_level']}")
# for warning in analysis["warnings"]:
# print(f"Warning: {warning}")Install with Tessl CLI
npx tessl i tessl/pypi-pyobjc-framework-mailkit