Главная страница
Навигация по странице:

  • Class MailModel . dart

  • Class RecipeentMessagePage

  • Class MessageBoxList

  • Курсовая работа ММиВА. Куровая Работа Почтовый Клиент. Разработка почтового клиента


    Скачать 0.8 Mb.
    НазваниеРазработка почтового клиента
    АнкорКурсовая работа ММиВА
    Дата23.03.2022
    Размер0.8 Mb.
    Формат файлаdocx
    Имя файлаКуровая Работа Почтовый Клиент.docx
    ТипКурсовая
    #411055

    МИНИСТЕРСТВО ЦИФРОВОГО РАЗВИТИЯ,

    СВЯЗИ И МАССОВЫХ КОММУНИКАЦИЙ РОССИЙСКОЙ ФЕДЕРАЦИИ

    Федеральное государственное бюджетное образовательное учреждение высшего образования «Санкт-Петербургский государственный университет телекоммуникаций им. проф. М. А. Бонч-Бруевича»

    (СПбГУТ)
    Факультет инфокоммуникационных сетей и систем

    Кафедра программной инженерии и вычислительной техники


    КУРСОВАЯ РАБОТА

    по дисциплине «Математические методы и вычислительные алгоритмы современных систем связи»

    на тему «Разработка почтового клиента»


    студент гр. ИКПИ-84

    _______________

    Сулейменов Д.Р.










    преподаватель каф. ПИиВТ

    _______________

    к.п.н., доцент Коробов С. А.



    Санкт-Петербург

    2022

    Оглавление


    1.ПОСТАНОВКА ЗАДАЧИ 2

    2.ВЫБОР И ОБОСНОВАНИЕ ИНСТРУМЕНТОВ ПРОГРАММИРОВАНИЯ 3

    1.1.Выбор инструментов программирования 4

    3.РАЗРАБОТКА ГРАФИЧЕСКОГО ИНТЕРФЕЙСА 5

    1.2.Форма Авторизации 6

    1.3.Случай не удачного входа (неправильный логин или пароль) 7

    1.4.Главный интерфейс программы ящика со списком писем 8

    1.5.Главный интерфейс просмотра сообщения 10

    1.6.Главный интерфейс отправки сообщения 12

    4.РАЗРАБОТКА КОДА 17

    1.7.Разработка модульной структуры 17

    ЗАКЛЮЧЕНИЕ 18

    СПИСОК ЛИТЕРАТУРЫ 19

    КОД ПРИЛОЖЕНИЯ 19


    1. ПОСТАНОВКА ЗАДАЧИ



    Разработать клиентское приложение для получения и отправки электронных почтовых сообщений.

    Приложение должно реализовывать следующие функции:

    • Отображение электронных папок с сообщениями (IMAP).

    • Отправка сообщений (SMTP).

    • Добавление, переименование/перемещение, удаление папок электронной почты (IMAP).

    • Копирование и удаление сообщений (IMAP).

    Интерфейс программы должен включать:

    • Главное окно для отображения папок и писем.

    • Модальное окно настроек параметров для авторизации.

    • Модальное окно для отправки сообщения.

    • Модальные окна для добавления, переименования/перемещения, удаления папок.

    • Модальные окна для копирования и удаления сообщений.

    • Дополнительные вспомогательные окна.

    Приложение должно использовать только зашифрованные соединения, а также иметь графический интерфейс, достаточный для выполнения всех задач.

    1. ВЫБОР И ОБОСНОВАНИЕ ИНСТРУМЕНТОВ ПРОГРАММИРОВАНИЯ




      1. Выбор инструментов программирования


    Выбранный язык программирования: Dart

    Выбранные инструменты программирования:

    • Фреймворк Flutter

    • Библиотека Foundation

    • Библиотека enogh_mail ^1.3.6

    Обоснование выбора.

    • Dart представляет язык программирования общего назначения от компании Google, который предназначен прежде всего для разработки веб-приложений (как на стороне клиента, так и на стороне сервера) и мобильных приложений. Это также значит, что одну и ту же программу на Dart можно компилировать под различные платформы - Windows (x86/64), Android, iOS.

    • Flutter — комплект средств разработки и фреймворк с открытым исходным кодом для создания мобильных приложений под Android и iOS, веб-приложений, а также настольных приложений под Windows, macOS и Linux с использованием языка программирования Dart, разработанный и развиваемый корпорацией Google. Движок Flutter написан преимущественно на C++, поддерживает низкоуровневый рендеринг с помощью графической библиотеки Google Skia, имеет возможность взаимодействовать с платформозависимыми SDK под Android и iOS.

    • Библиотека Foundation, написанная на языке Dart, содержит основные классы и методы для создания приложений Flutter и взаимодействия с движком Flutter

    • Дизайн пользовательского интерфейса приложений Flutter предполагает использование виджетов, описываемых как неизменяемые объекты какой-либо части пользовательского интерфейса. Все графические объекты, включая текст, формы и анимацию, создаются с помощью виджетов; комбинированием простых виджетов создаются сложные виджеты. С фреймворком поставляется два основных набора виджетов — Material Design (стиль Google) и Cupertino (стиль Apple). При этом создавать приложения Flutter можно и без виджетов, напрямую вызывая методы библиотеки Foundation для работы с канвой.

    Разработка осуществляется одновременно для Android/IOS/Web.
    enough_mail - Библиотека для разработчиков электронной почты, содержит в себе протоколы IMAP, POP3, SMTP. А также поддерживает защищенное соединение SSL. Может использоваться как высокоуровневый API, так и низкоуровневый API.

    API высокого уровня абстрагируется от деталей IMAP и POP3, автоматически переподключается и позволяет легко отслеживать почтовый ящик на наличие новых сообщений.

    Поддерживаемые кодировки:

    • ASCII (7bit)

    • UTF-8 (uft8, 8bit)

    • ISO-8859-1 (latin-1)

    • ISO-8859-2 - 16 (latin-2 - 16)

    • Windows-1250, 1251, 1252, 1253, 1254 and 1256

    • GB-2312, GBK, GB-18030, Chinese, CSGB-2312, CSGB-231280, CSISO-58-GB-231280, ISO-IR-58, X-Mac-ChineseSimp

    1. РАЗРАБОТКА ГРАФИЧЕСКОГО ИНТЕРФЕЙСА




      1. Форма Авторизации




    Рис. 3.1 Форма авторизации, ввод данных, ожидание входа


      1. Текстовое поле email – Ожидает ввода адреса электронной почты пользователя.

      2. Текстовое поле пароль – Ожидает ввода пароля от электронной почты



      1. Случай не удачного входа (неправильный логин или пароль)




    Рис. 3.2 Уведомление о неудачном входе в почту
    В случаи проблем, таких как: Неправильный логин или пароль, нет подключения к интернету и т.д., приложение выведет уведомление о неудачной попытке.

      1. Главный интерфейс программы ящика со списком писем




    Рис. 3.3 Список Входящих/Отправленных/Удаленных сообщений


    Рис. 3.4 Список сообщений отправленных спам

    Приложение имеет возможность показывать 4 основные папки электронной почты. Входящие/Отправленные/Спам/Корзина.


    Рис 3.5 Всплывающее меню выбора папок, а также кнопка «Выйти».
    После нажатия кнопки «Выйти» приложение выходит из текущего сеанса, и предлагает зайти в новый электронный ящик.

      1. Главный интерфейс просмотра сообщения





    Рис 3.6 Детальное отображение сообщения.
    В данном интерфейсе можно подробнее узнать о выбранном сообщении. Содержит в себе:

    • Тему сообщения

    • Изображение отправителя

    • Почта отправителя

    • Дату получения, отправления

    • Текст, контент сообщения

      1. Главный интерфейс отправки сообщения




    Рис 3.7 Интерфейс отправки сообщения.
    Данный интерфейс содержит в себе формы ввода:

    • Email получателя

    • Тема письма

    • Текст письма



    В случае, если пользователь не введет сообщение, то приложение выведет предупреждение и не даст отправить сообщение


    Рис 3.8. Не заполнены поля



    Рис 3.9 Успешная отправка сообщения

    1. РАЗРАБОТКА КОДА




      1. Разработка модульной структуры


    Class_RecipeentMessagePage'>Class_MailModel_._dart'>Class MailModel.dart – Содержит в себе модель структуры сообщения.

    • MailClient mailClient – Текущая конфигурация клиента(подключение)

    • List messages – Список текущих сообщений выбранной папки

    • String title – Тема сообщения

    • String content – Текст или контент сообщения

    • String personalName – Имя отправителя

    • String avatar – Текст изображения пользователя

    • String date – Дата отправки сообщения

    Сlass LoginPage.dart – Страница авторизации, содержит поля для ввода данных.

    • String email – Почтовый адрес

    • String password – пароль от почтового адреса

    Сlass MainPanel.dart – Основная страница, которая выводит список сообщений

    • String nameBox – Название почтового ящика, который нужно вывести

    Class RecipeentMessagePage – Страница детального отображения сообщения

    Сlass SenMessagePage – Страница отправки сообщения

    • String email – адрес получателя

    • String text – текст для получателя

    • String subject – тема для получателя

    Class MessageBoxList – Виджет для отображения списка писем

    • String box - название списка, который нужно вывести

    functions.dart – функции использующиеся для программы.

    • Future connect – Подключение к аккаунту электронный почты. Возвращает true, если удалось подключиться, false, если возникли проблемы

    • Future> getMails – Получает список сообщений. Возвращает список сообщений в виде моделей описанной в классе MailModel

    • Future send – Отправляет сообщение. Возвращает true, если удалось отправить, false, если возникли проблемы.


    ЗАКЛЮЧЕНИЕ



    Данная программа выполняет все поставленные задачи: отображение электронных сообщений (IMAP), отправка сообщений (SMTP), добавление, переименование/перемещение и удаление папок электронной почты (IMAP), копирование и удаление сообщений (IMAP).

    В ходе курсовой работы была освоена и закреплена раота с протоколами IMAP, POP3, SMTP. А также улучшены навыки разработки на языке Dart с использованием фреймворка Flutter 2.0.

    СПИСОК ЛИТЕРАТУРЫ





    1. С. А. Коробов. Лекции по дисциплине «Математические методы и вычислительные алгоритмы современных систем связи».

    2. Flutter documentation. Документация Flutter. [Электронный ресурс] URL: https://docs.flutter.dev


    КОД ПРИЛОЖЕНИЯ



    main.dart

    import 'package:email_client/Pages/RecipientMessagePage.dart';
    import 'package:email_client/Pages/SendMessagePage.dart';
    import 'package:email_client/Pages/loginPage.dart';
    import 'package:flutter/material.dart';
    import 'Models/MailModel.dart';
    import 'Pages/MainPanel.dart';
    import 'functions/functions.dart';

    void main() {
    return runApp(MaterialApp(
    debugShowCheckedModeBanner: false,
    initialRoute: 'loginPage',
    // routes: {
    // '/mainPanel': (context) => MainPanel(),
    // '/detailPage': (context) => RecipientMessagePage()
    // },
    onGenerateRoute: (RouteSettings settings) {
    var routes = {
    //'/': (context) => MainPanel(),
    'loginPage': (context) => LoginPage(),
    'mainPanel': (context) => MainPanel(nameBox: 'inbox'),
    'detailPage': (context) => RecipientMessagePage(mailModel: settings.arguments as MailModel),
    'sendMessage': (context) => SendMessagePage(),
    };
    WidgetBuilder builder = routes[settings.name]!;
    return MaterialPageRoute(builder: (context) => builder(context));
    }
    )
    );
    }
    MailModel.dart

    import 'package:enough_mail/enough_mail.dart';


    class MailModel{
    static late MailClient mailClient;
    static late List messages;
    String title;
    String? content;
    String? personalName;
    String avatar;
    String date;

    MailModel(
    {required this.title,
    required this.content,
    required this.personalName,
    required this.avatar,
    required this.date,

    }){
    title = normalizeTitle(title);
    }


    String normalizeTitle(String string){
    string.replaceAll('\n', ' ');

    return string;
    }
    }

    LoginPage.dart

    import 'package:flutter/cupertino.dart';
    import 'package:flutter/material.dart';

    import '../functions/functions.dart';
    import 'MainPanel.dart';

    class LoginPage extends StatelessWidget {
    LoginPage({Key? key}) : super(key: key);
    Widget boxDivider = const SizedBox(
    height: 20,
    );

    final _formKey = GlobalKey();

    late String email;
    late String password;

    @override
    Widget build(BuildContext context) {
    return Scaffold(
    appBar: AppBar(
    backgroundColor: Colors.white,
    title: Text('Авторизация',
    style: const TextStyle(
    color: Colors.black,
    fontFamily: 'roboto',
    fontStyle: FontStyle.normal
    ),),
    centerTitle: true,
    ),
    body: Center(
    child: SingleChildScrollView(
    child: SafeArea(
    child: Padding(
    padding: const EdgeInsets.all(20.0),
    child: Form(
    key: _formKey,
    child: Column(
    crossAxisAlignment: CrossAxisAlignment.center,
    mainAxisAlignment: MainAxisAlignment.center,
    children: [
    Icon(Icons.email,size: 120,color: Colors.grey.shade300,),
    TextFormField(
    decoration: const InputDecoration(
    border: OutlineInputBorder(),
    enabledBorder: OutlineInputBorder(
    borderSide: BorderSide(color: Colors.black),
    borderRadius: BorderRadius.all(Radius.circular(20))
    ),
    hintText: 'email',
    hintStyle: TextStyle(fontSize: 13),
    ),
    validator: (value){
    if(value == null || value.isEmpty){
    return 'Введите email';
    }
    return null;
    },
    onSaved: (value){
    email = value!;
    },
    ),
    boxDivider,
    TextFormField(
    obscureText: true,
    enableSuggestions: false,
    autocorrect: false,
    decoration: const InputDecoration(
    border: OutlineInputBorder(),
    enabledBorder: OutlineInputBorder(
    borderSide: BorderSide(color: Colors.black),
    borderRadius: BorderRadius.all(Radius.circular(20))
    ),
    hintText: 'пароль',
    hintStyle: TextStyle(fontSize: 13),
    ),
    validator: (value){
    if(value == null || value.isEmpty){
    return 'Введите пароль';
    }
    return null;
    },
    onSaved: (value){
    password = value!;
    },
    ),
    boxDivider,
    SizedBox(
    width: double.infinity,
    height: 50,
    child: ElevatedButton(
    style: ElevatedButton.styleFrom(
    primary: Colors.grey.shade300,
    ),

    onPressed: () {
    if (_formKey.currentState!.validate()) {
    _formKey.currentState!.save();

    print('$email $password');
    showDialog(context: context,
    builder: (BuildContext context) => AlertDialog(
    content: Row(
    mainAxisAlignment: MainAxisAlignment.spaceAround,
    children: [
    Column(
    mainAxisAlignment: MainAxisAlignment.center,
    mainAxisSize: MainAxisSize.min,
    children:const [
    SizedBox(
    height: 10,
    width: 10,
    ),
    SizedBox(
    height: 30,
    width: 30,
    child: CircularProgressIndicator(),
    ),
    SizedBox(
    height: 10,
    width: 10,
    )
    ],
    ),
    const Text('Вход...', style: TextStyle(
    fontSize: 20
    ),)
    ],
    ),
    )
    );
    connect(email,password).then((value)
    {
    if(value){
    Navigator.pop(context);
    ScaffoldMessenger.of(context).showSnackBar(
    const SnackBar(content: Text('Вход выполнен'))
    );
    Navigator.pushNamedAndRemoveUntil(context, 'mainPanel', (route) => false);
    }else{
    Navigator.pop(context);
    showDialog(context: context,
    builder: (BuildContext context) => const AlertDialog(
    content: Text('Не удалось подключиться'),
    ));
    }
    });

    }
    },
    child: const Text('Войти',
    style: TextStyle(color: Colors.black)),
    ),)

    ],
    ),
    ),
    )

    ),
    ),
    ),
    );
    }
    }
    MainPanel.dart

    import 'package:email_client/Models/MailModel.dart';
    import 'package:email_client/Widgets/MessageBoxList.dart';
    import 'package:flutter/cupertino.dart';
    import 'package:flutter/material.dart';

    // GlobalKey _scaffoldKey = new GlobalKey();


    class MainPanel extends StatelessWidget {
    final _scaffoldKey = GlobalKey();

    String nameBox = 'inbox';
    MainPanel({Key? key, required this.nameBox }) : super(key: key);

    @override
    Widget build(BuildContext context) {
    return Scaffold(
    key: _scaffoldKey,
    appBar: AppBar(
    backgroundColor: Colors.white,
    leading: IconButton(onPressed: () {
    _scaffoldKey.currentState?.openDrawer();
    }, icon: Icon(Icons.menu, color: Colors.black,),),
    title: /*(nameBox == 'inbox')? Text('Входящие'): (nameBox=='sendbox')? Text('Отправленные'):(nameBox == 'trashbox')? Text('Корзина'): Text('Спам'),*/
    Text((nameBox == 'inbox')? ('Входящие'): (nameBox=='sendbox')? ('Отправленные'):(nameBox == 'trashbox')? ('Корзина'): ('Спам'),
    style: const TextStyle(
    color: Colors.black,
    fontFamily: 'roboto',
    fontStyle: FontStyle.normal
    ),),
    centerTitle: true,
    ),
    body: MessageBoxList(box: nameBox),

    floatingActionButton: FloatingActionButton(

    backgroundColor: Colors.grey,
    child: const Icon(Icons.send_outlined),
    onPressed: (){

    Navigator.pushNamed(context, 'sendMessage');

    },
    ),

    drawer: Container(
    width: 250,
    child: Drawer(
    child: ListView(
    padding: EdgeInsets.zero,
    children: [
    const DrawerHeader(
    padding: EdgeInsets.all(20),
    decoration: BoxDecoration(
    color: Colors.grey,
    ),
    child: Text('MAILER'),
    ),
    ListTile(
    title: Text('Входящие'),
    onTap: (){
    Navigator.of(context).pushAndRemoveUntil(MaterialPageRoute(builder: (context) =>
    MainPanel(nameBox: 'inbox')
    ), (route) => false);
    },
    ),
    ListTile(
    title: const Text('Отправленные'),
    onTap: (){

    Navigator.of(context).pushAndRemoveUntil(MaterialPageRoute(builder: (context) =>
    MainPanel(nameBox: 'sendbox')
    ), (route) => false);
    },
    ),
    ListTile(
    title: const Text('Спам'),
    onTap: (){
    Navigator.of(context).pushAndRemoveUntil(MaterialPageRoute(builder: (context) =>
    MainPanel(nameBox: 'spam')
    ), (route) => false);
    },
    ),
    ListTile(
    title: const Text('Корзина'),
    onTap: (){
    Navigator.of(context).pushAndRemoveUntil(MaterialPageRoute(builder: (context) =>
    MainPanel(nameBox: 'trashbox')
    ), (route) => false);
    },
    ),
    ListTile(
    title: const Text('Выйти'),
    onTap: (){
    Navigator.pushNamedAndRemoveUntil(context, 'loginPage', (route) => false);
    MailModel.mailClient.disconnect();
    },
    )
    ],
    ),
    ),
    ),
    );
    }
    }
    ReciepentMessagePage.dart

    import 'package:flutter/cupertino.dart';
    import 'package:flutter/material.dart';

    import '../Models/MailModel.dart';

    class RecipientMessagePage extends StatelessWidget {
    MailModel mailModel;
    RecipientMessagePage({
    required this.mailModel,
    Key? key

    }
    ) : super(key: key);

    @override
    Widget build(BuildContext context) {
    return Scaffold(
    appBar: AppBar(
    backgroundColor: Colors.white,
    title: const Text('Сообщение', style:
    TextStyle(
    color: Colors.black,
    fontFamily: 'roboto',
    fontStyle: FontStyle.normal,
    ),),
    centerTitle: true,
    ),
    body: Padding(
    padding: const EdgeInsets.all(20.0),
    child: Column(
    crossAxisAlignment: CrossAxisAlignment.start,
    children: [
    Text(mailModel.title),
    Padding(
    padding: const EdgeInsets.only(top: 20),
    child: Container(
    child: Row(
    children: [
    const CircleAvatar(
    backgroundColor: Colors.red,
    radius: 40,
    ),
    Padding(
    padding: const EdgeInsets.only(left: 20),
    child: Container(
    height: 65,
    child: Column(
    mainAxisAlignment: MainAxisAlignment.spaceAround,
    children: [
    Text(mailModel.personalName.toString()),
    Text(mailModel.date),
    ],
    ),
    ),
    )
    ],
    )
    ),
    ),
    Padding(
    padding: const EdgeInsets.only(top: 20),
    child: Center(
    child: Text(mailModel.content.toString())),
    ),
    ],
    ),
    ) ,
    );
    }
    }
    SendMessagePage.dart

    import 'package:email_client/Models/MailModel.dart';
    import 'package:email_client/functions/functions.dart';
    import 'package:flutter/cupertino.dart';
    import 'package:flutter/material.dart';

    class SendMessagePage extends StatelessWidget {
    SendMessagePage({Key? key}) : super(key: key);
    var _formKey = GlobalKey();

    String? email;
    String? text;
    String? subject;

    Widget boxDivider = const SizedBox(
    height: 20,
    );
    @override
    Widget build(BuildContext context) {
    return Scaffold(
    appBar: AppBar(
    leading: IconButton(
    onPressed: (){
    Navigator.pop(context);
    }, icon: Icon(Icons.arrow_back, color: Colors.black,),
    ),
    centerTitle: true,
    backgroundColor: Colors.white,
    title: Text('Отправить', style:
    TextStyle(
    color: Colors.black,
    fontFamily: 'roboto',
    fontStyle: FontStyle.normal,
    ),),
    ),
    body: Scrollbar(
    child: SingleChildScrollView(
    child: Padding(
    padding: const EdgeInsets.all(20.0),
    child: Form(
    key: _formKey,
    child: Column(
    crossAxisAlignment: CrossAxisAlignment.start,
    children: [
    TextFormField(
    decoration: const InputDecoration(
    border: OutlineInputBorder(),
    enabledBorder: OutlineInputBorder(
    borderSide: BorderSide(color: Colors.black),
    borderRadius: BorderRadius.all(Radius.circular(20))
    ),
    hintText: 'email',
    hintStyle: TextStyle(fontSize: 13, color: Colors.grey),
    ),
    validator: (value){
    if(value==null || value.isEmpty){
    return "Введите email";
    }
    },
    onSaved: (value){
    email = value;
    },
    ),
    boxDivider,
    TextFormField(
    decoration: const InputDecoration(
    border: OutlineInputBorder(),
    enabledBorder: OutlineInputBorder(
    borderSide: BorderSide(color: Colors.black),
    borderRadius: BorderRadius.all(Radius.circular(20))
    ),
    hintText: 'Тема',
    hintStyle: TextStyle(fontSize: 13, color: Colors.grey),
    ),

    onSaved: (value){
    if(value!.isEmpty){
    subject = '';
    }else{
    subject = value;
    }
    },
    ),
    boxDivider,
    TextFormField(
    maxLines: null,
    minLines: 10,
    textAlignVertical: TextAlignVertical.top,
    style: const TextStyle(
    color: Colors.black,
    ),
    decoration: const InputDecoration(
    border: OutlineInputBorder(),
    /* contentPadding: EdgeInsets.symmetric(vertical: 20),*/
    enabledBorder: OutlineInputBorder(
    borderSide: BorderSide( color: Colors.black),
    borderRadius: BorderRadius.all(Radius.circular(20))
    ),
    hintText: 'Введите сообщение',
    hintStyle: TextStyle(fontSize: 13, color: Colors.grey),
    ),
    validator: (value){
    if(value==null || value.isEmpty){
    return "Введите сообщение";
    }
    },
    onSaved: (value){
    text = value;
    },
    ),
    boxDivider,
    SizedBox(
    width: double.infinity,
    height: 50,
    child: ElevatedButton(
    style: ElevatedButton.styleFrom(
    primary: Colors.grey.shade400,
    ),
    onPressed: () {
    if(_formKey.currentState!.validate()){
    _formKey.currentState!.save();
    send(email!, MailModel.mailClient.account.email.toString(), text!, subject!)
    .then((value) => {
    if(value){
    showDialog(
    barrierDismissible: true,
    context: context,
    builder: (BuildContext context) => AlertDialog(
    content: Row(
    children: const [
    Icon(Icons.check, color: Colors.green, size: 20,),
    Text('Сообщение отправлено')
    ],
    ),
    actions: [
    TextButton(
    onPressed: (){
    Navigator.pushNamedAndRemoveUntil(context, 'mainPanel', (route) => false);
    },
    child: const Text('ок'))
    ],
    )
    )
    }else{
    showDialog(
    barrierDismissible: true,
    context: context,
    builder: (BuildContext context) => AlertDialog(
    content: Row(
    children: const [
    Icon(Icons.close, color: Colors.black, size: 20,),
    Text('Сообщение не отправлено, проблема с подключением к клиенту')
    ],
    ),
    actions: [
    TextButton(
    onPressed: (){
    Navigator.pop(context);
    },
    child: const Text('назад'))
    ],
    )
    )
    }
    });
    }

    },
    child: const Text('Отправить'),
    ))
    ],
    ),
    ),
    ),
    ),
    ),
    );
    }
    }

    MessageBoxList.dart

    import 'package:email_client/Pages/RecipientMessagePage.dart';
    import 'package:email_client/functions/functions.dart';
    import 'package:flutter/cupertino.dart';
    import 'package:flutter/material.dart';
    import 'package:enough_mail/enough_mail.dart';
    import '../Data/MailData.dart';
    import '../Models/MailModel.dart';
    import 'dart:math' as math;

    late Future > items;

    class MessageBoxList extends StatefulWidget {
    String box;
    MessageBoxList({Key? key, required this.box}) : super(key: key);

    @override
    State createState() => _MessageBoxListState();
    }

    class _MessageBoxListState extends State {
    @override
    void initState() {
    items = getMails(widget.box);
    super.initState();
    }

    @override
    Widget build(BuildContext context) {
    return FutureBuilder(
    future: items,
    builder: (BuildContext context, snapshot) {
    if(snapshot.hasData){
    List items = snapshot.data as List;
    items = items.reversed.toList();
    return ListView.separated(
    itemCount: items.length,
    itemBuilder: (BuildContext context, int index) {
    return ListTile(
    contentPadding: const EdgeInsets.all(0),
    minVerticalPadding: 0,
    title: SizedBox(
    height: 150,
    width: double.infinity,
    child: TextButton(
    onPressed: () {
    Navigator.pushNamed(context, 'detailPage', arguments: items[index]);
    },
    child: Row(
    children: [
    Expanded(
    flex: 25,
    child: Container(
    child: Column(
    mainAxisAlignment: MainAxisAlignment.spaceAround,
    children: [
    CircleAvatar(
    backgroundColor: Color((math.Random().nextDouble() * 0xFFFFFF).toInt()).withOpacity(1.0),
    radius: 20,
    child: Text(items[index].avatar, style:
    const TextStyle(
    color: Colors.white,
    fontWeight: FontWeight.bold,
    fontSize: 17,
    ),),
    ),
    PopupMenuButton(
    icon: Icon(Icons.menu, color: Colors.grey,),
    itemBuilder: (context) {
    return [
    PopupMenuItem(
    child: TextButton(
    onPressed: () {
    setState(() {
    items.removeAt(index);
    MailModel.mailClient.deleteMessage(MailModel.messages[index]);
    Navigator.pop(context);
    });
    },
    child: const Text('Удалить', style: TextStyle(color: Colors.grey),),
    )),
    PopupMenuItem(
    child: TextButton(
    onPressed: () {
    setState(() {
    items.removeAt(index);
    MailModel.mailClient.moveMessageToFlag(MailModel.messages[index], MailboxFlag.junk);
    Navigator.pop(context);
    });
    },
    child: const Text('В спам', style: TextStyle(color: Colors.grey)),
    ))
    ];
    })
    ],
    ),
    ),
    ),
    Expanded(
    flex: 50,
    child: Column(
    mainAxisAlignment: MainAxisAlignment.spaceAround,
    crossAxisAlignment: CrossAxisAlignment.start,
    children: [
    Container(width: double.infinity, height: 25,
    child: Text(items[index].personalName.toString(),
    overflow: TextOverflow.ellipsis,
    style: TextStyle(color: Colors.grey, fontSize: 14),
    )),
    Container(width: double.infinity, height: 30,
    child: Text(items[index].title,
    overflow: TextOverflow.ellipsis,
    style: TextStyle(color: Colors.black, fontSize: 18)
    )),
    Container(width: double.infinity, height: 70,
    child: Text(items[index].content.toString(),
    overflow: TextOverflow.fade,
    style: TextStyle(color: Colors.grey, fontSize: 14)
    ), ),
    ],
    ),
    ),
    Expanded(
    flex: 25,
    child: Column(
    mainAxisAlignment: MainAxisAlignment.start,
    children: [
    Text((items[index].date).toString(),
    style: TextStyle(color: Colors.grey, fontSize: 14)),
    ],
    ),
    )
    ],
    ),
    ),
    ),
    );
    },
    separatorBuilder: (BuildContext context, int index) {
    return const Divider(
    height: 0,
    thickness: 2,
    indent: 0,
    endIndent: 0,
    color: Colors.black12,
    );
    },
    );
    }
    else if(snapshot.hasError){
    return Text(snapshot.error.toString());
    }
    else{
    return Center(child: CircularProgressIndicator());
    }
    }

    );
    }
    }

    functions.dart

    import 'package:email_client/Models/MailModel.dart';
    import 'package:enough_mail/enough_mail.dart';


    Future connect(String email,String password) async {

    //Автоматическое обнаружение конфигурации
    final config = await Discover.discover(email, isLogEnabled: false);


    try {
    var account = MailAccount.fromDiscoveredSettings('my account', email, password, config!);
    MailModel.mailClient = MailClient(account, isLogEnabled: false);
    await MailModel.mailClient.connect();
    print('connected');
    return true;
    } on MailException catch (e) {
    print('High level API failed with $e');
    return false;
    } on MailAccount catch(e){
    print('Неверный логин или пароль');
    return false;
    }

    }

    Future> getMails(String nameBox) async{
    final mailboxes = MailModel.mailClient.mailboxes;
    var _mailboxes = await MailModel.mailClient.listMailboxes();
    var inbox;
    if(nameBox == 'inbox'){
    inbox = _mailboxes.firstWhere((box) => box.isInbox);
    }
    else if (nameBox == 'sendbox'){
    inbox = _mailboxes.firstWhere((box) => box.isSent);
    }
    else if(nameBox == 'trashbox'){
    inbox = _mailboxes.firstWhere((box) => box.isTrash);
    }
    else if(nameBox == 'spam'){
    inbox = _mailboxes.firstWhere((box) => box.isJunk);
    }
    else{
    print('Ошибка');
    }
    print( 'name BOX ----> ${inbox.name}');
    await MailModel.mailClient.selectMailbox(inbox);
    MailModel.messages = await MailModel.mailClient.fetchMessages();

    List mails = [];
    MailModel.messages.forEach((message) {
    String title = message.decodeSubject().toString();
    String? personalName = message.from!.first.personalName;
    String? date = '${message.decodeDate()!.day}/${message.decodeDate()!.month}/${message.decodeDate()!.year}';
    String? content = message.decodeTextPlainPart();
    content ??= message.decodeContentText();
    mails.add(
    MailModel(
    title: title,
    content: content,
    personalName: personalName,
    avatar: personalName![0],
    date: date,
    ));
    });
    return mails;
    }

    Future send(String emailTo, String emailFrom, String text, String subject) async{
    try {
    List emails = [];
    emails.add(
    MailAddress(emailTo,text),
    );
    MimeMessage mimeMessage = MessageBuilder.buildSimpleTextMessage(
    MailAddress(emailFrom,emailFrom),
    emails,
    text,
    subject: subject,
    );
    await MailModel.mailClient.sendMessage(mimeMessage);
    return true;
    } on Exception catch (e) {
    return false;
    }
    }


    написать администратору сайта