11import smtplib
2+ import socket
3+ import ssl
24from email .mime .multipart import MIMEMultipart
35from email .mime .text import MIMEText
46from typing import Literal
@@ -48,9 +50,7 @@ def SMTPCredentialsField() -> SMTPCredentialsInput:
4850
4951
5052class SMTPConfig (BaseModel ):
51- smtp_server : str = SchemaField (
52- default = "smtp.example.com" , description = "SMTP server address"
53- )
53+ smtp_server : str = SchemaField (description = "SMTP server address" )
5454 smtp_port : int = SchemaField (default = 25 , description = "SMTP port number" )
5555
5656 model_config = ConfigDict (title = "SMTP Config" )
@@ -67,10 +67,7 @@ class Input(BlockSchemaInput):
6767 body : str = SchemaField (
6868 description = "Body of the email" , placeholder = "Enter the email body"
6969 )
70- config : SMTPConfig = SchemaField (
71- description = "SMTP Config" ,
72- default = SMTPConfig (),
73- )
70+ config : SMTPConfig = SchemaField (description = "SMTP Config" )
7471 credentials : SMTPCredentialsInput = SMTPCredentialsField ()
7572
7673 class Output (BlockSchemaOutput ):
@@ -120,7 +117,7 @@ def send_email(
120117 msg ["Subject" ] = subject
121118 msg .attach (MIMEText (body , "plain" ))
122119
123- with smtplib .SMTP (smtp_server , smtp_port ) as server :
120+ with smtplib .SMTP (smtp_server , smtp_port , timeout = 30 ) as server :
124121 server .starttls ()
125122 server .login (smtp_username , smtp_password )
126123 server .sendmail (smtp_username , to_email , msg .as_string ())
@@ -130,10 +127,59 @@ def send_email(
130127 async def run (
131128 self , input_data : Input , * , credentials : SMTPCredentials , ** kwargs
132129 ) -> BlockOutput :
133- yield "status" , self .send_email (
134- config = input_data .config ,
135- to_email = input_data .to_email ,
136- subject = input_data .subject ,
137- body = input_data .body ,
138- credentials = credentials ,
139- )
130+ try :
131+ status = self .send_email (
132+ config = input_data .config ,
133+ to_email = input_data .to_email ,
134+ subject = input_data .subject ,
135+ body = input_data .body ,
136+ credentials = credentials ,
137+ )
138+ yield "status" , status
139+ except socket .gaierror :
140+ yield "error" , (
141+ f"Cannot connect to SMTP server '{ input_data .config .smtp_server } '. "
142+ "Please verify the server address is correct."
143+ )
144+ except socket .timeout :
145+ yield "error" , (
146+ f"Connection timeout to '{ input_data .config .smtp_server } ' "
147+ f"on port { input_data .config .smtp_port } . "
148+ "The server may be down or unreachable."
149+ )
150+ except ConnectionRefusedError :
151+ yield "error" , (
152+ f"Connection refused to '{ input_data .config .smtp_server } ' "
153+ f"on port { input_data .config .smtp_port } . "
154+ "Common SMTP ports are: 587 (TLS), 465 (SSL), 25 (plain). "
155+ "Please verify the port is correct."
156+ )
157+ except smtplib .SMTPNotSupportedError :
158+ yield "error" , (
159+ f"STARTTLS not supported by server '{ input_data .config .smtp_server } '. "
160+ "Try using port 465 for SSL or port 25 for unencrypted connection."
161+ )
162+ except ssl .SSLError as e :
163+ yield "error" , (
164+ f"SSL/TLS error when connecting to '{ input_data .config .smtp_server } ': { str (e )} . "
165+ "The server may require a different security protocol."
166+ )
167+ except smtplib .SMTPAuthenticationError :
168+ yield "error" , (
169+ "Authentication failed. Please verify your username and password are correct."
170+ )
171+ except smtplib .SMTPRecipientsRefused :
172+ yield "error" , (
173+ f"Recipient email address '{ input_data .to_email } ' was rejected by the server. "
174+ "Please verify the email address is valid."
175+ )
176+ except smtplib .SMTPSenderRefused :
177+ yield "error" , (
178+ "Sender email address defined in the credentials that where used"
179+ "was rejected by the server. "
180+ "Please verify your account is authorized to send emails."
181+ )
182+ except smtplib .SMTPDataError as e :
183+ yield "error" , f"Email data rejected by server: { str (e )} "
184+ except Exception as e :
185+ raise e
0 commit comments