Skip to content

Commit 40fca29

Browse files
Merge pull request #2 from Devotel/feature/email-resource-implementation
feat(email): implement Email resource
2 parents 5851829 + 6a7443b commit 40fca29

File tree

5 files changed

+436
-46
lines changed

5 files changed

+436
-46
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,3 +190,5 @@ Thumbs.db
190190
api_keys.txt
191191
secrets.json
192192
.api_key
193+
194+
setup-dev-env.ps1

examples/email_example.py

Lines changed: 52 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import os
22

3-
from devo_global_comms_python import DevoException
3+
from devo_global_comms_python import DevoCommsClient, DevoException
44

55

66
def main():
@@ -9,42 +9,72 @@ def main():
99
print("❌ Please set DEVO_API_KEY environment variable")
1010
return
1111

12+
client = DevoCommsClient(api_key=api_key)
1213
print("✅ Devo Email Client initialized successfully")
1314
print("=" * 60)
1415

1516
try:
16-
# Example 1: Send a simple email
17+
# Example: Send an email using the Email API
1718
print("📧 EMAIL SEND EXAMPLE")
1819
print("-" * 30)
1920

2021
print("📤 Sending email...")
21-
print("⚠️ This is a placeholder implementation.")
22-
print(" Update this example when Email API is implemented.")
23-
24-
# Placeholder email send - update when implementing Email resource
25-
print(" ```python")
26-
print(" email_response = client.email.send(")
27-
print(" to='recipient@example.com',")
28-
print(" subject='Test Email from Devo SDK',")
29-
print(" body='This is a test email.',")
30-
print(" html_body='<h1>Test</h1><p>This is a test email.</p>',")
31-
print(" from_email='sender@yourdomain.com'")
32-
print(" )")
33-
print(" print(f'Email sent! ID: {email_response.id}')")
34-
print(" ```")
22+
email_response = client.email.send_email(
23+
subject="Test Email from Devo SDK",
24+
body="This is a test email sent using the Devo Global Communications Python SDK.",
25+
sender="sender@example.com",
26+
recipient="recipient@example.com",
27+
)
28+
29+
print("✅ Email sent successfully!")
30+
print(f" 📧 Message ID: {email_response.message_id}")
31+
print(f" 📦 Bulk Email ID: {email_response.bulk_email_id}")
32+
print(f" 📝 Subject: {email_response.subject}")
33+
print(f" 📊 Status: {email_response.status}")
34+
print(f" 💬 Message: {email_response.message}")
35+
print(f" 🕐 Timestamp: {email_response.timestamp}")
36+
print(f" ✅ Success: {email_response.success}")
37+
38+
# Example with different content
39+
print("\n📧 SENDING EMAIL WITH RICH CONTENT")
40+
print("-" * 40)
41+
42+
rich_email_response = client.email.send_email(
43+
subject="🎉 Welcome to Devo Communications!",
44+
body=(
45+
"Dear valued customer,\n\n"
46+
"Welcome to our service! We're excited to have you on board.\n\n"
47+
"Best regards,\nThe Devo Team"
48+
),
49+
sender="welcome@yourcompany.com",
50+
recipient="newcustomer@example.com",
51+
)
52+
53+
print("✅ Rich content email sent!")
54+
print(f" 📧 Message ID: {rich_email_response.message_id}")
55+
print(f" 📊 Status: {rich_email_response.status}")
56+
print(f" ✅ Success: {rich_email_response.success}")
3557

3658
except DevoException as e:
3759
print(f"❌ Email operation failed: {e}")
60+
except Exception as e:
61+
print(f"❌ Unexpected error: {e}")
3862

3963
print("\n" + "=" * 60)
4064
print("📊 EMAIL EXAMPLE SUMMARY")
4165
print("-" * 30)
42-
print("⚠️ This is a placeholder example for Email functionality.")
43-
print("💡 To implement:")
44-
print(" 1. Define Email API endpoints and specifications")
45-
print(" 2. Create Email Pydantic models")
46-
print(" 3. Implement EmailResource class")
47-
print(" 4. Update this example with real functionality")
66+
print("✅ Email API implementation complete!")
67+
print("📤 Successfully demonstrated:")
68+
print(" • Basic email sending")
69+
print(" • Email with rich content and emojis")
70+
print(" • Response parsing and status checking")
71+
print(" • Error handling")
72+
print("\n💡 Features available:")
73+
print(" • Subject and body content")
74+
print(" • Sender and recipient validation")
75+
print(" • Message tracking with unique IDs")
76+
print(" • Status monitoring")
77+
print(" • Timestamp tracking")
4878

4979

5080
if __name__ == "__main__":

src/devo_global_comms_python/models/email.py

Lines changed: 38 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,44 @@
44
from pydantic import BaseModel, Field
55

66

7+
# Request Models
8+
class EmailSendRequest(BaseModel):
9+
"""
10+
Request model for email send API.
11+
12+
Used for POST /user-api/email/send
13+
"""
14+
15+
subject: str = Field(..., description="Email subject")
16+
body: str = Field(..., description="Email body content")
17+
sender: str = Field(..., description="Sender email address")
18+
recipient: str = Field(..., description="Recipient email address")
19+
20+
21+
# Response Models
22+
class EmailSendResponse(BaseModel):
23+
"""
24+
Response model for email send API.
25+
26+
Returned from POST /user-api/email/send
27+
"""
28+
29+
success: bool = Field(..., description="Whether the email was sent successfully")
30+
message_id: str = Field(..., description="Unique message identifier")
31+
bulk_email_id: str = Field(..., description="Bulk email identifier")
32+
subject: str = Field(..., description="Email subject")
33+
status: str = Field(..., description="Message status")
34+
message: str = Field(..., description="Status message")
35+
timestamp: datetime = Field(..., description="Timestamp of the response")
36+
37+
738
class EmailAttachment(BaseModel):
839
"""Email attachment model."""
940

1041
filename: str = Field(..., description="Attachment filename")
1142
content_type: str = Field(..., description="MIME content type")
1243
size: int = Field(..., description="File size in bytes")
13-
content_id: Optional[str] = Field(
14-
None, description="Content ID for inline attachments"
15-
)
44+
content_id: Optional[str] = Field(None, description="Content ID for inline attachments")
1645

1746

1847
class EmailMessage(BaseModel):
@@ -34,27 +63,17 @@ class EmailMessage(BaseModel):
3463
html_body: Optional[str] = Field(None, description="HTML email body")
3564
status: str = Field(..., description="Message status")
3665
direction: str = Field(..., description="Message direction (inbound/outbound)")
37-
attachments: Optional[List[EmailAttachment]] = Field(
38-
None, description="Email attachments"
39-
)
66+
attachments: Optional[List[EmailAttachment]] = Field(None, description="Email attachments")
4067
error_code: Optional[str] = Field(None, description="Error code if failed")
4168
error_message: Optional[str] = Field(None, description="Error message if failed")
42-
date_created: Optional[datetime] = Field(
43-
None, description="Message creation timestamp"
44-
)
69+
date_created: Optional[datetime] = Field(None, description="Message creation timestamp")
4570
date_sent: Optional[datetime] = Field(None, description="Message sent timestamp")
46-
date_delivered: Optional[datetime] = Field(
47-
None, description="Message delivered timestamp"
48-
)
49-
date_opened: Optional[datetime] = Field(
50-
None, description="Message opened timestamp"
51-
)
71+
date_delivered: Optional[datetime] = Field(None, description="Message delivered timestamp")
72+
date_opened: Optional[datetime] = Field(None, description="Message opened timestamp")
5273
date_clicked: Optional[datetime] = Field(None, description="Link clicked timestamp")
53-
date_updated: Optional[datetime] = Field(
54-
None, description="Message last updated timestamp"
55-
)
74+
date_updated: Optional[datetime] = Field(None, description="Message last updated timestamp")
5675
metadata: Optional[Dict[str, Any]] = Field(None, description="Custom metadata")
5776

5877
class Config:
59-
allow_population_by_field_name = True
78+
validate_by_name = True
6079
json_encoders = {datetime: lambda v: v.isoformat() if v else None}

src/devo_global_comms_python/resources/email.py

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,63 @@
44
from .base import BaseResource
55

66
if TYPE_CHECKING:
7-
from ..models.email import EmailMessage
7+
from ..models.email import EmailMessage, EmailSendResponse
88

99

1010
class EmailResource(BaseResource):
1111
"""
1212
Email resource for sending and managing email messages.
1313
1414
Example:
15-
>>> message = client.email.send(
16-
... to="recipient@example.com",
15+
>>> response = client.email.send_email(
1716
... subject="Hello, World!",
18-
... body="This is a test email."
17+
... body="This is a test email.",
18+
... sender="sender@example.com",
19+
... recipient="recipient@example.com"
1920
... )
20-
>>> print(message.id)
21+
>>> print(response.message_id)
2122
"""
2223

24+
def send_email(
25+
self,
26+
subject: str,
27+
body: str,
28+
sender: str,
29+
recipient: str,
30+
) -> "EmailSendResponse":
31+
"""
32+
Send an email using the exact API specification.
33+
34+
Args:
35+
subject: Email subject
36+
body: Email body content
37+
sender: Sender email address
38+
recipient: Recipient email address
39+
40+
Returns:
41+
EmailSendResponse: The email send response
42+
"""
43+
# Validate inputs
44+
subject = validate_required_string(subject, "subject")
45+
body = validate_required_string(body, "body")
46+
sender = validate_email(sender)
47+
recipient = validate_email(recipient)
48+
49+
# Prepare request data matching the exact API specification
50+
data = {
51+
"subject": subject,
52+
"body": body,
53+
"sender": sender,
54+
"recipient": recipient,
55+
}
56+
57+
# Send request to the exact endpoint
58+
response = self.client.post("email/send", json=data)
59+
60+
from ..models.email import EmailSendResponse
61+
62+
return EmailSendResponse.model_validate(response.json())
63+
2364
def send(
2465
self,
2566
to: str,

0 commit comments

Comments
 (0)