I want to send an email directly from a flutter form. Which is the best option? This can't be difficult. The plugins always have errors and no direct.
There is no option to put a mailto and send the email?
Thanks
have you tried to use this package? https://pub.dev/packages/flutter_email_sender
This is a good email sender but this plugins redirects you to gmail app to send an actual email. It works.
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:flutter_email_sender/flutter_email_sender.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
// TODO: implement build
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Home(),
);
}
}
class Home extends StatefulWidget {
#override
State<StatefulWidget> createState() {
// TODO: implement createState
return _HomeState();
}
}
class _HomeState extends State<Home> {
var _emailFormKey = GlobalKey<FormState>();
TextEditingController emailController = new TextEditingController();
TextEditingController messageController = new TextEditingController();
#override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
resizeToAvoidBottomPadding: false,
appBar: AppBar(
title: Text("Email sending App"),
),
body: Form(
key: _emailFormKey,
child: Column(
children: <Widget>[
Container(
margin: EdgeInsets.only(top: 50.0, left: 15.0, right: 15.0),
child: TextFormField(
controller: emailController,
validator: (value){
if(value.isEmpty) {
return "please Enter email";
}
},
decoration: InputDecoration(
labelText: "Enter email",
border: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.red,
width: 2.0,
))),
),
),
Container(
margin: EdgeInsets.only(top: 15.0, left: 15.0, right: 15.0),
child: TextFormField(
controller: messageController,
validator: (value){
if(value.isEmpty) {
return "please Enter message";
}
},
decoration: InputDecoration(
labelText: "Enter Message",
border: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.red,
width: 2.0,
))),
),
),
Container(
margin: EdgeInsets.only(top: 15.0),
child: RaisedButton(child: Text("Send"), onPressed: (){
if(_emailFormKey.currentState.validate()){
sendMessage();
}
}),
)
],
),
),
);
}
void sendMessage(){
String inputEmail ;
String inputMessage;
Email email ;
setState(() {
inputEmail= emailController.text;
inputMessage = messageController.text;
if(inputMessage.isNotEmpty&&inputEmail.isNotEmpty) {
email = Email(
body: inputMessage,
subject: 'Email subject',
recipients: [inputEmail],
);
send(email);
}
});
debugPrint('email - > $inputEmail message -> $inputMessage');
}
void send(Email email) async {
await FlutterEmailSender.send(email);
}
}
// please add "flutter_email_sender:" plugin in pubspec.yaml file
Now I have this problem with the email sender:
flutter_email_sender does not specify a Swift version and none of the targets (Runner) integrating it have the
SWIFT_VERSION attribute set. Please contact the author or set the SWIFT_VERSION attribute in at least one of the
targets that integrate this pod.
/usr/local/Cellar/cocoapods/1.7.2/libexec/gems/cocoapods-1.7.2/lib/cocoapods/installer/xcode/target_validator.rb:122:in
verify_swift_pods_swift_version'
/usr/local/Cellar/cocoapods/1.7.2/libexec/gems/cocoapods-1.7.2/lib/cocoapods/installer/xcode/target_validator.rb:37:in
validate!'
/usr/local/Cellar/cocoapods/1.7.2/libexec/gems/cocoapods-1.7.2/lib/cocoapods/installer.rb:578:in validate_targets'
/usr/local/Cellar/cocoapods/1.7.2/libexec/gems/cocoapods-1.7.2/lib/cocoapods/installer.rb:158:ininstall!'
/usr/local/Cellar/cocoapods/1.7.2/libexec/gems/cocoapods-1.7.2/lib/cocoapods/command/install.rb:51:in run'
/usr/local/Cellar/cocoapods/1.7.2/libexec/gems/claide-1.0.2/lib/claide/command.rb:334:inrun'
/usr/local/Cellar/cocoapods/1.7.2/libexec/gems/cocoapods-1.7.2/lib/cocoapods/command.rb:52:in run'
/usr/local/Cellar/cocoapods/1.7.2/libexec/gems/cocoapods-1.7.2/bin/pod:55:in'
/usr/local/Cellar/cocoapods/1.7.2/libexec/bin/pod:22:in load'
/usr/local/Cellar/cocoapods/1.7.2/libexec/bin/pod:22:in'
Error output from CocoaPods:
↳
[!] Automatically assigning platform `ios` with version `8.0` on target `Runner` because no platform was specified. Please
specify a platform for this target in your Podfile. See `https://guides.cocoapods.org/syntax/podfile.html#platform`.
Related
I'am trying to do a mobile app which is about crypto currencies.
I want to make two TextFields like USDT and BTC, And they are supposed to work like:
Let me say that BTC is equal to 15$,
And USDT is equal to 1$,
Now those text fields should be editable. so if I write 1 on BTC textfield, USDT textfield should me edited as 15.
Also, when I write 30 on USDT textfield, BTC field should become 2. Moreover, while in this position, if I delete 0 from the usdt field, BTC should updated with "0.something" directly.
How can I do that?
Thanks for the replies !
I managed to do something like USDT is input, and BTC is output. However, I want to make them both input and output. Below are my classes, widgets and codes.
import 'package:cryptx/Constants/app_colors.dart';
import 'package:cryptx/Providers/basic_providers.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
class USDTInput extends ConsumerWidget {
const USDTInput({
Key? key,
}) : super(key: key);
#override
Widget build(BuildContext context, WidgetRef ref) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 12.0),
child: TextField(
decoration: InputDecoration(
icon: SizedBox(
height: 30,
child: Image.network(
"https://assets.coingecko.com/coins/images/325/small/Tether.png?1668148663")),
hintText: "USDT",
border: InputBorder.none,
),
onChanged: (value) {
ref
.read(usdProvider.notifier)
.update((state) => value != "" ? num.parse(value) : 0);
},
autocorrect: false,
keyboardType: const TextInputType.numberWithOptions(decimal: true),
),
);
}
}
import 'package:cryptx/Objects/coin.dart';
import 'package:cryptx/Providers/basic_providers.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
class CoinOutput extends ConsumerWidget {
const CoinOutput({super.key});
#override
Widget build(BuildContext context, WidgetRef ref) {
Coin coin = ref.watch(coinDetailProvider) as Coin;
num usd = ref.watch(usdProvider);
num amount = usd != 0 ? usd / coin.current_price : 0;
//return Text(amount.toString());
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 12.0),
child: TextField(
decoration: InputDecoration(
icon: SizedBox(height: 30, child: Image.network(coin.image)),
hintText: "Coin",
border: InputBorder.none,
),
controller:
TextEditingController(text: "$amount ${coin.symbol.toUpperCase()}"),
readOnly: true,
autocorrect: false,
keyboardType: const TextInputType.numberWithOptions(decimal: true),
onChanged: (value) {
ref.watch(coin_usdProvider.notifier).update((state) =>
value != "" ? num.parse(value) / coin.current_price : 0);
},
),
);
}
}
I think the easiest solution would be to create an outside function which can relate/update these two values.
for example:
void updateValues(float BTC, var USDT)
And then use a FocusNode (see also stackoverflow_question) to detect which of the TextFields is/was selected. That was you know which value is the new one and which one to change.
In this solution you should call this function in an onChanged property of the widgets.
FocusNode can be used either to call something when its focus is changed or to check if something has a focus. So using this class you can solve it in a couple different ways.
Try this example out:
import 'package:flutter/material.dart';
const Color darkBlue = Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
#override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final btcTextController = TextEditingController();
final usdtTextController = TextEditingController();
final btcFocusNode = FocusNode();
final usdtFocusNode = FocusNode();
double btcValue = 15;
double usdTValue = 1;
String curSelection = "";
#override
void initState() {
btcTextController.addListener(calcBTC);
usdtTextController.addListener(calcUSDT);
super.initState();
}
void calcBTC() {
if (btcFocusNode.hasFocus) {
usdtTextController.clear();
if (btcTextController.text.isNotEmpty &&
double.tryParse(btcTextController.text) != null) {
setState(() {
usdtTextController.text =
(double.parse(btcTextController.text) * (btcValue / usdTValue))
.toString();
});
}
}
}
void calcUSDT() {
if (usdtFocusNode.hasFocus) {
btcTextController.clear();
if (usdtTextController.text.isNotEmpty &&
double.tryParse(usdtTextController.text) != null) {
setState(() {
btcTextController.text =
(double.parse(usdtTextController.text) * (usdTValue / btcValue))
.toString();
});
}
}
}
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark().copyWith(
scaffoldBackgroundColor: darkBlue,
),
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: Card(
color: Colors.white,
shape:
RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
elevation: 4,
child: Container(
margin: const EdgeInsets.all(10),
width: 300,
height: 300,
child: Column(
children: [
Expanded(
child: TextField(
style: const TextStyle(color: Colors.black),
controller: btcTextController,
focusNode: btcFocusNode,
decoration: InputDecoration(
filled: true,
fillColor: Colors.blue.shade100,
labelText: 'BTC',
labelStyle: const TextStyle(color: Colors.pink),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide.none,
)),
),
),
Expanded(
child: TextField(
style: const TextStyle(color: Colors.black),
controller: usdtTextController,
focusNode: usdtFocusNode,
decoration: InputDecoration(
filled: true,
fillColor: Colors.blue.shade100,
labelText: 'USDT',
labelStyle: const TextStyle(color: Colors.pink),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide.none,
)),
)),
],
),
),
),
),
),
);
}
}
You will deffo need to add more validation etc. Also you can possibly use one single function to do calculations and use the focusNodes to decide which side needs to be calculated against which.
Error message :
Missing concrete implementation of 'State.build'.
Try implementing the missing method, or make the class abstract.
I get the above error for class _ResetPasswordViewState which is located on Line 13 , in the code below. I get the error message in spite of writing the code for that override. I started getting the error on writing the code for Future passwordReset(), which starts on Line 22. Can someone tell me the mistake I did .
This is the code of my Password Reset file.
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:secure_pass/services/auth/auth_exceptions.dart';
import 'package:secure_pass/utilities/dialogs/error_dialog.dart';
class ResetPasswordView extends StatefulWidget {
const ResetPasswordView({Key? key}) : super(key: key);
#override
State<ResetPasswordView> createState() => _ResetPasswordViewState();
}
class _ResetPasswordViewState extends State<ResetPasswordView> {
final _email = TextEditingController();
#override
void dispose() {
_email.dispose();
super.dispose();
}
Future passwordReset() async{
try {
await FirebaseAuth.instance.sendPasswordResetEmail(email: _email.text);
showDialog(
context: context,
builder: (context) {
return const AlertDialog(
content : Text('Password reset link sent! Check your email'),
);
}
);
} on UserNotFoundAuthException {
await showErrorDialog(
context,
'User not found',
);
} on InvalidEmailAuthException {
await showErrorDialog(
context,
'This is an invalid email address',
);
} on GenericAuthException {
await showErrorDialog(
context,
'Please try again',
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.deepPurple[200],
elevation: 0,
),
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Padding(
padding: EdgeInsets.symmetric(horizontal: 23.0),
child: Text(
"Enter your Email and we will send you a password reset link",
textAlign: TextAlign.center,
),
),
const SizedBox(height: 10),
//email textfield
Padding(
padding: const EdgeInsets.symmetric(horizontal: 25.0),
child: Container(
decoration: BoxDecoration(
color: Colors.grey[200],
border: Border.all(color: Colors.white),
borderRadius: BorderRadius.circular(12),
),
child: Padding(
padding: const EdgeInsets.only(left: 20.0),
child: TextField(
controller: _email,
enableSuggestions: false,
autocorrect: false,
keyboardType: TextInputType.emailAddress,
decoration: const InputDecoration(
hintText: 'Enter your email here',
border: InputBorder.none
),
),
),
),
),
const SizedBox(height: 10),
MaterialButton(
onPressed: passwordReset,
child: Text('Reset Password'),
color: Colors.deepPurple[200],
),
],
),
);
}
}
}
Because you have put you build Widget method inside another method which is the reset password and the stateful widget is looking for the build method in the first stage to run it . i know you did it by mistake and you forgot a } at the end of the fucntion of the reset password, just add it and you will be good to go !
I have a text field in which user enters a number and a Raisedbutton.By clicking that button user should be able to make call on that number . How to write onPressed() function for that buton??
Above this code I have my main class in which Home() class is getting called
import 'package:flutter/material.dart';
class Home extends StatefulWidget{
#override
State<StatefulWidget> createState() {
return HomeState();
}
}
class HomeState extends State<Home> {
TextEditingController numcontroller = new TextEditingController();
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(
centerTitle: true,
backgroundColor: Colors.deepPurple,
title: Text('Calling App'),
),
body: Column(
children: <Widget>[
Container(
margin: EdgeInsets.only(top: 60.0, left: 10.0, right: 10.0),
child: TextField(
controller: numcontroller,
decoration: InputDecoration(
labelText: 'Enter Phone Number',
border: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.deepPurple,
)
)
)
),
),
Container(
height: 45.0,
width: 90.0,
margin: EdgeInsets.only(top: 40, left: 10, right: 10.0),
child: RaisedButton(
color: Colors.deepPurple,
elevation: 7.0,
child: Text(
'Call',
style: TextStyle(
color: Colors.white,
fontSize: 20.0,
),
),
onPressed: () {
_calling();
}
),
)
],
),
),
);
}
void _calling(){
}
}
suppose I have entered a number 94********.then on pressing that button the call should be connected to this number .If busy or switch off then should show any alert message.
First import the URL launcher dependency
url_launcher: ^5.2.5
Then your calling function should look like this
_calling() async {
const url = 'tel:+12345678';
if (await canLaunch(url)) {
await launch(url);
} else {
throw 'Could not launch $url';
}
}
if you want to make actually a phone call from the application then you need CALL_PHONE permission that is marked as a sensitive permission and your app will not be compatible with google play policy.
you can open the phone app instead,
first install url_launcher
in pubspec.yaml
dependencies:
url_launcher: ^5.0.3
then
void _calling(){
_launchURL(numcontroller.text);
}
_launchURL(String phone) async {
const url = 'tel:$phone';
if (await canLaunch(url)) {
await launch(url);
} else {
throw 'Could not launch $url';
}
}
I would like to create a contact form and would like to know: How to send data from a contact form to my email?
I would like to see a working example.
I wanted to submit a form like this:
return new Scaffold(
appBar: new AppBar(
title: new Text(widget.title),
actions: <Widget>[
new IconButton(icon: const Icon(Icons.save), onPressed: () {})
],
),
body: new Column(
children: <Widget>[
new ListTile(
leading: const Icon(Icons.person),
title: new TextField(
decoration: new InputDecoration(
hintText: "Name",
),
),
),
new ListTile(
leading: const Icon(Icons.phone),
title: new TextField(
decoration: new InputDecoration(
hintText: "Phone",
),
),
),
new ListTile(
leading: const Icon(Icons.email),
title: new TextField(
decoration: new InputDecoration(
hintText: "Email",
),
),
),
You can navigate to default Email app. You can also set the following attributes from your flutter app.
to mail ID,
subject and
body
using url_launcher plugin.
Steps:
Add this to your package's pubspec.yaml file:
url_launcher: "^3.0.1"
main.dart file
import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';
void main() => runApp(new MaterialApp(home: new MyApp(), debugShowCheckedModeBanner: false,));
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => new _MyAppState();
}
class _MyAppState extends State<MyApp> {
#override
Widget build(BuildContext context) {
return new Scaffold(
body: new Center(
child: new RaisedButton(onPressed: () => _launchURL('xxx#gmail.com', 'Flutter Email Test', 'Hello Flutter'), child: new Text('Send mail'),),
),
);
}
_launchURL(String toMailId, String subject, String body) async {
var url = 'mailto:$toMailId?subject=$subject&body=$body';
if (await canLaunch(url)) {
await launch(url);
} else {
throw 'Could not launch $url';
}
}
}
Try flutter_email_sender package. Here is an example taken from their github.
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_email_sender/flutter_email_sender.dart';
import 'package:image_picker/image_picker.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
String attachment;
final _recipientController = TextEditingController(
text: 'example#example.com',
);
final _subjectController = TextEditingController(text: 'The subject');
final _bodyController = TextEditingController(
text: 'Mail body.',
);
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
Future<void> send() async {
final Email email = Email(
body: _bodyController.text,
subject: _subjectController.text,
recipients: [_recipientController.text],
attachmentPath: attachment,
);
String platformResponse;
try {
await FlutterEmailSender.send(email);
platformResponse = 'success';
} catch (error) {
platformResponse = error.toString();
}
if (!mounted) return;
_scaffoldKey.currentState.showSnackBar(SnackBar(
content: Text(platformResponse),
));
}
#override
Widget build(BuildContext context) {
final Widget imagePath = Text(attachment ?? '');
return MaterialApp(
theme: ThemeData(primaryColor: Colors.red),
home: Scaffold(
key: _scaffoldKey,
appBar: AppBar(
title: Text('Plugin example app'),
actions: <Widget>[
IconButton(
onPressed: send,
icon: Icon(Icons.send),
)
],
),
body: SingleChildScrollView(
child: Center(
child: Padding(
padding: EdgeInsets.all(8.0),
child: Column(
mainAxisSize: MainAxisSize.max,
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Padding(
padding: EdgeInsets.all(8.0),
child: TextField(
controller: _recipientController,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Recipient',
),
),
),
Padding(
padding: EdgeInsets.all(8.0),
child: TextField(
controller: _subjectController,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Subject',
),
),
),
Padding(
padding: EdgeInsets.all(8.0),
child: TextField(
controller: _bodyController,
maxLines: 10,
decoration: InputDecoration(
labelText: 'Body', border: OutlineInputBorder()),
),
),
imagePath,
],
),
),
),
),
floatingActionButton: FloatingActionButton.extended(
icon: Icon(Icons.camera),
label: Text('Add Image'),
onPressed: _openImagePicker,
),
),
);
}
void _openImagePicker() async {
File pick = await ImagePicker.pickImage(source: ImageSource.gallery);
setState(() {
attachment = pick.path;
});
}
}
Please check "mailer" package from flutter. It will use smtp to send email from background without opening userinterface app. It has gmail, yahoo mail, mailgun options to send email.
Reference link :
https://pub.dartlang.org/packages/mailer
If you wanna send it silence and without pop-up any email dialog, you may consider the way which using firebase extension and an SMTP provider.
For my example, I'm using Firebase as our backend API, so we choose an extension of Firebase called "trigger email" to send emails silently.
After you set up an SMTP provider and decided to choose the "Firebase trigger email extension", you can send emails through the form you made in Flutter code silently.
I hope it helps.
I tried to create this form with validation, so it shows the errors when the user returns each field. But for some reason it doesn't work. I have no reason why. I'm just stuck now.
Here's the code:
import 'package:flutter/material.dart';
import 'package:validate/validate.dart';
void main() => runApp(new MaterialApp(
title: 'Forms in Flutter',
home: new LoginForm(),
theme: ThemeData.dark(),
));
class LoginForm extends StatefulWidget {
String email;
String password;
final Function saveEmail;
final Function savePassword;
final Function attemptLogin;
LoginForm({this.email, this.password, this.saveEmail, this.savePassword,
this.attemptLogin});
#override
LoginFormState createState(){
return new LoginFormState();
}
}
class LoginFormState extends State<LoginForm> {
final loginFormKey = GlobalKey<FormState>();
final emailController = new TextEditingController();
final passController = new TextEditingController();
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text('Login'),
),
body: new Container(
padding: new EdgeInsets.all(10.0),
child: new Form(
key: loginFormKey,
child: new Column(
children: <Widget>[
new Row(
children: <Widget>[
new Container(
width: 2.0,
height: 18.0,
color: Colors.white,
),
new Container(
width: 5.0,
height: 0.0
),
new Expanded(child: new TextFormField(
decoration: new InputDecoration.collapsed(
hintText: "EMAIL",
),
validator: (String value) {
if (!Validate.isEmail(value)) {
return 'Please enter Email';
}
},
onFieldSubmitted: (val) {
print(loginFormKey.currentState.validate());
if (loginFormKey.currentState.validate()) {
widget.email = val;
widget.saveEmail(val);
}
},
controller: emailController,
),)
],
),
new Row(
children: <Widget>[
new Container(
width: 2.0,
height: 18.0,
color: Colors.white,
padding: const EdgeInsets.fromLTRB(0.0, 0.0, 5.0, 0.0),
),
new Container(
width: 5.0,
height: 0.0
),
new Expanded(child: new TextFormField(
obscureText: true,
decoration: new InputDecoration.collapsed(
hintText: 'PASSWORD',
),
validator: (val) =>
val.length < 6 ?
'Still too short' : '',
onFieldSubmitted: (val) {
if (loginFormKey.currentState.validate()) {
widget.email = emailController.text;
print(widget.email);
widget.saveEmail(emailController.text);
widget.password = val;
print(widget.password);
widget.savePassword(val);
widget.attemptLogin();
}
},
controller: passController,
),)
],
)
],
),
),
)
);
}
}
I really don't know what's causing this. It seems like everything in the onfieldSubmitted part of the fields don't work. If I remove the If statements, they work okay, but once it's added it gives no response.
Seems like something simple but I'm just missing the point. Any help would be greatly appreciated. Thanks.
am having the same issue now. I think the !Validate.isEmail(value) is not working.
I commented it out and my code ran well. Try writing your own custom email validation instead of using !Validate.isEmail(value)
The onFieldSubmitted property works when clicking enter or submit on the keyboard. I think, you should add a submit button for submitting because your validations works for form, not an field or input. So, It means if a user entered the email address but this user didn't enter any password, it will take validation error message for password on email field when clicked the enter button. It's not a good feedback. If you use a submit button, it should shows more good feedback for validation messages.
// The button widget
new FlatButton(
onPressed: () => this._submit(),
child: new Text('Login')
);
// The submit function
void _submit() {
if (this.loginFormKey.currentState.validate()) {
this.loginFormKey.currentState.save();
// Do your jobs with the validated form data.
}
}