202 lines
No EOL
7.7 KiB
Python
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)}"}
|
|
) |