Introducing the Plunk Email Library for Dart Developers
For Dart and Flutter developers looking to integrate robust email capabilities into their applications look no further than this OSS.

Email remains one of the most effective channels for communicating with users, whether you’re sending transactional messages, marketing campaigns, or important notifications. For Dart and Flutter developers looking to integrate robust email capabilities into their applications, the Plunk library offers a comprehensive solution that’s easy to use and packed with features.
What is Plunk?
Plunk is an open source modern email platform backed by Amazon SES and designed specifically for SaaS applications. It provides powerful tools for sending transactional emails, managing contacts, and running email marketing campaigns. The plunk
package is a Dart client that makes it easy to integrate with the Plunk API in your Dart or Flutter applications.
In this article, we’ll explore how to use the Plunk library to add sophisticated email capabilities to your applications.
Getting Started with Plunk
Installation
To get started, add the Plunk package to your pubspec.yaml
file:
dependencies:
plunk: ^2.0.0
Run dart pub get
or flutter pub get
to install the package.
Basic Setup
Using Plunk starts with initializing the client with your API key:
import 'package:plunk/plunk.dart';
void main() {
final plunk = Plunk(apiKey: 'YOUR_API_KEY');
// Now you can use plunk to send emails, manage contacts, etc.
}
Note: You’ll need to sign up for a Plunk account at useplunk.com to get an API key.
Sending Your First Email
Let’s start with the most common task: sending a transactional email:
Future<void> sendWelcomeEmail(String userEmail, String userName) async {
final plunk = Plunk(apiKey: 'YOUR_API_KEY');
try {
final response = await plunk.sendEmail(
to: [userEmail],
subject: 'Welcome to Our App!',
body: 'Hi $userName, thanks for signing up!',
subscribed: true, // Add the user to your contact list
);
print('Email sent successfully: ${response.success}');
} catch (e) {
print('Failed to send email: $e');
}
}
This simple example demonstrates how easy it is to send an email using Plunk. The sendEmail
method returns a SendResponse
object that contains information about the sent email, including whether it was successful and timestamps.
Core Features of the Plunk Library
The Plunk library offers a rich set of features for managing your email communications. Let’s dive into the key capabilities:
Contact Management
Plunk allows you to manage your contacts programmatically:
Creating Contacts
You can create contacts without sending them an email:
Future<void> addUserToContacts(String email, Map<String, dynamic> userData) async {
final plunk = Plunk(apiKey: 'YOUR_API_KEY');
final contact = await plunk.createContact(
email: email,
subscribed: true,
data: userData, // Custom data about your user
);
print('Contact created with ID: ${contact.id}');
}
Retrieving Contact Information
You can fetch details about a specific contact:
Future<void> getContactDetails(String contactId) async {
final plunk = Plunk(apiKey: 'YOUR_API_KEY');
final contact = await plunk.getContact(id: contactId);
print('Contact details: ${contact.email}, Subscribed: ${contact.subscribed}');
print('Custom data: ${contact.data}');
}
Managing Subscriptions
Plunk makes it easy to manage subscription status:
// Subscribe a contact
await plunk.subscribeContact(email: 'user@example.com');
// Unsubscribe a contact
await plunk.unsubscribeContact(email: 'user@example.com');
Updating Contact Data
You can update a contact’s information:
await plunk.updateContact(
id: 'contact_id',
data: {
'plan': 'premium',
'lastLogin': DateTime.now().toIso8601String(),
},
);
Event Tracking
Plunk allows you to track user events, which can be used to trigger automated emails:
Future<void> trackPurchase(String userEmail, String productId, double amount) async {
final plunk = Plunk(apiKey: 'YOUR_API_KEY');
await plunk.trackEvent(
email: userEmail,
event: 'purchase',
data: {
'productId': productId,
'amount': amount,
'date': DateTime.now().toIso8601String(),
},
);
}
Campaign Management
For marketing emails, Plunk provides campaign management capabilities:
Creating a Campaign
Future<void> createNewsletterCampaign(String subject, String content, List<String> recipients) async {
final plunk = Plunk(apiKey: 'YOUR_API_KEY');
final campaign = await plunk.createCampaign(
subject: subject,
body: content,
recipients: recipients,
style: CampaignStyle.html, // Use HTML formatting
);
print('Campaign created with ID: ${campaign.id}');
}
Sending a Campaign
Future<void> sendCampaign(String campaignId) async {
final plunk = Plunk(apiKey: 'YOUR_API_KEY');
final result = await plunk.sendCampaign(
id: campaignId,
live: true, // Set to false for testing
);
if (result) {
print('Campaign sent successfully');
}
}
Advanced Usage
Error Handling
Plunk provides specific exception types to help you handle errors appropriately:
try {
await plunk.sendEmail(
to: ['invalid-email'],
subject: 'Test',
body: 'Test body',
);
} catch (e) {
if (e is PlunkInvalidRequestException) {
print('Invalid request: ${e.message}');
} else if (e is PlunkAuthorizationException) {
print('Authorization error: ${e.message}');
} else if (e is PlunkQuotaException) {
print('Quota exceeded: ${e.message}');
} else if (e is PlunkUnknownException) {
print('Unknown error: ${e.message}');
}
}
Customizing Email Headers
You can customize the email headers for more control:
await plunk.sendEmail(
to: ['user@example.com'],
subject: 'Important notification',
body: 'Your account has been updated',
from: 'support@yourdomain.com',
name: 'Your App Support',
reply: 'no-reply@yourdomain.com',
headers: {
'X-Custom-Header': 'custom-value',
'X-Priority': '1',
},
);
Real-World Examples
Let’s explore a few real-world examples to demonstrate how Plunk can be integrated into your application workflows:
Example 1: User Registration Flow
Future<void> registerUser(String email, String name, String password) async {
final plunk = Plunk(apiKey: 'YOUR_API_KEY');
// 1. Create user in your database
final user = await createUserInDatabase(email, name, password);
// 2. Add user to Plunk contacts
await plunk.createContact(
email: email,
subscribed: true,
data: {
'name': name,
'registrationDate': DateTime.now().toIso8601String(),
},
);
// 3. Send welcome email
await plunk.sendEmail(
to: [email],
subject: 'Welcome to ${appName}!',
body: '''
<h1>Welcome, ${name}!</h1>
<p>Thank you for joining our platform. We're excited to have you!</p>
<p>Get started by <a href="https://yourapp.com/getting-started">exploring our features</a>.</p>
''',
name: appName,
);
// 4. Track signup event
await plunk.trackEvent(
email: email,
event: 'user_registered',
data: {
'userId': user.id,
},
);
}
Example 2: Password Reset Functionality
Future<void> initiatePasswordReset(String email) async {
final plunk = Plunk(apiKey: 'YOUR_API_KEY');
// 1. Generate reset token and store in your database
final resetToken = generateResetToken();
await storeResetTokenInDatabase(email, resetToken);
// 2. Create reset URL
final resetUrl = 'https://yourapp.com/reset-password?token=$resetToken';
// 3. Send password reset email
await plunk.sendEmail(
to: [email],
subject: 'Password Reset Request',
body: '''
<h2>Password Reset Request</h2>
<p>We received a request to reset your password. If you didn't make this request, you can ignore this email.</p>
<p>To reset your password, click the link below:</p>
<p><a href="$resetUrl">Reset Password</a></p>
<p>This link will expire in 1 hour.</p>
''',
);
// 4. Track password reset request event
await plunk.trackEvent(
email: email,
event: 'password_reset_requested',
);
}
Example 3: Campaign for New Features
Future<void> announceNewFeatures(List<String> premiumUserEmails) async {
final plunk = Plunk(apiKey: 'YOUR_API_KEY');
// 1. Create a campaign
final campaign = await plunk.createCampaign(
subject: 'Exciting New Features Just Released!',
body: '''
<h1>We've Added New Features You'll Love</h1>
<p>As a premium user, you now have access to:</p>
<ul>
<li>Advanced reporting</li>
<li>Custom integrations</li>
<li>Priority support</li>
</ul>
<p><a href="https://yourapp.com/new-features">Learn More</a></p>
''',
recipients: premiumUserEmails,
style: CampaignStyle.html,
);
// 2. Send the campaign
await plunk.sendCampaign(
id: campaign.id,
live: true,
delay: 3600, // Delay send by 1 hour
);
}
Best Practices
Managing API Keys Securely
Never hardcode your Plunk API key in your application. Instead:
— For server-side applications: Use environment variables
— For Flutter apps: Use secure storage or a backend proxy
// Example using environment variables
final apiKey = Platform.environment['PLUNK_API_KEY'] ?? '';
final plunk = Plunk(apiKey: apiKey);
Handling Rate Limits and Quotas
Plunk has rate limits and quotas based on your plan. Implement proper error handling:
try {
await plunk.sendEmail(/* ... */);
} catch (e) {
if (e is PlunkQuotaException) {
// Log the error and implement backoff strategy
await Future.delayed(Duration(minutes: 5));
// Try again or notify admin
}
}
Testing Email Functionality
For testing, you might want to create a mock implementation:
class MockPlunk implements Plunk {
@override
Future<SendResponse> sendEmail({
required List<String> to,
required String subject,
required String body,
bool subscribed = false,
String? name,
String? from,
String? reply,
Map<String, dynamic> headers = const {},
}) async {
// Return a mock response
return SendResponse(
success: true,
emails: [],
timestamp: DateTime.now(),
);
}
// Implement other methods...
}
Conclusion
The Plunk library offers Dart and Flutter developers a powerful way to integrate email functionality into their applications. With features for sending transactional emails, managing contacts, tracking events, and running campaigns, it provides everything you need for sophisticated email communications.
The library’s clean API makes it easy to get started, while its comprehensive feature set ensures it can grow with your application’s needs. Whether you’re building a small side project or a large-scale SaaS application, Plunk provides the tools you need to communicate effectively with your users.
Resources
— Plunk Official Website
— Plunk API Documentation
— Plunk Dart Package on pub.dev
— GitHub Repository
Start adding powerful email capabilities to your Dart and Flutter applications today with the Plunk library!