Documentation
¶
Overview ¶
Package smtp provides an SMTP email provider implementation for gomail.
The SMTP provider supports standard SMTP servers with optional STARTTLS encryption and authentication. It is **universal** and works with ANY SMTP server, including:
- Public providers (Gmail, Outlook, SendGrid, Mailgun, AWS SES, etc.)
- Personal/self-hosted email servers
- Internal corporate mail servers
- Custom SMTP implementations
For ready-to-use configuration templates, see PROVIDER-TEMPLATES.md in the repository root.
Configuration ¶
The provider requires an smtp.Config struct with connection details:
config := smtp.Config{
Host: "smtp.gmail.com", // SMTP server hostname
Port: 587, // Port (587=STARTTLS, 465=SSL, 25=plain)
Username: "user@gmail.com", // SMTP username
Password: "app-password", // SMTP password
From: "user@gmail.com", // Default sender address
EncryptionType: smtp.EncryptionTLS, // Encryption method
TLSMinVersion: tls.VersionTLS12, // Minimum TLS version (optional)
}
Encryption Types (v1.0.0+) ¶
The provider supports three encryption types for secure communication:
- EncryptionTLS (recommended): STARTTLS - upgrades plain connection to TLS (port 587)
- EncryptionSSL: Direct SSL/TLS connection (SMTPS) for port 465
- EncryptionNone: Plain SMTP without encryption (NOT recommended for production)
Example with explicit encryption:
config := smtp.Config{
Host: "smtp.gmail.com",
Port: 587,
Username: "user@gmail.com",
Password: "app-password",
From: "user@gmail.com",
EncryptionType: smtp.EncryptionTLS, // Explicit STARTTLS
TLSMinVersion: tls.VersionTLS12, // Enforce TLS 1.2+
}
For legacy SMTPS (port 465):
config := smtp.Config{
Host: "smtp.example.com",
Port: 465,
Username: "user@example.com",
Password: "password",
From: "user@example.com",
EncryptionType: smtp.EncryptionSSL, // Direct SSL/TLS
}
Custom CA Certificates (v1.0.0+) ¶
For internal or private SMTP servers with custom CA certificates:
import (
"crypto/tls"
"os"
)
// Load custom CA certificate
caCert, err := os.ReadFile("/path/to/ca-cert.pem")
if err != nil {
log.Fatal(err)
}
config := smtp.Config{
Host: "mail.internal.company.com",
Port: 587,
Username: "user@company.com",
Password: "password",
From: "user@company.com",
EncryptionType: smtp.EncryptionTLS,
TLSMinVersion: tls.VersionTLS12,
CustomCACert: caCert, // Add custom CA
}
Configuration Validation (v1.0.0+) ¶
Validate configuration before using it:
if err := smtp.ValidateConfig(&config); err != nil {
log.Fatalf("Invalid SMTP configuration: %v", err)
}
Test SMTP connection without sending email:
provider := smtp.New(&config)
if err := provider.TestConnection(ctx); err != nil {
log.Fatalf("SMTP connection test failed: %v", err)
}
Send test email to verify full configuration:
if err := provider.TestSend(ctx); err != nil {
log.Fatalf("Test email failed: %v", err)
}
Basic Usage ¶
Create a provider and use it with the gomail client:
import (
"github.com/ftrinciante/gomail"
"github.com/ftrinciante/gomail/provider/smtp"
)
// Create SMTP provider
provider := smtp.New(&config)
// Create email client
client := gomail.NewClient(provider)
// Send email
err := client.Send(ctx, &gomail.Message{
To: []string{"recipient@example.com"},
Subject: "Hello from gomail!",
Body: "This is a test email.",
IsHTML: false,
})
Port Selection ¶
Choose the appropriate port based on your SMTP server:
- Port 587 (STARTTLS) - Recommended for modern servers (EncryptionTLS)
- Port 465 (SSL/TLS) - Direct TLS connection (EncryptionSSL)
- Port 25 (Plain SMTP) - Unencrypted, avoid in production (EncryptionNone)
- Port 2525 (Alternative) - Used by SendGrid, Mailgun with TLS
Backward Compatibility ¶
The UseTLS field is deprecated but still supported for backward compatibility. It automatically maps to EncryptionType:
- UseTLS=true → EncryptionTLS (STARTTLS)
- UseTLS=false → EncryptionNone (Plain SMTP)
New code should use EncryptionType explicitly:
// Old style (still works)
config := smtp.Config{
Host: "smtp.gmail.com",
Port: 587,
UseTLS: true, // Deprecated
}
// New style (v1.0.0+)
config := smtp.Config{
Host: "smtp.gmail.com",
Port: 587,
EncryptionType: smtp.EncryptionTLS, // Explicit
TLSMinVersion: tls.VersionTLS12, // Enforce TLS 1.2+
}
Provider-Specific Setup ¶
Gmail:
- Requires App Password (2FA must be enabled first)
- See: https://support.google.com/accounts/answer/185833
- Host: smtp.gmail.com, Port: 587, UseTLS: true
Outlook/Microsoft 365:
- Host: smtp-mail.outlook.com, Port: 587, UseTLS: true
- Use your email address as username
SendGrid:
- Host: smtp.sendgrid.net, Port: 587, UseTLS: true
- Username: "apikey" (literal string)
- Password: Your SendGrid API key
Office 365 (Business):
- Host: smtp.office365.com, Port: 587, UseTLS: true
Security ¶
Always use TLS (UseTLS: true) in production environments. Plain SMTP (port 25) transmits credentials and email content unencrypted and should only be used for internal/testing purposes.
Store credentials securely:
- Use environment variables for development
- Use Docker secrets for production deployment
- Encrypt passwords with AES-256-GCM before database storage
- Never commit credentials to version control
Advanced Configuration ¶
For self-signed certificates in testing environments (NOT recommended for production):
config := smtp.Config{
Host: "mail.internal.local",
Port: 587,
Username: "user@internal.local",
Password: "password",
From: "noreply@internal.local",
EncryptionType: smtp.EncryptionTLS,
InsecureSkipVerify: true, // Only for testing!
}
Error Handling ¶
The provider returns typed errors for better error handling:
err := client.Send(ctx, msg)
if err != nil {
if sendErr, ok := err.(*gomail.SendError); ok {
log.Printf("Provider: %s, Error: %v", sendErr.Provider, sendErr.Err)
}
}
Common errors:
- Authentication failed: Check username and password
- Connection refused: Check host and port, verify firewall settings
- TLS handshake failed: Verify UseTLS setting matches server requirements
- No from address: Set From in EncryptionType setting matches server requirements
- Certificate verification failed: Use CustomCACert for private servers or InsecureSkipVerify for testing
Performance Considerations ¶
The SMTP provider creates a new connection for each email. For high-volume sending, consider:
- Using the queue (v0.2.0) for async sending with retries
- Implementing connection pooling (planned for v1.x)
- Using a specialized provider (SendGrid, SES) for bulk operations
Testing ¶
Use a local SMTP server for testing without sending real emails:
// MailHog (Docker)
// docker run -p 1025:1025 -p 8025:8025 mailhog/mailhog
config := smtp "localhost",
Port: 1025,
Username: "", // No auth needed for MailHog
Password: "",
From: "test@example.com",
EncryptionType: smtp.EncryptionNone, // MailHog doesn't require TLS
}
View sent emails at http://localhost:8025
Related Packages ¶
- github.com/ftrinciante/gomail - Core email client
- github.com/ftrinciante/gomail/provider/sendgrid - SendGrid API provider
- github.com/ftrinciante/gomail/provider/ses - AWS SES provider
- github.com/ftrinciante/gomail/queue/redis - Redis queue for async sending
- github.com/ftrinciante/gomail/receiver/imap - IMAP email receiveranned)
- github.com/ftrinciante/gomail/provider/ses - AWS SES provider (planned)
Examples ¶
See examples/basic for a complete working example.
Example ¶
Example demonstrates basic SMTP provider configuration.
package main
import (
"context"
"fmt"
"log"
"github.com/ftrinciante/gomail"
"github.com/ftrinciante/gomail/provider/smtp"
)
func main() {
// Basic SMTP configuration
config := smtp.Config{
Host: "smtp.example.com",
Port: 587,
Username: "user@example.com",
Password: "your-password",
From: "sender@example.com",
UseTLS: true,
}
// Create provider
provider := smtp.New(&config)
// Create client
client := gomail.NewClient(provider)
defer client.Close()
// Send email
msg := &gomail.Message{
To: []string{"recipient@example.com"},
Subject: "SMTP Provider Example",
Body: "Sent via SMTP provider.",
IsHTML: false,
}
err := client.Send(context.Background(), msg)
if err != nil {
log.Fatalf("Failed to send: %v", err)
}
fmt.Println("Email sent via SMTP")
}
Output:
Example (CustomCA) ¶
Example_customCA demonstrates using custom CA certificates (v1.0.0+).
package main
import (
"context"
"crypto/tls"
"fmt"
"log"
"os"
"github.com/ftrinciante/gomail"
"github.com/ftrinciante/gomail/provider/smtp"
)
func main() {
// Load custom CA certificate for internal SMTP server
caCert, err := os.ReadFile("/path/to/ca-cert.pem")
if err != nil {
log.Fatalf("Failed to load CA certificate: %v", err)
}
config := smtp.Config{
Host: "mail.internal.company.com",
Port: 587,
Username: "user@company.com",
Password: "your-password",
From: "user@company.com",
EncryptionType: smtp.EncryptionTLS,
TLSMinVersion: tls.VersionTLS12,
CustomCACert: caCert, // Custom CA certificate
}
provider := smtp.New(&config)
client := gomail.NewClient(provider)
defer client.Close()
msg := &gomail.Message{
To: []string{"recipient@company.com"},
Subject: "Email from Internal Server",
Body: "This email uses a custom CA certificate for internal SMTP.",
IsHTML: false,
}
err = client.Send(context.Background(), msg)
if err != nil {
log.Fatalf("Failed to send: %v", err)
}
fmt.Println("Email sent with custom CA")
}
Output:
Example (CustomPort) ¶
Example_customPort demonstrates using custom SMTP ports.
package main
import (
"context"
"fmt"
"log"
"github.com/ftrinciante/gomail"
"github.com/ftrinciante/gomail/provider/smtp"
)
func main() {
// Custom port configuration (e.g., port 465 for SSL)
config := smtp.Config{
Host: "smtp.example.com",
Port: 465, // SSL port
Username: "user@example.com",
Password: "your-password",
From: "sender@example.com",
UseTLS: false, // Direct SSL, not STARTTLS
}
provider := smtp.New(&config)
client := gomail.NewClient(provider)
defer client.Close()
msg := &gomail.Message{
To: []string{"recipient@example.com"},
Subject: "Custom Port Example",
Body: "Sent via custom SMTP port.",
IsHTML: false,
}
err := client.Send(context.Background(), msg)
if err != nil {
log.Fatalf("Failed to send via custom port: %v", err)
}
fmt.Println("Email sent via custom port")
}
Output:
Example (EncryptionSSL) ¶
Example_encryptionSSL demonstrates direct SSL/TLS connection (v1.0.0+).
package main
import (
"context"
"crypto/tls"
"fmt"
"log"
"github.com/ftrinciante/gomail"
"github.com/ftrinciante/gomail/provider/smtp"
)
func main() {
// Direct SSL/TLS (SMTPS) configuration for port 465
config := smtp.Config{
Host: "smtp.example.com",
Port: 465,
Username: "user@example.com",
Password: "your-password",
From: "user@example.com",
EncryptionType: smtp.EncryptionSSL, // Direct SSL/TLS
TLSMinVersion: tls.VersionTLS12,
}
provider := smtp.New(&config)
client := gomail.NewClient(provider)
defer client.Close()
msg := &gomail.Message{
To: []string{"recipient@example.com"},
Subject: "Secure Email with SSL/TLS",
Body: "This email uses direct SSL/TLS connection (SMTPS).",
IsHTML: false,
}
err := client.Send(context.Background(), msg)
if err != nil {
log.Fatalf("Failed to send: %v", err)
}
fmt.Println("Email sent with SSL/TLS")
}
Output:
Example (EncryptionTLS) ¶
Example_encryptionTLS demonstrates explicit STARTTLS encryption (v1.0.0+).
package main
import (
"context"
"crypto/tls"
"fmt"
"log"
"github.com/ftrinciante/gomail"
"github.com/ftrinciante/gomail/provider/smtp"
)
func main() {
// Explicit STARTTLS configuration (recommended)
config := smtp.Config{
Host: "smtp.gmail.com",
Port: 587,
Username: "your-email@gmail.com",
Password: "your-app-password",
From: "your-email@gmail.com",
EncryptionType: smtp.EncryptionTLS, // Explicit STARTTLS
TLSMinVersion: tls.VersionTLS12, // Enforce TLS 1.2+
}
provider := smtp.New(&config)
client := gomail.NewClient(provider)
defer client.Close()
msg := &gomail.Message{
To: []string{"recipient@example.com"},
Subject: "Secure Email with STARTTLS",
Body: "This email uses explicit STARTTLS encryption with TLS 1.2+.",
IsHTML: false,
}
err := client.Send(context.Background(), msg)
if err != nil {
log.Fatalf("Failed to send: %v", err)
}
fmt.Println("Email sent with STARTTLS")
}
Output:
Example (Gmail) ¶
Example_gmail demonstrates Gmail SMTP configuration.
package main
import (
"context"
"fmt"
"log"
"github.com/ftrinciante/gomail"
"github.com/ftrinciante/gomail/provider/smtp"
)
func main() {
// Gmail SMTP configuration
// Note: Use App Password, not your regular Gmail password
// Generate at: https://myaccount.google.com/apppasswords
config := smtp.Config{
Host: "smtp.gmail.com",
Port: 587,
Username: "your-email@gmail.com",
Password: "your-app-password", // 16-character app password
From: "your-email@gmail.com",
UseTLS: true,
}
provider := smtp.New(&config)
client := gomail.NewClient(provider)
defer client.Close()
msg := &gomail.Message{
To: []string{"recipient@example.com"},
Subject: "Hello from Gmail",
Body: "This email was sent via Gmail SMTP.",
IsHTML: false,
}
err := client.Send(context.Background(), msg)
if err != nil {
log.Fatalf("Failed to send via Gmail: %v", err)
}
fmt.Println("Email sent via Gmail SMTP")
}
Output:
Example (Office365) ¶
Example_office365 demonstrates Office 365 SMTP configuration.
package main
import (
"context"
"fmt"
"log"
"github.com/ftrinciante/gomail"
"github.com/ftrinciante/gomail/provider/smtp"
)
func main() {
// Office 365 SMTP configuration
config := smtp.Config{
Host: "smtp.office365.com",
Port: 587,
Username: "your-email@yourdomain.com",
Password: "your-password",
From: "your-email@yourdomain.com",
UseTLS: true,
}
provider := smtp.New(&config)
client := gomail.NewClient(provider)
defer client.Close()
msg := &gomail.Message{
To: []string{"recipient@example.com"},
Subject: "Hello from Office 365",
Body: "This email was sent via Office 365 SMTP.",
IsHTML: false,
}
err := client.Send(context.Background(), msg)
if err != nil {
log.Fatalf("Failed to send via Office 365: %v", err)
}
fmt.Println("Email sent via Office 365 SMTP")
}
Output:
Example (Outlook) ¶
Example_outlook demonstrates Outlook/Hotmail SMTP configuration.
package main
import (
"context"
"fmt"
"log"
"github.com/ftrinciante/gomail"
"github.com/ftrinciante/gomail/provider/smtp"
)
func main() {
// Outlook.com / Hotmail.com SMTP configuration
config := smtp.Config{
Host: "smtp-mail.outlook.com",
Port: 587,
Username: "your-email@outlook.com",
Password: "your-password",
From: "your-email@outlook.com",
UseTLS: true,
}
provider := smtp.New(&config)
client := gomail.NewClient(provider)
defer client.Close()
msg := &gomail.Message{
To: []string{"recipient@example.com"},
Subject: "Hello from Outlook",
Body: "This email was sent via Outlook SMTP.",
IsHTML: false,
}
err := client.Send(context.Background(), msg)
if err != nil {
log.Fatalf("Failed to send via Outlook: %v", err)
}
fmt.Println("Email sent via Outlook SMTP")
}
Output:
Example (PersonalServer) ¶
Example_personalServer demonstrates configuration for personal/self-hosted SMTP servers.
package main
import (
"context"
"fmt"
"log"
"github.com/ftrinciante/gomail"
"github.com/ftrinciante/gomail/provider/smtp"
)
func main() {
// Personal SMTP server configuration
config := smtp.Config{
Host: "mail.yourdomain.com",
Port: 587,
Username: "admin@yourdomain.com",
Password: "your-password",
From: "noreply@yourdomain.com",
UseTLS: true,
}
provider := smtp.New(&config)
client := gomail.NewClient(provider)
defer client.Close()
msg := &gomail.Message{
To: []string{"recipient@example.com"},
Subject: "From Personal Server",
Body: "This email was sent from a personal SMTP server.",
IsHTML: false,
}
err := client.Send(context.Background(), msg)
if err != nil {
log.Fatalf("Failed to send from personal server: %v", err)
}
fmt.Println("Email sent from personal server")
}
Output:
Example (Sendgrid) ¶
Example_sendgrid demonstrates SendGrid SMTP relay configuration.
package main
import (
"context"
"fmt"
"log"
"github.com/ftrinciante/gomail"
"github.com/ftrinciante/gomail/provider/smtp"
)
func main() {
// SendGrid SMTP configuration
// Get API key from: https://app.sendgrid.com/settings/api_keys
config := smtp.Config{
Host: "smtp.sendgrid.net",
Port: 587,
Username: "apikey", // Literal string "apikey"
Password: "SG.your-api-key-here",
From: "verified-sender@yourdomain.com",
UseTLS: true,
}
provider := smtp.New(&config)
client := gomail.NewClient(provider)
defer client.Close()
msg := &gomail.Message{
To: []string{"recipient@example.com"},
Subject: "Hello from SendGrid",
Body: "This email was sent via SendGrid SMTP relay.",
IsHTML: false,
}
err := client.Send(context.Background(), msg)
if err != nil {
log.Fatalf("Failed to send via SendGrid: %v", err)
}
fmt.Println("Email sent via SendGrid SMTP")
}
Output:
Example (TestConnection) ¶
Example_testConnection demonstrates testing SMTP connection (v1.0.0+).
package main
import (
"context"
"fmt"
"log"
"github.com/ftrinciante/gomail/provider/smtp"
)
func main() {
config := smtp.Config{
Host: "smtp.gmail.com",
Port: 587,
Username: "user@gmail.com",
Password: "app-password",
From: "user@gmail.com",
EncryptionType: smtp.EncryptionTLS,
}
provider := smtp.New(&config)
// Test connection without sending email
ctx := context.Background()
if err := provider.TestConnection(ctx); err != nil {
log.Fatalf("Connection test failed: %v", err)
}
fmt.Println("SMTP connection successful")
}
Output:
Example (TestSend) ¶
Example_testSend demonstrates sending a test email (v1.0.0+).
package main
import (
"context"
"fmt"
"log"
"github.com/ftrinciante/gomail/provider/smtp"
)
func main() {
config := smtp.Config{
Host: "smtp.gmail.com",
Port: 587,
Username: "user@gmail.com",
Password: "app-password",
From: "user@gmail.com",
EncryptionType: smtp.EncryptionTLS,
}
provider := smtp.New(&config)
// Send test email to verify full configuration
ctx := context.Background()
if err := provider.TestSend(ctx); err != nil {
log.Fatalf("Test email failed: %v", err)
}
fmt.Println("Test email sent successfully")
}
Output:
Example (Tls) ¶
Example_tls demonstrates TLS configuration options.
package main
import (
"context"
"fmt"
"log"
"github.com/ftrinciante/gomail"
"github.com/ftrinciante/gomail/provider/smtp"
)
func main() {
// TLS configuration with STARTTLS
config := smtp.Config{
Host: "smtp.example.com",
Port: 587,
Username: "user@example.com",
Password: "your-password",
From: "sender@example.com",
UseTLS: true,
InsecureSkipVerify: false, // Verify TLS certificates (production)
}
provider := smtp.New(&config)
client := gomail.NewClient(provider)
defer client.Close()
msg := &gomail.Message{
To: []string{"recipient@example.com"},
Subject: "Secure Email",
Body: "This email was sent with TLS encryption.",
IsHTML: false,
}
err := client.Send(context.Background(), msg)
if err != nil {
log.Fatalf("Failed to send with TLS: %v", err)
}
fmt.Println("Email sent with TLS")
}
Output:
Example (TlsVersion) ¶
Example_tlsVersion demonstrates enforcing specific TLS versions (v1.0.0+).
package main
import (
"context"
"crypto/tls"
"fmt"
"log"
"github.com/ftrinciante/gomail"
"github.com/ftrinciante/gomail/provider/smtp"
)
func main() {
// Enforce TLS 1.3 for maximum security
config := smtp.Config{
Host: "smtp.example.com",
Port: 587,
Username: "user@example.com",
Password: "your-password",
From: "user@example.com",
EncryptionType: smtp.EncryptionTLS,
TLSMinVersion: tls.VersionTLS13, // Require TLS 1.3
}
provider := smtp.New(&config)
client := gomail.NewClient(provider)
defer client.Close()
msg := &gomail.Message{
To: []string{"recipient@example.com"},
Subject: "Maximum Security",
Body: "This email requires TLS 1.3 or higher.",
IsHTML: false,
}
err := client.Send(context.Background(), msg)
if err != nil {
log.Fatalf("Failed to send: %v", err)
}
fmt.Println("Email sent with TLS 1.3")
}
Output:
Example (ValidateConfig) ¶
Example_validateConfig demonstrates configuration validation (v1.0.0+).
package main
import (
"fmt"
"log"
"github.com/ftrinciante/gomail/provider/smtp"
)
func main() {
config := smtp.Config{
Host: "smtp.gmail.com",
Port: 587,
Username: "user@gmail.com",
Password: "app-password",
From: "user@gmail.com",
EncryptionType: smtp.EncryptionTLS,
}
// Validate configuration before using
if err := smtp.ValidateConfig(&config); err != nil {
log.Fatalf("Invalid configuration: %v", err)
}
fmt.Println("Configuration is valid")
}
Output: Configuration is valid
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ValidateConfig ¶
ValidateConfig validates the SMTP configuration. Returns nil if valid, or an error describing the validation failure.
Types ¶
type Config ¶
type Config struct {
Host string
Username string
Password string
From string
EncryptionType EncryptionType
CustomCACert []byte
Port int
TLSMinVersion uint16
UseTLS bool
InsecureSkipVerify bool
}
Config holds the SMTP server configuration.
type EncryptionType ¶
type EncryptionType string
EncryptionType specifies the SMTP connection encryption method.
const ( // EncryptionTLS uses STARTTLS (SMTP over TLS) - recommended for port 587 EncryptionTLS EncryptionType = "tls" // EncryptionSSL uses direct SSL/TLS connection (SMTPS) - for port 465 EncryptionSSL EncryptionType = "ssl" // EncryptionNone uses plain SMTP without encryption - NOT recommended for production EncryptionNone EncryptionType = "none" )
type Provider ¶
type Provider struct {
// contains filtered or unexported fields
}
Provider is the SMTP email provider implementation.
func (*Provider) TestConnection ¶
TestConnection tests the SMTP connection without sending an email. This performs a connection test and returns any errors encountered.