|
1 | 1 | from __future__ import annotations |
2 | 2 | import base64 |
| 3 | +import os |
3 | 4 |
|
4 | 5 | from email.mime.multipart import MIMEMultipart |
5 | 6 | from email.mime.text import MIMEText |
@@ -164,24 +165,100 @@ def send_intermediate_email_with_yagmail(i_email: IntermediateEmail): |
164 | 165 | raise NotImplementedError |
165 | 166 |
|
166 | 167 |
|
167 | | -def send_intermediate_email_with_mailgun(i_email: IntermediateEmail): |
| 168 | +def send_intermediate_email_with_mailgun( |
| 169 | + api_key: str, |
| 170 | + domain: str, |
| 171 | + sender: str, |
| 172 | + i_email: IntermediateEmail, |
| 173 | +): |
168 | 174 | """ |
169 | 175 | Send an Intermediate Email object via Mailgun. |
170 | 176 |
|
171 | 177 | Parameters |
172 | 178 | ---------- |
| 179 | + api_key |
| 180 | + Mailgun API key (found in account settings) |
| 181 | + domain |
| 182 | + Your verified Mailgun domain (e.g., "mg.yourdomain.com") |
| 183 | + sender |
| 184 | + Email address to send from (must be authorized in your domain) |
173 | 185 | i_email |
174 | 186 | IntermediateEmail object containing the email content and attachments |
175 | 187 |
|
176 | 188 | Returns |
177 | 189 | ------- |
178 | | - None |
| 190 | + Response |
| 191 | + Response from Mailgun API |
| 192 | +
|
| 193 | + Raises |
| 194 | + ------ |
| 195 | + Exception |
| 196 | + If the Mailgun API returns an error |
179 | 197 |
|
| 198 | + Examples |
| 199 | + -------- |
| 200 | + ```python |
| 201 | + email = IntermediateEmail( |
| 202 | + html="<p>Hello world</p>", |
| 203 | + subject="Test Email", |
| 204 | + |
| 205 | + ) |
| 206 | +
|
| 207 | + response = send_intermediate_email_with_mailgun( |
| 208 | + api_key="your-api-key", |
| 209 | + domain="mg.yourdomain.com", |
| 210 | + |
| 211 | + i_email=email |
| 212 | + ) |
| 213 | + ``` |
| 214 | + |
180 | 215 | Notes |
181 | 216 | ----- |
182 | | - This function is a placeholder and has not been implemented yet. |
| 217 | + Requires the `mailgun` package: `pip install mailgun` |
183 | 218 | """ |
184 | | - raise NotImplementedError |
| 219 | + from mailgun.client import Client |
| 220 | + |
| 221 | + # Create Mailgun client |
| 222 | + client = Client(auth=("api", api_key)) |
| 223 | + |
| 224 | + # Prepare the basic email data |
| 225 | + data = { |
| 226 | + "from": sender, |
| 227 | + "to": i_email.recipients, |
| 228 | + "subject": i_email.subject, |
| 229 | + "html": i_email.html, |
| 230 | + } |
| 231 | + |
| 232 | + # Add text content if available |
| 233 | + if i_email.text: |
| 234 | + data["text"] = i_email.text |
| 235 | + |
| 236 | + # Prepare files for attachments |
| 237 | + files = [] |
| 238 | + |
| 239 | + # Handle inline images (embedded in HTML with cid:) |
| 240 | + for image_name, image_base64 in i_email.inline_attachments.items(): |
| 241 | + img_bytes = base64.b64decode(image_base64) |
| 242 | + # Use 'inline' for images referenced in HTML with cid: |
| 243 | + files.append(("inline", (image_name, img_bytes))) |
| 244 | + |
| 245 | + # Handle external attachments |
| 246 | + for filename in i_email.external_attachments: |
| 247 | + with open(filename, "rb") as f: |
| 248 | + file_data = f.read() |
| 249 | + |
| 250 | + # Extract just the filename (not full path) for the attachment name |
| 251 | + basename = os.path.basename(filename) |
| 252 | + files.append(("attachment", (basename, file_data))) |
| 253 | + |
| 254 | + # Send the message using Mailgun client |
| 255 | + response = client.messages.create( |
| 256 | + data=data, |
| 257 | + files=files if files else None, |
| 258 | + domain=domain |
| 259 | + ) |
| 260 | + |
| 261 | + return response |
185 | 262 |
|
186 | 263 |
|
187 | 264 | def send_intermediate_email_with_smtp( |
|
0 commit comments