Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions MicrosoftOutlook/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Changed

- Upgraded `sekoia-automation-sdk` to `1.23.1` and migrated `pydantic.v1`-shim models to native Pydantic v2 to avoid v1/v2 model-mixing errors.

## 2026-07-09 - 0.1.3

### Fixed

- Simplified message action argument validation by reusing a shared `NonEmptyStr` Pydantic constraint for `user` and `message_id`, still rejecting missing or blank values before calling Microsoft Graph.

## 2025-09-22 - 0.1.2

### Added
Expand Down
2 changes: 1 addition & 1 deletion MicrosoftOutlook/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,5 @@
"categories": [
"Email"
],
"version": "0.1.2"
"version": "0.1.3"
}
1 change: 1 addition & 0 deletions MicrosoftOutlook/microsoft_outlook_modules/action_base.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from abc import ABC
from typing import Any
from functools import cached_property

from requests import Response
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
from typing import Any

from pydantic import BaseModel, Field

from .action_base import MicrosoftGraphActionBase
from .models import NonEmptyStr


class DeleteMessageArguments(BaseModel):
user: NonEmptyStr = Field(..., description="User id or user principal name")
message_id: NonEmptyStr = Field(..., description="Message id")


class DeleteMessageAction(MicrosoftGraphActionBase):
def run(self, arguments: Any) -> Any:
user_id_or_principal_name = arguments["user"]
message_id = arguments["message_id"]
def run(self, arguments: DeleteMessageArguments) -> Any:
user_id_or_principal_name = arguments.user
message_id = arguments.message_id

response = self.client.delete(
f"https://graph.microsoft.com/v1.0/users/{user_id_or_principal_name}/messages/{message_id}",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,25 @@
from typing import Any
from typing import Any, List

from pydantic import BaseModel, Field

from .action_base import MicrosoftGraphActionBase
from .models import NonEmptyStr


class ForwardMessageArguments(BaseModel):
user: NonEmptyStr = Field(..., description="User id or user principal name")
message_id: NonEmptyStr = Field(..., description="Message id")
recipients: List[str] = Field(..., description="Recipients to forward the message to")
comment: str = Field(default="", description="Comment to add to the forwarded message")


class ForwardMessageAction(MicrosoftGraphActionBase):
def run(self, arguments: Any) -> Any:
user_id_or_principal_name = arguments["user"]
message_id = arguments["message_id"]
recipients: list[str] = arguments["recipients"]
def run(self, arguments: ForwardMessageArguments) -> Any:
user_id_or_principal_name = arguments.user
message_id = arguments.message_id
recipients = arguments.recipients

comment = arguments.get("comment", "")
comment = arguments.comment

payload = {
"comment": comment,
Expand Down
14 changes: 11 additions & 3 deletions MicrosoftOutlook/microsoft_outlook_modules/action_get_message.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
from typing import Any

from pydantic import BaseModel, Field

from .action_base import MicrosoftGraphActionBase
from .models import NonEmptyStr


class GetMessageArguments(BaseModel):
user: NonEmptyStr = Field(..., description="User id or user principal name")
message_id: NonEmptyStr = Field(..., description="Message id")


class GetMessageAction(MicrosoftGraphActionBase):
def run(self, arguments: Any) -> Any:
user_id_or_principal_name = arguments["user"]
message_id = arguments["message_id"]
def run(self, arguments: GetMessageArguments) -> Any:
user_id_or_principal_name = arguments.user
message_id = arguments.message_id

response = self.client.get(
f"https://graph.microsoft.com/v1.0/users/{user_id_or_principal_name}/messages/{message_id}",
Expand Down
46 changes: 32 additions & 14 deletions MicrosoftOutlook/microsoft_outlook_modules/action_send_message.py
Original file line number Diff line number Diff line change
@@ -1,28 +1,46 @@
from typing import Any
from typing import Any, List, Optional

import requests
from pydantic import BaseModel, ConfigDict, Field

from .action_base import MicrosoftGraphActionBase
from .models import NonEmptyStr


class SendMessageArguments(BaseModel):
user: NonEmptyStr = Field(..., description="User id or user principal name")
save_to_sent_items: bool = Field(default=True, description="Whether to save the message to sent items")
content: Optional[str] = None
content_type: str = Field(default="text", description="Content type of the message body")
bcc: Optional[List[str]] = None
cc: Optional[List[str]] = None
sender: Optional[str] = None
from_: Optional[str] = Field(default=None, alias="from")
subject: Optional[str] = None
recipients: Optional[List[str]] = None
importance: Optional[str] = None

model_config = ConfigDict(populate_by_name=True)


class SendMessageAction(MicrosoftGraphActionBase):
@staticmethod
def generate_recipient(email: str) -> dict[str, Any]:
return {"emailAddress": {"name": email, "address": email}}

def run(self, arguments: Any) -> Any:
user_id_or_principal_name = arguments["user"]
save_to_sent_items = arguments.get("save_to_sent_items", True)

content = arguments.get("content")
content_type = arguments.get("content_type", "text")
bcc: list[str] | None = arguments.get("bcc")
cc: list[str] | None = arguments.get("cc")
sender = arguments.get("sender")
mailbox_owner = arguments.get("from")
subject = arguments.get("subject")
recipients: list[str] | None = arguments.get("recipients")
importance = arguments.get("importance")
def run(self, arguments: SendMessageArguments) -> Any:
user_id_or_principal_name = arguments.user
save_to_sent_items = arguments.save_to_sent_items

content = arguments.content
content_type = arguments.content_type
bcc = arguments.bcc
cc = arguments.cc
sender = arguments.sender
mailbox_owner = arguments.from_
subject = arguments.subject
recipients = arguments.recipients
importance = arguments.importance

message: dict[str, Any] = {}
if content:
Expand Down
44 changes: 31 additions & 13 deletions MicrosoftOutlook/microsoft_outlook_modules/action_update_message.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,24 @@
from typing import Any
from typing import Any, List, Optional

from pydantic import BaseModel, ConfigDict, Field

from .action_base import MicrosoftGraphActionBase
from .models import NonEmptyStr


class UpdateMessageArguments(BaseModel):
user: NonEmptyStr = Field(..., description="User id or user principal name")
message_id: NonEmptyStr = Field(..., description="Message id")
content: Optional[str] = None
bcc: Optional[List[str]] = None
cc: Optional[List[str]] = None
sender: Optional[str] = None
from_: Optional[str] = Field(default=None, alias="from")
subject: Optional[str] = None
recipients: Optional[List[str]] = None
importance: Optional[str] = None

model_config = ConfigDict(populate_by_name=True)


class UpdateMessageAction(MicrosoftGraphActionBase):
Expand All @@ -12,18 +30,18 @@ def fill_non_empty(d: dict[str, Any]) -> dict[str, Any]:
def generate_recipient(email: str) -> dict[str, Any]:
return {"emailAddress": {"name": email, "address": email}}

def run(self, arguments: Any) -> Any:
user_id_or_principal_name = arguments["user"]
message_id = arguments["message_id"]

content = arguments.get("content")
bcc: list[str] | None = arguments.get("bcc")
cc: list[str] | None = arguments.get("cc")
sender = arguments.get("sender")
mailbox_owner = arguments.get("from")
subject = arguments.get("subject")
recipients: list[str] | None = arguments.get("recipients")
importance = arguments.get("importance")
def run(self, arguments: UpdateMessageArguments) -> Any:
user_id_or_principal_name = arguments.user
message_id = arguments.message_id

content = arguments.content
bcc = arguments.bcc
cc = arguments.cc
sender = arguments.sender
mailbox_owner = arguments.from_
subject = arguments.subject
recipients = arguments.recipients
importance = arguments.importance

payload: dict[str, Any] = self.fill_non_empty(
{
Expand Down
8 changes: 6 additions & 2 deletions MicrosoftOutlook/microsoft_outlook_modules/models.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
from pydantic.v1 import BaseModel, Field
from typing import Annotated

from pydantic import BaseModel, Field, StringConstraints

NonEmptyStr = Annotated[str, StringConstraints(strip_whitespace=True, min_length=1)]


class MicrosoftOutlookModuleConfiguration(BaseModel):
Expand All @@ -10,8 +14,8 @@ class MicrosoftOutlookModuleConfiguration(BaseModel):
# noqa: E501
)
client_secret: str = Field(
secret=True,
description="Client Secret associated with the registered application. Admin Consent has to be granted to the "
"application for it to work.",
json_schema_extra={"secret": True},
# noqa: E501
)
Loading