Documentation
¶
Overview ¶
Package smtpmailer provides a simple SMTP email client with TLS support for sending HTML and plain text emails.
Basic Usage ¶
Create a mailer and send an email:
import smtpmailer "github.com/poly-workshop/go-webmods/smtpmailer"
mailer := smtpmailer.NewMailer(smtpmailer.Config{
Host: "smtp.gmail.com",
Port: 587,
Username: "your-email@gmail.com",
Password: "your-app-password",
FromEmail: "your-email@gmail.com",
FromName: "My Application",
})
err := mailer.SendEmail(smtpmailer.Message{
ToEmails: []string{"user@example.com"},
Subject: "Welcome to our service",
Body: "Thank you for signing up!",
IsHTML: false,
})
HTML Emails ¶
Send HTML-formatted emails:
err := mailer.SendEmail(smtpmailer.Message{
ToEmails: []string{"user@example.com"},
Subject: "Welcome!",
Body: `
<html>
<body>
<h1>Welcome to our service!</h1>
<p>Thank you for signing up.</p>
<a href="https://example.com/verify">Verify Email</a>
</body>
</html>
`,
IsHTML: true,
})
Multiple Recipients ¶
Send to multiple recipients:
err := mailer.SendEmail(smtpmailer.Message{
ToEmails: []string{
"user1@example.com",
"user2@example.com",
"user3@example.com",
},
Subject: "Newsletter",
Body: "Check out our latest updates!",
})
Common SMTP Providers ¶
Gmail (requires App Password):
Config{
Host: "smtp.gmail.com",
Port: 587,
Username: "your-email@gmail.com",
Password: "app-password", // Not your regular password
}
Office 365:
Config{
Host: "smtp.office365.com",
Port: 587,
Username: "your-email@outlook.com",
Password: "your-password",
}
SendGrid:
Config{
Host: "smtp.sendgrid.net",
Port: 587,
Username: "apikey",
Password: "your-sendgrid-api-key",
}
Mailgun:
Config{
Host: "smtp.mailgun.org",
Port: 587,
Username: "postmaster@your-domain.mailgun.org",
Password: "your-mailgun-password",
}
Configuration with Viper ¶
Example configuration file (configs/default.yaml):
smtp:
host: smtp.gmail.com
port: 587
username: ${SMTP_USERNAME}
password: ${SMTP_PASSWORD}
from_email: noreply@example.com
from_name: My Application
Loading configuration:
import (
"github.com/poly-workshop/go-webmods/app"
"github.com/poly-workshop/go-webmods/smtpmailer"
)
app.Init(".")
cfg := app.Config()
mailer := smtpmailer.NewMailer(smtpmailer.Config{
Host: cfg.GetString("smtp.host"),
Port: cfg.GetInt("smtp.port"),
Username: cfg.GetString("smtp.username"),
Password: cfg.GetString("smtp.password"),
FromEmail: cfg.GetString("smtp.from_email"),
FromName: cfg.GetString("smtp.from_name"),
})
Security ¶
The mailer uses TLS for secure communication:
- Connects via plain TCP initially
- Upgrades to TLS using STARTTLS
- Enforces minimum TLS version 1.2
- Validates server certificate
Email Templates ¶
For HTML emails with dynamic content, use Go's html/template:
import (
"bytes"
"html/template"
)
tmpl, err := template.ParseFiles("templates/welcome.html")
if err != nil {
return err
}
var body bytes.Buffer
err = tmpl.Execute(&body, struct {
Name string
URL string
}{
Name: "Alice",
URL: "https://example.com/verify?token=abc123",
})
if err != nil {
return err
}
err = mailer.SendEmail(smtpmailer.Message{
ToEmails: []string{"alice@example.com"},
Subject: "Verify your email",
Body: body.String(),
IsHTML: true,
})
Error Handling ¶
SendEmail returns an error if:
- Connection to SMTP server fails
- TLS upgrade fails
- Authentication fails
- Email is rejected by the server
- Network errors occur during sending
Always check the error:
err := mailer.SendEmail(msg)
if err != nil {
log.Printf("Failed to send email: %v", err)
// Handle error (retry, log, notify admin, etc.)
return err
}
Best Practices ¶
- Store SMTP credentials in environment variables or secret management
- Use app passwords for Gmail (not your account password)
- Set appropriate From name for better deliverability
- Validate email addresses before sending
- Use HTML templates for consistent styling
- Include plain text alternatives for HTML emails (not currently supported, consider adding)
- Implement retry logic for transient failures
- Rate limit email sending to avoid being flagged as spam
- Use dedicated email service providers (SendGrid, Mailgun) for production
- Test emails thoroughly before production deployment
Rate Limiting ¶
Implement rate limiting for bulk emails:
import "time"
for _, recipient := range recipients {
err := mailer.SendEmail(smtpmailer.Message{
ToEmails: []string{recipient},
Subject: "Newsletter",
Body: content,
})
if err != nil {
log.Printf("Failed to send to %s: %v", recipient, err)
}
time.Sleep(100 * time.Millisecond) // Rate limit
}
Limitations ¶
Current limitations:
- No attachment support
- No CC/BCC support
- No plain text alternative for HTML emails
- No email validation
- No retry mechanism
- No bulk sending optimization
For advanced features, consider using a dedicated email library or service.
Example: Password Reset Email ¶
func sendPasswordReset(mailer *smtpmailer.Mailer, email, token string) error {
resetURL := fmt.Sprintf("https://example.com/reset?token=%s", token)
body := fmt.Sprintf(`
<html>
<body style="font-family: Arial, sans-serif;">
<h2>Password Reset Request</h2>
<p>Click the link below to reset your password:</p>
<a href="%s" style="display: inline-block; padding: 10px 20px; background-color: #007bff; color: white; text-decoration: none; border-radius: 5px;">
Reset Password
</a>
<p>This link will expire in 1 hour.</p>
<p>If you didn't request this, please ignore this email.</p>
</body>
</html>
`, resetURL)
return mailer.SendEmail(smtpmailer.Message{
ToEmails: []string{email},
Subject: "Password Reset Request",
Body: body,
IsHTML: true,
})
}
Example ¶
Example demonstrates basic email sending.
package main
import (
"fmt"
)
func main() {
// mailer := smtpmailer.NewMailer(smtpmailer.Config{
// Host: "smtp.example.com",
// Port: 587,
// Username: "user@example.com",
// Password: "password",
// FromEmail: "noreply@example.com",
// FromName: "My Application",
// })
//
// err := mailer.SendEmail(smtpmailer.Message{
// ToEmails: []string{"recipient@example.com"},
// Subject: "Hello",
// Body: "This is a test email.",
// IsHTML: false,
// })
//
// if err != nil {
// fmt.Println("Error:", err)
// return
// }
fmt.Println("Email sent successfully")
}
Output: Email sent successfully
Example (Gmail) ¶
Example_gmail demonstrates configuring Gmail SMTP.
package main
import (
"fmt"
smtpmailer "github.com/poly-workshop/go-webmods/smtpmailer"
)
func main() {
// Note: For Gmail, you need to use an App Password
// Go to Google Account > Security > 2-Step Verification > App Passwords
mailer := smtpmailer.NewMailer(smtpmailer.Config{
Host: "smtp.gmail.com",
Port: 587,
Username: "your-email@gmail.com",
Password: "your-app-password", // Not your regular password!
FromEmail: "your-email@gmail.com",
FromName: "My App",
})
_ = mailer
fmt.Println("Gmail mailer configured")
}
Output: Gmail mailer configured
Example (Html) ¶
Example_html demonstrates sending HTML emails.
package main
import (
"fmt"
)
func main() {
// mailer := smtpmailer.NewMailer(smtpmailer.Config{
// Host: "smtp.example.com",
// Port: 587,
// Username: "user@example.com",
// Password: "password",
// FromEmail: "noreply@example.com",
// FromName: "My Application",
// })
//
// htmlBody := `
// <html>
// <body>
// <h1>Welcome!</h1>
// <p>Thank you for signing up.</p>
// <a href="https://example.com/verify">Verify Email</a>
// </body>
// </html>
// `
//
// err := mailer.SendEmail(smtpmailer.Message{
// ToEmails: []string{"user@example.com"},
// Subject: "Welcome to Our Service",
// Body: htmlBody,
// IsHTML: true,
// })
//
// if err != nil {
// fmt.Println("Error:", err)
// return
// }
fmt.Println("HTML email sent")
}
Output: HTML email sent
Example (MultipleRecipients) ¶
Example_multipleRecipients demonstrates sending to multiple recipients.
package main
import (
"fmt"
)
func main() {
// mailer := smtpmailer.NewMailer(smtpmailer.Config{
// Host: "smtp.example.com",
// Port: 587,
// Username: "user@example.com",
// Password: "password",
// FromEmail: "noreply@example.com",
// FromName: "Newsletter",
// })
//
// err := mailer.SendEmail(smtpmailer.Message{
// ToEmails: []string{
// "user1@example.com",
// "user2@example.com",
// "user3@example.com",
// },
// Subject: "Monthly Newsletter",
// Body: "Check out our latest updates!",
// IsHTML: false,
// })
//
// if err != nil {
// fmt.Println("Error:", err)
// return
// }
fmt.Println("Newsletter sent to multiple recipients")
}
Output: Newsletter sent to multiple recipients
Example (PasswordReset) ¶
Example_passwordReset demonstrates a password reset email.
package main
import (
"fmt"
)
func main() {
// mailer := smtpmailer.NewMailer(smtpmailer.Config{
// Host: "smtp.example.com",
// Port: 587,
// Username: "user@example.com",
// Password: "password",
// FromEmail: "noreply@example.com",
// FromName: "My Application",
// })
//
// resetToken := "abc123xyz"
// resetURL := fmt.Sprintf("https://example.com/reset?token=%s", resetToken)
//
// htmlBody := fmt.Sprintf(`
// <html>
// <body style="font-family: Arial, sans-serif;">
// <h2>Password Reset Request</h2>
// <p>Click the link below to reset your password:</p>
// <a href="%s" style="display: inline-block; padding: 10px 20px; background-color: #007bff; color: white; text-decoration: none; border-radius: 5px;">
// Reset Password
// </a>
// <p>This link will expire in 1 hour.</p>
// <p>If you didn't request this, please ignore this email.</p>
// </body>
// </html>
// `, resetURL)
//
// err := mailer.SendEmail(smtpmailer.Message{
// ToEmails: []string{"user@example.com"},
// Subject: "Password Reset Request",
// Body: htmlBody,
// IsHTML: true,
// })
//
// if err != nil {
// fmt.Println("Error:", err)
// return
// }
fmt.Println("Password reset email sent")
}
Output: Password reset email sent
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.