Skip to content

Commit b7ba3fe

Browse files
committed
send password reset emails
1 parent be61147 commit b7ba3fe

File tree

1 file changed

+138
-3
lines changed

1 file changed

+138
-3
lines changed

main.go

Lines changed: 138 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ type SignupData struct {
3939
Token string `json:"token" binding:"required"`
4040
}
4141

42-
type ActivateData struct {
42+
type ActivateOrResetData struct {
4343
Email string `json:"email" binding:"required,email"`
4444
Token string `json:"token" binding:"required"`
4545
}
@@ -315,6 +315,97 @@ const activate_template = `
315315
</body>
316316
</html>`
317317

318+
const pwdreset_template = `
319+
<!DOCTYPE html>
320+
<html>
321+
<head>
322+
<style>
323+
body {
324+
font-family: Arial, sans-serif;
325+
line-height: 1.6;
326+
color: #333;
327+
max-width: 600px;
328+
margin: 0 auto;
329+
}
330+
.header {
331+
background-color: #f8f9fa;
332+
padding: 20px;
333+
border-bottom: 2px solid #007bff;
334+
text-align: center;
335+
}
336+
.logo {
337+
max-width: 200px;
338+
margin-bottom: 10px;
339+
}
340+
.content {
341+
padding: 0 20px 20px 20px;
342+
}
343+
.button {
344+
background-color: #007bff;
345+
color: white;
346+
padding: 12px 24px;
347+
text-decoration: none;
348+
border-radius: 4px;
349+
font-weight: bold;
350+
display: inline-block;
351+
margin: 20px 0;
352+
}
353+
.button:hover {
354+
background-color: #0069d9;
355+
}
356+
.important-note {
357+
background-color: #f8f9fa;
358+
border-left: 4px solid #ffc107;
359+
padding: 15px;
360+
margin: 15px 0;
361+
font-size: 0.9em;
362+
}
363+
.footer {
364+
margin-top: 30px;
365+
padding-top: 15px;
366+
border-top: 1px solid #eee;
367+
font-size: 0.9em;
368+
color: #777;
369+
text-align: center;
370+
}
371+
.contact-info {
372+
margin-top: 20px;
373+
}
374+
</style>
375+
</head>
376+
<body>
377+
<div class="header">
378+
<h2>Password Reset Request</h2>
379+
</div>
380+
381+
<div class="content">
382+
383+
384+
<p>Your password can be reset by clicking the button below. If you did not request a new password, please ignore this email.</p>
385+
386+
<a href="https://rent.ragodevs.com/admins/reset?token={{.Token}}" class="button">Reset Password</a>
387+
388+
<div class="important-note">
389+
<p>Please note that this reset link will expire 45 minutes and can only be used once.</p>
390+
</div>
391+
392+
<div class="contact-info">
393+
<p>If you have any questions or need assistance, please contact our support team:</p>
394+
<p>Email: <a href="mailto:[email protected]">[email protected]</a><br>
395+
Phone: 0654051622</p>
396+
</div>
397+
398+
<p>Best regards,</p>
399+
<p>The Rent Management System Team</p>
400+
401+
<div class="footer">
402+
<p><a href="https://www.rent.ragodevs.com">www.rent.ragodevs.com</a></p>
403+
<p>© 2025 Rent Management System. All rights reserved.</p>
404+
</div>
405+
</div>
406+
</body>
407+
</html>`
408+
318409
func enableCORS() gin.HandlerFunc {
319410

320411
corsConfig := cors.DefaultConfig()
@@ -395,7 +486,7 @@ func (mc *MailConfig) sendWelcomeEmail(data SignupData) error {
395486
return nil
396487
}
397488

398-
func (mc *MailConfig) sendActivateEmail(data ActivateData) error {
489+
func (mc *MailConfig) sendActivateEmail(data ActivateOrResetData) error {
399490

400491
tmpl, err := template.New("email").Parse(activate_template)
401492
if err != nil {
@@ -420,6 +511,33 @@ func (mc *MailConfig) sendActivateEmail(data ActivateData) error {
420511

421512
return nil
422513
}
514+
515+
func (mc *MailConfig) sendPasswordResetEmail(data ActivateOrResetData) error {
516+
517+
tmpl, err := template.New("email").Parse(pwdreset_template)
518+
if err != nil {
519+
return fmt.Errorf("failed to parse email template: %v", err)
520+
}
521+
522+
var emailBody bytes.Buffer
523+
if err := tmpl.Execute(&emailBody, data); err != nil {
524+
return fmt.Errorf("failed to execute email template: %v", err)
525+
}
526+
527+
recipients := []string{data.Email}
528+
529+
subject := "Password Reset Request for Rent Management System"
530+
msg := fmt.Sprintf("Subject: %s\nTo: %s\nContent-Type: text/html\n\n%s", subject, data.Email, emailBody.String())
531+
532+
auth := smtp.PlainAuth("", mc.USER, mc.PWD, mc.HOST)
533+
err = smtp.SendMail(mc.HOST+":"+mc.PORT, auth, mc.USER, recipients, []byte(msg))
534+
if err != nil {
535+
return fmt.Errorf("failed to send email: %v", err)
536+
}
537+
538+
return nil
539+
}
540+
423541
func main() {
424542

425543
mc := &MailConfig{}
@@ -473,7 +591,7 @@ func main() {
473591

474592
router.POST("/rent-activate", func(c *gin.Context) {
475593

476-
var data ActivateData
594+
var data ActivateOrResetData
477595
if err := c.ShouldBindJSON(&data); err != nil {
478596
c.JSON(400, gin.H{"error": err.Error()})
479597
return
@@ -488,6 +606,23 @@ func main() {
488606
c.JSON(200, gin.H{"message": "Email sent successfully!"})
489607
})
490608

609+
router.POST("/rent-resetpwd", func(c *gin.Context) {
610+
611+
var data ActivateOrResetData
612+
if err := c.ShouldBindJSON(&data); err != nil {
613+
c.JSON(400, gin.H{"error": err.Error()})
614+
return
615+
}
616+
617+
if err := mc.sendPasswordResetEmail(data); err != nil {
618+
log.Printf("Error sending email: %v", err)
619+
c.JSON(500, gin.H{"error": "Failed to send email"})
620+
return
621+
}
622+
623+
c.JSON(200, gin.H{"message": "Email sent successfully!"})
624+
})
625+
491626
port := os.Getenv("PORT")
492627
if port == "" {
493628
port = "8080"

0 commit comments

Comments
 (0)