203 lines
No EOL
7.8 KiB
Python
203 lines
No EOL
7.8 KiB
Python
from typing import Dict, Any, Optional
|
|
import logging
|
|
from datetime import datetime, UTC
|
|
from O365 import Account, MSGraphProtocol
|
|
|
|
from modules.methods.methodBase import MethodBase, AuthSource, MethodResult
|
|
from modules.models.userConnection import UserConnection
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
class MethodOutlook(MethodBase):
|
|
"""Outlook method implementation for email operations"""
|
|
|
|
def __init__(self):
|
|
super().__init__()
|
|
self.name = "outlook"
|
|
self.description = "Handle Outlook email operations like reading and sending emails"
|
|
self.auth_source = AuthSource.MICROSOFT
|
|
|
|
@property
|
|
def actions(self) -> Dict[str, Dict[str, Any]]:
|
|
"""Available actions and their parameters"""
|
|
return {
|
|
"readMails": {
|
|
"description": "Read emails from Outlook",
|
|
"retryMax": 2,
|
|
"timeout": 30,
|
|
"parameters": {
|
|
"folder": {"type": "string", "required": False},
|
|
"query": {"type": "string", "required": False},
|
|
"maxResults": {"type": "number", "required": False},
|
|
"includeAttachments": {"type": "boolean", "required": False}
|
|
}
|
|
},
|
|
"sendMail": {
|
|
"description": "Send email through Outlook",
|
|
"retryMax": 2,
|
|
"timeout": 30,
|
|
"parameters": {
|
|
"to": {"type": "array", "items": "string", "required": True},
|
|
"subject": {"type": "string", "required": True},
|
|
"body": {"type": "string", "required": True},
|
|
"cc": {"type": "array", "items": "string", "required": False},
|
|
"bcc": {"type": "array", "items": "string", "required": False},
|
|
"attachments": {"type": "array", "items": "string", "required": False}
|
|
}
|
|
}
|
|
}
|
|
|
|
async def execute(self, action: str, parameters: Dict[str, Any], auth_data: Optional[Dict[str, Any]] = None) -> MethodResult:
|
|
"""Execute Outlook method"""
|
|
try:
|
|
# Validate parameters
|
|
if not await self.validate_parameters(action, parameters):
|
|
return self._create_result(
|
|
success=False,
|
|
data={"error": f"Invalid parameters for {action}"}
|
|
)
|
|
|
|
# Get UserConnection from auth_data
|
|
if not auth_data or "userConnection" not in auth_data:
|
|
return self._create_result(
|
|
success=False,
|
|
data={"error": "UserConnection required for Outlook operations"}
|
|
)
|
|
|
|
user_connection: UserConnection = auth_data["userConnection"]
|
|
|
|
# Execute action
|
|
if action == "readMails":
|
|
return await self._read_mails(parameters, user_connection)
|
|
elif action == "sendMail":
|
|
return await self._send_mail(parameters, user_connection)
|
|
else:
|
|
return self._create_result(
|
|
success=False,
|
|
data={"error": f"Unknown action: {action}"}
|
|
)
|
|
|
|
except Exception as e:
|
|
logger.error(f"Error executing Outlook {action}: {e}")
|
|
return self._create_result(
|
|
success=False,
|
|
data={"error": str(e)}
|
|
)
|
|
|
|
async def _read_mails(self, parameters: Dict[str, Any], user_connection: UserConnection) -> MethodResult:
|
|
"""Read emails from Outlook"""
|
|
try:
|
|
folder = parameters.get("folder", "inbox")
|
|
query = parameters.get("query")
|
|
max_results = parameters.get("maxResults", 10)
|
|
include_attachments = parameters.get("includeAttachments", False)
|
|
|
|
# Create Outlook account
|
|
account = Account(
|
|
credentials=(user_connection.authToken, user_connection.refreshToken),
|
|
protocol=MSGraphProtocol()
|
|
)
|
|
|
|
# Get mailbox
|
|
mailbox = account.mailbox()
|
|
|
|
# Get folder
|
|
target_folder = mailbox.folder(folder_name=folder)
|
|
|
|
# Get messages
|
|
if query:
|
|
messages = target_folder.get_messages(query=query, limit=max_results)
|
|
else:
|
|
messages = target_folder.get_messages(limit=max_results)
|
|
|
|
# Process messages
|
|
results = []
|
|
for message in messages:
|
|
msg_data = {
|
|
"id": message.object_id,
|
|
"subject": message.subject,
|
|
"from": message.sender.address,
|
|
"to": [to.address for to in message.to],
|
|
"cc": [cc.address for cc in message.cc],
|
|
"received": message.received.strftime("%Y-%m-%d %H:%M:%S"),
|
|
"body": message.body,
|
|
"hasAttachments": message.has_attachments
|
|
}
|
|
|
|
if include_attachments and message.has_attachments:
|
|
attachments = []
|
|
for attachment in message.attachments:
|
|
attachments.append({
|
|
"name": attachment.name,
|
|
"contentType": attachment.content_type,
|
|
"size": attachment.size
|
|
})
|
|
msg_data["attachments"] = attachments
|
|
|
|
results.append(msg_data)
|
|
|
|
return self._create_result(
|
|
success=True,
|
|
data={
|
|
"folder": folder,
|
|
"query": query,
|
|
"messages": results
|
|
}
|
|
)
|
|
except Exception as e:
|
|
logger.error(f"Error reading Outlook emails: {e}")
|
|
return self._create_result(
|
|
success=False,
|
|
data={"error": f"Read failed: {str(e)}"}
|
|
)
|
|
|
|
async def _send_mail(self, parameters: Dict[str, Any], user_connection: UserConnection) -> MethodResult:
|
|
"""Send email through Outlook"""
|
|
try:
|
|
to_addresses = parameters["to"]
|
|
subject = parameters["subject"]
|
|
body = parameters["body"]
|
|
cc_addresses = parameters.get("cc", [])
|
|
bcc_addresses = parameters.get("bcc", [])
|
|
attachments = parameters.get("attachments", [])
|
|
|
|
# Create Outlook account
|
|
account = Account(
|
|
credentials=(user_connection.authToken, user_connection.refreshToken),
|
|
protocol=MSGraphProtocol()
|
|
)
|
|
|
|
# Get mailbox
|
|
mailbox = account.mailbox()
|
|
|
|
# Create new message
|
|
message = mailbox.new_message()
|
|
message.to.add(to_addresses)
|
|
if cc_addresses:
|
|
message.cc.add(cc_addresses)
|
|
if bcc_addresses:
|
|
message.bcc.add(bcc_addresses)
|
|
message.subject = subject
|
|
message.body = body
|
|
|
|
# Add attachments
|
|
for attachment_path in attachments:
|
|
message.attachments.add(attachment_path)
|
|
|
|
# Send message
|
|
message.send()
|
|
|
|
return self._create_result(
|
|
success=True,
|
|
data={
|
|
"to": to_addresses,
|
|
"subject": subject,
|
|
"sent": datetime.now(UTC).isoformat()
|
|
}
|
|
)
|
|
except Exception as e:
|
|
logger.error(f"Error sending Outlook email: {e}")
|
|
return self._create_result(
|
|
success=False,
|
|
data={"error": f"Send failed: {str(e)}"}
|
|
) |