resend to smtp

This commit is contained in:
Cipher Vance
2025-11-22 22:40:24 -06:00
parent 2dc5c0a912
commit a4a1a93567

View File

@@ -2,81 +2,163 @@ package email
import ( import (
"fmt" "fmt"
"net/smtp"
"os" "os"
"strconv"
"github.com/resend/resend-go/v2"
) )
type Service struct { type Service struct {
client *resend.Client smtpServer string
from string smtpPort int
smtpUser string
smtpPassword string
from string
} }
func NewService() *Service { func NewService() *Service {
senderEmail := os.Getenv("SENDER_EMAIL") smtpServer := os.Getenv("SMTP_SERVER")
if senderEmail == "" { if smtpServer == "" {
senderEmail = "noreply@rideaware.app" smtpServer = "localhost"
} }
apiKey := os.Getenv("RESEND_API_KEY") smtpPort := os.Getenv("SMTP_PORT")
if apiKey == "" { if smtpPort == "" {
apiKey = "re_test" smtpPort = "587"
}
port, err := strconv.Atoi(smtpPort)
if err != nil {
port = 587
}
smtpUser := os.Getenv("SMTP_USER")
if smtpUser == "" {
smtpUser = "noreply@rideaware.app"
}
smtpPassword := os.Getenv("SMTP_PASSWORD")
from := os.Getenv("SENDER_EMAIL")
if from == "" {
from = "noreply@rideaware.app"
} }
return &Service{ return &Service{
client: resend.NewClient(apiKey), smtpServer: smtpServer,
from: senderEmail, smtpPort: port,
smtpUser: smtpUser,
smtpPassword: smtpPassword,
from: from,
} }
} }
func (s *Service) sendEmail(to []string, subject, htmlBody string) error {
// Create message
headers := fmt.Sprintf("From: %s\r\nTo: %s\r\nSubject: %s\r\nMIME-Version: 1.0\r\nContent-Type: text/html; charset=\"UTF-8\"\r\n\r\n",
s.from,
to[0],
subject,
)
message := headers + htmlBody
// SMTP server address
addr := fmt.Sprintf("%s:%d", s.smtpServer, s.smtpPort)
// Create SMTP authentication
auth := smtp.PlainAuth("", s.smtpUser, s.smtpPassword, s.smtpServer)
// Send email
err := smtp.SendMail(addr, auth, s.from, to, []byte(message))
if err != nil {
return fmt.Errorf("failed to send email: %w", err)
}
return nil
}
func (s *Service) SendPasswordResetEmail(email, username, resetLink string) error { func (s *Service) SendPasswordResetEmail(email, username, resetLink string) error {
params := &resend.SendEmailRequest{ subject := "Reset Your RideAware Password"
From: s.from, htmlBody := fmt.Sprintf(`
To: []string{email}, <!DOCTYPE html>
Subject: "Reset Your RideAware Password", <html>
Html: fmt.Sprintf(` <head>
<h2>Password Reset Request</h2> <style>
<p>Hi %s,</p> body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }
<p>We received a request to reset your password. Click the link below to create a new password:</p> .container { max-width: 600px; margin: 0 auto; padding: 20px; }
<p><a href="%s">Reset Password</a></p> .header { background: linear-gradient(135deg, #1e4e9c 0%, #337cf2 100%); color: white; padding: 20px; border-radius: 8px; }
<p>This link will expire in 1 hour.</p> .content { padding: 20px; background: #f9f9f9; margin: 20px 0; border-radius: 8px; }
<p>If you didn't request this, you can ignore this email.</p> .button { background: linear-gradient(135deg, #1e4e9c 0%, #337cf2 100%); color: white; padding: 12px 24px; text-decoration: none; border-radius: 6px; display: inline-block; margin: 20px 0; }
`, username, resetLink), .footer { text-align: center; color: #666; font-size: 12px; margin-top: 20px; }
} </style>
</head>
<body>
<div class="container">
<div class="header">
<h2>Password Reset Request</h2>
</div>
<div class="content">
<p>Hi %s,</p>
<p>We received a request to reset your password. Click the button below to create a new password:</p>
<p><a href="%s" class="button">Reset Password</a></p>
<p><strong>Note:</strong> This link will expire in 1 hour.</p>
<p>If you didn't request this, you can safely ignore this email.</p>
</div>
<div class="footer">
<p>&copy; 2025 RideAware. All rights reserved.</p>
</div>
</div>
</body>
</html>
`, username, resetLink)
sent, err := s.client.Emails.Send(params) return s.sendEmail([]string{email}, subject, htmlBody)
if err != nil {
return fmt.Errorf("failed to send email: %w", err)
}
if sent.Id == "" {
return fmt.Errorf("failed to send email")
}
return nil
} }
func (s *Service) SendWelcomeEmail(email, username string) error { func (s *Service) SendWelcomeEmail(email, username string) error {
params := &resend.SendEmailRequest{ subject := "Welcome to RideAware"
From: s.from, htmlBody := fmt.Sprintf(`
To: []string{email}, <!DOCTYPE html>
Subject: "Welcome to RideAware", <html>
Html: fmt.Sprintf(` <head>
<h2>Welcome to RideAware</h2> <style>
<p>Hi %s,</p> body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }
<p>Your account has been created successfully!</p> .container { max-width: 600px; margin: 0 auto; padding: 20px; }
<p>Start tracking your rides and improve your performance.</p> .header { background: linear-gradient(135deg, #1e4e9c 0%, #337cf2 100%); color: white; padding: 20px; border-radius: 8px; }
`, username), .content { padding: 20px; background: #f9f9f9; margin: 20px 0; border-radius: 8px; }
} .button { background: linear-gradient(135deg, #1e4e9c 0%, #337cf2 100%); color: white; padding: 12px 24px; text-decoration: none; border-radius: 6px; display: inline-block; margin: 20px 0; }
.footer { text-align: center; color: #666; font-size: 12px; margin-top: 20px; }
</style>
</head>
<body>
<div class="container">
<div class="header">
<h2>Welcome to RideAware</h2>
</div>
<div class="content">
<p>Hi %s,</p>
<p>Your account has been created successfully! 🚀</p>
<p>You're now ready to:</p>
<ul>
<li>Track your cycling performance</li>
<li>Manage your equipment</li>
<li>Create custom training zones</li>
<li>Plan structured workouts</li>
</ul>
<p>Get started by logging in to your account and setting up your profile.</p>
<p><a href="https://dev.rideaware.org" class="button">Go to RideAware</a></p>
</div>
<div class="footer">
<p>&copy; 2025 RideAware. All rights reserved.</p>
</div>
</div>
</body>
</html>
`, username)
sent, err := s.client.Emails.Send(params) return s.sendEmail([]string{email}, subject, htmlBody)
if err != nil { }
return fmt.Errorf("failed to send email: %w", err)
} func (s *Service) SendNewsletterEmail(email, subject, htmlBody string) error {
return s.sendEmail([]string{email}, subject, htmlBody)
if sent.Id == "" {
return fmt.Errorf("failed to send email")
}
return nil
} }