Spaces:
Sleeping
Sleeping
| import os | |
| import smtplib | |
| import logging | |
| from email.mime.multipart import MIMEMultipart | |
| from email.mime.text import MIMEText | |
| from email.mime.base import MIMEBase | |
| from email import encoders | |
| from typing import List | |
| class EmailService: | |
| """Professional email service for newsletter distribution""" | |
| def __init__(self): | |
| self.smtp_server = os.getenv("SMTP_SERVER", "smtp.gmail.com") | |
| self.smtp_port = int(os.getenv("SMTP_PORT", "587")) | |
| self.email_user = os.getenv("EMAIL_USER", "newsletter@professional.com") | |
| self.email_password = os.getenv("EMAIL_PASSWORD", "dummy_password") | |
| def send_newsletter(self, newsletter_html: str, recipients: List[str], topic: str) -> str: | |
| """Send professional newsletter to recipients""" | |
| try: | |
| # Validate recipients | |
| valid_recipients = [email.strip() for email in recipients if self._is_valid_email(email.strip())] | |
| if not valid_recipients: | |
| return "❌ No valid email addresses provided" | |
| # Setup email | |
| msg = MIMEMultipart('alternative') | |
| msg['From'] = self.email_user | |
| msg['Subject'] = f"Professional Newsletter: {topic}" | |
| # Create both plain text and HTML versions | |
| plain_text = self._html_to_text(newsletter_html) | |
| # Attach parts | |
| part1 = MIMEText(plain_text, 'plain') | |
| part2 = MIMEText(newsletter_html, 'html') | |
| msg.attach(part1) | |
| msg.attach(part2) | |
| # Send emails | |
| success_count = 0 | |
| failed_recipients = [] | |
| with smtplib.SMTP(self.smtp_server, self.smtp_port) as server: | |
| server.starttls() | |
| server.login(self.email_user, self.email_password) | |
| for recipient in valid_recipients: | |
| try: | |
| msg['To'] = recipient | |
| server.send_message(msg) | |
| success_count += 1 | |
| logging.info(f"Newsletter sent successfully to {recipient}") | |
| # Remove To header for next iteration | |
| del msg['To'] | |
| except Exception as e: | |
| failed_recipients.append(recipient) | |
| logging.error(f"Failed to send to {recipient}: {e}") | |
| # Return status | |
| if success_count == len(valid_recipients): | |
| return f"✅ Newsletter sent successfully to all {success_count} recipients" | |
| else: | |
| return f"⚠️ Newsletter sent to {success_count}/{len(valid_recipients)} recipients. Failed: {', '.join(failed_recipients)}" | |
| except Exception as e: | |
| logging.error(f"Email service error: {e}") | |
| return f"❌ Failed to send newsletter: {str(e)}" | |
| def _is_valid_email(self, email: str) -> bool: | |
| """Validate email address format""" | |
| import re | |
| pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$' | |
| return re.match(pattern, email) is not None | |
| def _html_to_text(self, html: str) -> str: | |
| """Convert HTML to plain text for email compatibility""" | |
| import re | |
| # Simple HTML to text conversion | |
| text = re.sub(r'<[^>]+>', '', html) # Remove HTML tags | |
| text = re.sub(r'\s+', ' ', text) # Normalize whitespace | |
| text = text.strip() | |
| return text | |
| def create_professional_email_template(self, newsletter_content: str, topic: str) -> str: | |
| """Create professional email template""" | |
| return f""" | |
| <!DOCTYPE html> | |
| <html> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Professional Newsletter: {topic}</title> | |
| </head> | |
| <body style="font-family: Arial, sans-serif; line-height: 1.6; color: #333; max-width: 800px; margin: 0 auto;"> | |
| <div style="background: #f8f9fa; padding: 20px; text-align: center; border-bottom: 3px solid #007bff;"> | |
| <h1 style="color: #007bff; margin: 0;">Professional Newsletter</h1> | |
| <p style="margin: 5px 0; color: #666;">Data-Driven Insights & Analysis</p> | |
| </div> | |
| <div style="padding: 20px;"> | |
| {newsletter_content} | |
| </div> | |
| <div style="background: #f8f9fa; padding: 20px; text-align: center; border-top: 1px solid #ddd; margin-top: 30px;"> | |
| <p style="margin: 0; color: #666; font-size: 0.9em;"> | |
| This newsletter was generated using advanced AI research and data analysis. | |
| <br> | |
| For questions or feedback, please contact our research team. | |
| </p> | |
| </div> | |
| </body> | |
| </html> | |
| """ | |
| def schedule_newsletter(self, newsletter_html: str, recipients: List[str], topic: str, schedule_time: str) -> str: | |
| """Schedule newsletter for future delivery (placeholder for future implementation)""" | |
| return "📅 Newsletter scheduling feature coming soon. Please send immediately for now." | |
| def get_email_analytics(self) -> dict: | |
| """Get email delivery analytics (placeholder for future implementation)""" | |
| return { | |
| "total_sent": 0, | |
| "delivery_rate": "N/A", | |
| "open_rate": "N/A", | |
| "click_rate": "N/A" | |
| } | |