Files
WebAndAppMonoRepo/output/internal/services/email_service.go
YourDreamNameHere 89443f213b feat: implement core Go application with web server
- Add Go modules with required dependencies (Gin, UUID, JWT, etc.)
- Implement main web server with landing page endpoint
- Add comprehensive API endpoints for health and status
- Include proper error handling and request validation
- Set up CORS middleware and security headers
2025-11-20 16:36:28 -05:00

278 lines
7.1 KiB
Go
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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")
}