Flutter Templates
Cómo construir una aplicación de respuesta automática de correos electrónicos con Flutter y Back4App
41 min
introducción en este tutorial, construirás una aplicación de respuesta automática de correo electrónico impulsada por ia utilizando flutter para el frontend y back4app para el backend la aplicación se integrará con servicios de correo electrónico como gmail u outlook, analizará los correos electrónicos entrantes utilizando modelos de ia (como gpt 3 de openai) y generará respuestas personalizadas al final de este tutorial, tendrás una aplicación funcional que puede gestionar correos electrónicos, generar respuestas automatizadas y permitir a los usuarios personalizar sus interacciones por correo electrónico esta aplicación aprovecha el poder del parse server de back4app para manejar la autenticación de usuarios, el almacenamiento de datos y las funciones en la nube, proporcionando una solución de backend escalable sin la necesidad de gestionar la infraestructura del servidor integrar capacidades de ia y servicios de correo electrónico mejorará tus habilidades de desarrollo en flutter y proporcionará una base para construir aplicaciones avanzadas y basadas en datos requisitos previos para completar este tutorial, necesitarás una cuenta de back4app regístrate para obtener una cuenta gratuita en back4app https //www back4app com/ flutter sdk instalado en tu máquina local sigue la guía de instalación de flutter https //flutter dev/docs/get started/install para tu sistema operativo conocimientos básicos de dart y flutter desarrollo si eres nuevo en flutter, considera revisar la documentación de flutter https //flutter dev/docs antes de continuar familiaridad con rest apis y programación asíncrona en dart una cuenta con un proveedor de servicios de ia (por ejemplo, openai) regístrate para obtener una clave api para acceder a los modelos de ia una cuenta de correo electrónico (gmail u outlook) para pruebas de integración paso 1 — configurando tu backend de back4app en este paso, crearás una nueva aplicación en back4app, configurarás tus clases de datos y configurarás el backend para trabajar con tu aplicación flutter 1 1 crear una nueva aplicación en back4app inicia sesión en tu panel de back4app https //dashboard back4app com/ haz clic en "crear nueva app" ingresa un nombre de la app (por ejemplo, "ai email responder") y selecciona tu ícono de la app elige la ubicación de tu servidor si se te solicita haz clic en "crear" 1 2 recuperar claves de aplicación en el panel de tu app, navega a configuración de la app > seguridad y claves anota el id de aplicación y clave de cliente necesitarás estos para la configuración de tu app flutter 1 3 define tus clases de modelo de datos crearemos las siguientes clases en back4app usuario (predeterminado) cuentadecorreo plantilladecorreo historialderespuestas 1 3 1 crear la clase cuentadecorreo ir a base de datos > navegador haga clic en "crear una clase" elija "personalizado" y nómbralo cuentadecorreo haga clic en "crear clase" agregue las siguientes columnas a emailaccount usuario (pointer< user>) apunta al usuario objeto direcciondecorreo (string) tipodecuenta (string) p ej , gmail, outlook tokendeautenticacion (string) almacenará tokens encriptados 1 3 2 crear la clase emailtemplate repita los pasos para crear una nueva clase llamada emailtemplate agregue las siguientes columnas a emailtemplate usuario (pointer< user>) nombredeplantilla (string) contenidodeplantilla (string) tipodeplantilla (string) p ej , formal, casual, seguimiento 1 3 3 crear la clase responsehistory cree una nueva clase llamada responsehistory agregue las siguientes columnas a responsehistory usuario (pointer< user>) resumenemailoriginal (string) respuestagenerada (string) respuestaeditadaporelusuario (string) tiempoahorrado (número) 1 4 establecer permisos a nivel de clase asegúrese de que solo los usuarios autenticados puedan acceder a sus datos en cada clase, vaya a la seguridad sección establezca permisos a nivel de clase (clp) para permitir acceso de lectura/escritura solo a usuarios autenticados paso 2 — inicializando su proyecto flutter en este paso, configurará su proyecto flutter y lo conectará a back4app 2 1 crear un nuevo proyecto flutter abra su terminal y ejecute flutter create ai email responder navega al directorio del proyecto cd ai email responder 2 2 agregar dependencias requeridas abre pubspec yaml y agrega las siguientes dependencias dependencies flutter sdk flutter parse server sdk flutter ^4 0 1 flutter email sender ^5 0 2 http ^0 13 4 provider ^6 0 2 fl chart ^0 45 1 ejecuta flutter pub get para instalar los paquetes 2 3 inicializa parse en tu aplicación crea un nuevo archivo lib/config/back4app config dart // lib/config/back4app config dart const string keyapplicationid = 'your application id'; const string keyclientkey = 'your client key'; const string keyparseserverurl = 'https //parseapi back4app com'; reemplace 'your application id' y 'your client key' con las claves de back4app en lib/main dart , inicializa parse // lib/main dart import 'package\ flutter/material dart'; import 'package\ parse server sdk flutter/parse server sdk dart'; import 'config/back4app config dart'; import 'app dart'; void main() async { widgetsflutterbinding ensureinitialized(); await parse() initialize( keyapplicationid, keyparseserverurl, clientkey keyclientkey, autosendsessionid true, debug true, ); runapp(myapp()); } crea lib/app dart // lib/app dart import 'package\ flutter/material dart'; import 'screens/home screen dart'; class myapp extends statelesswidget { @override widget build(buildcontext context) { return materialapp( title 'ai email responder', theme themedata( primaryswatch colors blue, ), home homescreen(), ); } } paso 3 — implementación de la autenticación de usuarios ahora implementarás el registro y el inicio de sesión de usuarios utilizando parse server 3 1 crear pantallas de autenticación crear lib/screens/login screen dart y lib/screens/signup screen dart para mayor brevedad, nos centraremos en la funcionalidad de inicio de sesión // lib/screens/login screen dart import 'package\ flutter/material dart'; import 'package\ parse server sdk flutter/parse server sdk dart'; import 'home screen dart'; class loginscreen extends statefulwidget { @override loginscreenstate createstate() => loginscreenstate(); } class loginscreenstate extends state\<loginscreen> { final texteditingcontroller usernamecontroller = texteditingcontroller(); final texteditingcontroller passwordcontroller = texteditingcontroller(); future\<void> douserlogin() async { final username = usernamecontroller text trim(); final password = passwordcontroller text trim(); final user = parseuser(username, password, null); final response = await user login(); if (response success) { navigator pushreplacement( context, materialpageroute(builder (context) => homescreen()), ); } else { showerror(response error! message); } } void showerror(string message) { scaffoldmessenger of(context) showsnackbar(snackbar(content text('error $message'))); } @override widget build(buildcontext context) { return scaffold( appbar appbar( title text('login'), ), body padding( padding const edgeinsets all(16), child column( children \[ textfield( controller usernamecontroller, decoration inputdecoration(labeltext 'username', icon icon(icons person)), ), textfield( controller passwordcontroller, decoration inputdecoration(labeltext 'password', icon icon(icons lock)), obscuretext true, ), sizedbox(height 20), elevatedbutton( onpressed douserlogin, child text('login'), ), ], ), ), ); } } 3 2 actualizar la navegación de la pantalla principal modifica lib/app dart para dirigir a los usuarios a la pantalla de inicio de sesión si no están autenticados // lib/app dart import 'package\ flutter/material dart'; import 'package\ parse server sdk flutter/parse server sdk dart'; import 'screens/home screen dart'; import 'screens/login screen dart'; class myapp extends statelesswidget { future\<bool> hasuserloggedin() async { final currentuser = await parseuser currentuser() as parseuser?; return currentuser != null; } @override widget build(buildcontext context) { return futurebuilder\<bool>( future hasuserloggedin(), builder (context, snapshot) { if (snapshot hasdata && snapshot data == true) { return materialapp( title 'ai email responder', theme themedata(primaryswatch colors blue), home homescreen(), ); } else { return materialapp( title 'ai email responder', theme themedata(primaryswatch colors blue), home loginscreen(), ); } }, ); } } paso 4 — integrando servicios de correo electrónico en este paso, configurarás la integración de correo electrónico utilizando el flutter email sender paquete 4 1 configurar el enviador de correo electrónico agrega los permisos necesarios a tus configuraciones de android e ios para android , actualiza android/app/src/main/androidmanifest xml \<uses permission android\ name="android permission internet"/> para ios , asegúrate de que tu info plist incluya \<key>nsapptransportsecurity\</key> \<dict> \<key>nsallowsarbitraryloads\</key> \<true/> \</dict> 4 2 implementar la funcionalidad de envío de correo electrónico crea lib/services/email service dart // lib/services/email service dart import 'package\ flutter email sender/flutter email sender dart'; class emailservice { future\<void> sendemail(string subject, string body, list\<string> recipients) async { final email email = email( body body, subject subject, recipients recipients, ishtml false, ); await flutteremailsender send(email); } } 4 3 implementar la obtención de correos electrónicos (marcador de posición) la obtención de correos electrónicos de proveedores como gmail requiere oauth e integración de api, lo que puede ser complejo para este tutorial, simularemos la obtención de correos electrónicos crear lib/models/email dart // lib/models/email dart class email { final string sender; final string subject; final string body; final datetime date; email({ required this sender, required this subject, required this body, required this date, }); } crear lib/services/email service dart (actualizar con datos ficticios) // lib/services/email service dart import ' /models/email dart'; class emailservice { future\<list\<email>> fetchemails() async { // simulate network delay await future delayed(duration(seconds 2)); return \[ email( sender 'john doe\@example com', subject 'meeting reminder', body 'don\\'t forget about our meeting tomorrow at 10 am ', date datetime now() subtract(duration(hours 1)), ), // add more dummy emails ]; } // existing sendemail method } paso 5 — integración de servicios de ia para la generación de respuestas ahora configurarás la integración de ia para generar respuestas de correo electrónico 5 1 configurar solicitudes http a la api de ia instalar el http paquete (ya agregado) crear lib/services/ai service dart // lib/services/ai service dart import 'dart\ convert'; import 'package\ http/http dart' as http; class aiservice { final string apikey = 'your openai api key'; final string apiurl = 'https //api openai com/v1/engines/davinci/completions'; future\<string> generateresponse(string emailcontent) async { final response = await http post( uri parse(apiurl), headers { 'authorization' 'bearer $apikey', 'content type' 'application/json', }, body jsonencode({ 'prompt' 'reply to the following email \n$emailcontent', 'max tokens' 150, }), ); if (response statuscode == 200) { final data = jsondecode(response body); return data\['choices']\[0]\['text'] trim(); } else { throw exception('failed to generate response'); } } } nota reemplace 'your openai api key' con su clave api real 5 2 implementar el widget del editor de respuestas crear lib/widgets/response editor dart // lib/widgets/response editor dart import 'package\ flutter/material dart'; class responseeditor extends statelesswidget { final string initialresponse; final texteditingcontroller controller; responseeditor({required this initialresponse}) controller = texteditingcontroller(text initialresponse); @override widget build(buildcontext context) { return textfield( controller controller, maxlines null, decoration inputdecoration( hinttext 'edit your response here ', border outlineinputborder(), ), ); } } nota reemplace 'your openai api key' con su clave api real 5 3 mostrando respuestas generadas por ia en lib/screens/email detail screen dart , integra el servicio de ia // lib/screens/email detail screen dart import 'package\ flutter/material dart'; import ' /models/email dart'; import ' /services/ai service dart'; import ' /widgets/response editor dart'; import ' /services/email service dart'; class emaildetailscreen extends statefulwidget { final email email; emaildetailscreen({required this email}); @override emaildetailscreenstate createstate() => emaildetailscreenstate(); } class emaildetailscreenstate extends state\<emaildetailscreen> { final aiservice aiservice = aiservice(); final emailservice emailservice = emailservice(); string? airesponse; bool isloading = false; future\<void> generateresponse() async { setstate(() { isloading = true; }); try { final response = await aiservice generateresponse(widget email body); setstate(() { airesponse = response; }); } catch (e) { scaffoldmessenger of(context) showsnackbar(snackbar(content text('ai error $e'))); } finally { setstate(() { isloading = false; }); } } void sendresponse(string responsetext) { emailservice sendemail( 're ${widget email subject}', responsetext, \[widget email sender], ); scaffoldmessenger of(context) showsnackbar(snackbar(content text('email sent'))); } @override void initstate() { super initstate(); generateresponse(); } @override widget build(buildcontext context) { final responseeditor = airesponse != null ? responseeditor(initialresponse airesponse!) null; return scaffold( appbar appbar( title text('email from ${widget email sender}'), ), body padding( padding const edgeinsets all(16), child isloading ? center(child circularprogressindicator()) column( children \[ text(widget email body), sizedbox(height 20), responseeditor != null ? expanded(child responseeditor) container(), elevatedbutton( onpressed () { if (responseeditor != null) { sendresponse(responseeditor controller text); } }, child text('send response'), ), ], ), ), ); } } paso 6 — gestionando plantillas de correo electrónico ahora implementarás la gestión de plantillas de correo electrónico utilizando back4app 6 1 define el modelo emailtemplate crear lib/models/email template dart // lib/models/email template dart import 'package\ parse server sdk flutter/parse server sdk dart'; class emailtemplate extends parseobject implements parsecloneable { emailtemplate() super('emailtemplate'); emailtemplate clone() this(); @override emailtemplate clone(map\<string, dynamic> map) => emailtemplate clone() fromjson(map); string? get templatename => get\<string>('templatename'); set templatename(string? value) => set\<string>('templatename', value); string? get templatecontent => get\<string>('templatecontent'); set templatecontent(string? value) => set\<string>('templatecontent', value); string? get templatetype => get\<string>('templatetype'); set templatetype(string? value) => set\<string>('templatetype', value); } 6 2 implementar el servicio de plantillas crear lib/services/template service dart // lib/services/template service dart import 'package\ parse server sdk flutter/parse server sdk dart'; import ' /models/email template dart'; class templateservice { future\<list\<emailtemplate>> fetchtemplates() async { final query = querybuilder\<emailtemplate>(emailtemplate()); final response = await query find(); if (response success && response results != null) { return response results as list\<emailtemplate>; } else { return \[]; } } future\<void> addtemplate(emailtemplate template) async { await template save(); } } 6 3 crear pantalla de gestión de plantillas crear lib/screens/template management screen dart // lib/screens/template management screen dart import 'package\ flutter/material dart'; import ' /models/email template dart'; import ' /services/template service dart'; class templatemanagementscreen extends statefulwidget { @override templatemanagementscreenstate createstate() => templatemanagementscreenstate(); } class templatemanagementscreenstate extends state\<templatemanagementscreen> { final templateservice templateservice = templateservice(); list\<emailtemplate> templates = \[]; bool isloading = true; future\<void> loadtemplates() async { final fetchedtemplates = await templateservice fetchtemplates(); setstate(() { templates = fetchedtemplates; isloading = false; }); } @override void initstate() { super initstate(); loadtemplates(); } @override widget build(buildcontext context) { return scaffold( appbar appbar( title text('email templates'), ), body isloading ? center(child circularprogressindicator()) listview\ builder( itemcount templates length, itembuilder (context, index) { final template = templates\[index]; return listtile( title text(template templatename ?? 'unnamed'), subtitle text(template templatetype ?? 'no type'), ); }, ), floatingactionbutton floatingactionbutton( onpressed () { // implement template creation }, child icon(icons add), )); } } paso 7 — implementación del seguimiento del historial de respuestas ahora guardarás las respuestas generadas por la ia y las ediciones de los usuarios en back4app para análisis 7 1 definir el modelo responsehistory crear lib/models/response history dart // lib/models/response history dart import 'package\ parse server sdk flutter/parse server sdk dart'; class responsehistory extends parseobject implements parsecloneable { responsehistory() super('responsehistory'); responsehistory clone() this(); @override responsehistory clone(map\<string, dynamic> map) => responsehistory clone() fromjson(map); string? get originalemailsummary => get\<string>('originalemailsummary'); set originalemailsummary(string? value) => set\<string>('originalemailsummary', value); string? get generatedresponse => get\<string>('generatedresponse'); set generatedresponse(string? value) => set\<string>('generatedresponse', value); string? get usereditedresponse => get\<string>('usereditedresponse'); set usereditedresponse(string? value) => set\<string>('usereditedresponse', value); int? get timesaved => get\<int>('timesaved'); set timesaved(int? value) => set\<int>('timesaved', value); } 7 2 guardar el historial de respuestas después de enviar el correo electrónico actualizar lib/screens/email detail screen dart en el sendresponse método import ' /models/response history dart'; // void sendresponse(string responsetext) async { await emailservice sendemail( 're ${widget email subject}', responsetext, \[widget email sender], ); // save response history final responsehistory = responsehistory() set('originalemailsummary', widget email body) set('generatedresponse', airesponse) set('usereditedresponse', responsetext) set('timesaved', calculatetimesaved()); await responsehistory save(); scaffoldmessenger of(context) showsnackbar(snackbar(content text('email sent'))); navigator pop(context); } int calculatetimesaved() { // placeholder implementation return 5; // assume 5 minutes saved } paso 8 — agregar analíticas con gráficos ahora implementarás un panel de analíticas básico usando fl chart 8 1 implementar servicio de analíticas crear lib/services/analytics service dart // lib/services/analytics service dart import 'package\ parse server sdk flutter/parse server sdk dart'; import ' /models/response history dart'; class analyticsservice { future\<list\<responsehistory>> fetchresponsehistories() async { final query = querybuilder\<responsehistory>(responsehistory()); final response = await query find(); if (response success && response results != null) { return response results as list\<responsehistory>; } else { return \[]; } } future\<int> calculatetotaltimesaved() async { final histories = await fetchresponsehistories(); return histories fold(0, (sum, item) => sum + (item timesaved ?? 0)); } } 8 2 crear el panel de analíticas crear lib/screens/analytics screen dart // lib/screens/analytics screen dart import 'package\ flutter/material dart'; import 'package\ fl chart/fl chart dart'; import ' /services/analytics service dart'; class analyticsscreen extends statefulwidget { @override analyticsscreenstate createstate() => analyticsscreenstate(); } class analyticsscreenstate extends state\<analyticsscreen> { final analyticsservice analyticsservice = analyticsservice(); int totaltimesaved = 0; future\<void> loadanalytics() async { final timesaved = await analyticsservice calculatetotaltimesaved(); setstate(() { totaltimesaved = timesaved; }); } @override void initstate() { super initstate(); loadanalytics(); } @override widget build(buildcontext context) { return scaffold( appbar appbar( title text('analytics'), ), body center( child text('total time saved $totaltimesaved minutes'), )); } } paso 9 — implementando soporte offline ahora agregarás capacidades offline a tu aplicación utilizando el almacenamiento de datos local de parse 9 1 habilitar almacenamiento de datos local en lib/main dart , habilita el almacenamiento de datos local await parse() initialize( keyapplicationid, keyparseserverurl, clientkey keyclientkey, autosendsessionid true, debug true, corestore await corestoresembastimp getinstance(), ); 9 2 modificar modelos de datos para fijar en tus modelos (por ejemplo, responsehistory ), agrega métodos para fijar y deshacer la fijación de objetos future\<void> pin() async { await this pin(); } future\<void> unpin() async { await this unpin(); } 9 3 implementar gestor offline crear lib/utils/offline manager dart // lib/utils/offline manager dart import ' /models/email dart'; import 'package\ parse server sdk flutter/parse server sdk dart'; class offlinemanager { future\<void> cacheemails(list\<email> emails) async { for (var email in emails) { final parseobject = parseobject('email') set('sender', email sender) set('subject', email subject) set('body', email body) set('date', email date); await parseobject pin(); } } future\<list\<email>> getcachedemails() async { final query = querybuilder\<parseobject>(parseobject('email')); final response = await query frompin() find(); if (response success && response results != null) { return response results! map((e) { return email( sender e get\<string>('sender') ?? '', subject e get\<string>('subject') ?? '', body e get\<string>('body') ?? '', date e get\<datetime>('date') ?? datetime now(), ); }) tolist(); } else { return \[]; } } } 9 4 usar datos offline cuando no hay conectividad en tu lógica de obtención de correos electrónicos, verifica la conectividad y utiliza datos en caché si estás offline conclusión en este tutorial, construiste una aplicación de respuesta automática de correos electrónicos utilizando flutter y back4app tú configuraste un backend de back4app con los modelos de datos necesarios y configuraciones de seguridad inicializaste un proyecto de flutter y lo conectaste a back4app implementaste la autenticación de usuarios con parse server integraste el envío de correos electrónicos y simulaste la obtención de correos integraste servicios de ia para generar respuestas a correos electrónicos gestionaste plantillas de correos electrónicos y las almacenaste en back4app rastreaste el historial de respuestas para análisis agregaste análisis básicos utilizando fl chart implementaste soporte offline utilizando el almacenamiento de datos local de parse esta aplicación proporciona una base para construir características más avanzadas, como integración real de correo electrónico con oauth, capacidades avanzadas de ia y un diseño mejorado de ui/ux próximos pasos integración de correo electrónico implementar la obtención real de correos electrónicos utilizando las api de gmail u outlook con autenticación oauth características mejoradas de ia ajustar los prompts de ia para mejores respuestas e implementar personalización basada en los datos del usuario mejoras de ui/ux mejorar la interfaz de la aplicación para una mejor experiencia del usuario pruebas y despliegue escribir pruebas unitarias e integradas y preparar la aplicación para el despliegue en las tiendas de aplicaciones mejoras de seguridad cifrar datos sensibles e implementar un manejo de errores robusto y validación de entradas para más información sobre el uso de back4app con flutter, consulte la guía de back4app flutter https //www back4app com/docs/flutter/parse sdk/