This commit is contained in:
teddy
2025-04-18 18:15:59 +07:00
parent f7db944b97
commit d20ff0b41b
10 changed files with 306 additions and 92 deletions

View File

@@ -1 +0,0 @@
package app

View File

@@ -1,21 +1,12 @@
package app
import (
"bytes"
"fmt"
"log"
"net/smtp"
"os"
"strconv"
"text/template"
)
const CONFIG_SMTP_HOST = "smtp.gmail.com"
const CONFIG_SMTP_PORT = 587
const CONFIG_SENDER_NAME = "HIS <hats.nutech@gmail.com>"
const CONFIG_AUTH_EMAIL = "hats.nutech@gmail.com"
const CONFIG_AUTH_PASSWORD = "lbfjfuywqktkexij"
type MailConfig struct {
SMTPHost string
SMTPPort int
@@ -25,13 +16,6 @@ type MailConfig struct {
}
func Mail() *MailConfig {
// dialer := gomail.NewDialer(
// CONFIG_SMTP_HOST,
// CONFIG_SMTP_PORT,
// CONFIG_AUTH_EMAIL,
// CONFIG_AUTH_PASSWORD,
// )
port, err := strconv.Atoi(os.Getenv("SMTP_PORT"))
if err != nil {
fmt.Println("error parsing to int", err.Error())
@@ -46,45 +30,17 @@ func Mail() *MailConfig {
}
}
func SendEmail(to []string, cc []string, subject, message string) error {
tmpl, err := template.ParseFiles("template/test.html")
if err != nil {
log.Fatalf("Error parsing template: %v", err)
}
fmt.Println("qwqwqw", os.Getenv("PORT"))
type Data struct {
Name string
Company string
}
data := Data{Name: "Salwa Balqis Sulaeman", Company: "HIS"}
var buf bytes.Buffer
if err := tmpl.Execute(&buf, data); err != nil {
log.Fatalf("Error executing template: %v", err)
}
// content, err := os.ReadFile("template/test.html")
// if err != nil {
// fmt.Println("Error reading file:", err)
// return err
// }
htmlString := buf.String()
func SendEmail(to []string, cc []string, name, subject, message, htmlString string) error {
sender := "From: " + Mail().SMTPSenderName + "\n"
subjectt := "Subject: 👋 Hello from Go\n"
subjectt := "Subject: " + subject + "\n"
mime := "MIME-version: 1.0;\nContent-Type: text/html; charset=\"UTF-8\";\n\n"
body := htmlString
messages := []byte(sender + subjectt + mime + body)
auth := smtp.PlainAuth("", Mail().AuthEmail, Mail().AuthPassword, Mail().SMTPHost)
smtpAddr := fmt.Sprintf("%s:%d", Mail().SMTPHost, Mail().SMTPPort)
fmt.Println("cek dong", Mail())
err = smtp.SendMail(smtpAddr, auth, Mail().AuthEmail, append(to, cc...), messages)
err := smtp.SendMail(smtpAddr, auth, Mail().AuthEmail, append(to, cc...), messages)
if err != nil {
return err
}

1
go.mod
View File

@@ -3,6 +3,7 @@ module email-notification
go 1.21.1
require (
github.com/google/uuid v1.6.0
github.com/joho/godotenv v1.5.1
gorm.io/driver/postgres v1.5.11
gorm.io/gorm v1.25.12

2
go.sum
View File

@@ -1,6 +1,8 @@
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk=

67
helper/helper.go Normal file
View File

@@ -0,0 +1,67 @@
package helper
import (
"bytes"
"fmt"
"html/template"
"log"
"time"
"github.com/google/uuid"
)
func GenerateSessionID() string {
return uuid.New().String()
}
func ParseHTML(filePath string, v any) string {
tmpl, err := template.ParseFiles(filePath)
if err != nil {
log.Fatalf("Error parsing template: %v", err)
}
// type Data struct {
// Name string
// }
// data := Data{Name: name}
var buf bytes.Buffer
if err := tmpl.Execute(&buf, v); err != nil {
log.Fatalf("Error executing template: %v", err)
}
return buf.String()
}
func FormatSince(t time.Time) string {
now := time.Now()
dur := now.Sub(t)
years := int(dur.Hours() / 24 / 365)
if years > 0 {
return fmt.Sprintf("%d", years)
}
// months := int(dur.Hours() / 24 / 30)
// if months > 0 {
// return fmt.Sprintf("%d bulan yang lalu", months)
// }
// days := int(dur.Hours() / 24)
// if days > 0 {
// return fmt.Sprintf("%d hari yang lalu", days)
// }
// hours := int(dur.Hours())
// if hours > 0 {
// return fmt.Sprintf("%d jam yang lalu", hours)
// }
// minutes := int(dur.Minutes())
// if minutes > 0 {
// return fmt.Sprintf("%d menit yang lalu", minutes)
// }
return "baru saja"
}

50
main.go
View File

@@ -2,11 +2,9 @@ package main
import (
"context"
"email-notification/app"
"email-notification/config"
"email-notification/model"
"email-notification/query"
"fmt"
"email-notification/middleware"
"email-notification/route"
"log"
"net/http"
"os"
@@ -15,51 +13,19 @@ import (
)
func main() {
fmt.Println("Test")
log.Println("Email Notification Service")
err := godotenv.Load()
if err != nil {
log.Fatal("Error loading .env file")
}
http.Handle("/", middleware.ResponseTimeMiddleware(func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Welcome!"))
}))
db := config.NewDatabase().WithContext(context.Background())
to := []string{"teddy.nutech@gmail.com"}
cc := []string{"teddy.nutech@gmail.com"}
subject := "test"
message := "test"
fmt.Println(to, cc, subject, message)
http.HandleFunc("/birthday-notification", func(w http.ResponseWriter, r *http.Request) {
data := new([]model.Birthday)
err := query.GetBirthday(db, data, "1", "1")
if err != nil {
w.WriteHeader(500)
w.Write([]byte(err.Error()))
}
fmt.Println("hasil query data", data)
for _, v := range *data {
fmt.Println("Birthday", v.Fullname)
sendTo := []string{v.Email}
go func() {
fmt.Println("sending email...")
err := app.SendEmail(sendTo, sendTo, subject, message)
if err != nil {
fmt.Println("error", err.Error())
w.WriteHeader(500)
w.Write([]byte(err.Error()))
} else {
fmt.Println("email sent")
}
}()
}
w.Write([]byte("success"))
})
route.Route(db)
port := os.Getenv("PORT")

17
middleware/middleware.go Normal file
View File

@@ -0,0 +1,17 @@
package middleware
import (
"log"
"net/http"
"time"
)
func ResponseTimeMiddleware(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
path := r.URL.Path
next(w, r)
duration := time.Since(start)
log.Printf("%+v response time %+v", path, duration)
}
}

123
route/route.go Normal file
View File

@@ -0,0 +1,123 @@
package route
import (
"email-notification/app"
"email-notification/helper"
"email-notification/middleware"
"email-notification/model"
"email-notification/query"
"fmt"
"log"
"net/http"
"time"
"gorm.io/gorm"
)
func Route(db *gorm.DB) {
http.HandleFunc("/birthday-notification", middleware.ResponseTimeMiddleware(func(w http.ResponseWriter, r *http.Request) {
sessionID := helper.GenerateSessionID()
module := "BIRTHDAY NOTIFICATION"
log.Printf("%+v %+v request %+v", sessionID, module, nil)
data := new([]model.Birthday)
month := int(time.Now().Month())
day := time.Now().Day()
subject := "Happy Birthday 🎉🎂🥳"
err := query.GetBirthday(db, data, fmt.Sprint(month), fmt.Sprint(day))
if err != nil {
log.Fatalf("%+v %+v response %+v", sessionID, module, err.Error())
w.WriteHeader(500)
w.Write([]byte(err.Error()))
}
for _, v := range *data {
fmt.Println("Birthday", v.Fullname)
sendTo := []string{v.Email}
type Data struct {
Name string
}
data := Data{Name: v.Fullname}
htmlString := helper.ParseHTML("template/birthday.html", data)
go func(v model.Birthday) {
log.Printf("%+v %+v SENDING EMAIL TO %+v", sessionID, module, v.Email)
err := app.SendEmail(sendTo, sendTo, "", subject, "", htmlString)
if err != nil {
log.Printf("%+v %+v response %+v", sessionID, module, err.Error())
w.WriteHeader(500)
w.Write([]byte(err.Error()))
} else {
log.Fatalf("%+v %+v EMAIL SENT TO %+v", sessionID, module, v.Email)
}
}(v)
}
log.Printf("%+v %+v response %+v", sessionID, module, "success")
w.Write([]byte("success"))
}))
http.HandleFunc("/workanniversary-notification", middleware.ResponseTimeMiddleware(func(w http.ResponseWriter, r *http.Request) {
sessionID := helper.GenerateSessionID()
module := "WORKANNIVERSARY NOTIFICATION"
log.Printf("%+v %+v request %+v", sessionID, module, nil)
data := new([]model.Workanniversary)
month := int(time.Now().Month())
day := time.Now().Day()
err := query.GetWorkanniversary(db, data, fmt.Sprint(month), fmt.Sprint(day))
if err != nil {
log.Fatalf("%+v %+v response %+v", sessionID, module, err.Error())
w.WriteHeader(500)
w.Write([]byte(err.Error()))
}
subject := "Work Anniversary 🎉"
for _, v := range *data {
fmt.Println("Workanniversary", v.Fullname)
sendTo := []string{v.Email}
type Data struct {
Name string
Year string
}
duration := helper.FormatSince(v.HireDate)
fmt.Println("durasi", duration)
data := Data{Name: v.Fullname, Year: duration}
htmlString := helper.ParseHTML("template/workanniversary.html", data)
go func(v model.Workanniversary) {
log.Printf("%+v %+v SENDING EMAIL TO %+v", sessionID, module, v.Email)
err := app.SendEmail(sendTo, sendTo, "", subject, "", htmlString)
if err != nil {
log.Printf("%+v %+v response %+v", sessionID, module, err.Error())
w.WriteHeader(500)
w.Write([]byte(err.Error()))
} else {
log.Fatalf("%+v %+v EMAIL SENT TO %+v", sessionID, module, v.Email)
}
}(v)
}
log.Printf("%+v %+v response %+v", sessionID, module, "success")
w.Write([]byte("success"))
}))
http.HandleFunc("/test", middleware.ResponseTimeMiddleware(func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("success"))
}))
}

View File

@@ -5,7 +5,7 @@
<title>Selamat Ulang Tahun!</title>
<style>
.container {
max-width: 600px;
max-width: 100%;
margin: auto;
padding: 30px;
background-color: #fef9f4;
@@ -44,7 +44,7 @@
</p>
<p class="footer">
Salam hangat dari kami,<br />
<b>Tim {{.Company}}</b>
<b>HIS</b>
</p>
<img
src="http://36.66.3.44:9000/create-bucket-test/test-folder/LOGO_HIS_NI_New_Contrasted-removebg-preview.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=BDYv2npRYZw5fcXzd80c%2F20250417%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20250417T045323Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=c399ff0031b0d8bc9b7073171bca8ad3a9c2b82a374e25e60dbd35bd5bd5775e"

View File

@@ -0,0 +1,83 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Work Anniversary</title>
<style>
body {
font-family: "Segoe UI", Tahoma, sans-serif;
background-color: #f5f7fa;
margin: 0;
padding: 0;
}
.email-container {
max-width: 100%;
margin: 30px auto;
background-color: #ffffff;
padding: 25px;
border-radius: 8px;
border: 1px solid #e0e0e0;
}
.header {
background-color: #00add8;
color: #ffffff;
padding: 20px;
text-align: center;
border-radius: 6px 6px 0 0;
}
.header h1 {
margin: 0;
font-size: 24px;
}
.content {
padding: 20px;
text-align: center;
}
.content h2 {
color: #00add8;
font-size: 20px;
}
.content p {
color: #444;
font-size: 16px;
line-height: 1.5;
}
.logo {
width: 80px;
margin: 20px auto;
}
.footer {
font-size: 13px;
color: #888;
text-align: center;
margin-top: 30px;
}
</style>
</head>
<body>
<div class="email-container">
<div class="header">
<h1>🎉 Work Anniversary!</h1>
</div>
<div class="content">
<img
src="http://36.66.3.44:9000/create-bucket-test/test-folder/LOGO_HIS_NI_New_Contrasted-removebg-preview.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=BDYv2npRYZw5fcXzd80c%2F20250417%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20250417T045323Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=c399ff0031b0d8bc9b7073171bca8ad3a9c2b82a374e25e60dbd35bd5bd5775e"
alt="logo"
width="100px"
/>
<h2>Hai {{.Name}},</h2>
<p>
Hari ini menandai tahun ke-<strong>{{.Year}}</strong> kamu di
perusahaan ini. Terima kasih atas dedikasi, semangat, dan kontribusimu
selama ini!
</p>
<p>
Kami bangga memiliki kamu dalam tim teknologi kami. Mari terus
berkembang bersama — satu commit, satu deploy, satu milestone pada
satu waktu. 🚀
</p>
</div>
<div class="footer">© HIS 💙</div>
</div>
</body>
</html>