139 lines
4.6 KiB
Go
139 lines
4.6 KiB
Go
package emailService
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"fmt"
|
|
"net/smtp"
|
|
"strings"
|
|
|
|
"git.ma-al.com/goc_marek/timetracker/app/config"
|
|
"git.ma-al.com/goc_marek/timetracker/app/service/langsService"
|
|
"git.ma-al.com/goc_marek/timetracker/app/templ/emails"
|
|
"git.ma-al.com/goc_marek/timetracker/app/utils/i18n"
|
|
"git.ma-al.com/goc_marek/timetracker/app/view"
|
|
)
|
|
|
|
// EmailService handles sending emails
|
|
type EmailService struct {
|
|
config *config.EmailConfig
|
|
}
|
|
|
|
// NewEmailService creates a new EmailService instance
|
|
func NewEmailService() *EmailService {
|
|
return &EmailService{
|
|
config: &config.Get().Email,
|
|
}
|
|
}
|
|
|
|
// getLangID returns the language ID from the ISO code using the language service
|
|
func getLangID(isoCode string) uint {
|
|
if isoCode == "" {
|
|
isoCode = "en"
|
|
}
|
|
|
|
lang, err := langsService.LangSrv.GetLanguageByISOCode(isoCode)
|
|
if err != nil || lang == nil {
|
|
return 1 // Default to English (ID 1)
|
|
}
|
|
|
|
return uint(lang.ID)
|
|
}
|
|
|
|
// SendEmail sends an email to the specified recipient
|
|
func (s *EmailService) SendEmail(to, subject, body string) error {
|
|
if !s.config.Enabled {
|
|
return fmt.Errorf("email service is disabled")
|
|
}
|
|
|
|
// Set up authentication
|
|
auth := smtp.PlainAuth("", s.config.SMTPUser, s.config.SMTPPassword, s.config.SMTPHost)
|
|
|
|
// Create email headers
|
|
headers := make(map[string]string)
|
|
headers["From"] = fmt.Sprintf("%s <%s>", s.config.FromName, s.config.FromEmail)
|
|
headers["To"] = to
|
|
headers["Subject"] = subject
|
|
headers["MIME-Version"] = "1.0"
|
|
headers["Content-Type"] = "text/html; charset=utf-8"
|
|
|
|
// Build email message
|
|
var msg strings.Builder
|
|
for k, v := range headers {
|
|
msg.WriteString(fmt.Sprintf("%s: %s\r\n", k, v))
|
|
}
|
|
msg.WriteString("\r\n")
|
|
msg.WriteString(body)
|
|
|
|
// Send email
|
|
addr := fmt.Sprintf("%s:%d", s.config.SMTPHost, s.config.SMTPPort)
|
|
if err := smtp.SendMail(addr, auth, s.config.FromEmail, []string{to}, []byte(msg.String())); err != nil {
|
|
return fmt.Errorf("failed to send email: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// SendVerificationEmail sends an email verification email
|
|
func (s *EmailService) SendVerificationEmail(to, token, baseURL, lang string) error {
|
|
// Use default language if not provided
|
|
if lang == "" {
|
|
lang = "en"
|
|
}
|
|
verificationURL := fmt.Sprintf("%s/%s/verify-email?token=%s", baseURL, lang, token)
|
|
|
|
langID := getLangID(lang)
|
|
subject := i18n.T___(langID, "email.email_verification_subject")
|
|
body := s.verificationEmailTemplate(to, verificationURL, langID)
|
|
|
|
return s.SendEmail(to, subject, body)
|
|
}
|
|
|
|
// SendPasswordResetEmail sends a password reset email
|
|
func (s *EmailService) SendPasswordResetEmail(to, token, baseURL, lang string) error {
|
|
// Use default language if not provided
|
|
if lang == "" {
|
|
lang = "en"
|
|
}
|
|
resetURL := fmt.Sprintf("%s/%s/reset-password?token=%s", baseURL, lang, token)
|
|
|
|
langID := getLangID(lang)
|
|
subject := i18n.T___(langID, "email.email_password_reset_subject")
|
|
body := s.passwordResetEmailTemplate(to, resetURL, langID)
|
|
|
|
return s.SendEmail(to, subject, body)
|
|
}
|
|
|
|
// SendNewUserAdminNotification sends an email to admin when a new user completes registration
|
|
func (s *EmailService) SendNewUserAdminNotification(userEmail, userName, baseURL string) error {
|
|
if s.config.AdminEmail == "" {
|
|
return nil // No admin email configured
|
|
}
|
|
|
|
subject := "New User Registration - Repository Assignment Required"
|
|
body := s.newUserAdminNotificationTemplate(userEmail, userName, baseURL)
|
|
|
|
return s.SendEmail(s.config.AdminEmail, subject, body)
|
|
}
|
|
|
|
// verificationEmailTemplate returns the HTML template for email verification
|
|
func (s *EmailService) verificationEmailTemplate(name, verificationURL string, langID uint) string {
|
|
buf := bytes.Buffer{}
|
|
emails.EmailVerificationWrapper(view.EmailLayout[view.EmailVerificationData]{LangID: langID, Data: view.EmailVerificationData{VerificationURL: verificationURL}}).Render(context.Background(), &buf)
|
|
return buf.String()
|
|
}
|
|
|
|
// passwordResetEmailTemplate returns the HTML template for password reset
|
|
func (s *EmailService) passwordResetEmailTemplate(name, resetURL string, langID uint) string {
|
|
buf := bytes.Buffer{}
|
|
emails.EmailPasswordResetWrapper(view.EmailLayout[view.EmailPasswordResetData]{LangID: langID, Data: view.EmailPasswordResetData{ResetURL: resetURL}}).Render(context.Background(), &buf)
|
|
return buf.String()
|
|
}
|
|
|
|
// newUserAdminNotificationTemplate returns the HTML template for admin notification
|
|
func (s *EmailService) newUserAdminNotificationTemplate(userEmail, userName, baseURL string) string {
|
|
buf := bytes.Buffer{}
|
|
emails.EmailAdminNotificationWrapper(view.EmailLayout[view.EmailAdminNotificationData]{LangID: 2, Data: view.EmailAdminNotificationData{UserEmail: userEmail, UserName: userName, BaseURL: baseURL}}).Render(context.Background(), &buf)
|
|
return buf.String()
|
|
}
|