any_logger_email 1.0.5
any_logger_email: ^1.0.5 copied to clipboard
Email appender for any_logger with SMTP support, batching, HTML formatting, and rate limiting. Works with Gmail, Office 365, SendGrid, and more.
Any Logger Email #
An email appender extension for Any Logger that enables sending log notifications via SMTP to any email address. Perfect for critical error alerts, daily digests, system monitoring, and production incident notifications.
Features #
- Universal SMTP Support - Works with any SMTP server including Gmail, Office 365, SendGrid, and more
- Smart Batching - Automatically batches logs to reduce email volume
- Rate Limiting - Prevents email flooding with configurable limits
- HTML & Plain Text - Beautiful HTML emails with fallback to plain text
- Priority Alerts - Immediate sending for critical errors
- Multiple Recipients - Support for TO, CC, and BCC recipients
- Flexible Templates - Customizable email templates or use built-in formats
- Service Presets - Pre-configured settings for popular email services
Installation #
dependencies:
any_logger: ^x.y.z
any_logger_email: ^x.y.z // See Installing
To register the EMAIL appender you have to import the library
import 'package:any_logger/any_logger.dart';
import 'package:any_logger_email/any_logger_email.dart';
and call:
AnyLoggerEmailExtension.register();
Quick Start #
Simple Setup with Gmail #
await LoggerFactory.builder()
.console(level: Level.INFO)
.gmail(
username: '[email protected]',
appPassword: 'your-app-password', // Use App Password, not regular password
toEmails: ['[email protected]'],
level: Level.ERROR,
)
.build();
Logger.info('This only goes to console');
Logger.error('This triggers an email alert!');
Custom SMTP Server #
await LoggerFactory.builder()
.email(
smtpHost: 'smtp.company.com',
smtpPort: 587,
fromEmail: '[email protected]',
toEmails: ['[email protected]'],
username: '[email protected]',
password: 'secure_password',
level: Level.ERROR,
sendAsHtml: true,
)
.build();
Email Service Configuration #
Gmail #
final appender = await emailAppenderBuilder()
.withGmailPreset('[email protected]', 'app-password')
.withTo(['[email protected]'])
.withLevel(Level.ERROR)
.build();
Important: Use an App Password for Gmail, not your regular password.
Office 365 / Outlook #
final appender = await emailAppenderBuilder()
.withOffice365Preset('[email protected]', 'password')
.withTo(['[email protected]'])
.withLevel(Level.ERROR)
.build();
SendGrid #
final appender = await emailAppenderBuilder()
.withSendGridPreset('your-sendgrid-api-key')
.withFrom('[email protected]')
.withTo(['[email protected]'])
.build();
Custom SMTP #
final appender = await emailAppenderBuilder()
.withSmtp('mail.server.com', 465, ssl: true)
.withCredentials('username', 'password')
.withFrom('[email protected]', 'System Logger')
.withTo(['[email protected]'])
.build();
Configuration Options #
Using Builder Pattern #
final appender = await emailAppenderBuilder()
.withSmtp('smtp.example.com', 587)
.withCredentials('user', 'pass')
.withFrom('[email protected]', 'My App')
.withTo(['[email protected]', '[email protected]'])
.withCc(['[email protected]'])
.withBcc(['[email protected]'])
.withReplyTo('[email protected]')
.withSubjectPrefix('[PRODUCTION]')
.withLevel(Level.ERROR)
.withBatchSize(10)
.withBatchIntervalMinutes(5)
.withRateLimit(20) // Max 20 emails per hour
.withHtmlFormat(true)
.withStackTraces(true)
.withMetadata(true)
.withGroupByLevel(true)
.withImmediateErrors(true)
.withErrorThreshold(3)
.build();
Using Configuration Map #
final config = {
'appenders': [
{
'type': 'EMAIL',
'smtpHost': 'smtp.example.com',
'smtpPort': 587,
'ssl': false,
'fromEmail': '[email protected]',
'fromName': 'App Logger',
'toEmails': ['[email protected]', '[email protected]'],
'ccEmails': ['[email protected]'],
'username': '[email protected]',
'password': 'secure_password',
'level': 'ERROR',
'subjectPrefix': '[APP ERROR]',
'batchSize': 25,
'batchIntervalMinutes': 10,
'maxEmailsPerHour': 30,
'sendAsHtml': true,
'includeStackTrace': true,
'includeMetadata': true,
'groupByLevel': true,
'sendImmediatelyOnError': true,
'immediateErrorThreshold': 5,
}
]
};
await LoggerFactory.init(config);
Configuration Parameters #
| Parameter | Type | Default | Description |
|---|---|---|---|
smtpHost |
String | Required | SMTP server hostname |
smtpPort |
int | Required | SMTP server port (25, 465, 587, etc.) |
ssl |
bool | false | Use SSL/TLS encryption |
allowInsecure |
bool | false | Allow insecure connections |
ignoreBadCertificate |
bool | false | Ignore certificate errors |
fromEmail |
String | Required | Sender email address |
fromName |
String | null | Sender display name |
toEmails |
List/String | Required | Recipient email(s) |
ccEmails |
List/String | [] | CC recipients |
bccEmails |
List/String | [] | BCC recipients |
replyTo |
String | null | Reply-to address |
username |
String | null | SMTP username |
password |
String | null | SMTP password |
level |
Level | ERROR | Minimum log level to email |
subjectPrefix |
String | '[LOG]' | Email subject prefix |
includeHostname |
bool | true | Include hostname in emails |
includeAppInfo |
bool | true | Include app version/device ID |
batchSize |
int | 50 | Logs per batch |
batchIntervalMinutes |
int | 5 | Minutes before sending partial batch |
maxEmailsPerHour |
int | 20 | Rate limit per hour |
sendAsHtml |
bool | true | Send HTML formatted emails |
includeStackTrace |
bool | true | Include stack traces |
includeMetadata |
bool | true | Include metadata |
groupByLevel |
bool | true | Group logs by level in email |
sendImmediatelyOnError |
bool | true | Send immediately on errors |
immediateErrorThreshold |
int | 10 | Error count to trigger immediate send |
Email Format Examples #
HTML Email (Default) #
The appender sends beautifully formatted HTML emails with:
- Color-coded log levels
- Grouped sections by severity
- Syntax-highlighted stack traces
- Metadata header with system info
- Responsive design for mobile
Plain Text Email #
For systems that require plain text:
.withHtmlFormat(false)
Produces clean, readable plain text emails with proper formatting.
Presets #
Critical Alert Preset #
final appender = await emailAppenderBuilder()
.withSmtp('smtp.example.com', 587)
.withFrom('[email protected]')
.withTo(['[email protected]'])
.withCriticalAlertPreset()
.build();
// Configures:
// - Level: ERROR
// - Batch size: 5
// - Interval: 1 minute
// - Immediate sending on first error
// - Include full stack traces
// - Subject: [CRITICAL ALERT]
Daily Digest Preset #
final appender = await emailAppenderBuilder()
.withSmtp('smtp.example.com', 587)
.withFrom('[email protected]')
.withTo(['[email protected]'])
.withDailyDigestPreset()
.build();
// Configures:
// - Level: INFO
// - Batch size: 1000
// - Interval: 24 hours
// - No immediate sending
// - Group by level
// - No stack traces (summary only)
Development Preset #
final appender = await emailAppenderBuilder()
.withSmtp('smtp.example.com', 587)
.withFrom('[email protected]')
.withTo(['[email protected]'])
.withDevelopmentPreset()
.build();
// Configures:
// - Level: DEBUG
// - Batch size: 20
// - Interval: 5 minutes
// - Include everything for debugging
Use Cases #
Production Error Monitoring #
await LoggerFactory.builder()
.file(filePattern: 'app', level: Level.INFO) // Log everything to file
.email(
smtpHost: 'smtp.sendgrid.net',
smtpPort: 587,
fromEmail: '[email protected]',
toEmails: ['[email protected]'],
username: 'apikey',
password: process.env['SENDGRID_API_KEY'],
level: Level.ERROR,
subjectPrefix: '[PROD ERROR]',
batchSize: 5,
sendImmediatelyOnError: true,
)
.build();
Daily Summary Reports #
await LoggerFactory.builder()
.console(level: Level.INFO)
.email(
smtpHost: 'smtp.gmail.com',
smtpPort: 587,
fromEmail: '[email protected]',
toEmails: ['[email protected]'],
username: '[email protected]',
password: 'app-password',
level: Level.INFO,
subjectPrefix: '[Daily Report]',
batchSize: 1000,
batchIntervalMinutes: 1440, // 24 hours
sendImmediatelyOnError: false,
groupByLevel: true,
includeStackTrace: false,
)
.build();
Critical System Alerts #
// Send to multiple channels for critical issues
await LoggerFactory.builder()
.email(
smtpHost: 'smtp.example.com',
smtpPort: 587,
fromEmail: '[email protected]',
toEmails: [
'[email protected]',
'[email protected]', // SMS via email gateway
],
level: Level.ERROR,
subjectPrefix: '🚨 CRITICAL',
batchSize: 1, // Send immediately
maxEmailsPerHour: 100, // Allow more for critical
)
.build();
Development Debugging #
await LoggerFactory.builder()
.console(level: Level.DEBUG)
.gmail(
username: '[email protected]',
appPassword: 'app-password',
toEmails: ['[email protected]'],
level: Level.ERROR,
subjectPrefix: '[DEV ERROR]',
sendAsHtml: true,
includeStackTrace: true,
)
.build();
Best Practices #
1. Use App Passwords #
For Gmail and other services with 2FA, always use app-specific passwords:
- Gmail: Create App Password
- Outlook: App passwords in Microsoft 365
2. Configure Rate Limits #
Prevent email flooding:
.withRateLimit(20) // Max 20 emails per hour
.withBatchSize(50) // Batch up to 50 logs
.withBatchIntervalMinutes(10) // Send every 10 minutes
3. Set Appropriate Thresholds #
// For critical systems
.withLevel(Level.ERROR)
.withImmediateErrors(true)
.withErrorThreshold(1) // Send on first error
// For development
.withLevel(Level.WARN)
.withErrorThreshold(10) // Batch warnings
4. Use Different Recipients for Different Levels #
// Critical errors to on-call
await LoggerFactory.builder()
.email(
// ... config
toEmails: ['[email protected]'],
level: Level.ERROR,
subjectPrefix: '[CRITICAL]',
)
// Daily digest to management
.email(
// ... config
toEmails: ['[email protected]'],
level: Level.INFO,
subjectPrefix: '[DAILY]',
batchIntervalMinutes: 1440,
)
.build();
5. Include Context in Subject #
final hostname = Platform.localHostname;
.withSubjectPrefix('[$hostname ERROR]')
Troubleshooting #
Emails Not Being Sent #
- Check SMTP credentials: Verify username/password are correct
- Check firewall: Ensure SMTP ports (25, 465, 587) are open
- Enable less secure apps: Some providers require this setting
- Use app passwords: For accounts with 2FA enabled
- Check rate limits: You may have hit the hourly limit
- Enable self-debugging:
await LoggerFactory.builder()
.email(/* config */)
.withSelfDebug(Level.DEBUG)
.build();
Gmail Specific Issues #
- Enable "Less secure app access" or use App Passwords
- Use port 587 (not 465) for TLS
- Ensure 2-factor authentication is properly configured
SSL/TLS Issues #
// For self-signed certificates
.withSmtp('smtp.internal.com', 465,
ssl: true,
ignoreBadCertificate: true)
High Memory Usage #
- Reduce
batchSizeto limit memory usage - Increase
batchIntervalMinutesfor less frequent sends - Disable
includeStackTracefor large volumes
Testing #
For unit tests, use test mode to avoid sending actual emails:
final appender = await emailAppenderBuilder()
.withSmtp('smtp.test.com', 587)
.withFrom('[email protected]')
.withTo(['[email protected]'])
.build(test: true); // No emails will be sent
Security Considerations #
- Never commit credentials: Use environment variables or secure vaults
- Use encrypted connections: Enable SSL/TLS when possible
- Rotate passwords regularly: Especially for production systems
- Limit recipient lists: Avoid exposing email addresses unnecessarily
- Sanitize log content: Be careful with sensitive data in logs
License #
MIT License - see LICENSE file for details.
Support #
- Main Package: any_logger
- Issues: GitHub Issues
- Examples: See
/examplefolder in the package
Part of the Any Logger ecosystem.
💚 Funding #
Happy Logging! 🎉