@@ -25,8 +25,8 @@ type EmailNotifier struct {
2525 TargetEmail string `json:"targetEmail" gorm:"not null;type:varchar(255);column:target_email"`
2626 SMTPHost string `json:"smtpHost" gorm:"not null;type:varchar(255);column:smtp_host"`
2727 SMTPPort int `json:"smtpPort" gorm:"not null;column:smtp_port"`
28- SMTPUser string `json:"smtpUser" gorm:"not null; type:varchar(255);column:smtp_user"`
29- SMTPPassword string `json:"smtpPassword" gorm:"not null; type:varchar(255);column:smtp_password"`
28+ SMTPUser string `json:"smtpUser" gorm:"type:varchar(255);column:smtp_user"`
29+ SMTPPassword string `json:"smtpPassword" gorm:"type:varchar(255);column:smtp_password"`
3030}
3131
3232func (e * EmailNotifier ) TableName () string {
@@ -46,12 +46,9 @@ func (e *EmailNotifier) Validate() error {
4646 return errors .New ("SMTP port is required" )
4747 }
4848
49- if e .SMTPUser == "" {
50- return errors .New ("SMTP user is required" )
51- }
52-
53- if e .SMTPPassword == "" {
54- return errors .New ("SMTP password is required" )
49+ // Authentication is optional - both user and password must be provided together or both empty
50+ if (e .SMTPUser == "" ) != (e .SMTPPassword == "" ) {
51+ return errors .New ("SMTP user and password must both be provided or both be empty" )
5552 }
5653
5754 return nil
@@ -60,6 +57,10 @@ func (e *EmailNotifier) Validate() error {
6057func (e * EmailNotifier ) Send (logger * slog.Logger , heading string , message string ) error {
6158 // Compose email
6259 from := e .SMTPUser
60+ if from == "" {
61+ from = "noreply@" + e .SMTPHost
62+ }
63+
6364 to := []string {e .TargetEmail }
6465
6566 // Format the email content
@@ -78,6 +79,9 @@ func (e *EmailNotifier) Send(logger *slog.Logger, heading string, message string
7879 addr := net .JoinHostPort (e .SMTPHost , fmt .Sprintf ("%d" , e .SMTPPort ))
7980 timeout := DefaultTimeout
8081
82+ // Determine if authentication is required
83+ authRequired := e .SMTPUser != "" && e .SMTPPassword != ""
84+
8185 // Handle different port scenarios
8286 if e .SMTPPort == ImplicitTLSPort {
8387 // Implicit TLS (port 465)
@@ -105,10 +109,12 @@ func (e *EmailNotifier) Send(logger *slog.Logger, heading string, message string
105109 _ = client .Quit ()
106110 }()
107111
108- // Set up authentication
109- auth := smtp .PlainAuth ("" , e .SMTPUser , e .SMTPPassword , e .SMTPHost )
110- if err := client .Auth (auth ); err != nil {
111- return fmt .Errorf ("SMTP authentication failed: %w" , err )
112+ // Set up authentication only if credentials are provided
113+ if authRequired {
114+ auth := smtp .PlainAuth ("" , e .SMTPUser , e .SMTPPassword , e .SMTPHost )
115+ if err := client .Auth (auth ); err != nil {
116+ return fmt .Errorf ("SMTP authentication failed: %w" , err )
117+ }
112118 }
113119
114120 // Set sender and recipients
@@ -138,9 +144,6 @@ func (e *EmailNotifier) Send(logger *slog.Logger, heading string, message string
138144 return nil
139145 } else {
140146 // STARTTLS (port 587) or other ports
141- // Set up authentication information
142- auth := smtp .PlainAuth ("" , e .SMTPUser , e .SMTPPassword , e .SMTPHost )
143-
144147 // Create a custom dialer with timeout
145148 dialer := & net.Dialer {Timeout : timeout }
146149 conn , err := dialer .Dial ("tcp" , addr )
@@ -169,8 +172,12 @@ func (e *EmailNotifier) Send(logger *slog.Logger, heading string, message string
169172 }
170173 }
171174
172- if err := client .Auth (auth ); err != nil {
173- return fmt .Errorf ("SMTP authentication failed: %w" , err )
175+ // Authenticate only if credentials are provided
176+ if authRequired {
177+ auth := smtp .PlainAuth ("" , e .SMTPUser , e .SMTPPassword , e .SMTPHost )
178+ if err := client .Auth (auth ); err != nil {
179+ return fmt .Errorf ("SMTP authentication failed: %w" , err )
180+ }
174181 }
175182
176183 if err := client .Mail (from ); err != nil {
0 commit comments