gateway/modules/methods/methodOutlook.py
2025-06-12 01:11:33 +02:00

202 lines
No EOL
7.7 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, 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"
@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], authData: Optional[Dict[str, Any]] = None) -> MethodResult:
"""Execute Outlook method"""
try:
# Validate parameters
if not await self.validateParameters(action, parameters):
return self._createResult(
success=False,
data={"error": f"Invalid parameters for {action}"}
)
# Get UserConnection from auth_data
if not authData or "userConnection" not in authData:
return self._createResult(
success=False,
data={"error": "UserConnection required for Outlook operations"}
)
userConnection: UserConnection = authData["userConnection"]
# Execute action
if action == "readMails":
return await self._readMails(parameters, userConnection)
elif action == "sendMail":
return await self._sendMail(parameters, userConnection)
else:
return self._createResult(
success=False,
data={"error": f"Unknown action: {action}"}
)
except Exception as e:
logger.error(f"Error executing Outlook {action}: {e}")
return self._createResult(
success=False,
data={"error": str(e)}
)
async def _readMails(self, parameters: Dict[str, Any], userConnection: UserConnection) -> MethodResult:
"""Read emails from Outlook"""
try:
folder = parameters.get("folder", "inbox")
query = parameters.get("query")
maxResults = parameters.get("maxResults", 10)
includeAttachments = parameters.get("includeAttachments", False)
# Create Outlook account
account = Account(
credentials=(userConnection.authToken, userConnection.refreshToken),
protocol=MSGraphProtocol()
)
# Get mailbox
mailbox = account.mailbox()
# Get folder
targetFolder = mailbox.folder(folder_name=folder)
# Get messages
if query:
messages = targetFolder.get_messages(query=query, limit=maxResults)
else:
messages = targetFolder.get_messages(limit=maxResults)
# Process messages
results = []
for message in messages:
msgData = {
"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 includeAttachments and message.has_attachments:
attachments = []
for attachment in message.attachments:
attachments.append({
"name": attachment.name,
"contentType": attachment.content_type,
"size": attachment.size
})
msgData["attachments"] = attachments
results.append(msgData)
return self._createResult(
success=True,
data={
"folder": folder,
"query": query,
"messages": results
}
)
except Exception as e:
logger.error(f"Error reading Outlook emails: {e}")
return self._createResult(
success=False,
data={"error": f"Read failed: {str(e)}"}
)
async def _sendMail(self, parameters: Dict[str, Any], userConnection: UserConnection) -> MethodResult:
"""Send email through Outlook"""
try:
toAddresses = parameters["to"]
subject = parameters["subject"]
body = parameters["body"]
ccAddresses = parameters.get("cc", [])
bccAddresses = parameters.get("bcc", [])
attachments = parameters.get("attachments", [])
# Create Outlook account
account = Account(
credentials=(userConnection.authToken, userConnection.refreshToken),
protocol=MSGraphProtocol()
)
# Get mailbox
mailbox = account.mailbox()
# Create new message
message = mailbox.new_message()
message.to.add(toAddresses)
if ccAddresses:
message.cc.add(ccAddresses)
if bccAddresses:
message.bcc.add(bccAddresses)
message.subject = subject
message.body = body
# Add attachments
for attachmentPath in attachments:
message.attachments.add(attachmentPath)
# Send message
message.send()
return self._createResult(
success=True,
data={
"to": toAddresses,
"subject": subject,
"sent": datetime.now(UTC).isoformat()
}
)
except Exception as e:
logger.error(f"Error sending Outlook email: {e}")
return self._createResult(
success=False,
data={"error": f"Send failed: {str(e)}"}
)