| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138 |
- #
- # Copyright 2024 The InfiniFlow Authors. All Rights Reserved.
- #
- # Licensed under the Apache License, Version 2.0 (the "License");
- # you may not use this file except in compliance with the License.
- # You may obtain a copy of the License at
- #
- # http://www.apache.org/licenses/LICENSE-2.0
- #
- # Unless required by applicable law or agreed to in writing, software
- # distributed under the License is distributed on an "AS IS" BASIS,
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- # See the License for the specific language governing permissions and
- # limitations under the License.
- #
-
- from abc import ABC
- import json
- import smtplib
- import logging
- from email.mime.text import MIMEText
- from email.mime.multipart import MIMEMultipart
- from email.header import Header
- from email.utils import formataddr
- from agent.component.base import ComponentBase, ComponentParamBase
-
- class EmailParam(ComponentParamBase):
- """
- Define the Email component parameters.
- """
- def __init__(self):
- super().__init__()
- # Fixed configuration parameters
- self.smtp_server = "" # SMTP server address
- self.smtp_port = 465 # SMTP port
- self.email = "" # Sender email
- self.password = "" # Email authorization code
- self.sender_name = "" # Sender name
-
- def check(self):
- # Check required parameters
- self.check_empty(self.smtp_server, "SMTP Server")
- self.check_empty(self.email, "Email")
- self.check_empty(self.password, "Password")
- self.check_empty(self.sender_name, "Sender Name")
-
- class Email(ComponentBase, ABC):
- component_name = "Email"
-
- def _run(self, history, **kwargs):
- # Get upstream component output and parse JSON
- ans = self.get_input()
- content = "".join(ans["content"]) if "content" in ans else ""
- if not content:
- return Email.be_output("No content to send")
-
- success = False
- try:
- # Parse JSON string passed from upstream
- email_data = json.loads(content)
-
- # Validate required fields
- if "to_email" not in email_data:
- return Email.be_output("Missing required field: to_email")
-
- # Create email object
- msg = MIMEMultipart('alternative')
-
- # Properly handle sender name encoding
- msg['From'] = formataddr((str(Header(self._param.sender_name,'utf-8')), self._param.email))
- msg['To'] = email_data["to_email"]
- if "cc_email" in email_data and email_data["cc_email"]:
- msg['Cc'] = email_data["cc_email"]
- msg['Subject'] = Header(email_data.get("subject", "No Subject"), 'utf-8').encode()
-
- # Use content from email_data or default content
- email_content = email_data.get("content", "No content provided")
- # msg.attach(MIMEText(email_content, 'plain', 'utf-8'))
- msg.attach(MIMEText(email_content, 'html', 'utf-8'))
-
- # Connect to SMTP server and send
- logging.info(f"Connecting to SMTP server {self._param.smtp_server}:{self._param.smtp_port}")
-
- context = smtplib.ssl.create_default_context()
- with smtplib.SMTP_SSL(self._param.smtp_server, self._param.smtp_port, context=context) as server:
- # Login
- logging.info(f"Attempting to login with email: {self._param.email}")
- server.login(self._param.email, self._param.password)
-
- # Get all recipient list
- recipients = [email_data["to_email"]]
- if "cc_email" in email_data and email_data["cc_email"]:
- recipients.extend(email_data["cc_email"].split(','))
-
- # Send email
- logging.info(f"Sending email to recipients: {recipients}")
- try:
- server.send_message(msg, self._param.email, recipients)
- success = True
- except Exception as e:
- logging.error(f"Error during send_message: {str(e)}")
- # Try alternative method
- server.sendmail(self._param.email, recipients, msg.as_string())
- success = True
-
- try:
- server.quit()
- except Exception as e:
- # Ignore errors when closing connection
- logging.warning(f"Non-fatal error during connection close: {str(e)}")
-
- if success:
- return Email.be_output("Email sent successfully")
-
- except json.JSONDecodeError:
- error_msg = "Invalid JSON format in input"
- logging.error(error_msg)
- return Email.be_output(error_msg)
-
- except smtplib.SMTPAuthenticationError:
- error_msg = "SMTP Authentication failed. Please check your email and authorization code."
- logging.error(error_msg)
- return Email.be_output(f"Failed to send email: {error_msg}")
-
- except smtplib.SMTPConnectError:
- error_msg = f"Failed to connect to SMTP server {self._param.smtp_server}:{self._param.smtp_port}"
- logging.error(error_msg)
- return Email.be_output(f"Failed to send email: {error_msg}")
-
- except smtplib.SMTPException as e:
- error_msg = f"SMTP error occurred: {str(e)}"
- logging.error(error_msg)
- return Email.be_output(f"Failed to send email: {error_msg}")
-
- except Exception as e:
- error_msg = f"Unexpected error: {str(e)}"
- logging.error(error_msg)
- return Email.be_output(f"Failed to send email: {error_msg}")
|