aboutsummaryrefslogtreecommitdiff
path: root/utils/email/email.go
blob: 168da25a46623926256c236221994d43026e3bf3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
package email

import (
	"bytes"
	"fmt"
	"html/template"
	"imageboard/config"
	"imageboard/database"
	"imageboard/models"
	"net/smtp"
	"regexp"
)

func extractEmailAddress(from string) string {
	re := regexp.MustCompile(`<([^>]+)>`)
	matches := re.FindStringSubmatch(from)
	if len(matches) == 2 {
		return matches[1]
	}
	return from
}

func SendMail(to, subject, body string) error {
	var auth smtp.Auth
	if config.SMTP.Username != "" {
		auth = smtp.PlainAuth("", config.SMTP.Username, config.SMTP.Password, config.SMTP.Host)
	} else {
		auth = nil
	}
	fromHeader := config.SMTP.From
	fromAddress := extractEmailAddress(config.SMTP.From)
	msg := 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",
		fromHeader, to, subject, body)
	addr := fmt.Sprintf("%s:%d", config.SMTP.Host, config.SMTP.Port)
	return smtp.SendMail(addr, auth, fromAddress, []string{to}, []byte(msg))
}

func SendVerificationEmail(user *models.User) error {
	token, err := database.GenerateEmailToken(int(user.ID), config.EmailTokenTypeVerification)
	if err != nil {
		return fmt.Errorf("failed to generate verification token: %w", err)
	}

	tmpl, err := template.ParseFiles("templates/email/verification.html")
	if err != nil {
		return fmt.Errorf("failed to parse email template: %w", err)
	}
	verificationLink := fmt.Sprintf("%s%s?token=%s", config.Server.AppBaseURL, config.URL_VERIFY_EMAIL, token.Token)
	data := struct {
		Username string
		Appname  string
		Link     string
	}{
		Username: user.Username,
		Appname:  config.Server.AppName,
		Link:     verificationLink,
	}

	var body bytes.Buffer
	if err := tmpl.Execute(&body, data); err != nil {
		return fmt.Errorf("failed to execute email template: %w", err)
	}

	subject := fmt.Sprintf("Verify your email for %s", config.Server.AppName)
	return SendMail(user.Email, subject, body.String())
}

// func SendPasswordResetEmail(user *models.User) error {
// 	token, err := user.GenerateToken(database.DB, models.EmailTokenTypePasswordReset)
// 	if err != nil {
// 		return fmt.Errorf("failed to generate password reset token: %w", err)
// 	}

// 	tmpl, err := template.ParseFiles("templates/email/password_reset.html")
// 	if err != nil {
// 		return fmt.Errorf("failed to parse email template: %w", err)
// 	}
// 	resetLink := fmt.Sprintf("%s/account/reset-password?token=%s", config.Server.AppBaseURL, token.Token)
// 	data := struct {
// 		Username string
// 		Link     string
// 	}{
// 		Username: user.Username,
// 		Link:     resetLink,
// 	}

// 	var body bytes.Buffer
// 	if err := tmpl.Execute(&body, data); err != nil {
// 		return fmt.Errorf("failed to execute email template: %w", err)
// 	}

// 	subject := fmt.Sprintf("Password reset for %s", config.Server.AppName)
// 	return SendMail(user.Email, subject, body.String())
// }

// func SendEmailChangeConfirmation(user *models.User, newEmail string) error {
// 	token, err := user.GenerateToken(database.DB, models.EmailTokenTypeChangeEmail)
// 	if err != nil {
// 		return fmt.Errorf("failed to generate email change token: %w", err)
// 	}

// 	tmpl, err := template.ParseFiles("templates/email/email_change.html")
// 	if err != nil {
// 		return fmt.Errorf("failed to parse email template: %w", err)
// 	}
// 	confirmLink := fmt.Sprintf("%s/account/confirm-email-change?token=%s&email=%s", config.Server.AppBaseURL, token.Token, newEmail)
// 	data := struct {
// 		Username string
// 		NewEmail string
// 		Link     string
// 	}{
// 		Username: user.Username,
// 		NewEmail: newEmail,
// 		Link:     confirmLink,
// 	}

// 	var body bytes.Buffer
// 	if err := tmpl.Execute(&body, data); err != nil {
// 		return fmt.Errorf("failed to execute email template: %w", err)
// 	}

// 	subject := fmt.Sprintf("Confirm email change for %s", config.Server.AppName)
// 	return SendMail(newEmail, subject, body.String())
// }