Integrations Module
Standardization: Provides a consistent approach to configuring and managing external systems.
Immutable Configurations: Uses secure, immutable configuration containers.
Common Interfaces: Defines standard methods for all integration implementations.
Adapters: Converts backend DTOs into integration instances.
Base Classes & Implementations: Offers reusable base functionality and specific service implementations.
1. Integration Configuration
The IntegrationConfig
is a frozen dataclass that stores configuration settings for integrations.
File: autoppia_sdk/src/integrations/config.py
pythonCopiarfrom dataclasses import dataclass
from typing import Dict, Any
@dataclass(frozen=True)
class IntegrationConfig:
"""Immutable configuration container for integration instances.
Attributes:
name (str): The unique identifier or name of the integration.
category (str): The category or type of integration (e.g., 'database', 'messaging', 'storage', etc.).
attributes (Dict[str, Any]): A dictionary containing configuration parameters specific to the integration.
"""
name: str
category: str
attributes: Dict[str, Any]
2. Integration Interface and Base Class
The IntegrationInterface
defines the required methods for integrations, while the Integration
base class implements the interface.
File: autoppia_sdk/src/integrations/interface.py
pythonCopiarclass IntegrationInterface:
"""Interface that all integration implementations must adhere to."""
def send(self, data):
raise NotImplementedError
def receive(self):
raise NotImplementedError
File: autoppia_sdk/src/integrations/implementations/base.py
pythonCopiarfrom autoppia_sdk.src.integrations.interface import IntegrationInterface
class Integration(IntegrationInterface):
"""Base Integration class that implements the IntegrationInterface.
This class serves as a base implementation for all integration types in the Autoppia SDK.
"""
pass
3. SMTP Email Integration
The SDK includes an example implementation for email functionality using SMTP (for sending emails) and IMAP (for receiving emails).
File: autoppia_sdk/src/integrations/implementations/email/smtp_integration.py
pythonCopiarimport email
import imaplib
import smtplib
from email import encoders
from email.mime.base import MIMEBase
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from typing import Dict, List, Optional
from autoppia_sdk.src.integrations.implementations.email.interface import EmailIntegration
from autoppia_sdk.src.integrations.config import IntegrationConfig
from autoppia_sdk.src.integrations.implementations.base import Integration
class SMPTEmailIntegration(EmailIntegration, Integration):
"""SMTP-based email integration for sending and receiving emails.
Attributes:
integration_config (IntegrationConfig): Configuration object containing email settings.
smtp_server (str): SMTP server hostname.
smtp_port (int): SMTP server port.
imap_server (str): IMAP server hostname.
imap_port (int): IMAP server port.
email (str): Email address used for authentication.
_password (str): Password used for authentication.
"""
def __init__(self, integration_config: IntegrationConfig):
self.integration_config = integration_config
self.smtp_server = integration_config.attributes.get("SMTP Server")
self.smtp_port = integration_config.attributes.get("SMTP Port")
self.imap_server = integration_config.attributes.get("IMAP Server")
self.imap_port = integration_config.attributes.get("IMAP Port")
self.email = integration_config.attributes.get("email")
self._password = integration_config.attributes.get("password")
def send_email(
self,
to: str,
subject: str,
body: str,
html_body: str = None,
files: List[str] = None,
) -> Optional[str]:
try:
msg = MIMEMultipart()
msg["From"] = self.email
msg["To"] = to
msg["Subject"] = subject
if html_body:
msg.attach(MIMEText(html_body, "html"))
else:
msg.attach(MIMEText(body, "plain"))
if files:
for file in files:
part = MIMEBase("application", "octet-stream")
with open(file, "rb") as f:
part.set_payload(f.read())
encoders.encode_base64(part)
part.add_header(
"Content-Disposition",
f"attachment; filename={file.split('/')[-1]}",
)
msg.attach(part)
server = smtplib.SMTP_SSL(self.smtp_server, self.smtp_port)
server.login(self.email, self._password)
server.send_message(msg)
server.quit()
content_snippet = (html_body or body)[:50]
return f"Email sent successfully from {self.email} to {to}. Message content preview: '{content_snippet}'"
except Exception as e:
print(f"An error occurred: {e}")
return None
def read_emails(self, num: int = 5) -> Optional[List[Dict[str, str]]]:
imap_conn = None
try:
imap_conn = imaplib.IMAP4_SSL(self.imap_server, self.imap_port)
imap_conn.login(self.email, self._password)
imap_conn.select("inbox")
_, message_numbers = imap_conn.search(None, "ALL")
start_index = max(0, len(message_numbers[0].split()) - num)
emails_list = []
for num in message_numbers[0].split()[start_index:]:
_, data = imap_conn.fetch(num, "(RFC822)")
msg = email.message_from_bytes(data[0][1])
email_data = {
"From": msg["From"],
"Subject": msg["Subject"],
"Body": "",
}
if msg.is_multipart():
for part in msg.walk():
if (
part.get_content_type() == "text/plain"
and "attachment" not in str(part.get("Content-Disposition"))
):
email_data["Body"] = part.get_payload(decode=True).decode()
break
else:
email_data["Body"] = (
msg.get_payload(decode=True).decode() if msg.get_payload() else ""
)
emails_list.append(email_data)
return emails_list
except Exception as e:
print(f"An error occurred: {e}")
return None
finally:
if imap_conn:
try:
imap_conn.logout()
except Exception as e:
print(f"Error during logout: {e}")
4. Integration Adapters
The adapters convert backend configuration DTOs into SDK objects and instantiate the corresponding integration implementations.
File: autoppia_sdk/src/integrations/adapter.py
pythonCopiarfrom autoppia_sdk.src.integrations.config import IntegrationConfig
from autoppia_sdk.src.integrations.implementations.email.smtp_integration import SMPTEmailIntegration
from autoppia_sdk.src.integrations.interface import IntegrationInterface
from autoppia_sdk.src.integrations.implementations.base import Integration
class IntegrationConfigAdapter:
"""
Adapter class for converting backend integration configuration data to IntegrationConfig objects.
"""
@staticmethod
def from_autoppia_backend(worker_config_dto):
# Convert attributes list to dictionary
attributes = {}
for attr in worker_config_dto.user_integration_attributes:
value = attr.value
if attr.credential_obj:
value = attr.credential_obj.credential
attributes[attr.integration_attribute_obj.name] = value
integration_config = IntegrationConfig(
worker_config_dto.integration_obj.name,
worker_config_dto.integration_obj.category,
attributes
)
return integration_config
class IntegrationsAdapter:
"""
Adapter class for managing and instantiating integration implementations based on backend configuration.
"""
def __init__(self):
self.integration_mapping = {
"email": {
"Smtp": SMPTEmailIntegration
}
}
def from_autoppia_backend(self, worker_config_dto):
integrations = {}
for integration in worker_config_dto.user_integration:
category = integration.integration_obj.category
if category not in integrations:
integrations[category] = {}
integration_config = IntegrationConfigAdapter.from_autoppia_backend(integration)
integration_class = self.integration_mapping[integration_config.category][integration_config.name]
integration_instance = integration_class(integration_config)
integrations[category][integration_config.name] = integration_instance
return integrations
Last updated