initial commit. Cloned timetracker repository
This commit is contained in:
138
app/service/emailService/email.go
Normal file
138
app/service/emailService/email.go
Normal file
@@ -0,0 +1,138 @@
|
||||
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/langs"
|
||||
"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 := langs.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()
|
||||
}
|
||||
Reference in New Issue
Block a user