update
This commit is contained in:
@@ -1 +0,0 @@
|
||||
package app
|
||||
@@ -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
1
go.mod
@@ -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
2
go.sum
@@ -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
67
helper/helper.go
Normal 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
50
main.go
@@ -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
17
middleware/middleware.go
Normal 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
123
route/route.go
Normal 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"))
|
||||
}))
|
||||
}
|
||||
@@ -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"
|
||||
83
template/workanniversary.html
Normal file
83
template/workanniversary.html
Normal 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>
|
||||
Reference in New Issue
Block a user