Repository navigation
Expand file tree
/
Copy pathemail_service.py
More file actions
171 lines (143 loc) · 6.14 KB
/
Copy pathemail_service.py
File metadata and controls
171 lines (143 loc) · 6.14 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
import os
import json
import requests
from io import StringIO
import csv
from datetime import datetime
class EmailService:
"""Email service using Resend API"""
def __init__(self):
self.api_key = os.environ.get('RESEND_API_KEY')
self.base_url = 'https://api.resend.com'
self.from_email = 'onboarding@resend.dev' # Default Resend test email
def send_data_report(self, to_email: str, data: list, metadata: dict, format_type: str = 'csv'):
"""Send data report via email with attachment"""
if not self.api_key:
raise ValueError("RESEND_API_KEY environment variable is required")
try:
# Prepare email content
subject = f"Zambia Data Report - {metadata.get('source', 'Multiple Sources')}"
# Create email body
html_content = self._create_email_html(data, metadata)
# Prepare attachment
attachment = self._create_attachment(data, metadata, format_type)
# Send email via Resend API
response = requests.post(
f"{self.base_url}/emails",
headers={
'Authorization': f'Bearer {self.api_key}',
'Content-Type': 'application/json'
},
json={
'from': self.from_email,
'to': [to_email],
'subject': subject,
'html': html_content,
'attachments': [attachment] if attachment else []
}
)
if response.status_code == 200:
return {'success': True, 'message': 'Email sent successfully'}
else:
return {'success': False, 'error': f'Failed to send email: {response.text}'}
except Exception as e:
return {'success': False, 'error': str(e)}
def _create_email_html(self, data: list, metadata: dict) -> str:
"""Create HTML email content"""
total_records = len(data)
source = metadata.get('source', 'Multiple Sources')
data_type = metadata.get('data_type', 'Various')
html = f"""
<html>
<head>
<style>
body {{ font-family: Arial, sans-serif; margin: 20px; }}
.header {{ background-color: #f8f9fa; padding: 20px; border-radius: 5px; }}
.summary {{ margin: 20px 0; }}
.data-preview {{ margin: 20px 0; }}
table {{ border-collapse: collapse; width: 100%; max-width: 600px; }}
th, td {{ border: 1px solid #ddd; padding: 8px; text-align: left; }}
th {{ background-color: #f2f2f2; }}
.footer {{ margin-top: 30px; font-size: 12px; color: #666; }}
</style>
</head>
<body>
<div class="header">
<h2>Zambia Data Collection Report</h2>
<p>Generated on {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}</p>
</div>
<div class="summary">
<h3>Report Summary</h3>
<ul>
<li><strong>Data Source:</strong> {source}</li>
<li><strong>Data Type:</strong> {data_type}</li>
<li><strong>Total Records:</strong> {total_records}</li>
</ul>
</div>
<div class="data-preview">
<h3>Data Preview (First 5 Records)</h3>
{self._create_data_table(data[:5])}
</div>
<div class="footer">
<p>This report was generated by the Zambia Data Collection Tool.</p>
<p>The complete dataset is attached to this email.</p>
</div>
</body>
</html>
"""
return html
def _create_data_table(self, data: list) -> str:
"""Create HTML table from data"""
if not data:
return "<p>No data available</p>"
# Get headers from first record
headers = list(data[0].keys())
table_html = "<table>"
# Add headers
table_html += "<tr>"
for header in headers:
table_html += f"<th>{header}</th>"
table_html += "</tr>"
# Add data rows
for record in data:
table_html += "<tr>"
for header in headers:
value = record.get(header, '')
table_html += f"<td>{value}</td>"
table_html += "</tr>"
table_html += "</table>"
return table_html
def _create_attachment(self, data: list, metadata: dict, format_type: str) -> dict | None:
"""Create email attachment based on format"""
if not data:
return None
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
source = metadata.get('source', 'zambia_data').replace(' ', '_').lower()
if format_type == 'csv':
# Create CSV content
output = StringIO()
if data:
writer = csv.DictWriter(output, fieldnames=data[0].keys())
writer.writeheader()
writer.writerows(data)
import base64
return {
'filename': f'{source}_{timestamp}.csv',
'content': base64.b64encode(output.getvalue().encode('utf-8')).decode('utf-8'),
'type': 'text/csv'
}
elif format_type == 'json':
# Create JSON content
json_data = {
'metadata': metadata,
'data': data,
'generated_at': datetime.now().isoformat()
}
import base64
return {
'filename': f'{source}_{timestamp}.json',
'content': base64.b64encode(json.dumps(json_data, indent=2).encode('utf-8')).decode('utf-8'),
'type': 'application/json'
}
# Default to CSV if format not recognized
return self._create_attachment(data, metadata, 'csv')