A reusable Flutter button and utility API that opens the user's default email client with a pre-filled feedback message.
- Pre-fills the recipient, subject, and optional email body.
- Optionally includes privacy-safe application, operating-system, device, and display diagnostics.
- Accepts application-specific diagnostic fields.
- Dart 3.7 or later.
- Flutter 3.29 or later.
- This package uses
package_info_plus8.3.1 through 8.x. - This package uses
device_info_plus11.3.3 through 11.x. - Android builds require API 19 or later, compile SDK 34, Java 17, Android Gradle Plugin 8.3 or later, and Gradle 8.4 or later.
- Apple builds require iOS 12 or later and macOS 10.14 or later.
import 'package:flutter/material.dart';
import 'package:send_email_feedback_button/send_email_feedback_button.dart';
class FeedbackButton extends StatelessWidget {
const FeedbackButton({super.key});
@override
Widget build(BuildContext context) {
return const SendEmailFeedbackButton(
emailAddress: 'support@example.com',
emailSubject: 'App feedback',
emailBody: 'Please describe the issue:',
includeRuntimeDiagnostics: true,
additionalDiagnostics: {
'Most recent error': 'FileSystemException',
'Publication mode': 'exclusive copy',
},
diagnosticsHeading: 'Diagnostics:',
);
}
}When runtime diagnostics are enabled, the package includes the application name, package identifier, version/build number, operating-system name and version, system locales, native process architecture, and a non-identifying device model where the platform provides one reliably. The widget also reports the resolved app locale, logical window size, and device pixel ratio from its own widget context.
The default diagnostics deliberately exclude CPU names, emulator status,
user-assigned device and host names, usernames, GUIDs, machine IDs, vendor
identifiers, and other unique identifiers. Values passed through
additionalDiagnostics are controlled entirely by the calling application.
If runtime metadata cannot be collected, the email launch is still attempted and the message reports that runtime diagnostics were unavailable.
Collecting runtime metadata can delay the launch by up to two seconds. The widget is disabled while a launch is in progress so repeated taps do not open multiple email composers. On web, a diagnostics-enabled launch uses the current browsing context because browsers may block a new window after an asynchronous metadata lookup.
For a custom button, call sendEmail directly:
final launchRequested = await sendEmail(
emailAddress: 'support@example.com',
emailSubject: 'App feedback',
emailBody: 'Please describe the issue:',
includeRuntimeDiagnostics: true,
diagnosticsContext: context,
additionalDiagnostics: {
'Current screen': 'Export',
},
);
if (!launchRequested) {
// Show an alternative contact method.
}Passing diagnosticsContext lets the utility report the locale resolved by the
nearest Flutter Localizations widget and metrics for the current view. It is
optional: calls without it still receive system locales and the other global
runtime diagnostics. This distinction matters when an app falls back to a
different language than the user's first system locale.
