package services import ( "crypto/tls" "fmt" "net/smtp" "time" "github.com/ydn/yourdreamnamehere/internal/config" ) type EmailService struct { config *config.Config auth smtp.Auth } func NewEmailService(config *config.Config) *EmailService { auth := smtp.PlainAuth("", config.Email.SMTPUser, config.Email.SMTPPassword, config.Email.SMTPHost) return &EmailService{ config: config, auth: auth, } } func (s *EmailService) SendWelcomeEmail(to, firstName string) error { subject := "Welcome to YourDreamNameHere!" body := fmt.Sprintf(` Dear %s, Welcome to YourDreamNameHere! Your sovereign data hosting journey begins now. What happens next: 1. Your domain will be registered through our OVH partner 2. A VPS will be provisioned and configured for you 3. Cloudron will be installed on your VPS 4. You'll receive an email invitation to complete your Cloudron setup This entire process typically takes 30-60 minutes. You'll receive updates at each step. If you have any questions, please don't hesitate to contact our support team. Best regards, The YourDreamNameHere Team `, firstName) return s.sendEmail(to, subject, body) } func (s *EmailService) SendAdminInvitation(to, domainName, cloudronURL, token string) error { subject := "Complete Your Cloudron Setup" body := fmt.Sprintf(` Your Cloudron instance is ready! Domain: %s Cloudron URL: %s To complete your setup, please click the link below: https://yourdreamnamehere.com/invitation/%s This link will expire in 7 days. What you'll need to do: 1. Set your administrator password 2. Configure your organization details 3. Choose your initial applications If you have any questions or need assistance, please contact our support team. Best regards, The YourDreamNameHere Team `, domainName, cloudronURL, token) return s.sendEmail(to, subject, body) } func (s *EmailService) SendDeploymentUpdate(to, domainName, step, status string) error { subject := fmt.Sprintf("Deployment Update for %s", domainName) var statusMessage string switch status { case "completed": statusMessage = "✅ Completed successfully" case "failed": statusMessage = "❌ Failed" case "in_progress": statusMessage = "🔄 In progress" default: statusMessage = "â„šī¸ " + status } body := fmt.Sprintf(` Deployment Update for %s Current Step: %s Status: %s `, domainName, step, statusMessage) switch step { case "domain_registration": body += ` Your domain registration is being processed. This typically takes a few minutes to complete. ` case "vps_provisioning": body += ` Your Virtual Private Server is being provisioned. This includes setting up the base operating system and security configurations. ` case "cloudron_install": body += ` Cloudron is being installed on your VPS. This is the most time-consuming step and can take 20-30 minutes. ` case "deployment_complete": body += ` 🎉 Congratulations! Your sovereign data hosting environment is now ready! You should receive a separate email with your administrator invitation to complete the Cloudron setup. ` } body += ` You can track the progress of your deployment by logging into your account at: https://yourdreamnamehere.com/dashboard Best regards, The YourDreamNameHere Team ` return s.sendEmail(to, subject, body) } func (s *EmailService) SendPaymentConfirmation(to, domainName string) error { subject := "Payment Confirmation - YourDreamNameHere" body := fmt.Sprintf(` Payment Confirmation Thank you for your payment! Your subscription for %s is now active. Subscription Details: - Domain: %s - Plan: Sovereign Data Hosting - Amount: $250.00 USD - Billing: Monthly What's Next: Your deployment process will begin immediately. You'll receive email updates as each step completes. If you have any questions, please contact our support team. Best regards, The YourDreamNameHere Team `, domainName, domainName) return s.sendEmail(to, subject, body) } func (s *EmailService) SendSubscriptionRenewalNotice(to, domainName string) error { subject := "Subscription Renewal Notice - YourDreamNameHere" body := fmt.Sprintf(` Subscription Renewal Notice This is a friendly reminder that your subscription for %s will be renewed soon. Subscription Details: - Domain: %s - Plan: Sovereign Data Hosting - Amount: $250.00 USD - Next Billing Date: %s Your subscription will be automatically renewed using your payment method on file. If you need to update your payment information or have any questions, please contact our support team. Best regards, The YourDreamNameHere Team `, domainName, domainName, getNextBillingDate()) return s.sendEmail(to, subject, body) } func (s *EmailService) SendPasswordReset(to, resetToken string) error { subject := "Password Reset - YourDreamNameHere" body := fmt.Sprintf(` Password Reset Request You requested a password reset for your YourDreamNameHere account. Click the link below to reset your password: https://yourdreamnamehere.com/reset-password?token=%s This link will expire in 1 hour. If you didn't request this password reset, please ignore this email or contact our support team. Best regards, The YourDreamNameHere Team `, resetToken) return s.sendEmail(to, subject, body) } func (s *EmailService) sendEmail(to, subject, body string) error { headers := make(map[string]string) headers["From"] = s.config.Email.From headers["To"] = to headers["Subject"] = subject headers["MIME-Version"] = "1.0" headers["Content-Type"] = "text/plain; charset=\"utf-8\"" message := "" for k, v := range headers { message += fmt.Sprintf("%s: %s\r\n", k, v) } message += "\r\n" + body // Create SMTP connection with TLS client, err := s.createSMTPClient() if err != nil { return fmt.Errorf("failed to create SMTP client: %w", err) } defer client.Close() // Set the sender and recipient if err := client.Mail(s.config.Email.From); err != nil { return fmt.Errorf("failed to set sender: %w", err) } if err := client.Rcpt(to); err != nil { return fmt.Errorf("failed to set recipient: %w", err) } // Send the email body w, err := client.Data() if err != nil { return fmt.Errorf("failed to create data writer: %w", err) } _, err = w.Write([]byte(message)) if err != nil { return fmt.Errorf("failed to write email body: %w", err) } if err := w.Close(); err != nil { return fmt.Errorf("failed to close data writer: %w", err) } return nil } func (s *EmailService) createSMTPClient() (*smtp.Client, error) { // Connect to SMTP server with TLS conn, err := tls.Dial("tcp", fmt.Sprintf("%s:%s", s.config.Email.SMTPHost, s.config.Email.SMTPPort), &tls.Config{ ServerName: s.config.Email.SMTPHost, }) if err != nil { return nil, fmt.Errorf("failed to connect to SMTP server: %w", err) } client, err := smtp.NewClient(conn, s.config.Email.SMTPHost) if err != nil { conn.Close() return nil, fmt.Errorf("failed to create SMTP client: %w", err) } // Authenticate if err := client.Auth(s.auth); err != nil { client.Close() return nil, fmt.Errorf("failed to authenticate: %w", err) } return client, nil } func getNextBillingDate() string { // Return next month's date in a readable format return time.Now().AddDate(0, 1, 0).Format("January 2, 2006") }