SMTP email provider implementation. Supports standard SMTP with TLS/SSL for Gmail, Office 365, and other SMTP servers.
| 328 | |
| 329 | |
| 330 | class SMTPEmailProvider(EmailProvider): |
| 331 | """ |
| 332 | SMTP email provider implementation. |
| 333 | |
| 334 | Supports standard SMTP with TLS/SSL for Gmail, Office 365, and other SMTP servers. |
| 335 | """ |
| 336 | |
| 337 | def __init__(self, config: EmailConfig): |
| 338 | super().__init__(config) |
| 339 | self._connection = None |
| 340 | |
| 341 | def send(self, to: str, subject: str, body: str, html: bool = False) -> bool: |
| 342 | """ |
| 343 | Send email via SMTP. |
| 344 | |
| 345 | Args: |
| 346 | to: Recipient email address |
| 347 | subject: Email subject |
| 348 | body: Email body |
| 349 | html: True if body is HTML |
| 350 | |
| 351 | Returns: |
| 352 | True if sent successfully |
| 353 | |
| 354 | Raises: |
| 355 | smtplib.SMTPException: If SMTP operation fails |
| 356 | """ |
| 357 | try: |
| 358 | # Create message |
| 359 | msg = MIMEMultipart('alternative') |
| 360 | msg['Subject'] = subject |
| 361 | msg['From'] = f"{self.config.from_name} <{self.config.from_address}>" |
| 362 | msg['To'] = to |
| 363 | |
| 364 | # Attach body |
| 365 | if html: |
| 366 | part = MIMEText(body, 'html') |
| 367 | else: |
| 368 | part = MIMEText(body, 'plain') |
| 369 | msg.attach(part) |
| 370 | |
| 371 | # Connect and send |
| 372 | if self.config.smtp_use_ssl: |
| 373 | # Use SMTP_SSL for port 465 |
| 374 | context = ssl.create_default_context() |
| 375 | with smtplib.SMTP_SSL( |
| 376 | self.config.smtp_host, |
| 377 | self.config.smtp_port, |
| 378 | context=context |
| 379 | ) as server: |
| 380 | server.login(self.config.smtp_username, self.config.smtp_password) |
| 381 | server.send_message(msg) |
| 382 | else: |
| 383 | # Use SMTP with STARTTLS for port 587 |
| 384 | with smtplib.SMTP( |
| 385 | self.config.smtp_host, |
| 386 | self.config.smtp_port, |
| 387 | timeout=30 |
no outgoing calls