[{"data":1,"prerenderedAt":11277},["ShallowReactive",2],{"navigation_docs":3,"-csharp-network-programming-smtp":3302,"-csharp-network-programming-smtp-surround":11272},[4,1707,1896,2350,2531,2572,2779,2901,2951,3008,3042,3168,3245,3298],{"title":5,"icon":6,"path":7,"stem":8,"children":9},"C#","i-devicon-csharp","\u002Fcsharp","01.csharp",[10,13,60,90,120,202,219,253,379,404,457,650,1364,1654,1703],{"title":11,"path":7,"stem":12},"C# та .NET","01.csharp\u002Findex",{"title":14,"icon":15,"path":16,"stem":17,"children":18,"page":59},"Fundamentals","i-lucide-book-open","\u002Fcsharp\u002Ffundamentals","01.csharp\u002F01.fundamentals",[19,23,27,31,35,39,43,47,51,55],{"title":20,"path":21,"stem":22},"Вступ до екосистеми .NET","\u002Fcsharp\u002Ffundamentals\u002Fintroduction-to-ecosystem","01.csharp\u002F01.fundamentals\u002F01.introduction-to-ecosystem",{"title":24,"path":25,"stem":26},"Структура програми на C#","\u002Fcsharp\u002Ffundamentals\u002Fprogram-structure","01.csharp\u002F01.fundamentals\u002F02.program-structure",{"title":28,"path":29,"stem":30},"Змінні та Типи Даних","\u002Fcsharp\u002Ffundamentals\u002Fvariables-data-types","01.csharp\u002F01.fundamentals\u002F03.variables-data-types",{"title":32,"path":33,"stem":34},"Масиви","\u002Fcsharp\u002Ffundamentals\u002Farrays","01.csharp\u002F01.fundamentals\u002F04.arrays",{"title":36,"path":37,"stem":38},"Strings & Text Handling","\u002Fcsharp\u002Ffundamentals\u002Fstrings-text-handling","01.csharp\u002F01.fundamentals\u002F05.strings-text-handling",{"title":40,"path":41,"stem":42},"Дати і Час","\u002Fcsharp\u002Ffundamentals\u002Fdates-time-handling","01.csharp\u002F01.fundamentals\u002F06.dates-time-handling",{"title":44,"path":45,"stem":46},"Потік Керування","\u002Fcsharp\u002Ffundamentals\u002Fcontrol-flow","01.csharp\u002F01.fundamentals\u002F07.control-flow",{"title":48,"path":49,"stem":50},"Методи","\u002Fcsharp\u002Ffundamentals\u002Fmethods","01.csharp\u002F01.fundamentals\u002F08.methods",{"title":52,"path":53,"stem":54},"Основи Відлагодження","\u002Fcsharp\u002Ffundamentals\u002Fdebugging-basics","01.csharp\u002F01.fundamentals\u002F09.debugging-basics",{"title":56,"path":57,"stem":58},"Інтерактивна Консоль (Classic)","\u002Fcsharp\u002Ffundamentals\u002Finteractive-console","01.csharp\u002F01.fundamentals\u002F10.interactive-console",false,{"title":61,"icon":62,"path":63,"stem":64,"children":65,"page":59},"OOP","i-lucide-box","\u002Fcsharp\u002Foop","01.csharp\u002F02.oop",[66,70,74,78,82,86],{"title":67,"path":68,"stem":69},"Package Management (Управління Пакетами)","\u002Fcsharp\u002Foop\u002Fpackage-management","01.csharp\u002F02.oop\u002F01.package-management",{"title":71,"path":72,"stem":73},"Класи та Об'єкти","\u002Fcsharp\u002Foop\u002Fclasses-objects","01.csharp\u002F02.oop\u002F02.classes-objects",{"title":75,"path":76,"stem":77},"Властивості та Поля","\u002Fcsharp\u002Foop\u002Fproperties-fields","01.csharp\u002F02.oop\u002F03.properties-fields",{"title":79,"path":80,"stem":81},"Стовпи ООП","\u002Fcsharp\u002Foop\u002Foop-pillars","01.csharp\u002F02.oop\u002F04.oop-pillars",{"title":83,"path":84,"stem":85},"Advanced Types","\u002Fcsharp\u002Foop\u002Fadvanced-types","01.csharp\u002F02.oop\u002F05.advanced-types",{"title":87,"path":88,"stem":89},"Namespaces (Простори Імен)","\u002Fcsharp\u002Foop\u002Fnamespaces","01.csharp\u002F02.oop\u002F06.namespaces",{"title":91,"icon":92,"path":93,"stem":94,"children":95,"page":59},"Advanced Core","i-lucide-zap","\u002Fcsharp\u002Fadvanced-core","01.csharp\u002F03.advanced-core",[96,100,104,108,112,116],{"title":97,"path":98,"stem":99},"Generics (Узагальнення)","\u002Fcsharp\u002Fadvanced-core\u002Fgenerics","01.csharp\u002F03.advanced-core\u002F01.generics",{"title":101,"path":102,"stem":103},"Делегати, Події та Лямбда-вирази","\u002Fcsharp\u002Fadvanced-core\u002Fdelegates-events-lambdas","01.csharp\u002F03.advanced-core\u002F02.delegates-events-lambdas",{"title":105,"path":106,"stem":107},"Interfaces Deep Dive (Інтерфейси: Поглиблений Розгляд)","\u002Fcsharp\u002Fadvanced-core\u002Finterfaces-deep-dive","01.csharp\u002F03.advanced-core\u002F03.interfaces-deep-dive",{"title":109,"path":110,"stem":111},"Обробка Винятків","\u002Fcsharp\u002Fadvanced-core\u002Fexception-handling","01.csharp\u002F03.advanced-core\u002F04.exception-handling",{"title":113,"path":114,"stem":115},"Pattern Matching","\u002Fcsharp\u002Fadvanced-core\u002Fpattern-matching","01.csharp\u002F03.advanced-core\u002F05.pattern-matching",{"title":117,"path":118,"stem":119},"Додаткові Можливості C#","\u002Fcsharp\u002Fadvanced-core\u002Fadditional-features","01.csharp\u002F03.advanced-core\u002F06.additional-features",{"title":121,"icon":122,"path":123,"stem":124,"children":125,"page":59},"Architecture Best Practices","i-lucide-building-2","\u002Fcsharp\u002Farchitecture-best-practices","01.csharp\u002F04.architecture-best-practices",[126,130,149,153,157,161,165,169],{"title":127,"path":128,"stem":129},"Software Design Principles (Частина 1)","\u002Fcsharp\u002Farchitecture-best-practices\u002Fsoftware-design-principles","01.csharp\u002F04.architecture-best-practices\u002F01.software-design-principles",{"title":131,"icon":132,"path":133,"stem":134,"children":135,"page":59},"Design Patterns","i-lucide-folder","\u002Fcsharp\u002Farchitecture-best-practices\u002Fdesign-patterns","01.csharp\u002F04.architecture-best-practices\u002F02.design-patterns",[136],{"title":137,"icon":132,"path":138,"stem":139,"children":140,"page":59},"Creational","\u002Fcsharp\u002Farchitecture-best-practices\u002Fdesign-patterns\u002Fcreational","01.csharp\u002F04.architecture-best-practices\u002F02.design-patterns\u002Fcreational",[141,145],{"title":142,"path":143,"stem":144},"Singleton (Одинак)","\u002Fcsharp\u002Farchitecture-best-practices\u002Fdesign-patterns\u002Fcreational\u002Fsingleton","01.csharp\u002F04.architecture-best-practices\u002F02.design-patterns\u002Fcreational\u002F01.singleton",{"title":146,"path":147,"stem":148},"Builder (Будівельник)","\u002Fcsharp\u002Farchitecture-best-practices\u002Fdesign-patterns\u002Fcreational\u002Fbuilder","01.csharp\u002F04.architecture-best-practices\u002F02.design-patterns\u002Fcreational\u002F02.builder",{"title":150,"path":151,"stem":152},"Building Professional CLIs","\u002Fcsharp\u002Farchitecture-best-practices\u002Fbuilding-professional-clis","01.csharp\u002F04.architecture-best-practices\u002F03.building-professional-clis",{"title":154,"path":155,"stem":156},"Validation & Flow Control","\u002Fcsharp\u002Farchitecture-best-practices\u002Fvalidation-flow-control","01.csharp\u002F04.architecture-best-practices\u002F04.validation-flow-control",{"title":158,"path":159,"stem":160},"The Modern .NET Host (Microsoft.Extensions)","\u002Fcsharp\u002Farchitecture-best-practices\u002Fmodern-dotnet-host","01.csharp\u002F04.architecture-best-practices\u002F05.modern-dotnet-host",{"title":162,"path":163,"stem":164},"Data Mapper: Repository та DAO патерни (Частина 1)","\u002Fcsharp\u002Farchitecture-best-practices\u002Fdata-mapper-part1","01.csharp\u002F04.architecture-best-practices\u002F06.data-mapper-part1",{"title":166,"path":167,"stem":168},"Data Mapper: Repository та DAO патерни (Частина 2)","\u002Fcsharp\u002Farchitecture-best-practices\u002Fdata-mapper-part2","01.csharp\u002F04.architecture-best-practices\u002F07.data-mapper-part2",{"title":170,"icon":132,"path":171,"stem":172,"children":173,"page":59},"Di Ioc","\u002Fcsharp\u002Farchitecture-best-practices\u002Fdi-ioc","01.csharp\u002F04.architecture-best-practices\u002F08.di-ioc",[174,178,182,186,190,194,198],{"title":175,"path":176,"stem":177},"Проблема залежностей та Інверсія Контролю","\u002Fcsharp\u002Farchitecture-best-practices\u002Fdi-ioc\u002Fthe-dependency-problem","01.csharp\u002F04.architecture-best-practices\u002F08.di-ioc\u002F01.the-dependency-problem",{"title":179,"path":180,"stem":181},"Будуємо власний Service Container","\u002Fcsharp\u002Farchitecture-best-practices\u002Fdi-ioc\u002Fbuild-your-own-container","01.csharp\u002F04.architecture-best-practices\u002F08.di-ioc\u002F02.build-your-own-container",{"title":183,"path":184,"stem":185},"Service Locator: Паттерн та Анти-паттерн","\u002Fcsharp\u002Farchitecture-best-practices\u002Fdi-ioc\u002Fservice-locator-pattern","01.csharp\u002F04.architecture-best-practices\u002F08.di-ioc\u002F03.service-locator-pattern",{"title":187,"path":188,"stem":189},"Паттерни Dependency Injection","\u002Fcsharp\u002Farchitecture-best-practices\u002Fdi-ioc\u002Fdependency-injection-patterns","01.csharp\u002F04.architecture-best-practices\u002F08.di-ioc\u002F04.dependency-injection-patterns",{"title":191,"path":192,"stem":193},"Microsoft DI: IServiceCollection та IServiceProvider","\u002Fcsharp\u002Farchitecture-best-practices\u002Fdi-ioc\u002Fmicrosoft-di-deep-dive","01.csharp\u002F04.architecture-best-practices\u002F08.di-ioc\u002F05.microsoft-di-deep-dive",{"title":195,"path":196,"stem":197},"Service Lifetimes та Scopes","\u002Fcsharp\u002Farchitecture-best-practices\u002Fdi-ioc\u002Fservice-lifetimes-and-scopes","01.csharp\u002F04.architecture-best-practices\u002F08.di-ioc\u002F06.service-lifetimes-and-scopes",{"title":199,"path":200,"stem":201},"DI Анти-паттерни та Найкращі Практики","\u002Fcsharp\u002Farchitecture-best-practices\u002Fdi-ioc\u002Fdi-anti-patterns-and-best-practices","01.csharp\u002F04.architecture-best-practices\u002F08.di-ioc\u002F07.di-anti-patterns-and-best-practices",{"title":203,"icon":132,"path":204,"stem":205,"children":206,"page":59},"Standard Library","\u002Fcsharp\u002Fstandard-library","01.csharp\u002F05.standard-library",[207,211,215],{"title":208,"path":209,"stem":210},"Collections (Колекції)","\u002Fcsharp\u002Fstandard-library\u002Fcollections","01.csharp\u002F05.standard-library\u002F01.collections",{"title":212,"path":213,"stem":214},"High Performance Types (Високопродуктивні Типи)","\u002Fcsharp\u002Fstandard-library\u002Fhigh-performance-types","01.csharp\u002F05.standard-library\u002F02.high-performance-types",{"title":216,"path":217,"stem":218},"LINQ (Language Integrated Query)","\u002Fcsharp\u002Fstandard-library\u002Flinq","01.csharp\u002F05.standard-library\u002F03.linq",{"title":220,"icon":221,"path":222,"stem":223,"children":224,"page":59},"System Internals Concurrency","i-lucide-server","\u002Fcsharp\u002Fsystem-internals-concurrency","01.csharp\u002F06.system-internals-concurrency",[225,229,233,237,241,245,249],{"title":226,"path":227,"stem":228},"Memory Management","\u002Fcsharp\u002Fsystem-internals-concurrency\u002Fmemory-management","01.csharp\u002F06.system-internals-concurrency\u002F01.memory-management",{"title":230,"path":231,"stem":232},"Reflection API: System.Type та Метадані","\u002Fcsharp\u002Fsystem-internals-concurrency\u002Freflection-fundamentals","01.csharp\u002F06.system-internals-concurrency\u002F02.reflection-fundamentals",{"title":234,"path":235,"stem":236},"Attributes та Dynamic Language Runtime","\u002Fcsharp\u002Fsystem-internals-concurrency\u002Fattributes-dynamic","01.csharp\u002F06.system-internals-concurrency\u002F03.attributes-dynamic",{"title":238,"path":239,"stem":240},"Expression Trees: Швидка Альтернатива Рефлексії","\u002Fcsharp\u002Fsystem-internals-concurrency\u002Fexpression-trees-compiled","01.csharp\u002F06.system-internals-concurrency\u002F04.expression-trees-compiled",{"title":242,"path":243,"stem":244},"Source Generators: Compile-Time Code Generation","\u002Fcsharp\u002Fsystem-internals-concurrency\u002Fsource-generators","01.csharp\u002F06.system-internals-concurrency\u002F05.source-generators",{"title":246,"path":247,"stem":248},"Multithreading Fundamentals","\u002Fcsharp\u002Fsystem-internals-concurrency\u002Fmultithreading-fundamentals","01.csharp\u002F06.system-internals-concurrency\u002F06.multithreading-fundamentals",{"title":250,"path":251,"stem":252},"Synchronization Primitives","\u002Fcsharp\u002Fsystem-internals-concurrency\u002Fsynchronization-primitives","01.csharp\u002F06.system-internals-concurrency\u002F07.synchronization-primitives",{"title":254,"icon":255,"path":256,"stem":257,"children":258,"page":59},"System Programming Windows","i-lucide-cpu","\u002Fcsharp\u002Fsystem-programming-windows","01.csharp\u002F07.system-programming-windows",[259,263,267,271,275,279,283,287,291,295,299,303,307,311,315,319,323,327,331,335,339,343,347,351,355,359,363,367,371,375],{"title":260,"path":261,"stem":262},"Як Працює Операційна Система","\u002Fcsharp\u002Fsystem-programming-windows\u002Fhow-os-works","01.csharp\u002F07.system-programming-windows\u002F01.how-os-works",{"title":264,"path":265,"stem":266},"Процеси в .NET — API та Запуск","\u002Fcsharp\u002Fsystem-programming-windows\u002Fprocesses-in-dotnet","01.csharp\u002F07.system-programming-windows\u002F02.processes-in-dotnet",{"title":268,"path":269,"stem":270},"Процеси в .NET — IPC та Міжпроцесна Комунікація","\u002Fcsharp\u002Fsystem-programming-windows\u002F02a.processes-ipc","01.csharp\u002F07.system-programming-windows\u002F02a.processes-ipc",{"title":272,"path":273,"stem":274},"Application Domains та Збірки — AppDomain і AssemblyLoadContext","\u002Fcsharp\u002Fsystem-programming-windows\u002Fappdomains-assemblies","01.csharp\u002F07.system-programming-windows\u002F03.appdomains-assemblies",{"title":276,"path":277,"stem":278},"Application Domains та Збірки — Plug-in Система з Hot-Reload","\u002Fcsharp\u002Fsystem-programming-windows\u002F03a.appdomains-plugin-system","01.csharp\u002F07.system-programming-windows\u002F03a.appdomains-plugin-system",{"title":280,"path":281,"stem":282},"Потоки — Основи та API Thread","\u002Fcsharp\u002Fsystem-programming-windows\u002Fthread-fundamentals","01.csharp\u002F07.system-programming-windows\u002F04.thread-fundamentals",{"title":284,"path":285,"stem":286},"Потоки — Lifecycle, Пріоритети та Безпечне Завершення","\u002Fcsharp\u002Fsystem-programming-windows\u002F04a.thread-lifecycle-priorities","01.csharp\u002F07.system-programming-windows\u002F04a.thread-lifecycle-priorities",{"title":288,"path":289,"stem":290},"Проблеми Спільного Стану — Race Condition та Data Race","\u002Fcsharp\u002Fsystem-programming-windows\u002Fshared-state-problems","01.csharp\u002F07.system-programming-windows\u002F05.shared-state-problems",{"title":292,"path":293,"stem":294},"Проблеми Спільного Стану — Memory Model та volatile","\u002Fcsharp\u002Fsystem-programming-windows\u002F05a.shared-state-memory-model","01.csharp\u002F07.system-programming-windows\u002F05a.shared-state-memory-model",{"title":296,"path":297,"stem":298},"Синхронізація — Monitor, lock та еволюція примітивів","\u002Fcsharp\u002Fsystem-programming-windows\u002Fsynchronization-fundamentals","01.csharp\u002F07.system-programming-windows\u002F06.synchronization-fundamentals",{"title":300,"path":301,"stem":302},"Синхронізація — Наскрізний Приклад та Deadlock Detection","\u002Fcsharp\u002Fsystem-programming-windows\u002F06a.synchronization-walkthrough","01.csharp\u002F07.system-programming-windows\u002F06a.synchronization-walkthrough",{"title":304,"path":305,"stem":306},"Синхронізація — Mutex, Semaphore та Event-Based Primitives","\u002Fcsharp\u002Fsystem-programming-windows\u002Fsynchronization-advanced","01.csharp\u002F07.system-programming-windows\u002F07.synchronization-advanced",{"title":308,"path":309,"stem":310},"Синхронізація — Interlocked, Volatile та Lock-Free Структури","\u002Fcsharp\u002Fsystem-programming-windows\u002F07a.synchronization-advanced-walkthrough","01.csharp\u002F07.system-programming-windows\u002F07a.synchronization-advanced-walkthrough",{"title":312,"path":313,"stem":314},"Interlocked, CAS та Lock-Free Структури","\u002Fcsharp\u002Fsystem-programming-windows\u002Finterlocked-cas-lockfree","01.csharp\u002F07.system-programming-windows\u002F08.interlocked-cas-lockfree",{"title":316,"path":317,"stem":318},"Volatile, Memory Model та Spinning","\u002Fcsharp\u002Fsystem-programming-windows\u002F08a.volatile-memory-model","01.csharp\u002F07.system-programming-windows\u002F08a.volatile-memory-model",{"title":320,"path":321,"stem":322},"ThreadPool — Пул Потоків для Ефективного Виконання","\u002Fcsharp\u002Fsystem-programming-windows\u002Fthread-pool","01.csharp\u002F07.system-programming-windows\u002F09.thread-pool",{"title":324,"path":325,"stem":326},"ThreadPool — Просунуті Сценарії та Внутрішня Будова","\u002Fcsharp\u002Fsystem-programming-windows\u002F09a.thread-pool-advanced","01.csharp\u002F07.system-programming-windows\u002F09a.thread-pool-advanced",{"title":328,"path":329,"stem":330},"Concurrent та Immutable Collections","\u002Fcsharp\u002Fsystem-programming-windows\u002Fconcurrent-collections","01.csharp\u002F07.system-programming-windows\u002F10.concurrent-collections",{"title":332,"path":333,"stem":334},"TPL, Task та Композиція — Від Thread до Task","\u002Fcsharp\u002Fsystem-programming-windows\u002Ftpl-parallel-plinq","01.csharp\u002F07.system-programming-windows\u002F11.tpl-parallel-plinq",{"title":336,"path":337,"stem":338},"Parallel Class та PLINQ — Data Parallelism","\u002Fcsharp\u002Fsystem-programming-windows\u002F11a.tpl-parallel-plinq-advanced","01.csharp\u002F07.system-programming-windows\u002F11a.tpl-parallel-plinq-advanced",{"title":340,"path":341,"stem":342},"Async\u002FAwait — Фундамент Асинхронного Програмування","\u002Fcsharp\u002Fsystem-programming-windows\u002Fasync-fundamentals","01.csharp\u002F07.system-programming-windows\u002F12.async-fundamentals",{"title":344,"path":345,"stem":346},"SynchronizationContext та ConfigureAwait — Контекст Виконання","\u002Fcsharp\u002Fsystem-programming-windows\u002Fasync-context-configureawait","01.csharp\u002F07.system-programming-windows\u002F13.async-context-configureawait",{"title":348,"path":349,"stem":350},"Async — Просунуті Паттерни","\u002Fcsharp\u002Fsystem-programming-windows\u002Fasync-advanced","01.csharp\u002F07.system-programming-windows\u002F14.async-advanced",{"title":352,"path":353,"stem":354},"System.Threading.Channels — Async Producer-Consumer","\u002Fcsharp\u002Fsystem-programming-windows\u002Fchannels","01.csharp\u002F07.system-programming-windows\u002F15.channels",{"title":356,"path":357,"stem":358},"Асинхронна Синхронізація","\u002Fcsharp\u002Fsystem-programming-windows\u002Fasync-synchronization","01.csharp\u002F07.system-programming-windows\u002F16.async-synchronization",{"title":360,"path":361,"stem":362},"Unsafe Code та Вказівники","\u002Fcsharp\u002Fsystem-programming-windows\u002Funsafe-code","01.csharp\u002F07.system-programming-windows\u002F17.unsafe-code",{"title":364,"path":365,"stem":366},"P\u002FInvoke та Windows API — Міст між .NET та Native Code","\u002Fcsharp\u002Fsystem-programming-windows\u002Fpinvoke-winapi","01.csharp\u002F07.system-programming-windows\u002F18.pinvoke-winapi",{"title":368,"path":369,"stem":370},"Реєстр Windows — Центральна База Конфігурації Системи","\u002Fcsharp\u002Fsystem-programming-windows\u002Fwindows-registry","01.csharp\u002F07.system-programming-windows\u002F19.windows-registry",{"title":372,"path":373,"stem":374},"Windows Hooks, Hotkeys та Services — Глибока Інтеграція з ОС","\u002Fcsharp\u002Fsystem-programming-windows\u002Fwindows-hooks-services","01.csharp\u002F07.system-programming-windows\u002F20.windows-hooks-services",{"title":376,"path":377,"stem":378},"Системне Програмування C# (Windows) — 07.system-programming-windows","\u002Fcsharp\u002Fsystem-programming-windows\u002Fimplementation_plan","01.csharp\u002F07.system-programming-windows\u002Fimplementation_plan",{"title":380,"icon":132,"path":381,"stem":382,"children":383,"page":59},"Io","\u002Fcsharp\u002Fio","01.csharp\u002F08.io",[384,388,392,396,400],{"title":385,"path":386,"stem":387},"8.1.1. Основи роботи з файловою системою","\u002Fcsharp\u002Fio\u002Ffile-system-basics","01.csharp\u002F08.io\u002F01.file-system-basics",{"title":389,"path":390,"stem":391},"8.1.2. Потоки (Streams) та Серіалізація Даних","\u002Fcsharp\u002Fio\u002Fstreams-serialization","01.csharp\u002F08.io\u002F02.streams-serialization",{"title":393,"path":394,"stem":395},"8.2.1. JSON Serialization з System.Text.Json","\u002Fcsharp\u002Fio\u002Fjson-serialization","01.csharp\u002F08.io\u002F03.json-serialization",{"title":397,"path":398,"stem":399},"8.2.2. XML Serialization та LINQ to XML","\u002Fcsharp\u002Fio\u002Fxml-serialization","01.csharp\u002F08.io\u002F04.xml-serialization",{"title":401,"path":402,"stem":403},"8.2.3. Binary Serialization: MessagePack та Protocol Buffers","\u002Fcsharp\u002Fio\u002Fbinary-serialization","01.csharp\u002F08.io\u002F05.binary-serialization",{"title":405,"icon":132,"path":406,"stem":407,"children":408,"page":59},"Ado Net","\u002Fcsharp\u002Fado-net","01.csharp\u002F09.ado-net",[409,413,417,421,425,429,433,437,441,445,449,453],{"title":410,"path":411,"stem":412},"9.1. Введення в ADO.NET","\u002Fcsharp\u002Fado-net\u002Fintroduction-to-adonet","01.csharp\u002F09.ado-net\u002F01.introduction-to-adonet",{"title":414,"path":415,"stem":416},"9.2. Клас DbConnection — з'єднання з базою даних","\u002Fcsharp\u002Fado-net\u002Fconnection","01.csharp\u002F09.ado-net\u002F02.connection",{"title":418,"path":419,"stem":420},"9.3. Клас DbCommand — виконання SQL-запитів","\u002Fcsharp\u002Fado-net\u002Fcommand-and-queries","01.csharp\u002F09.ado-net\u002F03.command-and-queries",{"title":422,"path":423,"stem":424},"9.4. Клас DbDataReader — ефективне читання даних","\u002Fcsharp\u002Fado-net\u002Fdatareader","01.csharp\u002F09.ado-net\u002F04.datareader",{"title":426,"path":427,"stem":428},"9.5. Параметризовані запити та захист від SQL Injection","\u002Fcsharp\u002Fado-net\u002Fparameters-and-sql-injection","01.csharp\u002F09.ado-net\u002F05.parameters-and-sql-injection",{"title":430,"path":431,"stem":432},"9.6. Транзакції в ADO.NET","\u002Fcsharp\u002Fado-net\u002Ftransactions","01.csharp\u002F09.ado-net\u002F06.transactions",{"title":434,"path":435,"stem":436},"9.7. DbProviderFactory — провайдер-незалежний код","\u002Fcsharp\u002Fado-net\u002Fprovider-factory","01.csharp\u002F09.ado-net\u002F07.provider-factory",{"title":438,"path":439,"stem":440},"9.8. Асинхронний доступ до даних","\u002Fcsharp\u002Fado-net\u002Fasync-data-access","01.csharp\u002F09.ado-net\u002F08.async-data-access",{"title":442,"path":443,"stem":444},"9.9. Від'єднаний режим: DataSet, DataTable, DataRow","\u002Fcsharp\u002Fado-net\u002Fdisconnected-mode-dataset","01.csharp\u002F09.ado-net\u002F09.disconnected-mode-dataset",{"title":446,"path":447,"stem":448},"9.10. DataAdapter — міст між DataSet та базою даних","\u002Fcsharp\u002Fado-net\u002Fdata-adapter","01.csharp\u002F09.ado-net\u002F10.data-adapter",{"title":450,"path":451,"stem":452},"9.11. Data Mapper та Repository: Архітектура доступу до даних","\u002Fcsharp\u002Fado-net\u002Fdata-mapper-repository","01.csharp\u002F09.ado-net\u002F11.data-mapper-repository",{"title":454,"path":455,"stem":456},"9.12. Identity Map, Unit of Work та Specification Pattern","\u002Fcsharp\u002Fado-net\u002Fadvanced-patterns","01.csharp\u002F09.ado-net\u002F12.advanced-patterns",{"title":458,"icon":255,"path":459,"stem":460,"children":461,"page":59},"Ef Core","\u002Fcsharp\u002Fef-core","01.csharp\u002F10.ef-core",[462,466,470,474,478,482,486,490,494,498,502,506,510,514,518,522,526,532,538,542,546,550,554,558,562,566,570,574,578,582,586,590,594,598,602,606,610,614,618,622,626,630,634,638,642,646],{"title":463,"path":464,"stem":465},"Що таке ORM? Від SQL до об'єктів","\u002Fcsharp\u002Fef-core\u002Fwhat-is-orm","01.csharp\u002F10.ef-core\u002F01.what-is-orm",{"title":467,"path":468,"stem":469},"Перший проєкт — від нуля до CRUD","\u002Fcsharp\u002Fef-core\u002Ffirst-project","01.csharp\u002F10.ef-core\u002F02.first-project",{"title":471,"path":472,"stem":473},"DbContext — Серце EF Core","\u002Fcsharp\u002Fef-core\u002Fdbcontext-deep-dive","01.csharp\u002F10.ef-core\u002F03.dbcontext-deep-dive",{"title":475,"path":476,"stem":477},"Провайдери баз даних — Архітектура та Вибір СУБД","\u002Fcsharp\u002Fef-core\u002Fdatabase-providers","01.csharp\u002F10.ef-core\u002F04.database-providers",{"title":479,"path":480,"stem":481},"Конвенції EF Core — Магія без конфігурації","\u002Fcsharp\u002Fef-core\u002Fconventions","01.csharp\u002F10.ef-core\u002F05.conventions",{"title":483,"path":484,"stem":485},"Fluent API та Data Annotations — Явна конфігурація моделі","\u002Fcsharp\u002Fef-core\u002Ffluent-api-vs-annotations","01.csharp\u002F10.ef-core\u002F06.fluent-api-vs-annotations",{"title":487,"path":488,"stem":489},"Зв'язки — One-to-One та One-to-Many","\u002Fcsharp\u002Fef-core\u002Frelationships-basics","01.csharp\u002F10.ef-core\u002F07.relationships-basics",{"title":491,"path":492,"stem":493},"Зв'язки Advanced — Many-to-Many та Складні Сценарії","\u002Fcsharp\u002Fef-core\u002Frelationships-advanced","01.csharp\u002F10.ef-core\u002F08.relationships-advanced",{"title":495,"path":496,"stem":497},"Властивості — Типи, Конвертери, Компаратори (Частина 1)","\u002Fcsharp\u002Fef-core\u002Fproperty-configuration-part1","01.csharp\u002F10.ef-core\u002F09.property-configuration-part1",{"title":499,"path":500,"stem":501},"Властивості — Value Comparers, Generators, Shadow Properties (Частина 2)","\u002Fcsharp\u002Fef-core\u002Fproperty-configuration-part2","01.csharp\u002F10.ef-core\u002F09.property-configuration-part2",{"title":503,"path":504,"stem":505},"Складні типи — Owned Types та Complex Types (Частина 1)","\u002Fcsharp\u002Fef-core\u002Fcomplex-types-owned-part1","01.csharp\u002F10.ef-core\u002F10.complex-types-owned-part1",{"title":507,"path":508,"stem":509},"Складні типи — Complex Types, Keyless Entities, Порівняння (Частина 2)","\u002Fcsharp\u002Fef-core\u002Fcomplex-types-owned-part2","01.csharp\u002F10.ef-core\u002F10.complex-types-owned-part2",{"title":511,"path":512,"stem":513},"JSON Columns — Складні дані у JSON (Частина 1)","\u002Fcsharp\u002Fef-core\u002Fjson-columns-part1","01.csharp\u002F10.ef-core\u002F11.json-columns-part1",{"title":515,"path":516,"stem":517},"JSON Columns — Value Comparers, Індекси, Провайдери (Частина 2)","\u002Fcsharp\u002Fef-core\u002Fjson-columns-part2","01.csharp\u002F10.ef-core\u002F11.json-columns-part2",{"title":519,"path":520,"stem":521},"Успадкування — Абстрактні класи та TPH (Частина 1)","\u002Fcsharp\u002Fef-core\u002Finheritance-part1","01.csharp\u002F10.ef-core\u002F12.inheritance-part1",{"title":523,"path":524,"stem":525},"Успадкування — TPT, TPC та Порівняння Стратегій (Частина 2)","\u002Fcsharp\u002Fef-core\u002Finheritance-part2","01.csharp\u002F10.ef-core\u002F12.inheritance-part2",{"title":527,"path":528,"stem":529,"children":530},"Індекси, Обмеження та Схема (Частина 1)","\u002Fcsharp\u002Fef-core\u002Findexes-constraints-part1","01.csharp\u002F10.ef-core\u002F13.indexes-constraints-part1",[531],{"title":527,"path":528,"stem":529},{"title":533,"path":534,"stem":535,"children":536},"Індекси, Обмеження та Схема (Частина 2)","\u002Fcsharp\u002Fef-core\u002Findexes-constraints-part2","01.csharp\u002F10.ef-core\u002F13.indexes-constraints-part2",[537],{"title":533,"path":534,"stem":535},{"title":539,"path":540,"stem":541},"Seed Data — Початкові Дані (Частина 1)","\u002Fcsharp\u002Fef-core\u002Fseeding-part1","01.csharp\u002F10.ef-core\u002F14.seeding-part1",{"title":543,"path":544,"stem":545},"Seed Data — SQL-скрипти, Bogus та Стратегії (Частина 2)","\u002Fcsharp\u002Fef-core\u002Fseeding-part2","01.csharp\u002F10.ef-core\u002F14.seeding-part2",{"title":547,"path":548,"stem":549},"Global Query Filters — Глобальні Фільтри (Частина 1)","\u002Fcsharp\u002Fef-core\u002Fglobal-query-filters-part1","01.csharp\u002F10.ef-core\u002F15.global-query-filters-part1",{"title":551,"path":552,"stem":553},"Global Query Filters — Підводні камені та Інтеграція (Частина 2)","\u002Fcsharp\u002Fef-core\u002Fglobal-query-filters-part2","01.csharp\u002F10.ef-core\u002F15.global-query-filters-part2",{"title":555,"path":556,"stem":557},"LINQ-запити в EF Core (Частина 1)","\u002Fcsharp\u002Fef-core\u002Flinq-queries-part1","01.csharp\u002F10.ef-core\u002F16.linq-queries-part1",{"title":559,"path":560,"stem":561},"LINQ-запити в EF Core (Частина 2)","\u002Fcsharp\u002Fef-core\u002Flinq-queries-part2","01.csharp\u002F10.ef-core\u002F16.linq-queries-part2",{"title":563,"path":564,"stem":565},"Завантаження Пов'язаних Даних (Частина 1)","\u002Fcsharp\u002Fef-core\u002Floading-related-data-part1","01.csharp\u002F10.ef-core\u002F17.loading-related-data-part1",{"title":567,"path":568,"stem":569},"Завантаження Пов'язаних Даних (Частина 2)","\u002Fcsharp\u002Fef-core\u002Floading-related-data-part2","01.csharp\u002F10.ef-core\u002F17.loading-related-data-part2",{"title":571,"path":572,"stem":573},"Raw SQL, Views та Stored Procedures (Частина 1)","\u002Fcsharp\u002Fef-core\u002Fraw-sql-part1","01.csharp\u002F10.ef-core\u002F18.raw-sql-part1",{"title":575,"path":576,"stem":577},"Raw SQL — Stored Procedures, DbFunction та Bulk Operations (Частина 2)","\u002Fcsharp\u002Fef-core\u002Fraw-sql-part2","01.csharp\u002F10.ef-core\u002F18.raw-sql-part2",{"title":579,"path":580,"stem":581},"Продвинуті Запити — Compiled Queries, Bulk та Оптимізація (Частина 1)","\u002Fcsharp\u002Fef-core\u002Fadvanced-queries-part1","01.csharp\u002F10.ef-core\u002F19.advanced-queries-part1",{"title":583,"path":584,"stem":585},"Продвинуті Запити — Query Tags, Bulk та Interceptors (Частина 2)","\u002Fcsharp\u002Fef-core\u002Fadvanced-queries-part2","01.csharp\u002F10.ef-core\u002F19.advanced-queries-part2",{"title":587,"path":588,"stem":589},"Change Tracker — Відстеження Змін (Частина 1)","\u002Fcsharp\u002Fef-core\u002Fchange-tracking-part1","01.csharp\u002F10.ef-core\u002F20.change-tracking-part1",{"title":591,"path":592,"stem":593},"Change Tracker — Графи Об'єктів та Disconnected (Частина 2)","\u002Fcsharp\u002Fef-core\u002Fchange-tracking-part2","01.csharp\u002F10.ef-core\u002F20.change-tracking-part2",{"title":595,"path":596,"stem":597},"Збереження Даних та Транзакції (Частина 1)","\u002Fcsharp\u002Fef-core\u002Fsaving-data-part1","01.csharp\u002F10.ef-core\u002F21.saving-data-part1",{"title":599,"path":600,"stem":601},"Збереження Даних — Concurrency та Outbox (Частина 2)","\u002Fcsharp\u002Fef-core\u002Fsaving-data-part2","01.csharp\u002F10.ef-core\u002F21.saving-data-part2",{"title":603,"path":604,"stem":605},"Конкурентність та Блокування (Частина 1)","\u002Fcsharp\u002Fef-core\u002Fconcurrency-part1","01.csharp\u002F10.ef-core\u002F22.concurrency-part1",{"title":607,"path":608,"stem":609},"Конкурентність — Дедлоки та Queue Processing (Частина 2)","\u002Fcsharp\u002Fef-core\u002Fconcurrency-part2","01.csharp\u002F10.ef-core\u002F22.concurrency-part2",{"title":611,"path":612,"stem":613},"Міграції в EF Core — Основи (Частина 1)","\u002Fcsharp\u002Fef-core\u002Fmigrations-basics-part1","01.csharp\u002F10.ef-core\u002F23.migrations-basics-part1",{"title":615,"path":616,"stem":617},"Міграції в EF Core — Основи (Частина 2)","\u002Fcsharp\u002Fef-core\u002Fmigrations-basics-part2","01.csharp\u002F10.ef-core\u002F23.migrations-basics-part2",{"title":619,"path":620,"stem":621},"Міграції — Просунуті Сценарії (Частина 1)","\u002Fcsharp\u002Fef-core\u002Fmigrations-advanced-part1","01.csharp\u002F10.ef-core\u002F24.migrations-advanced-part1",{"title":623,"path":624,"stem":625},"Міграції — Просунуті Сценарії (Частина 2)","\u002Fcsharp\u002Fef-core\u002Fmigrations-advanced-part2","01.csharp\u002F10.ef-core\u002F24.migrations-advanced-part2",{"title":627,"path":628,"stem":629},"Управління Схемою та Database-First (Частина 1)","\u002Fcsharp\u002Fef-core\u002Fschema-management-part1","01.csharp\u002F10.ef-core\u002F25.schema-management-part1",{"title":631,"path":632,"stem":633},"Управління Схемою та Database-First (Частина 2)","\u002Fcsharp\u002Fef-core\u002Fschema-management-part2","01.csharp\u002F10.ef-core\u002F25.schema-management-part2",{"title":635,"path":636,"stem":637},"Продуктивність EF Core — Основи (Частина 1)","\u002Fcsharp\u002Fef-core\u002Fperformance-fundamentals-part1","01.csharp\u002F10.ef-core\u002F26.performance-fundamentals-part1",{"title":639,"path":640,"stem":641},"Interceptors в EF Core (Частина 1)","\u002Fcsharp\u002Fef-core\u002Finterceptors-part1","01.csharp\u002F10.ef-core\u002F29.interceptors-part1",{"title":643,"path":644,"stem":645},"Interceptors в EF Core — Connection, Transaction та Materialization (Частина 2)","\u002Fcsharp\u002Fef-core\u002Finterceptors-part2","01.csharp\u002F10.ef-core\u002F29.interceptors-part2",{"title":647,"path":648,"stem":649},"План вивчення Entity Framework Core — Повний курс","\u002Fcsharp\u002Fef-core\u002Fimplementation_plan","01.csharp\u002F10.ef-core\u002Fimplementation_plan",{"title":651,"icon":652,"path":653,"stem":654,"children":655,"page":59},"ASP.NET","i-devicon-dotnetcore","\u002Fcsharp\u002Faspnet","01.csharp\u002F11.aspnet",[656,730,791,869,927,941,967,1057,1111,1182,1212,1289,1346],{"title":657,"icon":658,"path":659,"stem":660,"children":661,"page":59},"Minimal API","i-lucide-network","\u002Fcsharp\u002Faspnet\u002Fminimal-api","01.csharp\u002F11.aspnet\u002F01.minimal-api",[662,666,670,674,678,682,686,690,694,698,702,706,710,714,718,722,726],{"title":663,"path":664,"stem":665},"Вступ до ASP.NET та еволюція фреймворку","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Fintroduction","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F01.introduction",{"title":667,"path":668,"stem":669},"Перший додаток на ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Ffirst-application","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F02.first-application",{"title":671,"path":672,"stem":673},"WebApplication, Builder та Dependency Injection","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Fwebapplication-builder","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F03.webapplication-builder",{"title":675,"path":676,"stem":677},"Конвеєр запитів та Middleware","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Frequest-pipeline-middleware","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F04.request-pipeline-middleware",{"title":679,"path":680,"stem":681},"Маршрутизація в ASP.NET Core: Основи","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Frouting-basics","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F05.routing-basics",{"title":683,"path":684,"stem":685},"Маршрутизація в ASP.NET Core: Розширені можливості","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Frouting-advanced","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F06.routing-advanced",{"title":687,"path":688,"stem":689},"Статичні файли в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Fstatic-files","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F07.static-files",{"title":691,"path":692,"stem":693},"Статичні Активи: MapStaticAssets (ASP.NET Core 9.0)","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Fstatic-assets","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F08.static-assets",{"title":695,"path":696,"stem":697},"Конфігурація в ASP.NET Core: Основи","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Fconfiguration-fundamentals","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F09.configuration-fundamentals",{"title":699,"path":700,"stem":701},"Конфігурація: Паттерн Options","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Fconfiguration-options","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F10.configuration-options",{"title":703,"path":704,"stem":705},"Логування в ASP.NET Core: Основи","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Flogging-basics","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F11.logging-basics",{"title":707,"path":708,"stem":709},"Логування: Serilog та Middleware","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Flogging-advanced","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F12.logging-advanced",{"title":711,"path":712,"stem":713},"Управління станом: HttpContext.Items та Cookies","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Fstate-management","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F13.state-management",{"title":715,"path":716,"stem":717},"Стан сесії: Sessions","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Fsession-state","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F14.session-state",{"title":719,"path":720,"stem":721},"Структура проєкту: від хаосу до архітектури","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Fproject-structure","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F15.project-structure",{"title":723,"path":724,"stem":725},"Scalar у Minimal API: повний проєкт і Fluent OpenAPI","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Fscalar-openapi-fluent","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F16.scalar-openapi-fluent",{"title":727,"path":728,"stem":729},"Swagger \u002F Swashbuckle у Minimal API: окремий класичний шлях","\u002Fcsharp\u002Faspnet\u002Fminimal-api\u002Fswagger-swashbuckle","01.csharp\u002F11.aspnet\u002F01.minimal-api\u002F17.swagger-swashbuckle",{"title":731,"icon":658,"path":732,"stem":733,"children":734,"page":59},"API","\u002Fcsharp\u002Faspnet\u002Fapi","01.csharp\u002F11.aspnet\u002F02.api",[735,739,743,747,751,755,759,763,767,771,775,779,783,787],{"title":736,"path":737,"stem":738},"Що таке API. Клієнт-серверна архітектура","\u002Fcsharp\u002Faspnet\u002Fapi\u002Fwhat-is-api","01.csharp\u002F11.aspnet\u002F02.api\u002F01.what-is-api",{"title":740,"path":741,"stem":742},"Формати даних: JSON, XML, TOML та бінарні формати","\u002Fcsharp\u002Faspnet\u002Fapi\u002Fdata-formats","01.csharp\u002F11.aspnet\u002F02.api\u002F02.data-formats",{"title":744,"path":745,"stem":746},"Парадигми API та концепція REST","\u002Fcsharp\u002Faspnet\u002Fapi\u002Fapi-paradigms-rest","01.csharp\u002F11.aspnet\u002F02.api\u002F03.api-paradigms-rest",{"title":748,"path":749,"stem":750},"HTTP-методи, статус-коди та заголовки","\u002Fcsharp\u002Faspnet\u002Fapi\u002Fhttp-methods-status-codes","01.csharp\u002F11.aspnet\u002F02.api\u002F04.http-methods-status-codes",{"title":752,"path":753,"stem":754},"Організація HTTP API за принципами REST","\u002Fcsharp\u002Faspnet\u002Fapi\u002Frest-organizing","01.csharp\u002F11.aspnet\u002F02.api\u002F05.rest-organizing",{"title":756,"path":757,"stem":758},"Номенклатура URL та CRUD-операції","\u002Fcsharp\u002Faspnet\u002Fapi\u002Furl-nomenclature-crud","01.csharp\u002F11.aspnet\u002F02.api\u002F06.url-nomenclature-crud",{"title":760,"path":761,"stem":762},"Правила дизайну: іменування та стандарти","\u002Fcsharp\u002Faspnet\u002Fapi\u002Fapi-design-naming","01.csharp\u002F11.aspnet\u002F02.api\u002F07.api-design-naming",{"title":764,"path":765,"stem":766},"Валідація, ліміти та обробка помилок","\u002Fcsharp\u002Faspnet\u002Fapi\u002Fapi-design-validation","01.csharp\u002F11.aspnet\u002F02.api\u002F08.api-design-validation",{"title":768,"path":769,"stem":770},"Обробка помилок у Minimal API","\u002Fcsharp\u002Faspnet\u002Fapi\u002Ferror-handling-http","01.csharp\u002F11.aspnet\u002F02.api\u002F09.error-handling-http",{"title":772,"path":773,"stem":774},"Ідемпотентність та синхронізація стану","\u002Fcsharp\u002Faspnet\u002Fapi\u002Fidempotency-sync","01.csharp\u002F11.aspnet\u002F02.api\u002F10.idempotency-sync",{"title":776,"path":777,"stem":778},"Пагінація та організація списків","\u002Fcsharp\u002Faspnet\u002Fapi\u002Fpagination-lists","01.csharp\u002F11.aspnet\u002F02.api\u002F11.pagination-lists",{"title":780,"path":781,"stem":782},"Безпека API, кешування та інтернаціоналізація","\u002Fcsharp\u002Faspnet\u002Fapi\u002Fsecurity-auth","01.csharp\u002F11.aspnet\u002F02.api\u002F12.security-auth",{"title":784,"path":785,"stem":786},"Процес проєктування API та документування","\u002Fcsharp\u002Faspnet\u002Fapi\u002Fapi-design-process","01.csharp\u002F11.aspnet\u002F02.api\u002F13.api-design-process",{"title":788,"path":789,"stem":790},"OpenAPI: контракт, специфікація та документація API","\u002Fcsharp\u002Faspnet\u002Fapi\u002Fopenapi","01.csharp\u002F11.aspnet\u002F02.api\u002F14.openapi",{"title":792,"icon":793,"path":794,"stem":795,"children":796,"page":59},"Auth","i-lucide-shield-check","\u002Fcsharp\u002Faspnet\u002Fauth","01.csharp\u002F11.aspnet\u002F03.auth",[797,801,805,809,813,817,821,825,829,833,837,841,845,849,853,857,861,865],{"title":798,"path":799,"stem":800},"Основи аутентифікації та авторизації","\u002Fcsharp\u002Faspnet\u002Fauth\u002Fauth-fundamentals","01.csharp\u002F11.aspnet\u002F03.auth\u002F01.auth-fundamentals",{"title":802,"path":803,"stem":804},"JWT-аутентифікація","\u002Fcsharp\u002Faspnet\u002Fauth\u002Fjwt-authentication","01.csharp\u002F11.aspnet\u002F03.auth\u002F02.jwt-authentication",{"title":806,"path":807,"stem":808},"Авторизація: ролі, політики та resource-based доступ","\u002Fcsharp\u002Faspnet\u002Fauth\u002Fauthorization-policies","01.csharp\u002F11.aspnet\u002F03.auth\u002F03.authorization-policies",{"title":810,"path":811,"stem":812},"Cookie-аутентифікація та ASP.NET Core Identity","\u002Fcsharp\u002Faspnet\u002Fauth\u002Fcookie-auth-identity","01.csharp\u002F11.aspnet\u002F03.auth\u002F04.cookie-auth-identity",{"title":814,"path":815,"stem":816},"JWT + Refresh Tokens (HttpOnly Cookie)","\u002Fcsharp\u002Faspnet\u002Fauth\u002F04b.identity-auth-jwt","01.csharp\u002F11.aspnet\u002F03.auth\u002F04b.identity-auth-jwt",{"title":818,"path":819,"stem":820},"Identity: Підтвердження Email та Скидання Пароля","\u002Fcsharp\u002Faspnet\u002Fauth\u002Fidentity-email-confirmation","01.csharp\u002F11.aspnet\u002F03.auth\u002F05.identity-email-confirmation",{"title":822,"path":823,"stem":824},"Identity: Двофакторна Аутентифікація (2FA)","\u002Fcsharp\u002Faspnet\u002Fauth\u002Fidentity-two-factor","01.csharp\u002F11.aspnet\u002F03.auth\u002F06.identity-two-factor",{"title":826,"path":827,"stem":828},"Identity: Внутрішня Архітектура та Кастомізація","\u002Fcsharp\u002Faspnet\u002Fauth\u002Fidentity-internals","01.csharp\u002F11.aspnet\u002F03.auth\u002F07.identity-internals",{"title":830,"path":831,"stem":832},"OAuth 2.0 та зовнішні провайдери","\u002Fcsharp\u002Faspnet\u002Fauth\u002Foauth-external-providers","01.csharp\u002F11.aspnet\u002F03.auth\u002F08.oauth-external-providers",{"title":834,"path":835,"stem":836},"Безпека на практиці: CORS, HTTPS та захист від атак","\u002Fcsharp\u002Faspnet\u002Fauth\u002Fsecurity-hardening","01.csharp\u002F11.aspnet\u002F03.auth\u002F09.security-hardening",{"title":838,"path":839,"stem":840},"Теорія OAuth 2.0: Поняття, Аналогії та Флоу","\u002Fcsharp\u002Faspnet\u002Fauth\u002Foauth-theory","01.csharp\u002F11.aspnet\u002F03.auth\u002F10.oauth-theory",{"title":842,"path":843,"stem":844},"OIDC, OAuth 2.0 та Keycloak в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Fauth\u002Foidc-keycloak","01.csharp\u002F11.aspnet\u002F03.auth\u002F10.oidc-keycloak",{"title":846,"path":847,"stem":848},"API Keys аутентифікація в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Fauth\u002Fapi-keys","01.csharp\u002F11.aspnet\u002F03.auth\u002F11.api-keys",{"title":850,"path":851,"stem":852},"Rate Limiting та Throttling в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Fauth\u002Frate-limiting","01.csharp\u002F11.aspnet\u002F03.auth\u002F12.rate-limiting",{"title":854,"path":855,"stem":856},"Refresh Token Rotation в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Fauth\u002Frefresh-token-rotation","01.csharp\u002F11.aspnet\u002F03.auth\u002F13.refresh-token-rotation",{"title":858,"path":859,"stem":860},"Certificate Authentication та mTLS в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Fauth\u002Fcertificate-auth","01.csharp\u002F11.aspnet\u002F03.auth\u002F14.certificate-auth",{"title":862,"path":863,"stem":864},"RBAC, ABAC та ReBAC в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Fauth\u002Frbac-abac-rebac","01.csharp\u002F11.aspnet\u002F03.auth\u002F15.rbac-abac-rebac",{"title":866,"path":867,"stem":868},"Multi-tenancy та ізоляція даних в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Fauth\u002Fmulti-tenancy","01.csharp\u002F11.aspnet\u002F03.auth\u002F16.multi-tenancy",{"title":870,"icon":871,"path":872,"stem":873,"children":874,"page":59},"Нотифікації","i-lucide-bell","\u002Fcsharp\u002Faspnet\u002Fnotifications","01.csharp\u002F11.aspnet\u002F04.notifications",[875,879,883,887,891,895,899,903,907,911,915,919,923],{"title":876,"path":877,"stem":878},"In-App нотифікації через базу даних","\u002Fcsharp\u002Faspnet\u002Fnotifications\u002Fin-app-database-notifications","01.csharp\u002F11.aspnet\u002F04.notifications\u002F01.in-app-database-notifications",{"title":880,"path":881,"stem":882},"Polling: Регулярний запит оновлень","\u002Fcsharp\u002Faspnet\u002Fnotifications\u002Fpolling","01.csharp\u002F11.aspnet\u002F04.notifications\u002F02.polling",{"title":884,"path":885,"stem":886},"Server-Sent Events: Однострімовий push від сервера","\u002Fcsharp\u002Faspnet\u002Fnotifications\u002Fserver-sent-events","01.csharp\u002F11.aspnet\u002F04.notifications\u002F03.server-sent-events",{"title":888,"path":889,"stem":890},"WebSockets: Двостороннє з'єднання в реальному часі","\u002Fcsharp\u002Faspnet\u002Fnotifications\u002Fwebsockets","01.csharp\u002F11.aspnet\u002F04.notifications\u002F04.websockets",{"title":892,"path":893,"stem":894},"SignalR: Абстракція над транспортами реального часу","\u002Fcsharp\u002Faspnet\u002Fnotifications\u002Fsignalr","01.csharp\u002F11.aspnet\u002F04.notifications\u002F05.signalr",{"title":896,"path":897,"stem":898},"Background Services: Фонові задачі в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Fnotifications\u002Fbackground-services","01.csharp\u002F11.aspnet\u002F04.notifications\u002F06.background-services",{"title":900,"path":901,"stem":902},"Web Push нотифікації","\u002Fcsharp\u002Faspnet\u002Fnotifications\u002Fweb-push","01.csharp\u002F11.aspnet\u002F04.notifications\u002F07.web-push",{"title":904,"path":905,"stem":906},"Email нотифікації","\u002Fcsharp\u002Faspnet\u002Fnotifications\u002Femail-notifications","01.csharp\u002F11.aspnet\u002F04.notifications\u002F08.email-notifications",{"title":908,"path":909,"stem":910},"Порівняння підходів: Як вибрати правильну технологію нотифікацій","\u002Fcsharp\u002Faspnet\u002Fnotifications\u002Fchoosing-the-right-approach","01.csharp\u002F11.aspnet\u002F04.notifications\u002F09.choosing-the-right-approach",{"title":912,"path":913,"stem":914},"Hangfire: Надійне планування фонових задач","\u002Fcsharp\u002Faspnet\u002Fnotifications\u002Fhangfire","01.csharp\u002F11.aspnet\u002F04.notifications\u002F10.hangfire",{"title":916,"path":917,"stem":918},"Практика: Конвертація зображень у WebP через Hangfire","\u002Fcsharp\u002Faspnet\u002Fnotifications\u002Fhangfire-image-webp","01.csharp\u002F11.aspnet\u002F04.notifications\u002F11.hangfire-image-webp",{"title":920,"path":921,"stem":922},"Практика: Підготовка відео до HLS-стрімінгу через Hangfire","\u002Fcsharp\u002Faspnet\u002Fnotifications\u002Fhangfire-video-hls","01.csharp\u002F11.aspnet\u002F04.notifications\u002F12.hangfire-video-hls",{"title":924,"path":925,"stem":926},"Telegram-нотифікації: від одного повідомлення до масових розсилок і мульти-канального підходу","\u002Fcsharp\u002Faspnet\u002Fnotifications\u002Ftelegram-notifications","01.csharp\u002F11.aspnet\u002F04.notifications\u002F13.telegram-notifications",{"title":928,"icon":929,"path":930,"stem":931,"children":932,"page":59},"Інтернаціоналізація","i-lucide-languages","\u002Fcsharp\u002Faspnet\u002Fi18n","01.csharp\u002F11.aspnet\u002F05.i18n",[933,937],{"title":934,"path":935,"stem":936},"Інтернаціоналізація (i18n) у Minimal API: від A до Я","\u002Fcsharp\u002Faspnet\u002Fi18n\u002Finternationalization","01.csharp\u002F11.aspnet\u002F05.i18n\u002F01.internationalization",{"title":938,"path":939,"stem":940},"Humanizer: людиномовні рядки у .NET","\u002Fcsharp\u002Faspnet\u002Fi18n\u002Fhumanizer","01.csharp\u002F11.aspnet\u002F05.i18n\u002F02.humanizer",{"title":942,"icon":943,"path":944,"stem":945,"children":946,"page":59},"Кешування","i-lucide-layers","\u002Fcsharp\u002Faspnet\u002Fcaching","01.csharp\u002F11.aspnet\u002F06.caching",[947,951,955,959,963],{"title":948,"path":949,"stem":950},"Огляд кешування: чотири рівні і коли що обирати","\u002Fcsharp\u002Faspnet\u002Fcaching\u002Fcaching","01.csharp\u002F11.aspnet\u002F06.caching\u002F01.caching",{"title":952,"path":953,"stem":954},"IMemoryCache: кеш в оперативній пам'яті","\u002Fcsharp\u002Faspnet\u002Fcaching\u002Fmemory-cache","01.csharp\u002F11.aspnet\u002F06.caching\u002F02.memory-cache",{"title":956,"path":957,"stem":958},"IDistributedCache і Redis: розподілений кеш","\u002Fcsharp\u002Faspnet\u002Fcaching\u002Fdistributed-cache","01.csharp\u002F11.aspnet\u002F06.caching\u002F03.distributed-cache",{"title":960,"path":961,"stem":962},"Response Cache: HTTP-кешування через Cache-Control","\u002Fcsharp\u002Faspnet\u002Fcaching\u002Fresponse-cache","01.csharp\u002F11.aspnet\u002F06.caching\u002F04.response-cache",{"title":964,"path":965,"stem":966},"Output Cache: серверний кеш HTTP-відповідей (.NET 7+)","\u002Fcsharp\u002Faspnet\u002Fcaching\u002Foutput-cache","01.csharp\u002F11.aspnet\u002F06.caching\u002F05.output-cache",{"title":968,"icon":969,"path":970,"stem":971,"children":972,"page":59},"Тестування","i-lucide-test-tube","\u002Fcsharp\u002Faspnet\u002Ftesting","01.csharp\u002F11.aspnet\u002F07.testing",[973,977,981,985,989,993,997,1001,1005,1009,1013,1017,1021,1025,1029,1033,1037,1041,1045,1049,1053],{"title":974,"path":975,"stem":976},"Що таке тестування? Від інтуїції до науки","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Fwhat-is-testing","01.csharp\u002F11.aspnet\u002F07.testing\u002F01.what-is-testing",{"title":978,"path":979,"stem":980},"Піраміда тестування — Стратегія, а не Догма","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Ftesting-pyramid","01.csharp\u002F11.aspnet\u002F07.testing\u002F02.testing-pyramid",{"title":982,"path":983,"stem":984},"Дві Школи Тестування — Лондон проти Детройту","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Ftesting-schools","01.csharp\u002F11.aspnet\u002F07.testing\u002F03.testing-schools",{"title":986,"path":987,"stem":988},"TDD та BDD — Тести як Дизайн-інструмент","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Ftdd-and-bdd","01.csharp\u002F11.aspnet\u002F07.testing\u002F04.tdd-and-bdd",{"title":990,"path":991,"stem":992},"Що саме тестувати — Техніки аналізу та Циклomatична складність","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Fwhat-to-test","01.csharp\u002F11.aspnet\u002F07.testing\u002F05.what-to-test",{"title":994,"path":995,"stem":996},"Тестові Фреймворки — Навіщо вони і що всередині","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Ftest-frameworks","01.csharp\u002F11.aspnet\u002F07.testing\u002F06.test-frameworks",{"title":998,"path":999,"stem":1000},"xUnit — Факти, Теорії та Lifecycle тестів","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Fxunit-basics","01.csharp\u002F11.aspnet\u002F07.testing\u002F07.xunit-basics",{"title":1002,"path":1003,"stem":1004},"xUnit Advanced — Fixtures, Кастомізація та Розширення","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Fxunit-advanced","01.csharp\u002F11.aspnet\u002F07.testing\u002F08.xunit-advanced",{"title":1006,"path":1007,"stem":1008},"Moq — Глибоке занурення в мокування","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Fmocking-with-moq","01.csharp\u002F11.aspnet\u002F07.testing\u002F09.mocking-with-moq",{"title":1010,"path":1011,"stem":1012},"Тестування Баз Даних — EF Core, SQLite та Testcontainers","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Fdatabase-testing","01.csharp\u002F11.aspnet\u002F07.testing\u002F10.database-testing",{"title":1014,"path":1015,"stem":1016},"Integration Testing — Частина 1 [Теорія та WebApplicationFactory]","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Fintegration-testing","01.csharp\u002F11.aspnet\u002F07.testing\u002F11.integration-testing",{"title":1018,"path":1019,"stem":1020},"Інтеграційне тестування — Практика","\u002Fcsharp\u002Faspnet\u002Ftesting\u002F11a.integration-testing-practice","01.csharp\u002F11.aspnet\u002F07.testing\u002F11a.integration-testing-practice",{"title":1022,"path":1023,"stem":1024},"Integration Testing — Частина 2 [Просунуті Сценарії та Testcontainers]","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Fintegration-testing-advanced","01.csharp\u002F11.aspnet\u002F07.testing\u002F12.integration-testing-advanced",{"title":1026,"path":1027,"stem":1028},"Професійний Postman: Колекції, Змінні та GitHub Інтеграція","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Fpostman-professional","01.csharp\u002F11.aspnet\u002F07.testing\u002F13.postman-professional",{"title":1030,"path":1031,"stem":1032},"HttpClient у Тестах Частина 1: Архітектура та MockHttpMessageHandler","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Fhttpclient-testing","01.csharp\u002F11.aspnet\u002F07.testing\u002F14.httpclient-testing",{"title":1034,"path":1035,"stem":1036},"HttpClient у Тестах Частина 2: WireMock.Net та Resilience","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Fwiremock-net","01.csharp\u002F11.aspnet\u002F07.testing\u002F15.wiremock-net",{"title":1038,"path":1039,"stem":1040},"Патерни та Анти-патерни Тестування: Test Smells","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Ftesting-patterns","01.csharp\u002F11.aspnet\u002F07.testing\u002F16.testing-patterns",{"title":1042,"path":1043,"stem":1044},"Просунуті інструменти: Time, Snapshots та Властивості","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Fadvanced-testing-tools","01.csharp\u002F11.aspnet\u002F07.testing\u002F17.advanced-testing-tools",{"title":1046,"path":1047,"stem":1048},"Тестування Архітектури з NetArchTest","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Farchitecture-testing","01.csharp\u002F11.aspnet\u002F07.testing\u002F18.architecture-testing",{"title":1050,"path":1051,"stem":1052},"Тестування Продуктивності: BenchmarkDotNet, NBomber та k6","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Fperformance-testing","01.csharp\u002F11.aspnet\u002F07.testing\u002F19.performance-testing",{"title":1054,"path":1055,"stem":1056},"Залишок плану для курсу \"Тестування ASP.NET Minimal API\"","\u002Fcsharp\u002Faspnet\u002Ftesting\u002Fremaining_plan","01.csharp\u002F11.aspnet\u002F07.testing\u002Fremaining_plan",{"title":1058,"icon":1059,"path":1060,"stem":1061,"children":1062,"page":59},"Платежі","i-lucide-credit-card","\u002Fcsharp\u002Faspnet\u002Fpayments","01.csharp\u002F11.aspnet\u002F08.payments",[1063,1067,1071,1075,1079,1083,1087,1091,1095,1099,1103,1107],{"title":1064,"path":1065,"stem":1066},"Основи платіжної інфраструктури","\u002Fcsharp\u002Faspnet\u002Fpayments\u002Fpayment-fundamentals","01.csharp\u002F11.aspnet\u002F08.payments\u002F01.payment-fundamentals",{"title":1068,"path":1069,"stem":1070},"Методи оплати в Україні","\u002Fcsharp\u002Faspnet\u002Fpayments\u002Fpayment-methods-ukraine","01.csharp\u002F11.aspnet\u002F08.payments\u002F02.payment-methods-ukraine",{"title":1072,"path":1073,"stem":1074},"PCI DSS та безпека платежів","\u002Fcsharp\u002Faspnet\u002Fpayments\u002Fpci-dss-security","01.csharp\u002F11.aspnet\u002F08.payments\u002F03.pci-dss-security",{"title":1076,"path":1077,"stem":1078},"Архітектура платіжної підсистеми","\u002Fcsharp\u002Faspnet\u002Fpayments\u002Fpayment-architecture","01.csharp\u002F11.aspnet\u002F08.payments\u002F04.payment-architecture",{"title":1080,"path":1081,"stem":1082},"Інтеграція LiqPay (ПриватБанк)","\u002Fcsharp\u002Faspnet\u002Fpayments\u002Fliqpay-integration","01.csharp\u002F11.aspnet\u002F08.payments\u002F05.liqpay-integration",{"title":1084,"path":1085,"stem":1086},"Інтеграція Monobank Acquiring API","\u002Fcsharp\u002Faspnet\u002Fpayments\u002Fmonobank-acquiring","01.csharp\u002F11.aspnet\u002F08.payments\u002F06.monobank-acquiring",{"title":1088,"path":1089,"stem":1090},"Інтеграція Stripe","\u002Fcsharp\u002Faspnet\u002Fpayments\u002Fstripe-integration","01.csharp\u002F11.aspnet\u002F08.payments\u002F07.stripe-integration",{"title":1092,"path":1093,"stem":1094},"Webhooks — глибоке занурення","\u002Fcsharp\u002Faspnet\u002Fpayments\u002Fwebhooks-deep-dive","01.csharp\u002F11.aspnet\u002F08.payments\u002F08.webhooks-deep-dive",{"title":1096,"path":1097,"stem":1098},"Підписки та рекурентні платежі","\u002Fcsharp\u002Faspnet\u002Fpayments\u002Fsubscriptions-recurring","01.csharp\u002F11.aspnet\u002F08.payments\u002F09.subscriptions-recurring",{"title":1100,"path":1101,"stem":1102},"Повернення коштів та диспути","\u002Fcsharp\u002Faspnet\u002Fpayments\u002Frefunds-disputes","01.csharp\u002F11.aspnet\u002F08.payments\u002F10.refunds-disputes",{"title":1104,"path":1105,"stem":1106},"Тестування платіжних інтеграцій","\u002Fcsharp\u002Faspnet\u002Fpayments\u002Ftesting-payments","01.csharp\u002F11.aspnet\u002F08.payments\u002F11.testing-payments",{"title":1108,"path":1109,"stem":1110},"Чекліст виходу в Production","\u002Fcsharp\u002Faspnet\u002Fpayments\u002Fproduction-checklist","01.csharp\u002F11.aspnet\u002F08.payments\u002F12.production-checklist",{"title":1112,"icon":1113,"items":1114,"path":1127,"stem":1128,"children":1129,"page":59},"Популярні бібліотеки","lucide:box",[1115,1116,1117,1118,1119,1120,1121,1122,1123,1124,1125,1126],"01.fluent-validation","02.mapster","03.erroror-result-pattern","04.serilog","05.mediatr","06.polly","07.health-checks","08.feature-management","09.fluent-email","10.quest-pdf","11.bogus","12.humanizer-guard","\u002Fcsharp\u002Faspnet\u002Flibraries","01.csharp\u002F11.aspnet\u002F09.libraries",[1130,1134,1138,1142,1146,1150,1154,1158,1162,1166,1170,1174,1178],{"title":1131,"path":1132,"stem":1133},"Валідація з FluentValidation в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Flibraries\u002Ffluent-validation","01.csharp\u002F11.aspnet\u002F09.libraries\u002F01.fluent-validation",{"title":1135,"path":1136,"stem":1137},"Маппінг об","\u002Fcsharp\u002Faspnet\u002Flibraries\u002Fmapster","01.csharp\u002F11.aspnet\u002F09.libraries\u002F02.mapster",{"title":1139,"path":1140,"stem":1141},"Обробка помилок з ErrorOr та Result Pattern в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Flibraries\u002Ferroror-result-pattern","01.csharp\u002F11.aspnet\u002F09.libraries\u002F03.erroror-result-pattern",{"title":1143,"path":1144,"stem":1145},"Структуроване логування з Serilog в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Flibraries\u002Fserilog","01.csharp\u002F11.aspnet\u002F09.libraries\u002F04.serilog",{"title":1147,"path":1148,"stem":1149},"CQRS та Mediator з MediatR в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Flibraries\u002Fmediatr","01.csharp\u002F11.aspnet\u002F09.libraries\u002F05.mediatr",{"title":1151,"path":1152,"stem":1153},"Відмовостійкість з Polly в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Flibraries\u002Fpolly","01.csharp\u002F11.aspnet\u002F09.libraries\u002F06.polly",{"title":1155,"path":1156,"stem":1157},"Health Checks в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Flibraries\u002Fhealth-checks","01.csharp\u002F11.aspnet\u002F09.libraries\u002F07.health-checks",{"title":1159,"path":1160,"stem":1161},"Feature Management та Feature Flags в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Flibraries\u002Ffeature-management","01.csharp\u002F11.aspnet\u002F09.libraries\u002F08.feature-management",{"title":1163,"path":1164,"stem":1165},"Відправка Email з FluentEmail в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Flibraries\u002Ffluent-email","01.csharp\u002F11.aspnet\u002F09.libraries\u002F09.fluent-email",{"title":1167,"path":1168,"stem":1169},"Генерація PDF з QuestPDF в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Flibraries\u002Fquest-pdf","01.csharp\u002F11.aspnet\u002F09.libraries\u002F10.quest-pdf",{"title":1171,"path":1172,"stem":1173},"Генерація тестових даних з Bogus в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Flibraries\u002Fbogus","01.csharp\u002F11.aspnet\u002F09.libraries\u002F11.bogus",{"title":1175,"path":1176,"stem":1177},"Humanizer та Guard Clauses в ASP.NET Core","\u002Fcsharp\u002Faspnet\u002Flibraries\u002Fhumanizer-guard","01.csharp\u002F11.aspnet\u002F09.libraries\u002F12.humanizer-guard",{"title":1179,"path":1180,"stem":1181},"План модуля 10.libraries — Популярні бібліотеки ASP.NET","\u002Fcsharp\u002Faspnet\u002Flibraries\u002Fplan","01.csharp\u002F11.aspnet\u002F09.libraries\u002Fplan",{"title":1183,"icon":1184,"path":1185,"stem":1186,"children":1187,"page":59},"Razor Pages","i-lucide-layout-template","\u002Fcsharp\u002Faspnet\u002Frazor-pages","01.csharp\u002F11.aspnet\u002F10.razor-pages",[1188,1192,1196,1200,1204,1208],{"title":1189,"path":1190,"stem":1191},"Від Minimal API до Razor Pages: концептуальний перехід","\u002Fcsharp\u002Faspnet\u002Frazor-pages\u002Ffrom-minimal-api","01.csharp\u002F11.aspnet\u002F10.razor-pages\u002F01.from-minimal-api",{"title":1193,"path":1194,"stem":1195},"PageModel: логіка сторінки Razor Pages","\u002Fcsharp\u002Faspnet\u002Frazor-pages\u002Fpage-model","01.csharp\u002F11.aspnet\u002F10.razor-pages\u002F02.page-model",{"title":1197,"path":1198,"stem":1199},"Razor синтаксис: шаблонізатор у .cshtml","\u002Fcsharp\u002Faspnet\u002Frazor-pages\u002Frazor-syntax","01.csharp\u002F11.aspnet\u002F10.razor-pages\u002F03.razor-syntax",{"title":1201,"path":1202,"stem":1203},"Tag Helpers: типізований HTML","\u002Fcsharp\u002Faspnet\u002Frazor-pages\u002Ftag-helpers","01.csharp\u002F11.aspnet\u002F10.razor-pages\u002F04.tag-helpers",{"title":1205,"path":1206,"stem":1207},"Форми і валідація: повний цикл обробки даних","\u002Fcsharp\u002Faspnet\u002Frazor-pages\u002Fforms-validation","01.csharp\u002F11.aspnet\u002F10.razor-pages\u002F05.forms-validation",{"title":1209,"path":1210,"stem":1211},"Практичний проєкт: TaskManager на Razor Pages","\u002Fcsharp\u002Faspnet\u002Frazor-pages\u002Fproject-task-manager","01.csharp\u002F11.aspnet\u002F10.razor-pages\u002F06.project-task-manager",{"title":1213,"path":1214,"stem":1215,"children":1216,"page":59},"ASP.NET Core MVC","\u002Fcsharp\u002Faspnet\u002Fmvc","01.csharp\u002F11.aspnet\u002F11.mvc",[1217,1221,1225,1229,1233,1237,1241,1245,1249,1253,1257,1261,1265,1269,1273,1277,1281,1285],{"title":1218,"path":1219,"stem":1220},"Патерн MVC: архітектура, що змінила веб","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Fmvc-pattern","01.csharp\u002F11.aspnet\u002F11.mvc\u002F01.mvc-pattern",{"title":1222,"path":1223,"stem":1224},"Від Razor Pages до MVC: концептуальний перехід","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Ffrom-razor-pages","01.csharp\u002F11.aspnet\u002F11.mvc\u002F02.from-razor-pages",{"title":1226,"path":1227,"stem":1228},"Controllers та Actions: серце MVC","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Fcontrollers-actions","01.csharp\u002F11.aspnet\u002F11.mvc\u002F03.controllers-actions",{"title":1230,"path":1231,"stem":1232},"Маршрутизація в MVC: Convention vs Attribute Routing","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Frouting-mvc","01.csharp\u002F11.aspnet\u002F11.mvc\u002F04.routing-mvc",{"title":1234,"path":1235,"stem":1236},"Model Binding: від HTTP до C#","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Fmodel-binding","01.csharp\u002F11.aspnet\u002F11.mvc\u002F05.model-binding",{"title":1238,"path":1239,"stem":1240},"Views, ViewData, ViewBag, TempData і ViewModel","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Fviews-viewdata-tempdata","01.csharp\u002F11.aspnet\u002F11.mvc\u002F06.views-viewdata-tempdata",{"title":1242,"path":1243,"stem":1244},"Filters: аспектно-орієнтоване програмування в MVC","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Ffilters","01.csharp\u002F11.aspnet\u002F11.mvc\u002F07.filters",{"title":1246,"path":1247,"stem":1248},"Areas: структурування великих застосунків","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Fareas","01.csharp\u002F11.aspnet\u002F11.mvc\u002F08.areas",{"title":1250,"path":1251,"stem":1252},"View Components: повторювані незалежні блоки UI","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Fview-components","01.csharp\u002F11.aspnet\u002F11.mvc\u002F09.view-components",{"title":1254,"path":1255,"stem":1256},"Display та Editor Templates","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Fdisplay-editor-templates","01.csharp\u002F11.aspnet\u002F11.mvc\u002F10.display-editor-templates",{"title":1258,"path":1259,"stem":1260},"Валідація: IValidatableObject та FluentValidation","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Fvalidation-advanced","01.csharp\u002F11.aspnet\u002F11.mvc\u002F11.validation-advanced",{"title":1262,"path":1263,"stem":1264},"HTMX: інтерактивність через HTML-атрибути","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Fhtmx","01.csharp\u002F11.aspnet\u002F11.mvc\u002F12.htmx",{"title":1266,"path":1267,"stem":1268},"HTMX у ASP.NET Core MVC: серверна інтеграція","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Fajax-htmx-mvc","01.csharp\u002F11.aspnet\u002F11.mvc\u002F13.ajax-htmx-mvc",{"title":1270,"path":1271,"stem":1272},"Практичний проєкт: Каталог товарів з HTMX","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Fhtmx-project","01.csharp\u002F11.aspnet\u002F11.mvc\u002F14.htmx-project",{"title":1274,"path":1275,"stem":1276},"Завантаження та обробка файлів","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Ffile-upload","01.csharp\u002F11.aspnet\u002F11.mvc\u002F15.file-upload",{"title":1278,"path":1279,"stem":1280},"Глобалізація та Локалізація MVC","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Fglobalization-localization","01.csharp\u002F11.aspnet\u002F11.mvc\u002F16.globalization-localization",{"title":1282,"path":1283,"stem":1284},"Підсумковий проєкт: Блог-платформа","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Fmvc-project","01.csharp\u002F11.aspnet\u002F11.mvc\u002F17.mvc-project",{"title":1286,"path":1287,"stem":1288},"План курсу: ASP.NET Core MVC","\u002Fcsharp\u002Faspnet\u002Fmvc\u002Fplan","01.csharp\u002F11.aspnet\u002F11.mvc\u002Fplan",{"title":1290,"path":1291,"stem":1292,"children":1293,"page":59},"Web Api","\u002Fcsharp\u002Faspnet\u002Fweb-api","01.csharp\u002F11.aspnet\u002F12.web-api",[1294,1298,1302,1306,1310,1314,1318,1322,1326,1330,1334,1338,1342],{"title":1295,"path":1296,"stem":1297},"Від Minimal API до Controller-based API","\u002Fcsharp\u002Faspnet\u002Fweb-api\u002Ffrom-minimal-api-to-controllers","01.csharp\u002F11.aspnet\u002F12.web-api\u002F01.from-minimal-api-to-controllers",{"title":1299,"path":1300,"stem":1301},"ControllerBase, ActionResult\u003CT> та Response Types","\u002Fcsharp\u002Faspnet\u002Fweb-api\u002Fcontroller-base-actionresult","01.csharp\u002F11.aspnet\u002F12.web-api\u002F02.controller-base-actionresult",{"title":1303,"path":1304,"stem":1305},"Content Negotiation - JSON, XML та власні форматери","\u002Fcsharp\u002Faspnet\u002Fweb-api\u002Fcontent-negotiation","01.csharp\u002F11.aspnet\u002F12.web-api\u002F03.content-negotiation",{"title":1307,"path":1308,"stem":1309},"Версіонування API","\u002Fcsharp\u002Faspnet\u002Fweb-api\u002Fapi-versioning","01.csharp\u002F11.aspnet\u002F12.web-api\u002F04.api-versioning",{"title":1311,"path":1312,"stem":1313},"ProblemDetails та структурована обробка помилок","\u002Fcsharp\u002Faspnet\u002Fweb-api\u002Fproblemdetails-error-handling","01.csharp\u002F11.aspnet\u002F12.web-api\u002F05.problemdetails-error-handling",{"title":1315,"path":1316,"stem":1317},"Фільтри у Web API контексті","\u002Fcsharp\u002Faspnet\u002Fweb-api\u002Ffilters-for-api","01.csharp\u002F11.aspnet\u002F12.web-api\u002F06.filters-for-api",{"title":1319,"path":1320,"stem":1321},"Пагінація, фільтрація та сортування","\u002Fcsharp\u002Faspnet\u002Fweb-api\u002Fpagination-filtering-sorting","01.csharp\u002F11.aspnet\u002F12.web-api\u002F07.pagination-filtering-sorting",{"title":1323,"path":1324,"stem":1325},"HATEOAS та Resource Expansion","\u002Fcsharp\u002Faspnet\u002Fweb-api\u002Fhateoas-resource-expansion","01.csharp\u002F11.aspnet\u002F12.web-api\u002F08.hateoas-resource-expansion",{"title":1327,"path":1328,"stem":1329},"Гібридна архітектура - Minimal API + Controllers","\u002Fcsharp\u002Faspnet\u002Fweb-api\u002Fminimal-api-vs-controllers-hybrid","01.csharp\u002F11.aspnet\u002F12.web-api\u002F09.minimal-api-vs-controllers-hybrid",{"title":1331,"path":1332,"stem":1333},"Документація API - Swashbuckle, NSwag та генерація клієнтів","\u002Fcsharp\u002Faspnet\u002Fweb-api\u002Fapi-documentation-generation","01.csharp\u002F11.aspnet\u002F12.web-api\u002F10.api-documentation-generation",{"title":1335,"path":1336,"stem":1337},"Health Checks та моніторинг API","\u002Fcsharp\u002Faspnet\u002Fweb-api\u002Fhealth-checks-monitoring","01.csharp\u002F11.aspnet\u002F12.web-api\u002F11.health-checks-monitoring",{"title":1339,"path":1340,"stem":1341},"Підсумковий проєкт - Production-Ready REST API","\u002Fcsharp\u002Faspnet\u002Fweb-api\u002Fweb-api-project","01.csharp\u002F11.aspnet\u002F12.web-api\u002F12.web-api-project",{"title":1343,"path":1344,"stem":1345},"План курсу: ASP.NET Core Web API (Controllers)","\u002Fcsharp\u002Faspnet\u002Fweb-api\u002Fplan","01.csharp\u002F11.aspnet\u002F12.web-api\u002Fplan",{"title":1347,"icon":1348,"path":1349,"stem":1350,"children":1351,"page":59},"Моніторинг","i-lucide-activity","\u002Fcsharp\u002Faspnet\u002Fmonitoring","01.csharp\u002F11.aspnet\u002F13.monitoring",[1352,1356,1360],{"title":1353,"path":1354,"stem":1355},"Спостережуваність: від console.log до production-систем","\u002Fcsharp\u002Faspnet\u002Fmonitoring\u002Fobservability-intro","01.csharp\u002F11.aspnet\u002F13.monitoring\u002F01.observability-intro",{"title":1357,"path":1358,"stem":1359},"Health Checks: перший рівень observability","\u002Fcsharp\u002Faspnet\u002Fmonitoring\u002Fhealth-checks","01.csharp\u002F11.aspnet\u002F13.monitoring\u002F02.health-checks",{"title":1361,"path":1362,"stem":1363},"Вбудовані метрики .NET 10 та System.Diagnostics.Metrics","\u002Fcsharp\u002Faspnet\u002Fmonitoring\u002Fdotnet-metrics","01.csharp\u002F11.aspnet\u002F13.monitoring\u002F03.dotnet-metrics",{"title":1365,"icon":1366,"path":1367,"stem":1368,"children":1369,"page":59},"Desktop UI","i-lucide-app-window","\u002Fcsharp\u002Fdesktop-ui","01.csharp\u002F12.desktop-ui",[1370,1374,1378,1382,1386,1390,1394,1398,1402,1406,1410,1414,1418,1422,1426,1430,1434,1438,1442,1446,1450,1454,1458,1462,1466,1470,1474,1478,1482,1486,1490,1494,1498,1502,1506,1510,1514,1518,1522,1526,1530,1534,1538,1542,1546,1550,1554,1558,1562,1566,1570,1574,1578,1582,1586,1590,1594,1598,1602,1606,1610,1614,1618,1622,1626,1630,1634,1638,1642,1646,1650],{"title":1371,"path":1372,"stem":1373},"Що таке десктопна розробка?","\u002Fcsharp\u002Fdesktop-ui\u002Fwhat-is-desktop-dev","01.csharp\u002F12.desktop-ui\u002F01.what-is-desktop-dev",{"title":1375,"path":1376,"stem":1377},"Архітектура WPF — як влаштований графічний інтерфейс","\u002Fcsharp\u002Fdesktop-ui\u002Fwpf-architecture","01.csharp\u002F12.desktop-ui\u002F02.wpf-architecture",{"title":1379,"path":1380,"stem":1381},"Перший WPF-проєкт — від нуля до вікна","\u002Fcsharp\u002Fdesktop-ui\u002Ffirst-wpf-app","01.csharp\u002F12.desktop-ui\u002F03.first-wpf-app",{"title":1383,"path":1384,"stem":1385},"Перший Avalonia-проєкт: WPF для всіх платформ","\u002Fcsharp\u002Fdesktop-ui\u002F03a.first-avalonia-app","01.csharp\u002F12.desktop-ui\u002F03a.first-avalonia-app",{"title":1387,"path":1388,"stem":1389},"XAML: декларативний інтерфейс","\u002Fcsharp\u002Fdesktop-ui\u002Fxaml-basics","01.csharp\u002F12.desktop-ui\u002F04.xaml-basics",{"title":1391,"path":1392,"stem":1393},"Fluent UI у WPF — сучасний дизайн Windows 11","\u002Fcsharp\u002Fdesktop-ui\u002F04a.wpf-fluent-ui","01.csharp\u002F12.desktop-ui\u002F04a.wpf-fluent-ui",{"title":1395,"path":1396,"stem":1397},"WPF UI — сучасна бібліотека Fluent контролів","\u002Fcsharp\u002Fdesktop-ui\u002F04b.wpf-ui-library","01.csharp\u002F12.desktop-ui\u002F04b.wpf-ui-library",{"title":1399,"path":1400,"stem":1401},"HandyControl — велика бібліотека UI контролів для WPF","\u002Fcsharp\u002Fdesktop-ui\u002F04c.handycontrol-library","01.csharp\u002F12.desktop-ui\u002F04c.handycontrol-library",{"title":1403,"path":1404,"stem":1405},"Простори імен та ресурси XAML","\u002Fcsharp\u002Fdesktop-ui\u002Fxaml-namespaces-resources","01.csharp\u002F12.desktop-ui\u002F05.xaml-namespaces-resources",{"title":1407,"path":1408,"stem":1409},"XAML в Avalonia: ключові відмінності від WPF","\u002Fcsharp\u002Fdesktop-ui\u002F05a.avalonia-xaml-differences","01.csharp\u002F12.desktop-ui\u002F05a.avalonia-xaml-differences",{"title":1411,"path":1412,"stem":1413},"Розширення розмітки XAML (Markup Extensions)","\u002Fcsharp\u002Fdesktop-ui\u002Fxaml-markup-extensions","01.csharp\u002F12.desktop-ui\u002F06.xaml-markup-extensions",{"title":1415,"path":1416,"stem":1417},"Панелі Layout: StackPanel, WrapPanel, DockPanel","\u002Fcsharp\u002Fdesktop-ui\u002Flayout-panels-part1","01.csharp\u002F12.desktop-ui\u002F07.layout-panels-part1",{"title":1419,"path":1420,"stem":1421},"Grid, Canvas, UniformGrid","\u002Fcsharp\u002Fdesktop-ui\u002Flayout-panels-part2","01.csharp\u002F12.desktop-ui\u002F07.layout-panels-part2",{"title":1423,"path":1424,"stem":1425},"Просунуті техніки Layout","\u002Fcsharp\u002Fdesktop-ui\u002Flayout-advanced","01.csharp\u002F12.desktop-ui\u002F08.layout-advanced",{"title":1427,"path":1428,"stem":1429},"Адаптивний Layout та найкращі практики","\u002Fcsharp\u002Fdesktop-ui\u002Flayout-responsive","01.csharp\u002F12.desktop-ui\u002F09.layout-responsive",{"title":1431,"path":1432,"stem":1433},"Layout в Avalonia: відмінності та нові можливості","\u002Fcsharp\u002Fdesktop-ui\u002F09a.layout-avalonia","01.csharp\u002F12.desktop-ui\u002F09a.layout-avalonia",{"title":1435,"path":1436,"stem":1437},"Button, Image, ProgressBar та інші базові контроли","\u002Fcsharp\u002Fdesktop-ui\u002Fbasic-controls","01.csharp\u002F12.desktop-ui\u002F10.basic-controls",{"title":1439,"path":1440,"stem":1441},"Контроли в Avalonia: відмінності від WPF","\u002Fcsharp\u002Fdesktop-ui\u002F10a.controls-avalonia","01.csharp\u002F12.desktop-ui\u002F10a.controls-avalonia",{"title":1443,"path":1444,"stem":1445},"Текстові контроли — TextBlock, TextBox, RichTextBox","\u002Fcsharp\u002Fdesktop-ui\u002Ftext-controls","01.csharp\u002F12.desktop-ui\u002F11.text-controls",{"title":1447,"path":1448,"stem":1449},"Контроли вибору — CheckBox, RadioButton, ComboBox, ListBox, DatePicker","\u002Fcsharp\u002Fdesktop-ui\u002Fselection-controls","01.csharp\u002F12.desktop-ui\u002F12.selection-controls",{"title":1451,"path":1452,"stem":1453},"Content Model — GroupBox, Expander, TabControl, StatusBar","\u002Fcsharp\u002Fdesktop-ui\u002Fcontent-controls","01.csharp\u002F12.desktop-ui\u002F13.content-controls",{"title":1455,"path":1456,"stem":1457},"UI\u002FUX принципи десктопних застосунків","\u002Fcsharp\u002Fdesktop-ui\u002F13a.ui-ux-principles","01.csharp\u002F12.desktop-ui\u002F13a.ui-ux-principles",{"title":1459,"path":1460,"stem":1461},"Dependency Properties — Концепція та Value Resolution","\u002Fcsharp\u002Fdesktop-ui\u002Fdependency-properties-part1","01.csharp\u002F12.desktop-ui\u002F14.dependency-properties-part1",{"title":1463,"path":1464,"stem":1465},"Avalonia Property System — StyledProperty та DirectProperty","\u002Fcsharp\u002Fdesktop-ui\u002F14a.avalonia-property-system","01.csharp\u002F12.desktop-ui\u002F14a.avalonia-property-system",{"title":1467,"path":1468,"stem":1469},"Attached Properties — Властивості без меж","\u002Fcsharp\u002Fdesktop-ui\u002Fattached-properties","01.csharp\u002F12.desktop-ui\u002F15.attached-properties",{"title":1471,"path":1472,"stem":1473},"Routed Events — Маршрутизація подій у WPF","\u002Fcsharp\u002Fdesktop-ui\u002Frouted-events","01.csharp\u002F12.desktop-ui\u002F16.routed-events",{"title":1475,"path":1476,"stem":1477},"Data Binding — Від Code-Behind до Декларативності","\u002Fcsharp\u002Fdesktop-ui\u002Fdata-binding-basics-part1","01.csharp\u002F12.desktop-ui\u002F17.data-binding-basics-part1",{"title":1479,"path":1480,"stem":1481},"INotifyPropertyChanged — Живе оновлення UI","\u002Fcsharp\u002Fdesktop-ui\u002Fdata-binding-basics-part2","01.csharp\u002F12.desktop-ui\u002F17.data-binding-basics-part2",{"title":1483,"path":1484,"stem":1485},"Compiled Bindings в Avalonia — Безпека на етапі компіляції","\u002Fcsharp\u002Fdesktop-ui\u002F17a.avalonia-compiled-bindings","01.csharp\u002F12.desktop-ui\u002F17a.avalonia-compiled-bindings",{"title":1487,"path":1488,"stem":1489},"Просунутий Data Binding — ElementName, RelativeSource, MultiBinding","\u002Fcsharp\u002Fdesktop-ui\u002Fdata-binding-advanced","01.csharp\u002F12.desktop-ui\u002F18.data-binding-advanced",{"title":1491,"path":1492,"stem":1493},"Value Converters — Перетворення типів даних у Data Binding","\u002Fcsharp\u002Fdesktop-ui\u002Fvalue-converters","01.csharp\u002F12.desktop-ui\u002F19.value-converters",{"title":1495,"path":1496,"stem":1497},"Data Templates — Візуалізація об'єктів у WPF","\u002Fcsharp\u002Fdesktop-ui\u002Fdata-templates","01.csharp\u002F12.desktop-ui\u002F20.data-templates",{"title":1499,"path":1500,"stem":1501},"Collections Binding Part 1 — ObservableCollection та ItemsControl","\u002Fcsharp\u002Fdesktop-ui\u002Fcollections-binding-part1","01.csharp\u002F12.desktop-ui\u002F21.collections-binding-part1",{"title":1503,"path":1504,"stem":1505},"Collections Binding Part 2 — ICollectionView, Filtering, Sorting та Virtualization","\u002Fcsharp\u002Fdesktop-ui\u002Fcollections-binding-part2","01.csharp\u002F12.desktop-ui\u002F21.collections-binding-part2",{"title":1507,"path":1508,"stem":1509},"MVVM Pattern — Від Spaghetti Code до архітектури","\u002Fcsharp\u002Fdesktop-ui\u002Fmvvm-pattern","01.csharp\u002F12.desktop-ui\u002F22.mvvm-pattern",{"title":1511,"path":1512,"stem":1513},"ViewModel Implementation — Від BaseViewModel до валідації","\u002Fcsharp\u002Fdesktop-ui\u002Fviewmodel-implementation","01.csharp\u002F12.desktop-ui\u002F23.viewmodel-implementation",{"title":1515,"path":1516,"stem":1517},"Commands — Від event handlers до декларативних команд","\u002Fcsharp\u002Fdesktop-ui\u002Fcommands","01.csharp\u002F12.desktop-ui\u002F24.commands",{"title":1519,"path":1520,"stem":1521},"MVVM Toolkit — MVVM без boilerplate через Source Generators","\u002Fcsharp\u002Fdesktop-ui\u002Fmvvm-toolkit","01.csharp\u002F12.desktop-ui\u002F25.mvvm-toolkit",{"title":1523,"path":1524,"stem":1525},"Messenger Pattern — Комунікація між ViewModel без прямих посилань","\u002Fcsharp\u002Fdesktop-ui\u002Fmessenger-pattern","01.csharp\u002F12.desktop-ui\u002F26.messenger-pattern",{"title":1527,"path":1528,"stem":1529},"Стилі WPF — CSS для десктопу","\u002Fcsharp\u002Fdesktop-ui\u002Fstyles-basics","01.csharp\u002F12.desktop-ui\u002F27.styles-basics",{"title":1531,"path":1532,"stem":1533},"CSS-like стилі Avalonia","\u002Fcsharp\u002Fdesktop-ui\u002F27a.avalonia-css-styling","01.csharp\u002F12.desktop-ui\u002F27a.avalonia-css-styling",{"title":1535,"path":1536,"stem":1537},"Control Templates — Частина 1. Концепція та TemplateBinding","\u002Fcsharp\u002Fdesktop-ui\u002Fcontrol-templates-part1","01.csharp\u002F12.desktop-ui\u002F28.control-templates-part1",{"title":1539,"path":1540,"stem":1541},"Control Templates — Частина 2. Named Parts та ContentPresenter","\u002Fcsharp\u002Fdesktop-ui\u002Fcontrol-templates-part2","01.csharp\u002F12.desktop-ui\u002F28.control-templates-part2",{"title":1543,"path":1544,"stem":1545},"Control Themes в Avalonia — нова ера стилізації","\u002Fcsharp\u002Fdesktop-ui\u002F28a.avalonia-control-themes","01.csharp\u002F12.desktop-ui\u002F28a.avalonia-control-themes",{"title":1547,"path":1548,"stem":1549},"Triggers та Visual State Manager у WPF","\u002Fcsharp\u002Fdesktop-ui\u002Ftriggers-visual-states","01.csharp\u002F12.desktop-ui\u002F29.triggers-visual-states",{"title":1551,"path":1552,"stem":1553},"Pseudo-classes в Avalonia — замість WPF Triggers","\u002Fcsharp\u002Fdesktop-ui\u002F29a.avalonia-pseudo-classes","01.csharp\u002F12.desktop-ui\u002F29a.avalonia-pseudo-classes",{"title":1555,"path":1556,"stem":1557},"Теми та ресурсні словники у WPF","\u002Fcsharp\u002Fdesktop-ui\u002Fresources-themes","01.csharp\u002F12.desktop-ui\u002F30.resources-themes",{"title":1559,"path":1560,"stem":1561},"Avalonia Themes — Fluent Design та система тематизації","\u002Fcsharp\u002Fdesktop-ui\u002F30a.avalonia-themes-fluent","01.csharp\u002F12.desktop-ui\u002F30a.avalonia-themes-fluent",{"title":1563,"path":1564,"stem":1565},"Контроли колекцій — глибоке занурення","\u002Fcsharp\u002Fdesktop-ui\u002Fcollection-controls","01.csharp\u002F12.desktop-ui\u002F31.collection-controls",{"title":1567,"path":1568,"stem":1569},"DataGrid — колонки та базове відображення","\u002Fcsharp\u002Fdesktop-ui\u002Fdatagrid-part1","01.csharp\u002F12.desktop-ui\u002F32.datagrid-part1",{"title":1571,"path":1572,"stem":1573},"DataGrid — сортування, фільтрація, редагування","\u002Fcsharp\u002Fdesktop-ui\u002Fdatagrid-part2","01.csharp\u002F12.desktop-ui\u002F32.datagrid-part2",{"title":1575,"path":1576,"stem":1577},"TreeView та GridView","\u002Fcsharp\u002Fdesktop-ui\u002Ftreeview-listview","01.csharp\u002F12.desktop-ui\u002F33.treeview-listview",{"title":1579,"path":1580,"stem":1581},"Меню, Toolbar, ContextMenu, StatusBar","\u002Fcsharp\u002Fdesktop-ui\u002Fmenus-toolbars","01.csharp\u002F12.desktop-ui\u002F34.menus-toolbars",{"title":1583,"path":1584,"stem":1585},"Навігація та керування вікнами. Частина 1: вікна та сторінки","\u002Fcsharp\u002Fdesktop-ui\u002Fnavigation-windows-part1","01.csharp\u002F12.desktop-ui\u002F35.navigation-windows-part1",{"title":1587,"path":1588,"stem":1589},"Навігація та керування вікнами. Частина 2: MVVM-навігація","\u002Fcsharp\u002Fdesktop-ui\u002Fnavigation-windows-part2","01.csharp\u002F12.desktop-ui\u002F35.navigation-windows-part2",{"title":1591,"path":1592,"stem":1593},"Avalonia — Навігація та діалоги","\u002Fcsharp\u002Fdesktop-ui\u002F35a.avalonia-navigation-dialogs","01.csharp\u002F12.desktop-ui\u002F35a.avalonia-navigation-dialogs",{"title":1595,"path":1596,"stem":1597},"Діалоги та File Pickers у WPF","\u002Fcsharp\u002Fdesktop-ui\u002Fdialogs-file-pickers","01.csharp\u002F12.desktop-ui\u002F36.dialogs-file-pickers",{"title":1599,"path":1600,"stem":1601},"UserControl: компонентний підхід у WPF","\u002Fcsharp\u002Fdesktop-ui\u002Fuser-controls","01.csharp\u002F12.desktop-ui\u002F37.user-controls",{"title":1603,"path":1604,"stem":1605},"Custom Controls: Lookless Controls у WPF","\u002Fcsharp\u002Fdesktop-ui\u002Fcustom-controls","01.csharp\u002F12.desktop-ui\u002F38.custom-controls",{"title":1607,"path":1608,"stem":1609},"Avalonia TemplatedControl — Lookless Controls","\u002Fcsharp\u002Fdesktop-ui\u002F38a.avalonia-templated-controls","01.csharp\u002F12.desktop-ui\u002F38a.avalonia-templated-controls",{"title":1611,"path":1612,"stem":1613},"Анімації у WPF: Storyboard та Easing Functions","\u002Fcsharp\u002Fdesktop-ui\u002Fanimations-transitions","01.csharp\u002F12.desktop-ui\u002F39.animations-transitions",{"title":1615,"path":1616,"stem":1617},"Анімації в Avalonia","\u002Fcsharp\u002Fdesktop-ui\u002F39a.avalonia-animations","01.csharp\u002F12.desktop-ui\u002F39a.avalonia-animations",{"title":1619,"path":1620,"stem":1621},"2D Графіка та Мультимедіа у WPF","\u002Fcsharp\u002Fdesktop-ui\u002Fmedia-graphics","01.csharp\u002F12.desktop-ui\u002F40.media-graphics",{"title":1623,"path":1624,"stem":1625},"Dependency Injection у WPF та Avalonia","\u002Fcsharp\u002Fdesktop-ui\u002Fdi-integration","01.csharp\u002F12.desktop-ui\u002F41.di-integration",{"title":1627,"path":1628,"stem":1629},"SQLite та EF Core у десктопних додатках","\u002Fcsharp\u002Fdesktop-ui\u002Fdata-persistence-part1","01.csharp\u002F12.desktop-ui\u002F42.data-persistence-part1",{"title":1631,"path":1632,"stem":1633},"Repository Pattern та Unit of Work","\u002Fcsharp\u002Fdesktop-ui\u002Fdata-persistence-part2","01.csharp\u002F12.desktop-ui\u002F43.data-persistence-part2",{"title":1635,"path":1636,"stem":1637},"Тестування ViewModels","\u002Fcsharp\u002Fdesktop-ui\u002Fviewmodel-testing","01.csharp\u002F12.desktop-ui\u002F44.viewmodel-testing",{"title":1639,"path":1640,"stem":1641},"Avalonia Headless Testing — тестування UI без вікон","\u002Fcsharp\u002Fdesktop-ui\u002F44a.avalonia-headless-testing","01.csharp\u002F12.desktop-ui\u002F44a.avalonia-headless-testing",{"title":1643,"path":1644,"stem":1645},"Кросплатформна розробка з Avalonia","\u002Fcsharp\u002Fdesktop-ui\u002Favalonia-cross-platform","01.csharp\u002F12.desktop-ui\u002F45.avalonia-cross-platform",{"title":1647,"path":1648,"stem":1649},"Пакування та розгортання Avalonia додатків","\u002Fcsharp\u002Fdesktop-ui\u002Favalonia-packaging-deployment","01.csharp\u002F12.desktop-ui\u002F46.avalonia-packaging-deployment",{"title":1651,"path":1652,"stem":1653},"Розгортання WPF застосунків","\u002Fcsharp\u002Fdesktop-ui\u002Fwpf-packaging-deployment","01.csharp\u002F12.desktop-ui\u002F47.wpf-packaging-deployment",{"title":1655,"icon":658,"path":1656,"stem":1657,"children":1658,"page":59},"Network Programming","\u002Fcsharp\u002Fnetwork-programming","01.csharp\u002F13.network-programming",[1659,1663,1667,1671,1675,1679,1683,1687,1691,1695,1699],{"title":1660,"path":1661,"stem":1662},"Основи комп'ютерних мереж","\u002Fcsharp\u002Fnetwork-programming\u002Ffoundations","01.csharp\u002F13.network-programming\u002F01.foundations",{"title":1664,"path":1665,"stem":1666},"Модель OSI та стек TCP\u002FIP","\u002Fcsharp\u002Fnetwork-programming\u002Fosi-model","01.csharp\u002F13.network-programming\u002F02.osi-model",{"title":1668,"path":1669,"stem":1670},"IP-протокол та адресація","\u002Fcsharp\u002Fnetwork-programming\u002Fip-addressing","01.csharp\u002F13.network-programming\u002F03.ip-addressing",{"title":1672,"path":1673,"stem":1674},"UDP — протокол без з'єднання","\u002Fcsharp\u002Fnetwork-programming\u002Fudp","01.csharp\u002F13.network-programming\u002F05.udp",{"title":1676,"path":1677,"stem":1678},"UDP Broadcast та Multicast","\u002Fcsharp\u002Fnetwork-programming\u002Fudp-broadcast-multicast","01.csharp\u002F13.network-programming\u002F06.udp-broadcast-multicast",{"title":1680,"path":1681,"stem":1682},"HTTP — протокол вебу","\u002Fcsharp\u002Fnetwork-programming\u002Fhttp-fundamentals","01.csharp\u002F13.network-programming\u002F07.http-fundamentals",{"title":1684,"path":1685,"stem":1686},"HttpListener — вбудований HTTP-сервер .NET","\u002Fcsharp\u002Fnetwork-programming\u002F07a.http-listener","01.csharp\u002F13.network-programming\u002F07a.http-listener",{"title":1688,"path":1689,"stem":1690},"HTTP Advanced — cookies, аутентифікація та HTTPS","\u002Fcsharp\u002Fnetwork-programming\u002Fhttp-advanced","01.csharp\u002F13.network-programming\u002F08.http-advanced",{"title":1692,"path":1693,"stem":1694},"SMTP та протоколи електронної пошти","\u002Fcsharp\u002Fnetwork-programming\u002Fsmtp","01.csharp\u002F13.network-programming\u002F09.smtp",{"title":1696,"path":1697,"stem":1698},"WebSocket — повнодуплексний протокол реального часу","\u002Fcsharp\u002Fnetwork-programming\u002Fwebsockets","01.csharp\u002F13.network-programming\u002F10.websockets",{"title":1700,"path":1701,"stem":1702},"TLS\u002FSSL — криптографічний захист мережевих з'єднань","\u002Fcsharp\u002Fnetwork-programming\u002Ftls-ssl","01.csharp\u002F13.network-programming\u002F11.tls-ssl",{"title":1704,"path":1705,"stem":1706},"C# & .NET: The Ultimate Roadmap","\u002Fcsharp\u002Froadmap","01.csharp\u002Froadmap",{"title":1708,"icon":1709,"path":1710,"stem":1711,"children":1712,"page":59},"C++","i-devicon-cplusplus","\u002Fcpp","02.cpp",[1713,1717,1721,1725,1729,1733,1737,1741,1745,1748,1752,1756,1760,1764,1768,1772,1776,1780,1784,1788,1792,1796,1800,1804,1808,1812,1816,1820,1824,1828,1832,1836,1840,1844,1848,1852,1856,1860,1864,1868,1872,1876,1880,1884,1888,1892],{"title":1714,"path":1715,"stem":1716},"Вступ у програмування та алгоритми","\u002Fcpp\u002Fintro-algorithms","02.cpp\u002F01.intro-algorithms",{"title":1718,"path":1719,"stem":1720},"Code Style: угоди про оформлення коду","\u002Fcpp\u002Fcode-style","02.cpp\u002F02.code-style",{"title":1722,"path":1723,"stem":1724},"Середовище розробки та перший проєкт","\u002Fcpp\u002Fide-setup","02.cpp\u002F03.ide-setup",{"title":1726,"path":1727,"stem":1728},"Вивід даних на екран","\u002Fcpp\u002Fdata-output","02.cpp\u002F04.data-output",{"title":1730,"path":1731,"stem":1732},"Типи даних, змінні та константи","\u002Fcpp\u002Fdata-types-variables","02.cpp\u002F05.data-types-variables",{"title":1734,"path":1735,"stem":1736},"Ввід даних з клавіатури","\u002Fcpp\u002Fdata-input","02.cpp\u002F06.data-input",{"title":1738,"path":1739,"stem":1740},"Оператори, перетворення типів та логічні операції","\u002Fcpp\u002Foperators-type-conversion","02.cpp\u002F07.operators-type-conversion",{"title":1742,"path":1743,"stem":1744},"Цикли","\u002Fcpp\u002Floops","02.cpp\u002F08.loops",{"title":32,"path":1746,"stem":1747},"\u002Fcpp\u002Farrays","02.cpp\u002F09.arrays",{"title":1749,"path":1750,"stem":1751},"Алгоритми сортування та аналіз складності","\u002Fcpp\u002Fsorting","02.cpp\u002F10.sorting",{"title":1753,"path":1754,"stem":1755},"Алгоритми пошуку","\u002Fcpp\u002Fsearching","02.cpp\u002F11.searching",{"title":1757,"path":1758,"stem":1759},"Функції: основи","\u002Fcpp\u002Ffunctions-basics","02.cpp\u002F12.functions-basics",{"title":1761,"path":1762,"stem":1763},"Функції: прототипи, область видимості та додаткові можливості","\u002Fcpp\u002Ffunctions-scope","02.cpp\u002F13.functions-scope",{"title":1765,"path":1766,"stem":1767},"Функції: перевантаження та шаблони","\u002Fcpp\u002Ffunctions-overloading-templates","02.cpp\u002F14.functions-overloading-templates",{"title":1769,"path":1770,"stem":1771},"Вказівники: основи","\u002Fcpp\u002Fpointers-basics","02.cpp\u002F15.pointers-basics",{"title":1773,"path":1774,"stem":1775},"Посилання (References)","\u002Fcpp\u002Freferences","02.cpp\u002F16.references",{"title":1777,"path":1778,"stem":1779},"Вказівники, const і масиви","\u002Fcpp\u002Fpointers-const-arrays","02.cpp\u002F17.pointers-const-arrays",{"title":1781,"path":1782,"stem":1783},"Адресна арифметика","\u002Fcpp\u002Fpointer-arithmetic","02.cpp\u002F18.pointer-arithmetic",{"title":1785,"path":1786,"stem":1787},"Динамічна пам'ять","\u002Fcpp\u002Fdynamic-memory","02.cpp\u002F19.dynamic-memory",{"title":1789,"path":1790,"stem":1791},"Вказівники типу void","\u002Fcpp\u002Fvoid-pointers","02.cpp\u002F20.void-pointers",{"title":1793,"path":1794,"stem":1795},"Вказівники на вказівники","\u002Fcpp\u002Fpointers-to-pointers","02.cpp\u002F21.pointers-to-pointers",{"title":1797,"path":1798,"stem":1799},"Оператор доступу до членів через вказівник (->)","\u002Fcpp\u002Fmember-access-operator","02.cpp\u002F22.member-access-operator",{"title":1801,"path":1802,"stem":1803},"Цикл for-each (Range-based for)","\u002Fcpp\u002Fforeach-loop","02.cpp\u002F23.foreach-loop",{"title":1805,"path":1806,"stem":1807},"Вказівники на функції","\u002Fcpp\u002Ffunction-pointers","02.cpp\u002F24.function-pointers",{"title":1809,"path":1810,"stem":1811},"Лямбда-вирази","\u002Fcpp\u002Flambdas","02.cpp\u002F25.lambdas",{"title":1813,"path":1814,"stem":1815},"Лямбда-захоплення","\u002Fcpp\u002Flambda-captures","02.cpp\u002F26.lambda-captures",{"title":1817,"path":1818,"stem":1819},"Еліпсис","\u002Fcpp\u002Fellipsis","02.cpp\u002F27.ellipsis",{"title":1821,"path":1822,"stem":1823},"Безпечні альтернативи еліпсису","\u002Fcpp\u002F27a.ellipsis","02.cpp\u002F27a.ellipsis",{"title":1825,"path":1826,"stem":1827},"Аргументи командного рядка","\u002Fcpp\u002Fcommand-line-arguments","02.cpp\u002F28.command-line-arguments",{"title":1829,"path":1830,"stem":1831},"Перерахування (enum)","\u002Fcpp\u002Fenum","02.cpp\u002F29.enum",{"title":1833,"path":1834,"stem":1835},"Класи-перерахування (enum class)","\u002Fcpp\u002Fenum-class","02.cpp\u002F30.enum-class",{"title":1837,"path":1838,"stem":1839},"Псевдоніми типів (typedef і using)","\u002Fcpp\u002Ftype-aliases","02.cpp\u002F31.type-aliases",{"title":1841,"path":1842,"stem":1843},"Системи числення та двійкова арифметика","\u002Fcpp\u002Fnumber-systems","02.cpp\u002F32.number-systems",{"title":1845,"path":1846,"stem":1847},"Структури (struct): агрегування даних","\u002Fcpp\u002Fstruct","02.cpp\u002F33.struct",{"title":1849,"path":1850,"stem":1851},"Структури у функціях","\u002Fcpp\u002Fstruct-functions","02.cpp\u002F34.struct-functions",{"title":1853,"path":1854,"stem":1855},"Масиви структур і вкладені структури","\u002Fcpp\u002Fstruct-arrays","02.cpp\u002F35.struct-arrays",{"title":1857,"path":1858,"stem":1859},"Патерни struct та межі застосування","\u002Fcpp\u002Fstruct-patterns","02.cpp\u002F36.struct-patterns",{"title":1861,"path":1862,"stem":1863},"Символи та таблиця ASCII","\u002Fcpp\u002Fascii-characters","02.cpp\u002F37.ascii-characters",{"title":1865,"path":1866,"stem":1867},"Unicode та кодування UTF","\u002Fcpp\u002Funicode-utf","02.cpp\u002F38.unicode-utf",{"title":1869,"path":1870,"stem":1871},"C-style рядки","\u002Fcpp\u002Fc-strings","02.cpp\u002F39.c-strings",{"title":1873,"path":1874,"stem":1875},"Вступ до std::string","\u002Fcpp\u002Fstd-string-intro","02.cpp\u002F40.std-string-intro",{"title":1877,"path":1878,"stem":1879},"Довжина, ємність та доступ до символів std::string","\u002Fcpp\u002Fstd-string-capacity-access","02.cpp\u002F41.std-string-capacity-access",{"title":1881,"path":1882,"stem":1883},"Модифікація std::string: присвоювання, додавання, вставка, видалення та заміна","\u002Fcpp\u002Fstd-string-modification","02.cpp\u002F42.std-string-modification",{"title":1885,"path":1886,"stem":1887},"Пошук у std::string: find, npos та практичні патерни","\u002Fcpp\u002Fstd-string-search","02.cpp\u002F43.std-string-search",{"title":1889,"path":1890,"stem":1891},"std::string_view: невласницький погляд на рядок без копіювання","\u002Fcpp\u002Fstd-string-view","02.cpp\u002F44.std-string-view",{"title":1893,"path":1894,"stem":1895},"План навчання: Курс C++ — Продовження (Статті 29–60+)","\u002Fcpp\u002Fcurriculum-plan","02.cpp\u002Fcurriculum-plan",{"title":1897,"icon":1898,"path":1899,"stem":1900,"children":1901,"page":59},"JavaScript","i-devicon-javascript","\u002Fjavascript","03.javascript",[1902,1928,1982,2004,2308,2346],{"title":1903,"icon":1904,"path":1905,"stem":1906,"children":1907,"page":59},"Events","i-lucide-mouse-pointer-click","\u002Fjavascript\u002Fevents","03.javascript\u002F01.events",[1908,1912,1916,1920,1924],{"title":1909,"path":1910,"stem":1911},"Вступ до подій браузера","\u002Fjavascript\u002Fevents\u002Fintro","03.javascript\u002F01.events\u002F01.intro",{"title":1913,"path":1914,"stem":1915},"Бульбашковий механізм (Bubbling) та занурення (Capturing)","\u002Fjavascript\u002Fevents\u002Fbubbling-capturing","03.javascript\u002F01.events\u002F02.bubbling-capturing",{"title":1917,"path":1918,"stem":1919},"Делегування подій (Event Delegation)","\u002Fjavascript\u002Fevents\u002Fdelegate-events","03.javascript\u002F01.events\u002F03.delegate-events",{"title":1921,"path":1922,"stem":1923},"Типові дії браузера та preventDefault()","\u002Fjavascript\u002Fevents\u002Fprevent-default","03.javascript\u002F01.events\u002F04.prevent-default",{"title":1925,"path":1926,"stem":1927},"Запуск користувацьких подій (Custom Events)","\u002Fjavascript\u002Fevents\u002Fcustom-events","03.javascript\u002F01.events\u002F05.custom-events",{"title":1929,"icon":1930,"path":1931,"stem":1932,"children":1933,"page":59},"Network","i-lucide-globe","\u002Fjavascript\u002Fnetwork","03.javascript\u002F02.network",[1934,1938,1942,1946,1950,1954,1958,1962,1966,1970,1974,1978],{"title":1935,"path":1936,"stem":1937},"Fetch API - Сучасний підхід до HTTP-запитів","\u002Fjavascript\u002Fnetwork\u002F01-fetch-api","03.javascript\u002F02.network\u002F01-fetch-api",{"title":1939,"path":1940,"stem":1941},"FormData - Робота з формами та файлами","\u002Fjavascript\u002Fnetwork\u002F02-formdata","03.javascript\u002F02.network\u002F02-formdata",{"title":1943,"path":1944,"stem":1945},"Відстеження прогресу завантаження","\u002Fjavascript\u002Fnetwork\u002F03-download-progress","03.javascript\u002F02.network\u002F03-download-progress",{"title":1947,"path":1948,"stem":1949},"Переривання fetch-запитів","\u002Fjavascript\u002Fnetwork\u002F04-abort-requests","03.javascript\u002F02.network\u002F04-abort-requests",{"title":1951,"path":1952,"stem":1953},"CORS - Запити між різними джерелами","\u002Fjavascript\u002Fnetwork\u002F05-cors","03.javascript\u002F02.network\u002F05-cors",{"title":1955,"path":1956,"stem":1957},"Fetch API - Повний довідник опцій","\u002Fjavascript\u002Fnetwork\u002F06-fetch-options","03.javascript\u002F02.network\u002F06-fetch-options",{"title":1959,"path":1960,"stem":1961},"URL Objects - Робота з посиланнями","\u002Fjavascript\u002Fnetwork\u002F07-url-objects","03.javascript\u002F02.network\u002F07-url-objects",{"title":1963,"path":1964,"stem":1965},"XMLHttpRequest - AJAX та низькорівневі запити","\u002Fjavascript\u002Fnetwork\u002F08-xmlhttprequest","03.javascript\u002F02.network\u002F08-xmlhttprequest",{"title":1967,"path":1968,"stem":1969},"Відновлюване завантаження файлів","\u002Fjavascript\u002Fnetwork\u002F09-resumable-upload","03.javascript\u002F02.network\u002F09-resumable-upload",{"title":1971,"path":1972,"stem":1973},"Cookies, document.cookie та світ після \"Cookiepocalypse\"","\u002Fjavascript\u002Fnetwork\u002F10-cookies","03.javascript\u002F02.network\u002F10-cookies",{"title":1975,"path":1976,"stem":1977},"js-cookie: Керування Cookies без Болю","\u002Fjavascript\u002Fnetwork\u002F11-js-cookie","03.javascript\u002F02.network\u002F11-js-cookie",{"title":1979,"path":1980,"stem":1981},"Axios: Потужний HTTP-клієнт для JavaScript","\u002Fjavascript\u002Fnetwork\u002F12-axios","03.javascript\u002F02.network\u002F12-axios",{"title":1983,"icon":1984,"path":1985,"stem":1986,"children":1987,"page":59},"Bom","i-lucide-monitor","\u002Fjavascript\u002Fbom","03.javascript\u002F03.bom",[1988,1992,1996,2000],{"title":1989,"path":1990,"stem":1991},"LocalStorage, SessionStorage та patterns збереження даних","\u002Fjavascript\u002Fbom\u002F01-localstorage","03.javascript\u002F03.bom\u002F01-localstorage",{"title":1993,"path":1994,"stem":1995},"Location Object - Керування адресою сторінки","\u002Fjavascript\u002Fbom\u002F02-location-object","03.javascript\u002F03.bom\u002F02-location-object",{"title":1997,"path":1998,"stem":1999},"History API - Керування історією браузера","\u002Fjavascript\u002Fbom\u002F03-history-api","03.javascript\u002F03.bom\u002F03-history-api",{"title":2001,"path":2002,"stem":2003},"Navigator Object - Ідентифікація та Можливості Пристрою","\u002Fjavascript\u002Fbom\u002F04-navigator-object","03.javascript\u002F03.bom\u002F04-navigator-object",{"title":2005,"icon":2006,"path":2007,"stem":2008,"children":2009},"React","i-devicon-react","\u002Fjavascript\u002Freact","03.javascript\u002F04.react\u002Findex",[2010,2011,2015,2019,2023,2027,2090,2125,2277],{"title":2005,"path":2007,"stem":2008},{"title":2012,"path":2013,"stem":2014},"Робота з Формами в React","\u002Fjavascript\u002Freact\u002Freact-forms","03.javascript\u002F04.react\u002F01.react-forms",{"title":2016,"path":2017,"stem":2018},"React Hook Form: Професійна Робота з Формами","\u002Fjavascript\u002Freact\u002Freact-hook-form","03.javascript\u002F04.react\u002F02.react-hook-form",{"title":2020,"path":2021,"stem":2022},"React Hook Form: Глибоке Розуміння Архітектури та Оптимізації","\u002Fjavascript\u002Freact\u002Freact-hook-form-new","03.javascript\u002F04.react\u002F02.react-hook-form-new",{"title":2024,"path":2025,"stem":2026},"Axios та React: Професійна Архітектура Запитів","\u002Fjavascript\u002Freact\u002Fdata-fetching-axios","03.javascript\u002F04.react\u002F03.data-fetching-axios",{"title":2028,"icon":132,"path":2029,"stem":2030,"children":2031},"Tanstack Query","\u002Fjavascript\u002Freact\u002Ftanstack-query","03.javascript\u002F04.react\u002F04.tanstack-query\u002Findex",[2032,2034,2038,2042,2046,2050,2054,2058,2062,2066,2070,2074,2078,2082,2086],{"title":2033,"path":2029,"stem":2030},"TanStack Query: Майстерність Керування Станом Сервера",{"title":2035,"path":2036,"stem":2037},"Парадигма Server State: Чому useEffect недостатньо","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Fserver-state-paradigm","03.javascript\u002F04.react\u002F04.tanstack-query\u002F01.server-state-paradigm",{"title":2039,"path":2040,"stem":2041},"Встановлення та Налаштування: Фундамент","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Finstallation-and-devtools","03.javascript\u002F04.react\u002F04.tanstack-query\u002F02.installation-and-devtools",{"title":2043,"path":2044,"stem":2045},"Основи Запитів та Магія Ключів","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Fquery-basics-and-keys","03.javascript\u002F04.react\u002F04.tanstack-query\u002F03.query-basics-and-keys",{"title":2047,"path":2048,"stem":2049},"Синхронізація Даних: Життєвий Цикл Запиту","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Fdata-synchronization","03.javascript\u002F04.react\u002F04.tanstack-query\u002F04.data-synchronization",{"title":2051,"path":2052,"stem":2053},"Мутації та Інвалідація: Зміна Даних","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Fmutations-and-invalidation","03.javascript\u002F04.react\u002F04.tanstack-query\u002F05.mutations-and-invalidation",{"title":2055,"path":2056,"stem":2057},"Оптимістичні Оновлення: Швидше за Світло","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Foptimistic-updates","03.javascript\u002F04.react\u002F04.tanstack-query\u002F06.optimistic-updates",{"title":2059,"path":2060,"stem":2061},"Пагінація та Infinite Scroll","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Fpagination-and-load-more","03.javascript\u002F04.react\u002F04.tanstack-query\u002F07.pagination-and-load-more",{"title":2063,"path":2064,"stem":2065},"Просунуті Патерни та Оптимізація","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Fadvanced-patterns","03.javascript\u002F04.react\u002F04.tanstack-query\u002F08.advanced-patterns",{"title":2067,"path":2068,"stem":2069},"Архітектура та Best Practices","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Farchitecture-and-best-practices","03.javascript\u002F04.react\u002F04.tanstack-query\u002F09.architecture-and-best-practices",{"title":2071,"path":2072,"stem":2073},"Server-Side Rendering (SSR) та Гідратація","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Fserver-side-rendering","03.javascript\u002F04.react\u002F04.tanstack-query\u002F10.server-side-rendering",{"title":2075,"path":2076,"stem":2077},"Стратегії Тестування","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Ftesting-strategies","03.javascript\u002F04.react\u002F04.tanstack-query\u002F11.testing-strategies",{"title":2079,"path":2080,"stem":2081},"Аутентифікація та Обробка Помилок","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Fauthentication-and-errors","03.javascript\u002F04.react\u002F04.tanstack-query\u002F12.authentication-and-errors",{"title":2083,"path":2084,"stem":2085},"React Suspense та Майбутнє","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Freact-suspense","03.javascript\u002F04.react\u002F04.tanstack-query\u002F13.react-suspense",{"title":2087,"path":2088,"stem":2089},"Глибоке Занурення в Продуктивність","\u002Fjavascript\u002Freact\u002Ftanstack-query\u002Fperformance-deep-dive","03.javascript\u002F04.react\u002F04.tanstack-query\u002F14.performance-deep-dive",{"title":2091,"icon":2006,"path":2092,"stem":2093,"children":2094},"React Router","\u002Fjavascript\u002Freact\u002Freact-router","03.javascript\u002F04.react\u002F05.react-router\u002Findex",[2095,2097,2101,2105,2109,2113,2117,2121],{"title":2096,"path":2092,"stem":2093},"React Router: Навігаційна система сучасного вебу",{"title":2098,"path":2099,"stem":2100},"Налаштування та Базовий Роутинг","\u002Fjavascript\u002Freact\u002Freact-router\u002Fsetup-and-basic-routing","03.javascript\u002F04.react\u002F05.react-router\u002F01.setup-and-basic-routing",{"title":2102,"path":2103,"stem":2104},"Динамічна Навігація","\u002Fjavascript\u002Freact\u002Freact-router\u002Fnavigation-and-links","03.javascript\u002F04.react\u002F05.react-router\u002F02.navigation-and-links",{"title":2106,"path":2107,"stem":2108},"Вкладені Маршрути та Макети","\u002Fjavascript\u002Freact\u002Freact-router\u002Fnested-routes-and-layouts","03.javascript\u002F04.react\u002F05.react-router\u002F03.nested-routes-and-layouts",{"title":2110,"path":2111,"stem":2112},"Динамічні Маршрути та Параметри","\u002Fjavascript\u002Freact\u002Freact-router\u002Fdynamic-routing","03.javascript\u002F04.react\u002F05.react-router\u002F04.dynamic-routing",{"title":2114,"path":2115,"stem":2116},"Data APIs: Loaders та Actions","\u002Fjavascript\u002Freact\u002Freact-router\u002Fdata-loading","03.javascript\u002F04.react\u002F05.react-router\u002F05.data-loading",{"title":2118,"path":2119,"stem":2120},"Просунуті Патерни","\u002Fjavascript\u002Freact\u002Freact-router\u002Fadvanced-patterns","03.javascript\u002F04.react\u002F05.react-router\u002F06.advanced-patterns",{"title":2122,"path":2123,"stem":2124},"Legacy Routing: Компонентний підхід","\u002Fjavascript\u002Freact\u002Freact-router\u002Flegacy-routing","03.javascript\u002F04.react\u002F05.react-router\u002F07.legacy-routing",{"title":2126,"icon":132,"path":2127,"stem":2128,"children":2129},"Redux","\u002Fjavascript\u002Freact\u002Fredux","03.javascript\u002F04.react\u002F06.redux\u002Findex",[2130,2132,2148,2177,2186,2207,2223,2252],{"title":2131,"path":2127,"stem":2128},"Redux: Еволюція управління станом",{"title":14,"icon":15,"path":2133,"stem":2134,"children":2135,"page":59},"\u002Fjavascript\u002Freact\u002Fredux\u002Ffundamentals","03.javascript\u002F04.react\u002F06.redux\u002F01.fundamentals",[2136,2140,2144],{"title":2137,"path":2138,"stem":2139},"Вступ до State Management","\u002Fjavascript\u002Freact\u002Fredux\u002Ffundamentals\u002Fintro-state-management","03.javascript\u002F04.react\u002F06.redux\u002F01.fundamentals\u002F01.intro-state-management",{"title":2141,"path":2142,"stem":2143},"Філософія Redux та Три Принципи","\u002Fjavascript\u002Freact\u002Fredux\u002Ffundamentals\u002Fredux-philosophy","03.javascript\u002F04.react\u002F06.redux\u002F01.fundamentals\u002F02.redux-philosophy",{"title":2145,"path":2146,"stem":2147},"Чисті функції та Іммутабельність","\u002Fjavascript\u002Freact\u002Fredux\u002Ffundamentals\u002Fpure-functions-immutability","03.javascript\u002F04.react\u002F06.redux\u002F01.fundamentals\u002F03.pure-functions-immutability",{"title":2149,"icon":132,"path":2150,"stem":2151,"children":2152,"page":59},"Classic Redux","\u002Fjavascript\u002Freact\u002Fredux\u002Fclassic-redux","03.javascript\u002F04.react\u002F06.redux\u002F02.classic-redux",[2153,2157,2161,2165,2169,2173],{"title":2154,"path":2155,"stem":2156},"Створення Store (Classic Redux)","\u002Fjavascript\u002Freact\u002Fredux\u002Fclassic-redux\u002Fstore-setup","03.javascript\u002F04.react\u002F06.redux\u002F02.classic-redux\u002F01.store-setup",{"title":2158,"path":2159,"stem":2160},"Actions, Constants та Action Creators","\u002Fjavascript\u002Freact\u002Fredux\u002Fclassic-redux\u002Factions-constants","03.javascript\u002F04.react\u002F06.redux\u002F02.classic-redux\u002F02.actions-constants",{"title":2162,"path":2163,"stem":2164},"Логіка Reducers","\u002Fjavascript\u002Freact\u002Fredux\u002Fclassic-redux\u002Freducers","03.javascript\u002F04.react\u002F06.redux\u002F02.classic-redux\u002F03.reducers",{"title":2166,"path":2167,"stem":2168},"Комбінування Reducers (Root Reducer)","\u002Fjavascript\u002Freact\u002Fredux\u002Fclassic-redux\u002Fdata-flow","03.javascript\u002F04.react\u002F06.redux\u002F02.classic-redux\u002F04.data-flow",{"title":2170,"path":2171,"stem":2172},"Підключення до React (React-Redux)","\u002Fjavascript\u002Freact\u002Fredux\u002Fclassic-redux\u002Freact-redux-connection","03.javascript\u002F04.react\u002F06.redux\u002F02.classic-redux\u002F05.react-redux-connection",{"title":2174,"path":2175,"stem":2176},"Middleware та Асинхронність (Redux Thunk)","\u002Fjavascript\u002Freact\u002Fredux\u002Fclassic-redux\u002Fmiddleware-thunk","03.javascript\u002F04.react\u002F06.redux\u002F02.classic-redux\u002F06.middleware-thunk",{"title":2178,"icon":132,"path":2179,"stem":2180,"children":2181,"page":59},"Transition To Rtk","\u002Fjavascript\u002Freact\u002Fredux\u002Ftransition-to-rtk","03.javascript\u002F04.react\u002F06.redux\u002F03.transition-to-rtk",[2182],{"title":2183,"path":2184,"stem":2185},"Проблеми класичного Redux","\u002Fjavascript\u002Freact\u002Fredux\u002Ftransition-to-rtk\u002Fproblems-with-classic","03.javascript\u002F04.react\u002F06.redux\u002F03.transition-to-rtk\u002F01.problems-with-classic",{"title":2187,"icon":132,"path":2188,"stem":2189,"children":2190,"page":59},"Redux Toolkit","\u002Fjavascript\u002Freact\u002Fredux\u002Fredux-toolkit","03.javascript\u002F04.react\u002F06.redux\u002F04.redux-toolkit",[2191,2195,2199,2203],{"title":2192,"path":2193,"stem":2194},"Налаштування Store з configureStore","\u002Fjavascript\u002Freact\u002Fredux\u002Fredux-toolkit\u002Fconfigure-store","03.javascript\u002F04.react\u002F06.redux\u002F04.redux-toolkit\u002F01.configure-store",{"title":2196,"path":2197,"stem":2198},"createSlice: Революція в Redux","\u002Fjavascript\u002Freact\u002Fredux\u002Fredux-toolkit\u002Fcreate-slice","03.javascript\u002F04.react\u002F06.redux\u002F04.redux-toolkit\u002F02.create-slice",{"title":2200,"path":2201,"stem":2202},"Асинхронність з createAsyncThunk","\u002Fjavascript\u002Freact\u002Fredux\u002Fredux-toolkit\u002Fasync-thunks","03.javascript\u002F04.react\u002F06.redux\u002F04.redux-toolkit\u002F03.async-thunks",{"title":2204,"path":2205,"stem":2206},"04. Entity Adapter: Керування нормалізованим станом","\u002Fjavascript\u002Freact\u002Fredux\u002Fredux-toolkit\u002Fentity-adapter","03.javascript\u002F04.react\u002F06.redux\u002F04.redux-toolkit\u002F04.entity-adapter",{"title":2208,"icon":92,"path":2209,"stem":2210,"children":2211,"page":59},"Advanced","\u002Fjavascript\u002Freact\u002Fredux\u002Fadvanced","03.javascript\u002F04.react\u002F06.redux\u002F05.advanced",[2212,2216,2220],{"title":2213,"path":2214,"stem":2215},"Мемоізація та Селектори: Повний Гайд по Reselect","\u002Fjavascript\u002Freact\u002Fredux\u002Fadvanced\u002Fselectors-reselect","03.javascript\u002F04.react\u002F06.redux\u002F05.advanced\u002F01.selectors-reselect",{"title":2217,"path":2218,"stem":2219},"RTK Query: Архітектура Серверного Кешу","\u002Fjavascript\u002Freact\u002Fredux\u002Fadvanced\u002Frtk-query-intro","03.javascript\u002F04.react\u002F06.redux\u002F05.advanced\u002F02.rtk-query-intro",{"title":2067,"path":2221,"stem":2222},"\u002Fjavascript\u002Freact\u002Fredux\u002Fadvanced\u002Farchitecture-best-practices","03.javascript\u002F04.react\u002F06.redux\u002F05.advanced\u002F03.architecture-best-practices",{"title":2224,"icon":132,"path":2225,"stem":2226,"children":2227,"page":59},"Project Kanban","\u002Fjavascript\u002Freact\u002Fredux\u002Fproject-kanban","03.javascript\u002F04.react\u002F06.redux\u002F06.project-kanban",[2228,2232,2236,2240,2244,2248],{"title":2229,"path":2230,"stem":2231},"Проєкт: Kanban Board (Trello Clone)","\u002Fjavascript\u002Freact\u002Fredux\u002Fproject-kanban\u002Fproject-overview","03.javascript\u002F04.react\u002F06.redux\u002F06.project-kanban\u002F01.project-overview",{"title":2233,"path":2234,"stem":2235},"Налаштування та Типізація","\u002Fjavascript\u002Freact\u002Fredux\u002Fproject-kanban\u002Fsetup-and-types","03.javascript\u002F04.react\u002F06.redux\u002F06.project-kanban\u002F02.setup-and-types",{"title":2237,"path":2238,"stem":2239},"Board Slice: Серце Дошки","\u002Fjavascript\u002Freact\u002Fredux\u002Fproject-kanban\u002Fboard-slice","03.javascript\u002F04.react\u002F06.redux\u002F06.project-kanban\u002F03.board-slice",{"title":2241,"path":2242,"stem":2243},"Логіка Drag & Drop","\u002Fjavascript\u002Freact\u002Fredux\u002Fproject-kanban\u002Fdrag-and-drop-logic","03.javascript\u002F04.react\u002F06.redux\u002F06.project-kanban\u002F04.drag-and-drop-logic",{"title":2245,"path":2246,"stem":2247},"Інтеграція з RTK Query","\u002Fjavascript\u002Freact\u002Fredux\u002Fproject-kanban\u002Frtk-query-integration","03.javascript\u002F04.react\u002F06.redux\u002F06.project-kanban\u002F05.rtk-query-integration",{"title":2249,"path":2250,"stem":2251},"Optimistic Updates","\u002Fjavascript\u002Freact\u002Fredux\u002Fproject-kanban\u002Foptimistic-updates","03.javascript\u002F04.react\u002F06.redux\u002F06.project-kanban\u002F06.optimistic-updates",{"title":2253,"icon":132,"path":2254,"stem":2255,"children":2256,"page":59},"Testing","\u002Fjavascript\u002Freact\u002Fredux\u002Ftesting","03.javascript\u002F04.react\u002F06.redux\u002F07.testing",[2257,2261,2265,2269,2273],{"title":2258,"path":2259,"stem":2260},"Тестування Redux","\u002Fjavascript\u002Freact\u002Fredux\u002Ftesting\u002Fintro-testing","03.javascript\u002F04.react\u002F06.redux\u002F07.testing\u002F01.intro-testing",{"title":2262,"path":2263,"stem":2264},"Тестування Reducers","\u002Fjavascript\u002Freact\u002Fredux\u002Ftesting\u002Ftesting-reducers","03.javascript\u002F04.react\u002F06.redux\u002F07.testing\u002F02.testing-reducers",{"title":2266,"path":2267,"stem":2268},"Тестування Селекторів","\u002Fjavascript\u002Freact\u002Fredux\u002Ftesting\u002Ftesting-selectors","03.javascript\u002F04.react\u002F06.redux\u002F07.testing\u002F03.testing-selectors",{"title":2270,"path":2271,"stem":2272},"Тестування Компонентів (Integration)","\u002Fjavascript\u002Freact\u002Fredux\u002Ftesting\u002Ftesting-components","03.javascript\u002F04.react\u002F06.redux\u002F07.testing\u002F04.testing-components",{"title":2274,"path":2275,"stem":2276},"Тестування Async Thunks","\u002Fjavascript\u002Freact\u002Fredux\u002Ftesting\u002Ftesting-thunks","03.javascript\u002F04.react\u002F06.redux\u002F07.testing\u002F05.testing-thunks",{"title":2278,"icon":132,"path":2279,"stem":2280,"children":2281},"Ui Libraries","\u002Fjavascript\u002Freact\u002Fui-libraries","03.javascript\u002F04.react\u002F07.ui-libraries\u002Findex",[2282,2284,2288,2292,2296,2300,2304],{"title":2283,"path":2279,"stem":2280},"UI Бібліотеки в React",{"title":2285,"path":2286,"stem":2287},"Вступ до UI Бібліотек: Навіщо Винаходити Велосипед Двічі?","\u002Fjavascript\u002Freact\u002Fui-libraries\u002Fintroduction-to-ui-libraries","03.javascript\u002F04.react\u002F07.ui-libraries\u002F01.introduction-to-ui-libraries",{"title":2289,"path":2290,"stem":2291},"Філософія shadcn\u002Fui: \"Not a Component Library\"","\u002Fjavascript\u002Freact\u002Fui-libraries\u002Fshadcn-philosophy","03.javascript\u002F04.react\u002F07.ui-libraries\u002F02.shadcn-philosophy",{"title":2293,"path":2294,"stem":2295},"Установка та Налаштування shadcn\u002Fui","\u002Fjavascript\u002Freact\u002Fui-libraries\u002Fshadcn-installation","03.javascript\u002F04.react\u002F07.ui-libraries\u002F03.shadcn-installation",{"title":2297,"path":2298,"stem":2299},"Базові Компоненти shadcn\u002Fui: Фундамент Інтерфейсу","\u002Fjavascript\u002Freact\u002Fui-libraries\u002Fshadcn-components-basics","03.javascript\u002F04.react\u002F07.ui-libraries\u002F04.shadcn-components-basics",{"title":2301,"path":2302,"stem":2303},"Компоненти Форм: Побудова Інтерактивних Form","\u002Fjavascript\u002Freact\u002Fui-libraries\u002Fshadcn-components-forms","03.javascript\u002F04.react\u002F07.ui-libraries\u002F05.shadcn-components-forms",{"title":2305,"path":2306,"stem":2307},"Складні Компоненти: Dialog, Dropdown, Table та Command","\u002Fjavascript\u002Freact\u002Fui-libraries\u002Fshadcn-components-advanced","03.javascript\u002F04.react\u002F07.ui-libraries\u002F06.shadcn-components-advanced",{"title":2309,"icon":2310,"path":2311,"stem":2312,"children":2313,"page":59},"TypeScript","i-devicon-typescript","\u002Fjavascript\u002Ftypescript","03.javascript\u002F05.typescript",[2314,2318,2322,2326,2330,2334,2338,2342],{"title":2315,"path":2316,"stem":2317},"TypeScript: Броня для вашого коду","\u002Fjavascript\u002Ftypescript\u002Fintro-and-basic-types","03.javascript\u002F05.typescript\u002F01.intro-and-basic-types",{"title":2319,"path":2320,"stem":2321},"Майстерність Моделювання Даних: Інтерфейси та Просунуті Типи","\u002Fjavascript\u002Ftypescript\u002Finterfaces-and-advanced-types","03.javascript\u002F05.typescript\u002F02.interfaces-and-advanced-types",{"title":2323,"path":2324,"stem":2325},"Алхімія Типів: Generics та Utility Types","\u002Fjavascript\u002Ftypescript\u002Fgenerics-and-utilities","03.javascript\u002F05.typescript\u002F03.generics-and-utilities",{"title":2327,"path":2328,"stem":2329},"Архітектура та Шаблони: Класи в TypeScript","\u002Fjavascript\u002Ftypescript\u002Fclasses-and-oop","03.javascript\u002F05.typescript\u002F04.classes-and-oop",{"title":2331,"path":2332,"stem":2333},"Продакшн та Екосистема: Advanced Config & Workflow","\u002Fjavascript\u002Ftypescript\u002Fadvanced-patterns-and-config","03.javascript\u002F05.typescript\u002F05.advanced-patterns-and-config",{"title":2335,"path":2336,"stem":2337},"TypeScript у світі React","\u002Fjavascript\u002Ftypescript\u002Freact-basics","03.javascript\u002F05.typescript\u002F06.react-basics",{"title":2339,"path":2340,"stem":2341},"React + TypeScript: Продвинуті патерни","\u002Fjavascript\u002Ftypescript\u002Freact-advanced","03.javascript\u002F05.typescript\u002F07.react-advanced",{"title":2343,"path":2344,"stem":2345},"React + TypeScript: Екосистема та бібліотеки","\u002Fjavascript\u002Ftypescript\u002Freact-ecosystem","03.javascript\u002F05.typescript\u002F08.react-ecosystem",{"title":2347,"path":2348,"stem":2349},"Atomic Design","\u002Fjavascript\u002Fatomic-design","03.javascript\u002F2.atomic-design",{"title":2351,"icon":2352,"path":2353,"stem":2354,"children":2355,"page":59},"Java","i-devicon-java","\u002Fjava","04.java",[2356,2359,2362,2366,2370,2374,2378],{"title":162,"path":2357,"stem":2358},"\u002Fjava\u002Fdata-mapper-part1","04.java\u002F01.data-mapper-part1",{"title":166,"path":2360,"stem":2361},"\u002Fjava\u002Fdata-mapper-part2","04.java\u002F02.data-mapper-part2",{"title":2363,"path":2364,"stem":2365},"Service Layer: Організація бізнес-логіки","\u002Fjava\u002Fservice-layer","04.java\u002F03.service-layer",{"title":2367,"path":2368,"stem":2369},"Rich Domain Model та State Pattern","\u002Fjava\u002Frich-domain-model","04.java\u002F04.rich-domain-model",{"title":2371,"path":2372,"stem":2373},"Патерни для складної бізнес-логіки","\u002Fjava\u002Fbusiness-logic-patterns","04.java\u002F05.business-logic-patterns",{"title":2375,"path":2376,"stem":2377},"Обробка помилок та валідація","\u002Fjava\u002Ferror-handling-validation","04.java\u002F06.error-handling-validation",{"title":2379,"path":2380,"stem":2381,"children":2382,"page":59},"Проектування баз даних","\u002Fjava\u002Fpr2","04.java\u002Fpr2",[2383,2387,2391,2395,2399,2403,2407,2411,2415,2419,2423,2427,2431,2435,2439,2443,2447,2451,2455,2459,2463,2467,2471,2475,2479,2483,2487,2491,2495,2499,2503,2507,2511,2515,2519,2523,2527],{"title":2384,"path":2385,"stem":2386},"Концептуальне моделювання: Мистецтво розуміння предметної області","\u002Fjava\u002Fpr2\u002Fconceptual-modeling","04.java\u002Fpr2\u002F01.conceptual-modeling",{"title":2388,"path":2389,"stem":2390},"Логічне моделювання: Від бізнес-ідей до структур даних","\u002Fjava\u002Fpr2\u002Flogical-modeling","04.java\u002Fpr2\u002F02.logical-modeling",{"title":2392,"path":2393,"stem":2394},"Нормалізація: Гігієна даних та боротьба з аномаліями","\u002Fjava\u002Fpr2\u002Fnormalization","04.java\u002Fpr2\u002F03.normalization",{"title":2396,"path":2397,"stem":2398},"Фізична схема: Від абстракції до DDL","\u002Fjava\u002Fpr2\u002Fphysical-schema","04.java\u002Fpr2\u002F04.physical-schema",{"title":2400,"path":2401,"stem":2402},"Архітектурна класифікація таблиць","\u002Fjava\u002Fpr2\u002Ftable-classification","04.java\u002Fpr2\u002F05.table-classification",{"title":2404,"path":2405,"stem":2406},"Database Migrations: Версіонування схеми з Flyway","\u002Fjava\u002Fpr2\u002Fdatabase-migrations","04.java\u002Fpr2\u002F06.database-migrations",{"title":2408,"path":2409,"stem":2410},"А що, якби це була не реляційна БД?","\u002Fjava\u002Fpr2\u002Fbeyond-relational","04.java\u002Fpr2\u002F07.beyond-relational",{"title":2412,"path":2413,"stem":2414},"Object-Relational Impedance Mismatch: Два світи, що не хочуть дружити","\u002Fjava\u002Fpr2\u002Fimpedance-mismatch","04.java\u002Fpr2\u002F09.impedance-mismatch",{"title":2416,"path":2417,"stem":2418},"JDBC: Перший контакт із базою даних","\u002Fjava\u002Fpr2\u002Fjdbc-fundamentals","04.java\u002Fpr2\u002F10.jdbc-fundamentals",{"title":2420,"path":2421,"stem":2422},"Якість коду: Spotless, SpotBugs та SonarQube","\u002Fjava\u002Fpr2\u002F10a.code-quality","04.java\u002Fpr2\u002F10a.code-quality",{"title":2424,"path":2425,"stem":2426},"Connection Pool: Патерн Object Pool для JDBC-з'єднань","\u002Fjava\u002Fpr2\u002Fconnection-pool","04.java\u002Fpr2\u002F11.connection-pool",{"title":2428,"path":2429,"stem":2430},"Row Data Gateway: Об'єкт як обгортка рядка таблиці","\u002Fjava\u002Fpr2\u002Frow-data-gateway","04.java\u002Fpr2\u002F12.row-data-gateway",{"title":2432,"path":2433,"stem":2434},"Table Data Gateway: Фасад таблиці як архітектурний відступ","\u002Fjava\u002Fpr2\u002Ftable-data-gateway","04.java\u002Fpr2\u002F13.table-data-gateway",{"title":2436,"path":2437,"stem":2438},"Repository + Data Mapper: Правильна шарова архітектура з JDBC","\u002Fjava\u002Fpr2\u002Frepository-data-mapper","04.java\u002Fpr2\u002F14.repository-data-mapper",{"title":2440,"path":2441,"stem":2442},"Identity Map: Кешування сутностей у рамках сесії","\u002Fjava\u002Fpr2\u002Fidentity-map","04.java\u002Fpr2\u002F15.identity-map",{"title":2444,"path":2445,"stem":2446},"Unit of Work: Відстеження змін і координація JDBC-транзакцій","\u002Fjava\u002Fpr2\u002Funit-of-work","04.java\u002Fpr2\u002F16.unit-of-work",{"title":2448,"path":2449,"stem":2450},"Strategy: Замінювані SQL-стратегії для підтримки різних СУБД","\u002Fjava\u002Fpr2\u002Fstrategy-sql","04.java\u002Fpr2\u002F17.strategy-sql",{"title":2452,"path":2453,"stem":2454},"Proxy: Lazy Loading для One-To-Many колекцій","\u002Fjava\u002Fpr2\u002Fproxy-lazy-loading","04.java\u002Fpr2\u002F18.proxy-lazy-loading",{"title":2456,"path":2457,"stem":2458},"Generic Repository через Java Reflection: анотації та динамічний SQL","\u002Fjava\u002Fpr2\u002Fgeneric-repository-reflection","04.java\u002Fpr2\u002F19.generic-repository-reflection",{"title":2460,"path":2461,"stem":2462},"Specification Pattern: Композиція бізнес-правил для складних запитів","\u002Fjava\u002Fpr2\u002Fspecification-pattern","04.java\u002Fpr2\u002F20.specification-pattern",{"title":2464,"path":2465,"stem":2466},"Розширені можливості Specification Pattern: підзапити, агрегації та гібридний підхід","\u002Fjava\u002Fpr2\u002F20a.advanced-specifications","04.java\u002Fpr2\u002F20a.advanced-specifications",{"title":2468,"path":2469,"stem":2470},"Асинхронність у JDBC: Від блокуючих викликів до CompletableFuture","\u002Fjava\u002Fpr2\u002Fasynchronous-jdbc","04.java\u002Fpr2\u002F21.asynchronous-jdbc",{"title":2472,"path":2473,"stem":2474},"Інтеграційне тестування JDBC-репозиторіїв: Embedded H2 та патерн AAA","\u002Fjava\u002Fpr2\u002Fintegration-testing-h2","04.java\u002Fpr2\u002F22.integration-testing-h2",{"title":2476,"path":2477,"stem":2478},"Testcontainers: Тестування з реальною PostgreSQL у Docker-контейнерах","\u002Fjava\u002Fpr2\u002Fintegration-testing-testcontainers","04.java\u002Fpr2\u002F23.integration-testing-testcontainers",{"title":2480,"path":2481,"stem":2482},"Google Guice: Впровадження залежностей у JavaFX-проєкті","\u002Fjava\u002Fpr2\u002Fdependency-injection-guice","04.java\u002Fpr2\u002F24.dependency-injection-guice",{"title":2484,"path":2485,"stem":2486},"JavaFX: Основи побудови графічних інтерфейсів","\u002Fjava\u002Fpr2\u002Fjavafx-fundamentals","04.java\u002Fpr2\u002F25.javafx-fundamentals",{"title":2488,"path":2489,"stem":2490},"Properties та Bindings: Реактивність у JavaFX","\u002Fjava\u002Fpr2\u002Fjavafx-properties-bindings","04.java\u002Fpr2\u002F26.javafx-properties-bindings",{"title":2492,"path":2493,"stem":2494},"MVC vs MVP vs MVVM: Еволюція архітектурних патернів UI","\u002Fjava\u002Fpr2\u002Fui-architecture-patterns","04.java\u002Fpr2\u002F27.ui-architecture-patterns",{"title":2496,"path":2497,"stem":2498},"MVVM на практиці: Побудова ViewModel","\u002Fjava\u002Fpr2\u002Fmvvm-viewmodel-implementation","04.java\u002Fpr2\u002F28.mvvm-viewmodel-implementation",{"title":2500,"path":2501,"stem":2502},"View та Controller: Зв'язування з ViewModel через FXML","\u002Fjava\u002Fpr2\u002Fmvvm-view-controller","04.java\u002Fpr2\u002F29.mvvm-view-controller",{"title":2504,"path":2505,"stem":2506},"Інтеграція MVVM з Guice: Автоматична ін'єкція залежностей","\u002Fjava\u002Fpr2\u002Fmvvm-guice-integration","04.java\u002Fpr2\u002F30.mvvm-guice-integration",{"title":2508,"path":2509,"stem":2510},"Валідація та обробка помилок у MVVM","\u002Fjava\u002Fpr2\u002Fmvvm-validation-error-handling","04.java\u002Fpr2\u002F31.mvvm-validation-error-handling",{"title":2512,"path":2513,"stem":2514},"Навігація та управління екранами у JavaFX MVVM","\u002Fjava\u002Fpr2\u002Fmvvm-navigation-screen-management","04.java\u002Fpr2\u002F32.mvvm-navigation-screen-management",{"title":2516,"path":2517,"stem":2518},"Тестування JavaFX MVVM-додатків","\u002Fjava\u002Fpr2\u002Fmvvm-testing","04.java\u002Fpr2\u002F33.mvvm-testing",{"title":2520,"path":2521,"stem":2522},"Стилізація та теми у JavaFX: CSS та User Experience","\u002Fjava\u002Fpr2\u002Fjavafx-styling-themes","04.java\u002Fpr2\u002F34.javafx-styling-themes",{"title":2524,"path":2525,"stem":2526},"AtlantaFX: Сучасні теми для JavaFX додатків","\u002Fjava\u002Fpr2\u002Fatlantafx-modern-themes","04.java\u002Fpr2\u002F35.atlantafx-modern-themes",{"title":2528,"path":2529,"stem":2530},"Пакування та розповсюдження JavaFX-додатків","\u002Fjava\u002Fpr2\u002Fjar-packaging-distribution","04.java\u002Fpr2\u002F36.jar-packaging-distribution",{"title":2532,"icon":2533,"path":2534,"stem":2535,"children":2536,"page":59},"Python","i-devicon-python","\u002Fpython","05.python",[2537,2541,2544,2548,2552,2556,2560,2564,2568],{"title":2538,"path":2539,"stem":2540},"Модулі, Пакети та Віртуальні Середовища","\u002Fpython\u002Fmodules-packages-venv","05.python\u002F00.modules-packages-venv",{"title":71,"path":2542,"stem":2543},"\u002Fpython\u002Fclasses-objects","05.python\u002F01.classes-objects",{"title":2545,"path":2546,"stem":2547},"Інкапсуляція, Керування Доступом та Властивості","\u002Fpython\u002Fencapsulation","05.python\u002F02.encapsulation",{"title":2549,"path":2550,"stem":2551},"Наслідування, MRO та суперсила super()","\u002Fpython\u002Finheritance-mro","05.python\u002F03.inheritance-mro",{"title":2553,"path":2554,"stem":2555},"Абстракція — ABC проти Статичних Протоколів (PEP 544)","\u002Fpython\u002Fabstraction-protocols","05.python\u002F04.abstraction-protocols",{"title":2557,"path":2558,"stem":2559},"Магічні методи (Dunder) та Емуляція протоколів","\u002Fpython\u002Fdunder-methods","05.python\u002F05.dunder-methods",{"title":2561,"path":2562,"stem":2563},"Декоратори та Керування життєвим циклом методів","\u002Fpython\u002Fdecorators-static-class","05.python\u002F06.decorators-static-class",{"title":2565,"path":2566,"stem":2567},"📦 Повний посібник з модулів, пакетів та віртуальних середовищ у Python","\u002Fpython\u002Flesson_9","05.python\u002Flesson_9",{"title":2569,"path":2570,"stem":2571},"[object Object]","\u002Fpython\u002Foop-plan","05.python\u002Foop-plan",{"title":2573,"icon":2574,"path":2575,"stem":2576,"children":2577,"page":59},"Бази даних","i-lucide-database","\u002Fdatabases","06.databases",[2578,2608,2631,2668,2697,2715,2749,2761,2770],{"title":2579,"icon":2580,"path":2581,"stem":2582,"children":2583,"page":59},"Intro","i-lucide-play","\u002Fdatabases\u002Fintro","06.databases\u002F01.intro",[2584,2588,2592,2596,2600,2604],{"title":2585,"path":2586,"stem":2587},"Введення в теорію баз даних","\u002Fdatabases\u002Fintro\u002Fintroduction-to-databases","06.databases\u002F01.intro\u002F01.introduction-to-databases",{"title":2589,"path":2590,"stem":2591},"Реляційна модель даних","\u002Fdatabases\u002Fintro\u002Frelational-model-theory","06.databases\u002F01.intro\u002F02.relational-model-theory",{"title":2593,"path":2594,"stem":2595},"ER-моделювання","\u002Fdatabases\u002Fintro\u002Fer-modeling","06.databases\u002F01.intro\u002F03.er-modeling",{"title":2597,"path":2598,"stem":2599},"Логічне проектування БД","\u002Fdatabases\u002Fintro\u002Flogical-schema","06.databases\u002F01.intro\u002F04.logical-schema",{"title":2601,"path":2602,"stem":2603},"Класифікація таблиць","\u002Fdatabases\u002Fintro\u002Ftable-classification","06.databases\u002F01.intro\u002F05.table-classification",{"title":2605,"path":2606,"stem":2607},"PlantUML для баз даних","\u002Fdatabases\u002Fintro\u002Fplantuml-diagrams","06.databases\u002F01.intro\u002F06.plantuml-diagrams",{"title":2609,"icon":2574,"path":2610,"stem":2611,"children":2612,"page":59},"MS SQL Server Start","\u002Fdatabases\u002Fms-sql-server-start","06.databases\u002F02.ms-sql-server-start",[2613,2617,2623,2627],{"title":2614,"path":2615,"stem":2616},"Типи даних у MS SQL Server","\u002Fdatabases\u002Fms-sql-server-start\u002Fdata-types","06.databases\u002F02.ms-sql-server-start\u002F01.data-types",{"title":2618,"path":2619,"stem":2620,"children":2621},"Індекси у MS SQL Server","\u002Fdatabases\u002Fms-sql-server-start\u002Fsql-indexes","06.databases\u002F02.ms-sql-server-start\u002F02.sql-indexes",[2622],{"title":2618,"path":2619,"stem":2620},{"title":2624,"path":2625,"stem":2626},"Системні бази даних MS SQL Server","\u002Fdatabases\u002Fms-sql-server-start\u002Fsystem-databases","06.databases\u002F02.ms-sql-server-start\u002F03.system-databases",{"title":2628,"path":2629,"stem":2630},"Огляд мови SQL та запитів","\u002Fdatabases\u002Fms-sql-server-start\u002Fsql-queries-overview","06.databases\u002F02.ms-sql-server-start\u002F04.sql-queries-overview",{"title":2632,"icon":2574,"path":2633,"stem":2634,"children":2635,"page":59},"SQL","\u002Fdatabases\u002Fsql","06.databases\u002F03.sql",[2636,2640,2644,2648,2652,2656,2660,2664],{"title":2637,"path":2638,"stem":2639},"Налаштування демонстраційної бази даних","\u002Fdatabases\u002Fsql\u002Fsample-database-setup","06.databases\u002F03.sql\u002F00.sample-database-setup",{"title":2641,"path":2642,"stem":2643},"DDL - Створення таблиць (CREATE TABLE)","\u002Fdatabases\u002Fsql\u002Fddl-create-table","06.databases\u002F03.sql\u002F01.ddl-create-table",{"title":2645,"path":2646,"stem":2647},"DDL - Зміна та видалення таблиць (ALTER, DROP)","\u002Fdatabases\u002Fsql\u002Fddl-alter-drop-table","06.databases\u002F03.sql\u002F02.ddl-alter-drop-table",{"title":2649,"path":2650,"stem":2651},"SELECT запити - Основи","\u002Fdatabases\u002Fsql\u002Fselect-queries-fundamentals","06.databases\u002F03.sql\u002F03.select-queries-fundamentals",{"title":2653,"path":2654,"stem":2655},"SELECT запити - Розширені можливості","\u002Fdatabases\u002Fsql\u002Fselect-queries-advanced","06.databases\u002F03.sql\u002F04.select-queries-advanced",{"title":2657,"path":2658,"stem":2659},"INSERT запити - Додавання даних","\u002Fdatabases\u002Fsql\u002Finsert-queries","06.databases\u002F03.sql\u002F05.insert-queries",{"title":2661,"path":2662,"stem":2663},"UPDATE та DELETE запити","\u002Fdatabases\u002Fsql\u002Fupdate-delete-queries","06.databases\u002F03.sql\u002F06.update-delete-queries",{"title":2665,"path":2666,"stem":2667},"Транзакції в SQL","\u002Fdatabases\u002Fsql\u002Ftransactions","06.databases\u002F03.sql\u002F07.transactions",{"title":2669,"icon":2574,"path":2670,"stem":2671,"children":2672,"page":59},"Multi Table Databases","\u002Fdatabases\u002Fmulti-table-databases","06.databases\u002F04.multi-table-databases",[2673,2677,2681,2685,2689,2693],{"title":2674,"path":2675,"stem":2676},"Зв'язки та нормалізація БД","\u002Fdatabases\u002Fmulti-table-databases\u002Frelationships-and-normalization","06.databases\u002F04.multi-table-databases\u002F00.relationships-and-normalization",{"title":2678,"path":2679,"stem":2680},"INNER JOIN - З'єднання таблиць","\u002Fdatabases\u002Fmulti-table-databases\u002Finner-join","06.databases\u002F04.multi-table-databases\u002F01.inner-join",{"title":2682,"path":2683,"stem":2684},"OUTER JOINs - LEFT, RIGHT, FULL","\u002Fdatabases\u002Fmulti-table-databases\u002Fouter-joins","06.databases\u002F04.multi-table-databases\u002F02.outer-joins",{"title":2686,"path":2687,"stem":2688},"CROSS та SELF JOINs","\u002Fdatabases\u002Fmulti-table-databases\u002Fcross-self-joins","06.databases\u002F04.multi-table-databases\u002F03.cross-self-joins",{"title":2690,"path":2691,"stem":2692},"Підзапити (Subqueries)","\u002Fdatabases\u002Fmulti-table-databases\u002Fsubqueries","06.databases\u002F04.multi-table-databases\u002F04.subqueries",{"title":2694,"path":2695,"stem":2696},"Агрегації з JOIN","\u002Fdatabases\u002Fmulti-table-databases\u002Faggregations-with-joins","06.databases\u002F04.multi-table-databases\u002F05.aggregations-with-joins",{"title":2698,"icon":2699,"path":2700,"stem":2701,"children":2702,"page":59},"Aggregate Functions","i-lucide-calculator","\u002Fdatabases\u002Faggregate-functions","06.databases\u002F05.aggregate-functions",[2703,2707,2711],{"title":2704,"path":2705,"stem":2706},"Функції агрегування в MS SQL Server","\u002Fdatabases\u002Faggregate-functions\u002Fintroduction-aggregate-functions","06.databases\u002F05.aggregate-functions\u002F01.introduction-aggregate-functions",{"title":2708,"path":2709,"stem":2710},"Групування даних в MS SQL Server","\u002Fdatabases\u002Faggregate-functions\u002Fgrouping-data","06.databases\u002F05.aggregate-functions\u002F02.grouping-data",{"title":2712,"path":2713,"stem":2714},"Підзапити з агрегатними функціями","\u002Fdatabases\u002Faggregate-functions\u002Fsubqueries-aggregates","06.databases\u002F05.aggregate-functions\u002F03.subqueries-aggregates",{"title":2716,"icon":2717,"path":2718,"stem":2719,"children":2720,"page":59},"Тригери та зберігаємі процедури","i-lucide-database-zap","\u002Fdatabases\u002Ftriggers-stored-procedures","06.databases\u002F07.triggers-stored-procedures",[2721,2725,2729,2733,2737,2741,2745],{"title":2722,"path":2723,"stem":2724},"DML-тригери","\u002Fdatabases\u002Ftriggers-stored-procedures\u002Fdml-triggers","06.databases\u002F07.triggers-stored-procedures\u002F01.dml-triggers",{"title":2726,"path":2727,"stem":2728},"DDL-тригери","\u002Fdatabases\u002Ftriggers-stored-procedures\u002Fddl-triggers","06.databases\u002F07.triggers-stored-procedures\u002F02.ddl-triggers",{"title":2730,"path":2731,"stem":2732},"Transact-SQL розширення","\u002Fdatabases\u002Ftriggers-stored-procedures\u002Ftransact-sql-extensions","06.databases\u002F07.triggers-stored-procedures\u002F03.transact-sql-extensions",{"title":2734,"path":2735,"stem":2736},"Транзакції","\u002Fdatabases\u002Ftriggers-stored-procedures\u002Ftransactions","06.databases\u002F07.triggers-stored-procedures\u002F04.transactions",{"title":2738,"path":2739,"stem":2740},"Зберігаємі процедури","\u002Fdatabases\u002Ftriggers-stored-procedures\u002Fstored-procedures","06.databases\u002F07.triggers-stored-procedures\u002F05.stored-procedures",{"title":2742,"path":2743,"stem":2744},"Користувацькі функції","\u002Fdatabases\u002Ftriggers-stored-procedures\u002Fuser-defined-functions","06.databases\u002F07.triggers-stored-procedures\u002F06.user-defined-functions",{"title":2746,"path":2747,"stem":2748},"Безпека баз даних","\u002Fdatabases\u002Ftriggers-stored-procedures\u002Fsecurity","06.databases\u002F07.triggers-stored-procedures\u002F08.security",{"title":2746,"icon":793,"path":2750,"stem":2751,"children":2752,"page":59},"\u002Fdatabases\u002Fsecurity","06.databases\u002F08.security",[2753,2757],{"title":2754,"path":2755,"stem":2756},"Вступ до безпеки баз даних","\u002Fdatabases\u002Fsecurity\u002Fintroduction","06.databases\u002F08.security\u002F01.introduction",{"title":2758,"path":2759,"stem":2760},"Системні представлення та метадані","\u002Fdatabases\u002Fsecurity\u002Fsystem-views","06.databases\u002F08.security\u002F02.system-views",{"title":2762,"icon":2763,"path":2764,"stem":2765,"children":2766,"page":59},"Резервне копіювання та відновлення","i-lucide-database-backup","\u002Fdatabases\u002Fbackup-recovery","06.databases\u002F09.backup-recovery",[2767],{"title":2762,"path":2768,"stem":2769},"\u002Fdatabases\u002Fbackup-recovery\u002Fbackup-restore","06.databases\u002F09.backup-recovery\u002F01.backup-restore",{"title":2771,"icon":2772,"path":2773,"stem":2774,"children":2775,"page":59},"Повнотекстовий пошук","i-lucide-search","\u002Fdatabases\u002Ffull-text-search","06.databases\u002F10.full-text-search",[2776],{"title":2771,"path":2777,"stem":2778},"\u002Fdatabases\u002Ffull-text-search\u002Ffull-text-search","06.databases\u002F10.full-text-search\u002F01.full-text-search",{"title":2780,"icon":2781,"path":2782,"stem":2783,"children":2784,"page":59},"Tools","i-lucide-wrench","\u002Ftools","07.tools",[2785,2861],{"title":2786,"icon":2787,"path":2788,"stem":2789,"children":2790},"Docker","i-simple-icons-docker","\u002Ftools\u002Fdocker","07.tools\u002F01.docker\u002Findex",[2791,2793,2797,2801,2805,2809,2813,2817,2821,2825,2829,2833,2837,2841,2845,2849,2853,2857],{"title":2792,"path":2788,"stem":2789},"Docker: від нуля до production",{"title":2794,"path":2795,"stem":2796},"Контейнеризація — від проблеми до рішення","\u002Ftools\u002Fdocker\u002Fcontainerization-concept","07.tools\u002F01.docker\u002F01.containerization-concept",{"title":2798,"path":2799,"stem":2800},"Docker — що це і навіщо?","\u002Ftools\u002Fdocker\u002Fdocker-what-and-why","07.tools\u002F01.docker\u002F02.docker-what-and-why",{"title":2802,"path":2803,"stem":2804},"Архітектура Docker Engine","\u002Ftools\u002Fdocker\u002Fdocker-architecture","07.tools\u002F01.docker\u002F03.docker-architecture",{"title":2806,"path":2807,"stem":2808},"Встановлення Docker","\u002Ftools\u002Fdocker\u002Finstallation","07.tools\u002F01.docker\u002F04.installation",{"title":2810,"path":2811,"stem":2812},"Перший контейнер — docker run","\u002Ftools\u002Fdocker\u002Ffirst-container","07.tools\u002F01.docker\u002F05.first-container",{"title":2814,"path":2815,"stem":2816},"Життєвий цикл контейнера","\u002Ftools\u002Fdocker\u002Fcontainer-lifecycle","07.tools\u002F01.docker\u002F06.container-lifecycle",{"title":2818,"path":2819,"stem":2820},"Docker Images — фундаментальні концепції","\u002Ftools\u002Fdocker\u002Fdocker-images-fundamentals","07.tools\u002F01.docker\u002F07.docker-images-fundamentals",{"title":2822,"path":2823,"stem":2824},"Dockerfile — основи","\u002Ftools\u002Fdocker\u002Fdockerfile-basics","07.tools\u002F01.docker\u002F08.dockerfile-basics",{"title":2826,"path":2827,"stem":2828},"Dockerfile — просунуті техніки","\u002Ftools\u002Fdocker\u002Fdockerfile-advanced","07.tools\u002F01.docker\u002F09.dockerfile-advanced",{"title":2830,"path":2831,"stem":2832},"Build Context та кешування шарів","\u002Ftools\u002Fdocker\u002Fbuild-context-and-cache","07.tools\u002F01.docker\u002F10.build-context-and-cache",{"title":2834,"path":2835,"stem":2836},"Реєстри Docker-образів","\u002Ftools\u002Fdocker\u002Fimage-registries","07.tools\u002F01.docker\u002F11.image-registries",{"title":2838,"path":2839,"stem":2840},"Контейнеризація .NET додатків","\u002Ftools\u002Fdocker\u002Fdotnet-containerization","07.tools\u002F01.docker\u002F12.dotnet-containerization",{"title":2842,"path":2843,"stem":2844},"Томи та збереження даних","\u002Ftools\u002Fdocker\u002Fvolumes-and-data","07.tools\u002F01.docker\u002F13.volumes-and-data",{"title":2846,"path":2847,"stem":2848},"Основи мережі в Docker","\u002Ftools\u002Fdocker\u002Fnetworking-basics","07.tools\u002F01.docker\u002F14.networking-basics",{"title":2850,"path":2851,"stem":2852},"Змінні оточення та конфігурація","\u002Ftools\u002Fdocker\u002Fenvironment-and-configuration","07.tools\u002F01.docker\u002F15.environment-and-configuration",{"title":2854,"path":2855,"stem":2856},"Docker Compose — оркестрація контейнерів","\u002Ftools\u002Fdocker\u002Fdocker-compose-basics","07.tools\u002F01.docker\u002F16.docker-compose-basics",{"title":2858,"path":2859,"stem":2860},"Docker Compose — Multi-Service застосунки","\u002Ftools\u002Fdocker\u002Fcompose-multi-service","07.tools\u002F01.docker\u002F17.compose-multi-service",{"title":2862,"icon":2863,"path":2864,"stem":2865,"children":2866},"Kubernetes","simple-icons:kubernetes","\u002Ftools\u002Fkubernetes","07.tools\u002F02.kubernetes\u002Findex",[2867,2869,2873,2877,2881,2885,2889,2893,2897],{"title":2868,"path":2864,"stem":2865},"Kubernetes: від розробки до production",{"title":2870,"path":2871,"stem":2872},"Kubernetes — коли Docker Compose більше не вистачає","\u002Ftools\u002Fkubernetes\u002Fwhy-kubernetes","07.tools\u002F02.kubernetes\u002F01.why-kubernetes",{"title":2874,"path":2875,"stem":2876},"Архітектура Kubernetes — анатомія кластера","\u002Ftools\u002Fkubernetes\u002Fkubernetes-architecture","07.tools\u002F02.kubernetes\u002F02.kubernetes-architecture",{"title":2878,"path":2879,"stem":2880},"Локальне середовище — minikube, kind та k3s","\u002Ftools\u002Fkubernetes\u002Flocal-environment","07.tools\u002F02.kubernetes\u002F03.local-environment",{"title":2882,"path":2883,"stem":2884},"Pod — атомарна одиниця Kubernetes","\u002Ftools\u002Fkubernetes\u002Fpods-and-containers","07.tools\u002F02.kubernetes\u002F04.pods-and-containers",{"title":2886,"path":2887,"stem":2888},"Патерни використання Pod","\u002Ftools\u002Fkubernetes\u002Fpod-patterns","07.tools\u002F02.kubernetes\u002F05.pod-patterns",{"title":2890,"path":2891,"stem":2892},"Deployment — декларативне управління Pod","\u002Ftools\u002Fkubernetes\u002Fdeployment-basics","07.tools\u002F02.kubernetes\u002F06.deployment-basics",{"title":2894,"path":2895,"stem":2896},"Rolling Updates та управління життєвим циклом Deployment","\u002Ftools\u002Fkubernetes\u002Fdeployment-rolling-updates","07.tools\u002F02.kubernetes\u002F07.deployment-rolling-updates",{"title":2898,"path":2899,"stem":2900},"Service — мережева абстракція для Pod","\u002Ftools\u002Fkubernetes\u002Fservices-networking","07.tools\u002F02.kubernetes\u002F08.services-networking",{"title":2902,"icon":2903,"path":2904,"stem":2905,"children":2906,"page":59},"Software Engineering","i-lucide-code-2","\u002Fsoftware-engineering","09.software-engineering",[2907,2911,2915,2919,2923,2927,2931,2935,2939,2943,2947],{"title":2908,"path":2909,"stem":2910},"1. Аналіз предметної області. Експертні знання та складність","\u002Fsoftware-engineering\u002Fintro-subdomains","09.software-engineering\u002F01.intro-subdomains",{"title":2912,"path":2913,"stem":2914},"2. Обмежені контексти. Інтеграція обмежених контекстів","\u002Fsoftware-engineering\u002Fintegrating-limited-contexts","09.software-engineering\u002F02.integrating-limited-contexts",{"title":2916,"path":2917,"stem":2918},"3. Реалізація простої бізнес-логіки","\u002Fsoftware-engineering\u002Fsimple","09.software-engineering\u002F03.simple",{"title":2920,"path":2921,"stem":2922},"4. Опрацювання складної бізнес-логіки","\u002Fsoftware-engineering\u002Fcomplex-business-logic","09.software-engineering\u002F04.complex-business-logic",{"title":2924,"path":2925,"stem":2926},"5. Моделювання фактора часу. Подієво-орієнтована архітектура.","\u002Fsoftware-engineering\u002Fmodelling-the-time-factor","09.software-engineering\u002F05.modelling-the-time-factor",{"title":2928,"path":2929,"stem":2930},"6. Архітектурні патерни","\u002Fsoftware-engineering\u002Farchitectural-patterns","09.software-engineering\u002F06.architectural-patterns",{"title":2932,"path":2933,"stem":2934},"Паттерни взаємодії","\u002Fsoftware-engineering\u002Fpatterns-of-interaction","09.software-engineering\u002F07.patterns-of-interaction",{"title":2936,"path":2937,"stem":2938},"Евристика проєктування","\u002Fsoftware-engineering\u002Fdesign-heuristics","09.software-engineering\u002F08.design-heuristics",{"title":2940,"path":2941,"stem":2942},"Еволюція проєктних рішень","\u002Fsoftware-engineering\u002Fevolution-of-design-solutions","09.software-engineering\u002F09.evolution-of-design-solutions",{"title":2944,"path":2945,"stem":2946},"EventStorming","\u002Fsoftware-engineering\u002Feventstorming","09.software-engineering\u002F10.eventstorming",{"title":2948,"path":2949,"stem":2950},"DDD на практиці","\u002Fsoftware-engineering\u002Fddd-in-practice","09.software-engineering\u002F11.ddd-in-practice",{"title":2952,"icon":943,"path":2953,"stem":2954,"children":2955,"page":59},"DDD","\u002Fddd","10.ddd",[2956,2960,2964,2968,2972,2976,2980,2984,2988,2992,2996,3000,3004],{"title":2957,"path":2958,"stem":2959},"Аналіз предметної області","\u002Fddd\u002Fdomain-analysis","10.ddd\u002F01.domain-analysis",{"title":2961,"path":2962,"stem":2963},"Експертні знання про предметну область","\u002Fddd\u002Fdomain-expert-knowledge","10.ddd\u002F02.domain-expert-knowledge",{"title":2965,"path":2966,"stem":2967},"Як осмислити складність предметної області","\u002Fddd\u002Fmanaging-domain-complexity","10.ddd\u002F03.managing-domain-complexity",{"title":2969,"path":2970,"stem":2971},"Інтеграція обмежених контекстів","\u002Fddd\u002Fbounded-context-integration","10.ddd\u002F04.bounded-context-integration",{"title":2973,"path":2974,"stem":2975},"Реалізація простої бізнес-логіки","\u002Fddd\u002Fsimple-business-logic","10.ddd\u002F05.simple-business-logic",{"title":2977,"path":2978,"stem":2979},"Обробка складної бізнес-логіки","\u002Fddd\u002Fcomplex-business-logic","10.ddd\u002F06.complex-business-logic",{"title":2981,"path":2982,"stem":2983},"Моделювання фактора часу","\u002Fddd\u002Ftime-modeling","10.ddd\u002F07.time-modeling",{"title":2985,"path":2986,"stem":2987},"Глава 8. Архітектурні Патерни","\u002Fddd\u002Farchitectural-patterns","10.ddd\u002F08.architectural-patterns",{"title":2989,"path":2990,"stem":2991},"Глава 9. Патерни Взаємодії","\u002Fddd\u002Finteraction-patterns","10.ddd\u002F09.interaction-patterns",{"title":2993,"path":2994,"stem":2995},"Глава 10. Проектні Евристики","\u002Fddd\u002Fdesign-heuristics","10.ddd\u002F10.design-heuristics",{"title":2997,"path":2998,"stem":2999},"Глава 11. Еволюція Проектних Рішень","\u002Fddd\u002Fevolution-of-design-decisions","10.ddd\u002F11.evolution-of-design-decisions",{"title":3001,"path":3002,"stem":3003},"Глава 12. EventStorming","\u002Fddd\u002Fevent-storming","10.ddd\u002F12.event-storming",{"title":3005,"path":3006,"stem":3007},"Глава 13. DDD на Практиці","\u002Fddd\u002Fddd-in-practice","10.ddd\u002F13.ddd-in-practice",{"title":3009,"icon":3010,"path":3011,"stem":3012,"children":3013,"page":59},"Media Streaming","i-lucide-video","\u002Fmedia-streaming","11.media-streaming",[3014,3018,3022,3026,3030,3034,3038],{"title":3015,"path":3016,"stem":3017},"01. Магія Стрімінгу: Що відбувається, коли ви натискаєте \"Play\"","\u002Fmedia-streaming\u002Fintroduction","11.media-streaming\u002F01.introduction",{"title":3019,"path":3020,"stem":3021},"02. Анатомія Медіа: Кодеки, Контейнери та Стиснення","\u002Fmedia-streaming\u002Faudio-video-anatomy","11.media-streaming\u002F02.audio-video-anatomy",{"title":3023,"path":3024,"stem":3025},"03. The Gym: FFmpeg Deep Dive","\u002Fmedia-streaming\u002Fffmpeg-gym","11.media-streaming\u002F03.ffmpeg-gym",{"title":3027,"path":3028,"stem":3029},"04. HLS Protocol: HTTP Live Streaming у Деталях","\u002Fmedia-streaming\u002Fhls-protocol","11.media-streaming\u002F04.hls-protocol",{"title":3031,"path":3032,"stem":3033},"05. DASH Protocol: Відкритий Стандарт","\u002Fmedia-streaming\u002Fdash-protocol","11.media-streaming\u002F05.dash-protocol",{"title":3035,"path":3036,"stem":3037},"06. Масштабування: CDN та Adaptive Bitrate","\u002Fmedia-streaming\u002Fcdn-and-adaptive-bitrate","11.media-streaming\u002F06.cdn-and-adaptive-bitrate",{"title":3039,"path":3040,"stem":3041},"07. Війна із Затримкою (Latency)","\u002Fmedia-streaming\u002Frealtime-latency","11.media-streaming\u002F07.realtime-latency",{"title":3043,"icon":3044,"path":3045,"stem":3046,"children":3047,"page":59},"HTML & CSS","i-devicon-html5","\u002Fhtml-css","12.html-css",[3048,3052,3056,3060,3064,3068,3072,3076,3080,3084,3088,3092,3096,3100,3104,3108,3112,3116,3120,3124,3128,3132,3136,3140,3144,3148,3152,3156,3160,3164],{"title":3049,"path":3050,"stem":3051},"Вступ до HTML. Структура документа","\u002Fhtml-css\u002Fintro-html-structure","12.html-css\u002F01.intro-html-structure",{"title":3053,"path":3054,"stem":3055},"Форматування тексту в HTML","\u002Fhtml-css\u002Fhtml-text-formatting","12.html-css\u002F02.html-text-formatting",{"title":3057,"path":3058,"stem":3059},"Посилання та зображення в HTML","\u002Fhtml-css\u002Fhtml-links-images","12.html-css\u002F03.html-links-images",{"title":3061,"path":3062,"stem":3063},"Списки та таблиці в HTML","\u002Fhtml-css\u002Fhtml-lists-tables","12.html-css\u002F04.html-lists-tables",{"title":3065,"path":3066,"stem":3067},"Форми в HTML","\u002Fhtml-css\u002Fhtml-forms","12.html-css\u002F05.html-forms",{"title":3069,"path":3070,"stem":3071},"Семантичні елементи HTML5","\u002Fhtml-css\u002Fhtml-semantic-elements","12.html-css\u002F06.html-semantic-elements",{"title":3073,"path":3074,"stem":3075},"Мультимедіа та розширені елементи HTML","\u002Fhtml-css\u002Fhtml-multimedia-advanced","12.html-css\u002F07.html-multimedia-advanced",{"title":3077,"path":3078,"stem":3079},"Мікророзмітка та SEO в HTML","\u002Fhtml-css\u002Fhtml-microdata-seo","12.html-css\u002F08.html-microdata-seo",{"title":3081,"path":3082,"stem":3083},"Вступ до CSS. Селектори та специфічність","\u002Fhtml-css\u002Fcss-intro-selectors","12.html-css\u002F09.css-intro-selectors",{"title":3085,"path":3086,"stem":3087},"Блокова модель CSS. Відступи. Box Sizing","\u002Fhtml-css\u002Fcss-box-model","12.html-css\u002F10.css-box-model",{"title":3089,"path":3090,"stem":3091},"Розміри у CSS: повний довідник одиниць і ключових слів","\u002Fhtml-css\u002F10a.css-sizing","12.html-css\u002F10a.css-sizing",{"title":3093,"path":3094,"stem":3095},"Типографіка в CSS. Шрифти та текст","\u002Fhtml-css\u002Fcss-typography","12.html-css\u002F11.css-typography",{"title":3097,"path":3098,"stem":3099},"Кольори та фони в CSS","\u002Fhtml-css\u002Fcss-colors-backgrounds","12.html-css\u002F12.css-colors-backgrounds",{"title":3101,"path":3102,"stem":3103},"Тіні та фільтри в CSS","\u002Fhtml-css\u002F12b.css-shadows-filters","12.html-css\u002F12b.css-shadows-filters",{"title":3105,"path":3106,"stem":3107},"CSS Flexbox: Фундамент гнучких макетів","\u002Fhtml-css\u002Fcss-flexbox-fundamentals","12.html-css\u002F13.css-flexbox-fundamentals",{"title":3109,"path":3110,"stem":3111},"CSS Flexbox: Вирівнювання та Позиціонування","\u002Fhtml-css\u002Fcss-flexbox-alignment-sizing-and-patterns","12.html-css\u002F14.css-flexbox-alignment-sizing-and-patterns",{"title":3113,"path":3114,"stem":3115},"CSS Grid. Двовимірний макет. Частина 1","\u002Fhtml-css\u002Fcss-layout-grid","12.html-css\u002F15.css-layout-grid",{"title":3117,"path":3118,"stem":3119},"CSS Grid. Двовимірний макет. Частина 2","\u002Fhtml-css\u002Fcss-layout-grid-advanced","12.html-css\u002F16.css-layout-grid-advanced",{"title":3121,"path":3122,"stem":3123},"Позиціонування в CSS. Z-index. Stacking Context","\u002Fhtml-css\u002Fcss-positioning","12.html-css\u002F17.css-positioning",{"title":3125,"path":3126,"stem":3127},"CSS Анімації та Переходи","\u002Fhtml-css\u002Fcss-animations-transitions","12.html-css\u002F18.css-animations-transitions",{"title":3129,"path":3130,"stem":3131},"Адаптивний дизайн. Media Queries. Частина 1","\u002Fhtml-css\u002Fcss-responsive-media-queries","12.html-css\u002F19.css-responsive-media-queries",{"title":3133,"path":3134,"stem":3135},"Адаптивний дизайн. Частина 2: clamp(), Container Queries, @layer","\u002Fhtml-css\u002Fcss-responsive-advanced","12.html-css\u002F20.css-responsive-advanced",{"title":3137,"path":3138,"stem":3139},"CSS Custom Properties. Методології. Сучасний CSS","\u002Fhtml-css\u002Fcss-variables-methodologies","12.html-css\u002F21.css-variables-methodologies",{"title":3141,"path":3142,"stem":3143},"Сучасний CSS 2023–2025: Нові можливості","\u002Fhtml-css\u002Fcss-modern-features","12.html-css\u002F22.css-modern-features",{"title":3145,"path":3146,"stem":3147},"CSS Nesting, @layer, @scope та @property: нативний препроцесор","\u002Fhtml-css\u002F22a.css-nesting-modern-syntax","12.html-css\u002F22a.css-nesting-modern-syntax",{"title":3149,"path":3150,"stem":3151},"CSS для форм та інтерактивних станів","\u002Fhtml-css\u002Fcss-forms-interactive-states","12.html-css\u002F23.css-forms-interactive-states",{"title":3153,"path":3154,"stem":3155},"Доступність у CSS (CSS Accessibility)","\u002Fhtml-css\u002Fcss-accessibility","12.html-css\u002F24.css-accessibility",{"title":3157,"path":3158,"stem":3159},"CSS-функції та сучасні sizing primitives","\u002Fhtml-css\u002Fcss-functions-sizing","12.html-css\u002F25.css-functions-sizing",{"title":3161,"path":3162,"stem":3163},"Rendering Pipeline і CSS Performance","\u002Fhtml-css\u002Fcss-rendering-performance","12.html-css\u002F26.css-rendering-performance",{"title":3165,"path":3166,"stem":3167},"CSS Best Practices: типові ситуації та правильні рішення","\u002Fhtml-css\u002Fcss-best-practices","12.html-css\u002F27.css-best-practices",{"title":3169,"path":3170,"stem":3171,"children":3172,"page":59},"AWS","\u002Faws","13.aws",[3173,3177,3181,3185,3189,3193,3197,3201,3205,3209,3213,3217,3221,3225,3229,3233,3237,3241],{"title":3174,"path":3175,"stem":3176},"Реєстрація AWS акаунту та студентські програми","\u002Faws\u002Faccount-registration","13.aws\u002F00.account-registration",{"title":3178,"path":3179,"stem":3180},"Вступ до хмарних обчислень та AWS","\u002Faws\u002Fintroduction-to-cloud","13.aws\u002F01.introduction-to-cloud",{"title":3182,"path":3183,"stem":3184},"AWS IAM — Identity and Access Management","\u002Faws\u002Fiam","13.aws\u002F02.iam",{"title":3186,"path":3187,"stem":3188},"AWS IAM CLI — Довідник команд","\u002Faws\u002F02a.iam-doc","13.aws\u002F02a.iam-doc",{"title":3190,"path":3191,"stem":3192},"Docker та контейнеризація в AWS — ECR, ECS та Fargate","\u002Faws\u002Fdocker-ecs","13.aws\u002F03.docker-ecs",{"title":3194,"path":3195,"stem":3196},"AWS ECR \u002F ECS CLI — Довідник команд","\u002Faws\u002F03a.docker-ecs-doc","13.aws\u002F03a.docker-ecs-doc",{"title":3198,"path":3199,"stem":3200},"Amazon EC2 — Elastic Compute Cloud","\u002Faws\u002Fec2","13.aws\u002F04.ec2",{"title":3202,"path":3203,"stem":3204},"AWS EC2 CLI — Довідник команд","\u002Faws\u002F04a.ec2-doc","13.aws\u002F04a.ec2-doc",{"title":3206,"path":3207,"stem":3208},"Elastic Load Balancing та Auto Scaling","\u002Faws\u002Falb-asg","13.aws\u002F05.alb-asg",{"title":3210,"path":3211,"stem":3212},"Amazon S3 — Simple Storage Service","\u002Faws\u002Fs3","13.aws\u002F06.s3",{"title":3214,"path":3215,"stem":3216},"Amazon CloudFront — Content Delivery Network","\u002Faws\u002Fcloudfront","13.aws\u002F07.cloudfront",{"title":3218,"path":3219,"stem":3220},"Amazon RDS — Relational Database Service","\u002Faws\u002Frds","13.aws\u002F08.rds",{"title":3222,"path":3223,"stem":3224},"Amazon DynamoDB — NoSQL Database","\u002Faws\u002Fdynamodb","13.aws\u002F09.dynamodb",{"title":3226,"path":3227,"stem":3228},"AWS Lambda та Serverless Compute","\u002Faws\u002Flambda","13.aws\u002F10.lambda",{"title":3230,"path":3231,"stem":3232},"Amazon Bedrock - Foundation Models, RAG та Agents","\u002Faws\u002Fbedrock","13.aws\u002F22.bedrock",{"title":3234,"path":3235,"stem":3236},"Amazon Rekognition - Комп'ютерний зір","\u002Faws\u002Frekognition","13.aws\u002F23.rekognition",{"title":3238,"path":3239,"stem":3240},"Amazon Textract - Інтелектуальний аналіз документів","\u002Faws\u002Ftextract","13.aws\u002F24.textract",{"title":3242,"path":3243,"stem":3244},"Amazon Polly, Transcribe, Comprehend та Translate","\u002Faws\u002Faudio-nlp-services","13.aws\u002F25.audio-nlp-services",{"title":3246,"path":3247,"stem":3248,"children":3249,"page":59},"Tailwind","\u002Ftailwind","21.tailwind",[3250,3254,3258,3262,3266,3270,3274,3278,3282,3286,3290,3294],{"title":3251,"path":3252,"stem":3253},"Що таке Tailwind CSS і навіщо він потрібен","\u002Ftailwind\u002Ftailwind-intro-philosophy","21.tailwind\u002F01.tailwind-intro-philosophy",{"title":3255,"path":3256,"stem":3257},"Встановлення та налаштування Tailwind CSS v4","\u002Ftailwind\u002Ftailwind-installation-setup","21.tailwind\u002F02.tailwind-installation-setup",{"title":3259,"path":3260,"stem":3261},"Utility-класи: основи та система Tailwind","\u002Ftailwind\u002Ftailwind-utility-classes-core","21.tailwind\u002F03.tailwind-utility-classes-core",{"title":3263,"path":3264,"stem":3265},"Layout: Flexbox та Grid через Tailwind","\u002Ftailwind\u002Ftailwind-flexbox-grid","21.tailwind\u002F04.tailwind-flexbox-grid",{"title":3267,"path":3268,"stem":3269},"Кастомізація теми через @theme у Tailwind v4","\u002Ftailwind\u002Ftailwind-theme-customization","21.tailwind\u002F05.tailwind-theme-customization",{"title":3271,"path":3272,"stem":3273},"Варіанти: hover, focus, responsive, dark mode та нові v4","\u002Ftailwind\u002Ftailwind-variants-states","21.tailwind\u002F06.tailwind-variants-states",{"title":3275,"path":3276,"stem":3277},"Типографіка та система кольорів у Tailwind v4","\u002Ftailwind\u002Ftailwind-typography-colors","21.tailwind\u002F07.tailwind-typography-colors",{"title":3279,"path":3280,"stem":3281},"Компоненти та повторюваність: @apply, @utility та патерни","\u002Ftailwind\u002Ftailwind-components-patterns","21.tailwind\u002F08.tailwind-components-patterns",{"title":3283,"path":3284,"stem":3285},"Темна тема та система дизайн-токенів у Tailwind v4","\u002Ftailwind\u002Ftailwind-dark-mode-theming","21.tailwind\u002F09.tailwind-dark-mode-theming",{"title":3287,"path":3288,"stem":3289},"Довільні значення та контейнерні запити у Tailwind v4","\u002Ftailwind\u002Ftailwind-arbitrary-container-queries","21.tailwind\u002F10.tailwind-arbitrary-container-queries",{"title":3291,"path":3292,"stem":3293},"Анімації, трансформації та 3D у Tailwind v4","\u002Ftailwind\u002Ftailwind-animations-transforms","21.tailwind\u002F11.tailwind-animations-transforms",{"title":3295,"path":3296,"stem":3297},"Tailwind CLI, PostCSS та інтеграція з фреймворками","\u002Ftailwind\u002Ftailwind-cli-tooling","21.tailwind\u002F12.tailwind-cli-tooling",{"title":3299,"path":3300,"stem":3301},"Тестування компонентів діаграм","\u002Ftest-components","98.test-components",{"id":3303,"title":1692,"body":3304,"description":11266,"extension":11267,"links":11268,"meta":11269,"navigation":3467,"path":1693,"seo":11270,"stem":1694,"__hash__":11271},"docs\u002F01.csharp\u002F13.network-programming\u002F09.smtp.md",{"type":3305,"value":3306,"toc":11234},"minimark",[3307,3311,3316,3320,3336,3339,3429,3604,3609,3612,3644,3647,3651,3654,3658,3693,3700,3704,3711,3732,3743,3745,3749,3759,3763,3835,3839,3906,3921,3923,3927,3942,4241,4245,4387,4391,4394,4558,4560,4564,4570,4574,4589,4597,4601,4733,4737,4869,4959,4987,4989,4993,4999,5068,5072,5075,6585,6587,6591,6606,8014,8045,8047,8051,8054,8159,8774,8776,8780,8783,9705,9707,9711,9722,9948,9971,9973,9977,9988,10119,10291,10295,10297,10301,11135,11166,11168,11172,11175,11224,11230],[3308,3309,1692],"h1",{"id":3310},"smtp-та-протоколи-електронної-пошти",[3312,3313,3315],"h2",{"id":3314},"екосистема-протоколів-електронної-пошти","Екосистема протоколів електронної пошти",[3317,3318,3319],"p",{},"Електронна пошта — одна з найстаріших і найважливіших служб Інтернету. На відміну від HTTP, де один протокол обслуговує і запит, і відповідь, поштова інфраструктура розподілена між кількома спеціалізованими протоколами, кожен з яких вирішує окреме завдання в ланцюжку доставлення повідомлення від відправника до одержувача.",[3321,3322,3323,3327,3328,3331,3332,3335],"note",{},[3324,3325,3326],"strong",{},"Ключова ідея:"," Відправлення і отримання пошти — це принципово різні операції, що обслуговуються різними протоколами. SMTP відповідає виключно за ",[3324,3329,3330],{},"відправлення і ретрансляцію",". POP3 та IMAP — за ",[3324,3333,3334],{},"отримання"," клієнтом листів із поштового сервера.",[3317,3337,3338],{},"Перш ніж заглибитися у деталі SMTP, розглянемо повну картину поштової інфраструктури:",[3340,3341,3342,3361],"table",{},[3343,3344,3345],"thead",{},[3346,3347,3348,3352,3355,3358],"tr",{},[3349,3350,3351],"th",{},"Протокол",[3349,3353,3354],{},"RFC",[3349,3356,3357],{},"Порт (plaintext \u002F TLS)",[3349,3359,3360],{},"Призначення",[3362,3363,3364,3381,3397,3413],"tbody",{},[3346,3365,3366,3372,3375,3378],{},[3367,3368,3369],"td",{},[3324,3370,3371],{},"SMTP",[3367,3373,3374],{},"RFC 5321",[3367,3376,3377],{},"25 \u002F 465 (SMTPS), 587 (Submission)",[3367,3379,3380],{},"Відправлення та ретрансляція між серверами",[3346,3382,3383,3388,3391,3394],{},[3367,3384,3385],{},[3324,3386,3387],{},"POP3",[3367,3389,3390],{},"RFC 1939",[3367,3392,3393],{},"110 \u002F 995",[3367,3395,3396],{},"Завантаження листів із сервера на клієнт (з видаленням)",[3346,3398,3399,3404,3407,3410],{},[3367,3400,3401],{},[3324,3402,3403],{},"IMAP4",[3367,3405,3406],{},"RFC 3501",[3367,3408,3409],{},"143 \u002F 993",[3367,3411,3412],{},"Синхронізація листів між сервером та клієнтами",[3346,3414,3415,3420,3423,3426],{},[3367,3416,3417],{},[3324,3418,3419],{},"MIME",[3367,3421,3422],{},"RFC 2045–2049",[3367,3424,3425],{},"—",[3367,3427,3428],{},"Стандарт форматування вмісту листа (текст, HTML, вкладення)",[3430,3431,3432],"plant-uml",{},[3433,3434,3439],"pre",{"className":3435,"code":3436,"language":3437,"meta":3438,"style":3438},"language-plantuml shiki shiki-themes light-plus dark-plus dark-plus","@startuml\nskinparam style plain\nskinparam backgroundColor #ffffff\n\nactor \"Відправник\\n(Alice)\" as alice\nparticipant \"MUA\\n(Outlook\u002FThunderbird)\" as mua_a #e3f2fd\nparticipant \"MTA відправника\\nsmtp.alice.com\" as mta_a #e8f5e9\nparticipant \"MTA одержувача\\nsmtp.bob.com\" as mta_b #e8f5e9\nparticipant \"MDA\\nmailbox store\" as mda #fff3e0\nparticipant \"MUA\\n(Outlook\u002FThunderbird)\" as mua_b #e3f2fd\nactor \"Одержувач\\n(Bob)\" as bob\n\nalice -> mua_a : Написав листа\nmua_a -> mta_a : SMTP (port 587)\\nSubmission + AUTH\nmta_a -> mta_b : SMTP (port 25)\\nServer-to-server relay\nmta_b -> mda : Доставка до mailbox\nmda --> mua_b : IMAP (port 993)\\nабо POP3 (port 995)\nmua_b --> bob : Читає листа\n\nnote over mta_a, mta_b\n  Між MTA може бути\n  декілька relay-серверів.\n  Кожен додає заголовок\n  \"Received:\" до листа.\nend note\n\n@enduml\n","plantuml","",[3440,3441,3442,3450,3456,3462,3469,3475,3481,3487,3493,3499,3505,3511,3516,3522,3528,3534,3540,3546,3552,3557,3563,3569,3575,3581,3587,3593,3598],"code",{"__ignoreMap":3438},[3443,3444,3447],"span",{"class":3445,"line":3446},"line",1,[3443,3448,3449],{},"@startuml\n",[3443,3451,3453],{"class":3445,"line":3452},2,[3443,3454,3455],{},"skinparam style plain\n",[3443,3457,3459],{"class":3445,"line":3458},3,[3443,3460,3461],{},"skinparam backgroundColor #ffffff\n",[3443,3463,3465],{"class":3445,"line":3464},4,[3443,3466,3468],{"emptyLinePlaceholder":3467},true,"\n",[3443,3470,3472],{"class":3445,"line":3471},5,[3443,3473,3474],{},"actor \"Відправник\\n(Alice)\" as alice\n",[3443,3476,3478],{"class":3445,"line":3477},6,[3443,3479,3480],{},"participant \"MUA\\n(Outlook\u002FThunderbird)\" as mua_a #e3f2fd\n",[3443,3482,3484],{"class":3445,"line":3483},7,[3443,3485,3486],{},"participant \"MTA відправника\\nsmtp.alice.com\" as mta_a #e8f5e9\n",[3443,3488,3490],{"class":3445,"line":3489},8,[3443,3491,3492],{},"participant \"MTA одержувача\\nsmtp.bob.com\" as mta_b #e8f5e9\n",[3443,3494,3496],{"class":3445,"line":3495},9,[3443,3497,3498],{},"participant \"MDA\\nmailbox store\" as mda #fff3e0\n",[3443,3500,3502],{"class":3445,"line":3501},10,[3443,3503,3504],{},"participant \"MUA\\n(Outlook\u002FThunderbird)\" as mua_b #e3f2fd\n",[3443,3506,3508],{"class":3445,"line":3507},11,[3443,3509,3510],{},"actor \"Одержувач\\n(Bob)\" as bob\n",[3443,3512,3514],{"class":3445,"line":3513},12,[3443,3515,3468],{"emptyLinePlaceholder":3467},[3443,3517,3519],{"class":3445,"line":3518},13,[3443,3520,3521],{},"alice -> mua_a : Написав листа\n",[3443,3523,3525],{"class":3445,"line":3524},14,[3443,3526,3527],{},"mua_a -> mta_a : SMTP (port 587)\\nSubmission + AUTH\n",[3443,3529,3531],{"class":3445,"line":3530},15,[3443,3532,3533],{},"mta_a -> mta_b : SMTP (port 25)\\nServer-to-server relay\n",[3443,3535,3537],{"class":3445,"line":3536},16,[3443,3538,3539],{},"mta_b -> mda : Доставка до mailbox\n",[3443,3541,3543],{"class":3445,"line":3542},17,[3443,3544,3545],{},"mda --> mua_b : IMAP (port 993)\\nабо POP3 (port 995)\n",[3443,3547,3549],{"class":3445,"line":3548},18,[3443,3550,3551],{},"mua_b --> bob : Читає листа\n",[3443,3553,3555],{"class":3445,"line":3554},19,[3443,3556,3468],{"emptyLinePlaceholder":3467},[3443,3558,3560],{"class":3445,"line":3559},20,[3443,3561,3562],{},"note over mta_a, mta_b\n",[3443,3564,3566],{"class":3445,"line":3565},21,[3443,3567,3568],{},"  Між MTA може бути\n",[3443,3570,3572],{"class":3445,"line":3571},22,[3443,3573,3574],{},"  декілька relay-серверів.\n",[3443,3576,3578],{"class":3445,"line":3577},23,[3443,3579,3580],{},"  Кожен додає заголовок\n",[3443,3582,3584],{"class":3445,"line":3583},24,[3443,3585,3586],{},"  \"Received:\" до листа.\n",[3443,3588,3590],{"class":3445,"line":3589},25,[3443,3591,3592],{},"end note\n",[3443,3594,3596],{"class":3445,"line":3595},26,[3443,3597,3468],{"emptyLinePlaceholder":3467},[3443,3599,3601],{"class":3445,"line":3600},27,[3443,3602,3603],{},"@enduml\n",[3605,3606,3608],"h3",{"id":3607},"ролі-агентів-у-доставці-пошти","Ролі агентів у доставці пошти",[3317,3610,3611],{},"У поштовій екосистемі кожен компонент має власну назву та функцію:",[3613,3614,3615,3621,3626,3631],"field-group",{},[3616,3617,3620],"field",{"name":3618,"type":3619},"MUA (Mail User Agent)","Клієнт","Поштовий клієнт користувача: Outlook, Thunderbird, Apple Mail, веб-інтерфейс Gmail. Саме тут користувач пише, надсилає та читає листи. Спілкується із сервером через SMTP (відправлення) і IMAP\u002FPOP3 (отримання).",[3616,3622,3625],{"name":3623,"type":3624},"MTA (Mail Transfer Agent)","Сервер ретрансляції","Поштовий сервер, що приймає листи від MUA або іншого MTA і пересилає їх далі. Виконує DNS MX-lookup для визначення наступного сервера в ланцюжку. Приклади: Postfix, Exim, Microsoft Exchange, SendGrid.",[3616,3627,3630],{"name":3628,"type":3629},"MDA (Mail Delivery Agent)","Агент доставки","Компонент, що фінально зберігає лист у поштовій скриньці одержувача. Іноді інтегрований у MTA. Форматування сховища: Maildir (окремі файли), mbox (один файл). Dovecot — типовий MDA для Linux-систем.",[3616,3632,3635,3636,3639,3640,3643],{"name":3633,"type":3634},"MX-запис (Mail eXchanger)","DNS","Запис у DNS, що вказує, який сервер відповідає за прийом пошти для даного домену. При відправленні MTA виконує ",[3440,3637,3638],{},"DNS MX bob.com"," → отримує ",[3440,3641,3642],{},"smtp.bob.com"," → підключається по SMTP (port 25).",[3645,3646],"hr",{},[3312,3648,3650],{"id":3649},"огляд-imap-та-pop3-суміжні-протоколи","Огляд IMAP та POP3 (суміжні протоколи)",[3317,3652,3653],{},"Оскільки ці протоколи виходять за межі основної теми розділу, подамо їх описово, для повноти картини.",[3605,3655,3657],{"id":3656},"pop3-post-office-protocol-version-3-rfc-1939","POP3 — Post Office Protocol version 3 (RFC 1939)",[3317,3659,3660,3661,3664,3665,3668,3669,3668,3672,3668,3675,3668,3678,3668,3681,3684,3685,3688,3689,3692],{},"POP3 — найпростіший протокол отримання пошти, що дотримується моделі «завантажити і видалити». Клієнт підключається до сервера, завантажує всі нові листи у локальне сховище і, як правило, видаляє їх із сервера. Протокол є ",[3324,3662,3663],{},"текстовим"," і надзвичайно простим: клієнт надсилає команди (",[3440,3666,3667],{},"USER",", ",[3440,3670,3671],{},"PASS",[3440,3673,3674],{},"LIST",[3440,3676,3677],{},"RETR",[3440,3679,3680],{},"DELE",[3440,3682,3683],{},"QUIT","), сервер відповідає рядком ",[3440,3686,3687],{},"+OK"," або ",[3440,3690,3691],{},"-ERR",".",[3317,3694,3695,3696,3699],{},"Головна вада POP3 — ",[3324,3697,3698],{},"відсутність синхронізації між пристроями",". Якщо лист завантажено на ноутбук, він зникає з телефону. Через це POP3 майже витіснений IMAP у сучасних системах, проте досі використовується там, де потрібен офлайн-доступ без серверного сховища.",[3605,3701,3703],{"id":3702},"imap4-internet-message-access-protocol-version-4-rfc-3501","IMAP4 — Internet Message Access Protocol version 4 (RFC 3501)",[3317,3705,3706,3707,3710],{},"IMAP є значно потужнішою альтернативою POP3. Ключова відмінність: ",[3324,3708,3709],{},"листи залишаються на сервері",", а клієнт синхронізує їхній стан (прочитаний\u002Fнепрочитаний, переміщений, видалений). Це забезпечує однакове відображення поштової скриньки на всіх пристроях.",[3317,3712,3713,3714,3668,3717,3720,3721,3668,3724,3727,3728,3731],{},"IMAP підтримує ",[3324,3715,3716],{},"папки (mailbox)",[3324,3718,3719],{},"часткове завантаження"," (лише заголовки без тіла листа), ",[3324,3722,3723],{},"серверний пошук",[3324,3725,3726],{},"підписку на папки"," та ",[3324,3729,3730],{},"IDLE","-режим (push-нотифікації без постійного polling). Саме тому IMAP є стандартом у корпоративних системах та сучасних поштових клієнтах.",[3321,3733,3734,3735,3738,3739,3742],{},"У .NET нативна підтримка IMAP та POP3 відсутня у ",[3440,3736,3737],{},"System.Net.Mail",". Для роботи з цими протоколами використовують бібліотеку ",[3324,3740,3741],{},"MailKit"," — повноцінну реалізацію IMAP4, POP3 та SMTP із підтримкою OAuth 2.0, MIME та TLS. У межах цього розділу зосередимося на нативному SMTP.",[3645,3744],{},[3312,3746,3748],{"id":3747},"smtp-simple-mail-transfer-protocol","SMTP — Simple Mail Transfer Protocol",[3317,3750,3751,3754,3755,3758],{},[3324,3752,3753],{},"SMTP (RFC 5321)"," — протокол прикладного рівня для ",[3324,3756,3757],{},"відправлення та ретрансляції"," електронних повідомлень. Попри назву «Simple», протокол розвинувся у складну специфікацію з підтримкою аутентифікації, шифрування та розширень (ESMTP).",[3605,3760,3762],{"id":3761},"коротка-історія","Коротка історія",[3764,3765,3766,3787,3803,3813,3823,3829],"ul",{},[3767,3768,3769,3772,3773,3668,3776,3668,3779,3668,3782,3668,3785,3692],"li",{},[3324,3770,3771],{},"1982"," — RFC 821: перша стандартизація SMTP. Команди ",[3440,3774,3775],{},"HELO",[3440,3777,3778],{},"MAIL FROM",[3440,3780,3781],{},"RCPT TO",[3440,3783,3784],{},"DATA",[3440,3786,3683],{},[3767,3788,3789,3792,3793,3796,3797,3799,3800,3692],{},[3324,3790,3791],{},"1995"," — ESMTP (Extended SMTP, RFC 1869): команда ",[3440,3794,3795],{},"EHLO"," замість ",[3440,3798,3775],{},", розширення через ",[3440,3801,3802],{},"250-KEYWORD",[3767,3804,3805,3808,3809,3812],{},[3324,3806,3807],{},"1998"," — RFC 2554: розширення ",[3440,3810,3811],{},"AUTH"," для аутентифікації (PLAIN, LOGIN, CRAM-MD5).",[3767,3814,3815,3818,3819,3822],{},[3324,3816,3817],{},"2002"," — RFC 3207: ",[3440,3820,3821],{},"STARTTLS"," — механізм переходу до шифрованого з'єднання в рамках звичайного TCP-з'єднання.",[3767,3824,3825,3828],{},[3324,3826,3827],{},"2008"," — RFC 5321: сучасна специфікація SMTP, що об'єднала попередні RFC.",[3767,3830,3831,3834],{},[3324,3832,3833],{},"2011"," — RFC 6409: SMTP Submission (port 587) відокремлено від relay (port 25) — клієнти мають надсилати через 587.",[3605,3836,3838],{"id":3837},"порти-smtp-та-їх-призначення","Порти SMTP та їх призначення",[3340,3840,3841,3856],{},[3343,3842,3843],{},[3346,3844,3845,3848,3851,3854],{},[3349,3846,3847],{},"Порт",[3349,3849,3850],{},"Назва",[3349,3852,3853],{},"Шифрування",[3349,3855,3360],{},[3362,3857,3858,3874,3890],{},[3346,3859,3860,3865,3868,3871],{},[3367,3861,3862],{},[3324,3863,3864],{},"25",[3367,3866,3867],{},"SMTP Relay",[3367,3869,3870],{},"Plaintext або STARTTLS",[3367,3872,3873],{},"Server-to-server (MTA↔MTA). ISP блокують для клієнтів",[3346,3875,3876,3881,3884,3887],{},[3367,3877,3878],{},[3324,3879,3880],{},"465",[3367,3882,3883],{},"SMTPS (Legacy)",[3367,3885,3886],{},"TLS від початку (Implicit TLS)",[3367,3888,3889],{},"Застаріла схема; деякі провайдери досі підтримують",[3346,3891,3892,3897,3900,3903],{},[3367,3893,3894],{},[3324,3895,3896],{},"587",[3367,3898,3899],{},"Submission",[3367,3901,3902],{},"STARTTLS (обов'язково)",[3367,3904,3905],{},"Клієнт→Сервер. Стандарт для MUA з AUTH",[3907,3908,3909,3910,3912,3913,3916,3917,3920],"warning",{},"Порт ",[3324,3911,3880],{}," офіційно «звільнений» для SMTPS і знову стандартизований у RFC 8314 (2018) як ",[3324,3914,3915],{},"Implicit TLS",". Однак порт ",[3324,3918,3919],{},"587 з STARTTLS"," залишається найпоширенішим стандартом для submission. Google, Microsoft, SendGrid — всі підтримують обидва варіанти.",[3645,3922],{},[3312,3924,3926],{"id":3925},"smtp-сесія-покроковий-протокол","SMTP-сесія: покроковий протокол",[3317,3928,3929,3930,3933,3934,3937,3938,3941],{},"SMTP є ",[3324,3931,3932],{},"текстовим протоколом"," на базі TCP. Кожна команда — це рядок ASCII, що завершується ",[3440,3935,3936],{},"\\r\\n",". Сервер відповідає ",[3324,3939,3940],{},"тризначним кодом"," із необов'язковим текстовим поясненням. Розглянемо повну SMTP-сесію:",[3430,3943,3944],{},[3433,3945,3947],{"className":3435,"code":3946,"language":3437,"meta":3438,"style":3438},"@startuml\nskinparam style plain\nskinparam backgroundColor #ffffff\n\nparticipant \"SMTP Client\\n(MUA \u002F MTA)\" as client #e3f2fd\nparticipant \"SMTP Server\\nsmtp.example.com:587\" as server #e8f5e9\n\n== Встановлення з'єднання ==\nclient -> server : TCP SYN (port 587)\nserver --> client : 220 smtp.example.com ESMTP Postfix (Ubuntu)\n\n== ESMTP Greeting ==\nclient -> server : EHLO mail.myapp.com\nserver --> client : 250-smtp.example.com Hello\\n250-SIZE 52428800\\n250-STARTTLS\\n250-AUTH PLAIN LOGIN\\n250 ENHANCEDSTATUSCODES\n\n== Ініціалізація TLS ==\nclient -> server : STARTTLS\nserver --> client : 220 2.0.0 Ready to start TLS\nnote over client, server: TLS Handshake (TLS 1.3)\nclient -> server : EHLO mail.myapp.com (знову, після TLS!)\nserver --> client : 250-smtp.example.com Hello\\n250-AUTH PLAIN LOGIN\\n250 SIZE 52428800\n\n== Аутентифікація ==\nclient -> server : AUTH PLAIN AHVzZXJAZXhhbXBsZS5jb20AcGFzc3dvcmQ=\nserver --> client : 235 2.7.0 Authentication successful\n\n== Конверт (Envelope) ==\nclient -> server : MAIL FROM:\u003Calice@myapp.com> SIZE=1024\nserver --> client : 250 2.1.0 Ok\n\nclient -> server : RCPT TO:\u003Cbob@example.com>\nserver --> client : 250 2.1.5 Ok\n\nclient -> server : RCPT TO:\u003Ccarol@example.com>\nserver --> client : 250 2.1.5 Ok\n\n== Дані листа (DATA) ==\nclient -> server : DATA\nserver --> client : 354 End data with \u003CCR>\u003CLF>.\u003CCR>\u003CLF>\n\nclient -> server : From: Alice \u003Calice@myapp.com>\\r\\n\\\nTo: Bob \u003Cbob@example.com>\\r\\n\\\nSubject: Test Message\\r\\n\\\nDate: Fri, 23 May 2025 21:00:00 +0300\\r\\n\\\nMIME-Version: 1.0\\r\\n\\\nContent-Type: text\u002Fplain; charset=utf-8\\r\\n\\\n\\r\\n\\\nТіло листа.\\r\\n\\\n.\nserver --> client : 250 2.0.0 Ok: queued as A3B4C5D6\n\n== Завершення сесії ==\nclient -> server : QUIT\nserver --> client : 221 2.0.0 Bye\n\n@enduml\n",[3440,3948,3949,3953,3957,3961,3965,3970,3975,3979,3984,3989,3994,3998,4003,4008,4013,4017,4022,4027,4032,4037,4042,4047,4051,4056,4061,4066,4070,4075,4081,4087,4092,4098,4104,4109,4115,4120,4125,4131,4137,4143,4148,4154,4160,4166,4172,4178,4184,4190,4196,4202,4208,4213,4219,4225,4231,4236],{"__ignoreMap":3438},[3443,3950,3951],{"class":3445,"line":3446},[3443,3952,3449],{},[3443,3954,3955],{"class":3445,"line":3452},[3443,3956,3455],{},[3443,3958,3959],{"class":3445,"line":3458},[3443,3960,3461],{},[3443,3962,3963],{"class":3445,"line":3464},[3443,3964,3468],{"emptyLinePlaceholder":3467},[3443,3966,3967],{"class":3445,"line":3471},[3443,3968,3969],{},"participant \"SMTP Client\\n(MUA \u002F MTA)\" as client #e3f2fd\n",[3443,3971,3972],{"class":3445,"line":3477},[3443,3973,3974],{},"participant \"SMTP Server\\nsmtp.example.com:587\" as server #e8f5e9\n",[3443,3976,3977],{"class":3445,"line":3483},[3443,3978,3468],{"emptyLinePlaceholder":3467},[3443,3980,3981],{"class":3445,"line":3489},[3443,3982,3983],{},"== Встановлення з'єднання ==\n",[3443,3985,3986],{"class":3445,"line":3495},[3443,3987,3988],{},"client -> server : TCP SYN (port 587)\n",[3443,3990,3991],{"class":3445,"line":3501},[3443,3992,3993],{},"server --> client : 220 smtp.example.com ESMTP Postfix (Ubuntu)\n",[3443,3995,3996],{"class":3445,"line":3507},[3443,3997,3468],{"emptyLinePlaceholder":3467},[3443,3999,4000],{"class":3445,"line":3513},[3443,4001,4002],{},"== ESMTP Greeting ==\n",[3443,4004,4005],{"class":3445,"line":3518},[3443,4006,4007],{},"client -> server : EHLO mail.myapp.com\n",[3443,4009,4010],{"class":3445,"line":3524},[3443,4011,4012],{},"server --> client : 250-smtp.example.com Hello\\n250-SIZE 52428800\\n250-STARTTLS\\n250-AUTH PLAIN LOGIN\\n250 ENHANCEDSTATUSCODES\n",[3443,4014,4015],{"class":3445,"line":3530},[3443,4016,3468],{"emptyLinePlaceholder":3467},[3443,4018,4019],{"class":3445,"line":3536},[3443,4020,4021],{},"== Ініціалізація TLS ==\n",[3443,4023,4024],{"class":3445,"line":3542},[3443,4025,4026],{},"client -> server : STARTTLS\n",[3443,4028,4029],{"class":3445,"line":3548},[3443,4030,4031],{},"server --> client : 220 2.0.0 Ready to start TLS\n",[3443,4033,4034],{"class":3445,"line":3554},[3443,4035,4036],{},"note over client, server: TLS Handshake (TLS 1.3)\n",[3443,4038,4039],{"class":3445,"line":3559},[3443,4040,4041],{},"client -> server : EHLO mail.myapp.com (знову, після TLS!)\n",[3443,4043,4044],{"class":3445,"line":3565},[3443,4045,4046],{},"server --> client : 250-smtp.example.com Hello\\n250-AUTH PLAIN LOGIN\\n250 SIZE 52428800\n",[3443,4048,4049],{"class":3445,"line":3571},[3443,4050,3468],{"emptyLinePlaceholder":3467},[3443,4052,4053],{"class":3445,"line":3577},[3443,4054,4055],{},"== Аутентифікація ==\n",[3443,4057,4058],{"class":3445,"line":3583},[3443,4059,4060],{},"client -> server : AUTH PLAIN AHVzZXJAZXhhbXBsZS5jb20AcGFzc3dvcmQ=\n",[3443,4062,4063],{"class":3445,"line":3589},[3443,4064,4065],{},"server --> client : 235 2.7.0 Authentication successful\n",[3443,4067,4068],{"class":3445,"line":3595},[3443,4069,3468],{"emptyLinePlaceholder":3467},[3443,4071,4072],{"class":3445,"line":3600},[3443,4073,4074],{},"== Конверт (Envelope) ==\n",[3443,4076,4078],{"class":3445,"line":4077},28,[3443,4079,4080],{},"client -> server : MAIL FROM:\u003Calice@myapp.com> SIZE=1024\n",[3443,4082,4084],{"class":3445,"line":4083},29,[3443,4085,4086],{},"server --> client : 250 2.1.0 Ok\n",[3443,4088,4090],{"class":3445,"line":4089},30,[3443,4091,3468],{"emptyLinePlaceholder":3467},[3443,4093,4095],{"class":3445,"line":4094},31,[3443,4096,4097],{},"client -> server : RCPT TO:\u003Cbob@example.com>\n",[3443,4099,4101],{"class":3445,"line":4100},32,[3443,4102,4103],{},"server --> client : 250 2.1.5 Ok\n",[3443,4105,4107],{"class":3445,"line":4106},33,[3443,4108,3468],{"emptyLinePlaceholder":3467},[3443,4110,4112],{"class":3445,"line":4111},34,[3443,4113,4114],{},"client -> server : RCPT TO:\u003Ccarol@example.com>\n",[3443,4116,4118],{"class":3445,"line":4117},35,[3443,4119,4103],{},[3443,4121,4123],{"class":3445,"line":4122},36,[3443,4124,3468],{"emptyLinePlaceholder":3467},[3443,4126,4128],{"class":3445,"line":4127},37,[3443,4129,4130],{},"== Дані листа (DATA) ==\n",[3443,4132,4134],{"class":3445,"line":4133},38,[3443,4135,4136],{},"client -> server : DATA\n",[3443,4138,4140],{"class":3445,"line":4139},39,[3443,4141,4142],{},"server --> client : 354 End data with \u003CCR>\u003CLF>.\u003CCR>\u003CLF>\n",[3443,4144,4146],{"class":3445,"line":4145},40,[3443,4147,3468],{"emptyLinePlaceholder":3467},[3443,4149,4151],{"class":3445,"line":4150},41,[3443,4152,4153],{},"client -> server : From: Alice \u003Calice@myapp.com>\\r\\n\\\n",[3443,4155,4157],{"class":3445,"line":4156},42,[3443,4158,4159],{},"To: Bob \u003Cbob@example.com>\\r\\n\\\n",[3443,4161,4163],{"class":3445,"line":4162},43,[3443,4164,4165],{},"Subject: Test Message\\r\\n\\\n",[3443,4167,4169],{"class":3445,"line":4168},44,[3443,4170,4171],{},"Date: Fri, 23 May 2025 21:00:00 +0300\\r\\n\\\n",[3443,4173,4175],{"class":3445,"line":4174},45,[3443,4176,4177],{},"MIME-Version: 1.0\\r\\n\\\n",[3443,4179,4181],{"class":3445,"line":4180},46,[3443,4182,4183],{},"Content-Type: text\u002Fplain; charset=utf-8\\r\\n\\\n",[3443,4185,4187],{"class":3445,"line":4186},47,[3443,4188,4189],{},"\\r\\n\\\n",[3443,4191,4193],{"class":3445,"line":4192},48,[3443,4194,4195],{},"Тіло листа.\\r\\n\\\n",[3443,4197,4199],{"class":3445,"line":4198},49,[3443,4200,4201],{},".\n",[3443,4203,4205],{"class":3445,"line":4204},50,[3443,4206,4207],{},"server --> client : 250 2.0.0 Ok: queued as A3B4C5D6\n",[3443,4209,4211],{"class":3445,"line":4210},51,[3443,4212,3468],{"emptyLinePlaceholder":3467},[3443,4214,4216],{"class":3445,"line":4215},52,[3443,4217,4218],{},"== Завершення сесії ==\n",[3443,4220,4222],{"class":3445,"line":4221},53,[3443,4223,4224],{},"client -> server : QUIT\n",[3443,4226,4228],{"class":3445,"line":4227},54,[3443,4229,4230],{},"server --> client : 221 2.0.0 Bye\n",[3443,4232,4234],{"class":3445,"line":4233},55,[3443,4235,3468],{"emptyLinePlaceholder":3467},[3443,4237,4239],{"class":3445,"line":4238},56,[3443,4240,3603],{},[3605,4242,4244],{"id":4243},"основні-команди-smtp","Основні команди SMTP",[3613,4246,4247,4266,4289,4314,4336,4352,4379],{},[3616,4248,4251,4260],{"name":4249,"type":4250},"EHLO \u002F HELO","Greeting (обов'язково першою)",[3317,4252,4253,4254,4256,4257,4259],{},"Представлення клієнта серверу. ",[3440,4255,3795],{}," (Extended Hello) — сучасна версія для ESMTP; сервер відповідає списком підтримуваних розширень. ",[3440,4258,3775],{}," — застаріла версія для базового SMTP без розширень. Завжди надсилайте EHLO, і знову після STARTTLS — бо розширення можуть відрізнятись після встановлення TLS.",[3317,4261,4262,4263],{},"Формат: ",[3440,4264,4265],{},"EHLO \u003CFQDN або IP клієнта>",[3616,4267,4269,4284],{"name":3778,"type":4268},"Envelope Sender",[3317,4270,4271,4272,4275,4276,4279,4280,4283],{},"Визначає адресу ",[3324,4273,4274],{},"конверта відправника"," (envelope sender \u002F return path). Це не те саме, що заголовок ",[3440,4277,4278],{},"From:"," у листі! Якщо лист відхилено або збій доставки — bounce-повідомлення надсилається на цю адресу. Можна передати ",[3440,4281,4282],{},"SIZE=\u003Cbytes>"," для попередньої перевірки сервером.",[3317,4285,4262,4286],{},[3440,4287,4288],{},"MAIL FROM:\u003Calice@example.com> SIZE=4096",[3616,4290,4292,4302],{"name":3781,"type":4291},"Envelope Recipients",[3317,4293,4294,4295,4298,4299,4301],{},"Визначає адресу(и) ",[3324,4296,4297],{},"одержувача(ів)",". Команду можна повторити для кількох одержувачів — кожен ",[3440,4300,3781],{}," обробляється незалежно. Сервер може прийняти одних одержувачів і відхилити інших — необхідно перевіряти код відповіді для кожного.",[3317,4303,4262,4304,4307,4308,3688,4311],{},[3440,4305,4306],{},"RCPT TO:\u003Cbob@example.com>"," → Відповідь: ",[3440,4309,4310],{},"250 Ok",[3440,4312,4313],{},"550 No such user",[3616,4315,4317,4318,4321,4322,4325,4326,4329,4330,4332,4333,3692],{"name":3784,"type":4316},"Початок передачі тіла листа","Переводить сервер у режим прийому даних. Сервер відповідає ",[3440,4319,4320],{},"354 Start input",". Клієнт надсилає заголовки та тіло листа (формат MIME). ",[3324,4323,4324],{},"Ознака завершення"," — рядок, що містить лише одну крапку: ",[3440,4327,4328],{},"\\r\\n.\\r\\n"," (CRLF dot CRLF). Якщо в тілі листа є рядок, що починається з ",[3440,4331,3692],{},", він екранується подвоєнням: ",[3440,4334,4335],{},"..",[3616,4337,4339,4340,4342,4343,4345,4346,4349,4350,3692],{"name":3821,"type":4338},"TLS Upgrade (розширення RFC 3207)","Ініціює перехід від plaintext-з'єднання до TLS-шифрованого. Після успішного TLS Handshake необхідно повторно надіслати ",[3440,4341,3795],{}," — бо сервер може оголосити інший набір розширень (особливо ",[3440,4344,3811],{},", який не пропонується до TLS). Доступне лише якщо сервер оголосив ",[3440,4347,4348],{},"250-STARTTLS"," у відповіді на ",[3440,4351,3795],{},[3616,4353,4355,4356,4359,4360,4363,4364,4367,4368,4371,4372,3688,4375,4378],{"name":3811,"type":4354},"Аутентифікація (розширення RFC 4954)","Аутентифікація клієнта. Механізми: ",[3440,4357,4358],{},"PLAIN"," (base64 від ",[3440,4361,4362],{},"\\0user\\0password","), ",[3440,4365,4366],{},"LOGIN"," (окремо логін і пароль в base64), ",[3440,4369,4370],{},"CRAM-MD5"," (challenge-response, складніше). Сучасні сервери підтримують також OAuth 2.0 Bearer через ",[3440,4373,4374],{},"OAUTHBEARER",[3440,4376,4377],{},"XOAUTH2",". Завжди виконуйте AUTH після STARTTLS — інакше credentials передаються у відкритому вигляді.",[3616,4380,4382,4383,4386],{"name":3683,"type":4381},"Завершення сесії","Коректне завершення TCP-з'єднання. Сервер підтверджує ",[3440,4384,4385],{},"221 Bye"," і закриває з'єднання. Якщо клієнт закриває з'єднання без QUIT — сервер вважає сесію аварійно перерваною і може не прийняти лист у чергу.",[3605,4388,4390],{"id":4389},"коди-відповідей-smtp","Коди відповідей SMTP",[3317,4392,4393],{},"Перша цифра визначає клас відповіді, друга — категорію, третя — специфіку:",[3340,4395,4396,4409],{},[3343,4397,4398],{},[3346,4399,4400,4403,4406],{},[3349,4401,4402],{},"Код",[3349,4404,4405],{},"Значення",[3349,4407,4408],{},"Приклад ситуації",[3362,4410,4411,4430,4443,4459,4477,4490,4503,4515,4528,4541],{},[3346,4412,4413,4418,4421],{},[3367,4414,4415],{},[3324,4416,4417],{},"2xx",[3367,4419,4420],{},"Успіх",[3367,4422,4423,3668,4425,3668,4427],{},[3440,4424,4310],{},[3440,4426,4385],{},[3440,4428,4429],{},"235 Auth successful",[3346,4431,4432,4437,4440],{},[3367,4433,4434],{},[3324,4435,4436],{},"354",[3367,4438,4439],{},"Проміжний",[3367,4441,4442],{},"Чекаю дані листа (відповідь на DATA)",[3346,4444,4445,4450,4453],{},[3367,4446,4447],{},[3324,4448,4449],{},"4xx",[3367,4451,4452],{},"Тимчасова помилка",[3367,4454,4455,4458],{},[3440,4456,4457],{},"421 Service unavailable"," — спробуйте пізніше",[3346,4460,4461,4466,4469],{},[3367,4462,4463],{},[3324,4464,4465],{},"5xx",[3367,4467,4468],{},"Постійна помилка",[3367,4470,4471,3668,4474],{},[3440,4472,4473],{},"550 User unknown",[3440,4475,4476],{},"552 Message too large",[3346,4478,4479,4484,4487],{},[3367,4480,4481],{},[3324,4482,4483],{},"220",[3367,4485,4486],{},"Готовий",[3367,4488,4489],{},"Привітання сервера після TCP-підключення",[3346,4491,4492,4497,4500],{},[3367,4493,4494],{},[3324,4495,4496],{},"250",[3367,4498,4499],{},"Команда прийнята",[3367,4501,4502],{},"Стандартна відповідь на EHLO, MAIL FROM, RCPT TO",[3346,4504,4505,4509,4512],{},[3367,4506,4507],{},[3324,4508,4436],{},[3367,4510,4511],{},"Починайте введення",[3367,4513,4514],{},"Відповідь на DATA — сервер чекає тіло листа",[3346,4516,4517,4522,4525],{},[3367,4518,4519],{},[3324,4520,4521],{},"421",[3367,4523,4524],{},"Сервіс недоступний",[3367,4526,4527],{},"Перевантаження; MTA повторить спробу",[3346,4529,4530,4535,4538],{},[3367,4531,4532],{},[3324,4533,4534],{},"550",[3367,4536,4537],{},"Ящик не існує",[3367,4539,4540],{},"Постійна помилка — не повторювати",[3346,4542,4543,4548,4551],{},[3367,4544,4545],{},[3324,4546,4547],{},"552",[3367,4549,4550],{},"Ліміт розміру",[3367,4552,4553,4554,4557],{},"Лист перевищує ",[3440,4555,4556],{},"SIZE"," сервера",[3645,4559],{},[3312,4561,4563],{"id":4562},"mime-multipurpose-internet-mail-extensions","MIME — Multipurpose Internet Mail Extensions",[3317,4565,4566,4569],{},[3324,4567,4568],{},"MIME (RFC 2045–2049)"," — стандарт форматування вмісту листа. Базовий SMTP передає лише 7-bit ASCII текст. MIME розширив цю можливість: UTF-8 текст, HTML, вкладені файли, зображення, аудіо — все це стало доступним завдяки MIME-кодуванню.",[3605,4571,4573],{"id":4572},"анатомія-mime-листа","Анатомія MIME-листа",[3317,4575,4576,4577,4580,4581,4584,4585,4588],{},"Кожен лист складається з ",[3324,4578,4579],{},"заголовків"," (Headers) та ",[3324,4582,4583],{},"тіла"," (Body), розділених порожнім рядком (",[3440,4586,4587],{},"\\r\\n\\r\\n","):",[3433,4590,4595],{"className":4591,"code":4593,"language":4594,"meta":3438},[4592],"language-text","From: Alice \u003Calice@example.com>\nTo: Bob \u003Cbob@example.com>\nSubject: =?UTF-8?B?0KLQtdGB0YLQvtCy0LjQuSDQu9C40YHRgg==?=\nDate: Fri, 23 May 2025 21:00:00 +0300\nMessage-ID: \u003C20250523180000.A1B2C3@myapp.com>\nMIME-Version: 1.0\nContent-Type: multipart\u002Falternative; boundary=\"boundary_abc123\"\n\n--boundary_abc123\nContent-Type: text\u002Fplain; charset=utf-8\nContent-Transfer-Encoding: quoted-printable\n\n=D0=A2=D0=B5=D1=81=D1=82=D0=BE=D0=B2=D0=B8=D0=B9 =D0=BB=D0=B8=D1=81=D1=82\n\n--boundary_abc123\nContent-Type: text\u002Fhtml; charset=utf-8\nContent-Transfer-Encoding: base64\n\nPCFET0NUWVBFIGh0bWw+PGh0bWw+PGJvZHk+PGgxPlRlc3QgTWVzc2FnZTwvaDE+PC9ib2R5PjwvaHRtbD4=\n\n--boundary_abc123--\n","text",[3440,4596,4593],{"__ignoreMap":3438},[3605,4598,4600],{"id":4599},"ключові-заголовки-листа","Ключові заголовки листа",[3613,4602,4603,4624,4648,4673,4688,4712],{},[3616,4604,4607,4608,4611,4612,4615,4616,4619,4620,4623],{"name":4605,"type":4606},"From","string (RFC 5322)","Адреса відправника у заголовку листа. ",[3324,4609,4610],{},"Відрізняється від Envelope Sender"," (",[3440,4613,4614],{},"MAIL FROM:","). Саме цей заголовок відображається клієнту. Формат: ",[3440,4617,4618],{},"Name \u003Cemail@domain.com>"," або просто ",[3440,4621,4622],{},"email@domain.com",". Може бути підроблений у звичайного SMTP-клієнта — SPF\u002FDKIM\u002FDMARC перевіряють саме цю відповідність.",[3616,4625,4627,4628,4631,4632,4635,4636,4639,4640,4643,4644,4647],{"name":4626,"type":4606},"To \u002F Cc \u002F Bcc","Одержувачі в заголовку листа. ",[3440,4629,4630],{},"To"," — основні, ",[3440,4633,4634],{},"Cc"," (Carbon Copy) — копія, ",[3440,4637,4638],{},"Bcc"," (Blind Carbon Copy) — прихована копія. ",[3324,4641,4642],{},"Bcc не потрапляє до заголовка листа"," — одержувачі Bcc не бачать один одного. Проте всі вони перераховуються у ",[3440,4645,4646],{},"RCPT TO:"," команди SMTP-конверта.",[3616,4649,4652,4653,4656,4657,4660,4661,4664,4665,4668,4669,4672],{"name":4650,"type":4651},"Subject","encoded-word (RFC 2047)","Тема листа. Якщо містить не-ASCII символи (кирилиця, японська тощо) — кодується у форматі ",[3440,4654,4655],{},"=?charset?encoding?encoded_text?=",". Кодування: ",[3440,4658,4659],{},"B"," = Base64, ",[3440,4662,4663],{},"Q"," = Quoted-Printable. Приклад: ",[3440,4666,4667],{},"=?UTF-8?B?0KLQtdGB0YLQvtCy...?=",". ",[3440,4670,4671],{},"SmtpClient"," у .NET кодує Subject автоматично.",[3616,4674,4676,4677,4680,4681,3727,4684,4687],{"name":4675,"type":4606},"Message-ID","Унікальний ідентифікатор листа. Формат: ",[3440,4678,4679],{},"\u003Clocal-part@domain>",". Генерується MUA або MTA. Використовується для з'єднання листів у ланцюжки (threading) через ",[3440,4682,4683],{},"In-Reply-To:",[3440,4685,4686],{},"References:"," заголовки.",[3616,4689,4692,4693,4696,4697,4700,4701,3688,4704,4707,4708,4711],{"name":4690,"type":4691},"Content-Type","MIME type; parameters","Визначає тип вмісту. Для простого тексту: ",[3440,4694,4695],{},"text\u002Fplain; charset=utf-8",". Для HTML: ",[3440,4698,4699],{},"text\u002Fhtml; charset=utf-8",". Для мультичастинних листів: ",[3440,4702,4703],{},"multipart\u002Falternative; boundary=\"...\"",[3440,4705,4706],{},"multipart\u002Fmixed; boundary=\"...\"",". Параметр ",[3440,4709,4710],{},"boundary"," — унікальний рядок-роздільник між частинами.",[3616,4713,4716,4717,4720,4721,4724,4725,4728,4729,4732],{"name":4714,"type":4715},"Content-Transfer-Encoding","7bit | quoted-printable | base64","Кодування передачі вмісту. ",[3440,4718,4719],{},"7bit"," — лише ASCII (застаріло для unicode). ",[3440,4722,4723],{},"quoted-printable"," — ASCII-сумісний, не-ASCII символи замінюються ",[3440,4726,4727],{},"=HH"," (hex). ",[3440,4730,4731],{},"base64"," — повне Base64-кодування, збільшує розмір на ~33% але гарантує безпечну передачу бінарних даних.",[3605,4734,4736],{"id":4735},"типи-mime-multipart","Типи MIME multipart",[3430,4738,4739],{},[3433,4740,4742],{"className":3435,"code":4741,"language":3437,"meta":3438,"style":3438},"@startuml\nskinparam style plain\nskinparam backgroundColor #ffffff\n\nrectangle \"Лист із вкладенням та HTML\" #f5f5f5 {\n    rectangle \"multipart\u002Fmixed\\nboundary=outer\" #e3f2fd {\n        rectangle \"multipart\u002Falternative\\nboundary=inner\" #e8f5e9 {\n            rectangle \"text\u002Fplain\\nutf-8\" as plain #fff9c4\n            rectangle \"text\u002Fhtml\\nutf-8\" as html #fff9c4\n            plain -[hidden]right-> html\n        }\n        rectangle \"application\u002Fpdf\\nfilename=report.pdf\\nContent-Transfer-Encoding: base64\" as attach #fce4ec\n    }\n}\n\nnote right of plain\n  Клієнт обирає\n  кращий варіант\n  (зазвичай HTML)\nend note\n\nnote right of attach\n  Файл прикріплений\n  до листа\nend note\n\n@enduml\n",[3440,4743,4744,4748,4752,4756,4760,4765,4770,4775,4780,4785,4790,4795,4800,4805,4810,4814,4819,4824,4829,4834,4838,4842,4847,4852,4857,4861,4865],{"__ignoreMap":3438},[3443,4745,4746],{"class":3445,"line":3446},[3443,4747,3449],{},[3443,4749,4750],{"class":3445,"line":3452},[3443,4751,3455],{},[3443,4753,4754],{"class":3445,"line":3458},[3443,4755,3461],{},[3443,4757,4758],{"class":3445,"line":3464},[3443,4759,3468],{"emptyLinePlaceholder":3467},[3443,4761,4762],{"class":3445,"line":3471},[3443,4763,4764],{},"rectangle \"Лист із вкладенням та HTML\" #f5f5f5 {\n",[3443,4766,4767],{"class":3445,"line":3477},[3443,4768,4769],{},"    rectangle \"multipart\u002Fmixed\\nboundary=outer\" #e3f2fd {\n",[3443,4771,4772],{"class":3445,"line":3483},[3443,4773,4774],{},"        rectangle \"multipart\u002Falternative\\nboundary=inner\" #e8f5e9 {\n",[3443,4776,4777],{"class":3445,"line":3489},[3443,4778,4779],{},"            rectangle \"text\u002Fplain\\nutf-8\" as plain #fff9c4\n",[3443,4781,4782],{"class":3445,"line":3495},[3443,4783,4784],{},"            rectangle \"text\u002Fhtml\\nutf-8\" as html #fff9c4\n",[3443,4786,4787],{"class":3445,"line":3501},[3443,4788,4789],{},"            plain -[hidden]right-> html\n",[3443,4791,4792],{"class":3445,"line":3507},[3443,4793,4794],{},"        }\n",[3443,4796,4797],{"class":3445,"line":3513},[3443,4798,4799],{},"        rectangle \"application\u002Fpdf\\nfilename=report.pdf\\nContent-Transfer-Encoding: base64\" as attach #fce4ec\n",[3443,4801,4802],{"class":3445,"line":3518},[3443,4803,4804],{},"    }\n",[3443,4806,4807],{"class":3445,"line":3524},[3443,4808,4809],{},"}\n",[3443,4811,4812],{"class":3445,"line":3530},[3443,4813,3468],{"emptyLinePlaceholder":3467},[3443,4815,4816],{"class":3445,"line":3536},[3443,4817,4818],{},"note right of plain\n",[3443,4820,4821],{"class":3445,"line":3542},[3443,4822,4823],{},"  Клієнт обирає\n",[3443,4825,4826],{"class":3445,"line":3548},[3443,4827,4828],{},"  кращий варіант\n",[3443,4830,4831],{"class":3445,"line":3554},[3443,4832,4833],{},"  (зазвичай HTML)\n",[3443,4835,4836],{"class":3445,"line":3559},[3443,4837,3592],{},[3443,4839,4840],{"class":3445,"line":3565},[3443,4841,3468],{"emptyLinePlaceholder":3467},[3443,4843,4844],{"class":3445,"line":3571},[3443,4845,4846],{},"note right of attach\n",[3443,4848,4849],{"class":3445,"line":3577},[3443,4850,4851],{},"  Файл прикріплений\n",[3443,4853,4854],{"class":3445,"line":3583},[3443,4855,4856],{},"  до листа\n",[3443,4858,4859],{"class":3445,"line":3589},[3443,4860,3592],{},[3443,4862,4863],{"class":3445,"line":3595},[3443,4864,3468],{"emptyLinePlaceholder":3467},[3443,4866,4867],{"class":3445,"line":3600},[3443,4868,3603],{},[3340,4870,4871,4880],{},[3343,4872,4873],{},[3346,4874,4875,4878],{},[3349,4876,4877],{},"MIME Type",[3349,4879,3360],{},[3362,4881,4882,4892,4902,4916,4926,4936,4946],{},[3346,4883,4884,4889],{},[3367,4885,4886],{},[3440,4887,4888],{},"multipart\u002Fmixed",[3367,4890,4891],{},"Лист із вкладеннями. Частини є незалежними — текст + файли",[3346,4893,4894,4899],{},[3367,4895,4896],{},[3440,4897,4898],{},"multipart\u002Falternative",[3367,4900,4901],{},"Один вміст у кількох форматах. Клієнт обирає найкращий (зазвичай HTML)",[3346,4903,4904,4909],{},[3367,4905,4906],{},[3440,4907,4908],{},"multipart\u002Frelated",[3367,4910,4911,4912,4915],{},"HTML із вбудованими ресурсами (inline зображення через ",[3440,4913,4914],{},"cid:",")",[3346,4917,4918,4923],{},[3367,4919,4920],{},[3440,4921,4922],{},"text\u002Fplain",[3367,4924,4925],{},"Звичайний текст",[3346,4927,4928,4933],{},[3367,4929,4930],{},[3440,4931,4932],{},"text\u002Fhtml",[3367,4934,4935],{},"HTML-вміст",[3346,4937,4938,4943],{},[3367,4939,4940],{},[3440,4941,4942],{},"application\u002Foctet-stream",[3367,4944,4945],{},"Довільний бінарний файл (вкладення)",[3346,4947,4948,4956],{},[3367,4949,4950,3668,4953],{},[3440,4951,4952],{},"image\u002Fpng",[3440,4954,4955],{},"image\u002Fjpeg",[3367,4957,4958],{},"Зображення (для inline або вкладення)",[4960,4961,4962,4963,4966,4967,4969,4970,4972,4973,4975,4976,4978,4979,4981,4982,4984,4985,3692],"tip",{},"Правильна ієрархія для листа з HTML ",[3324,4964,4965],{},"і"," вкладеннями: ",[3440,4968,4888],{}," (зовнішній) → ",[3440,4971,4898],{}," (всередині) → ",[3440,4974,4922],{}," + ",[3440,4977,4932],{},". Зображення вбудовані в HTML (",[3440,4980,4914],{},") розміщуються у ",[3440,4983,4908],{},", що вкладається всередину ",[3440,4986,4898],{},[3645,4988],{},[3312,4990,4992],{"id":4991},"systemnetmail-нативна-відправка-smtp-у-net-10","System.Net.Mail — нативна відправка SMTP у .NET 10",[3317,4994,4995,4996,4998],{},"Простір імен ",[3440,4997,3737],{}," надає вбудовані засоби для відправки електронної пошти без залежностей від сторонніх бібліотек. Основні класи:",[3613,5000,5001,5022,5029,5041,5054],{},[3616,5002,5003,5004,5007,5008,4668,5011,5014,5015,5017,5018,5021],{"name":4671,"type":3737},"Клієнт SMTP-протоколу. Керує підключенням до сервера, аутентифікацією, шифруванням і надсиланням. Підтримує STARTTLS (",[3440,5005,5006],{},"EnableSsl = true","). Реалізує ",[3440,5009,5010],{},"IDisposable",[3324,5012,5013],{},"Важлива примітка",": Microsoft позначила ",[3440,5016,4671],{}," як ",[3440,5019,5020],{},"[Obsolete]"," у документації з рекомендацією використовувати MailKit для нових проектів, однак клас залишається повністю функціональним у .NET 10 для базових сценаріїв.",[3616,5023,5025,5026,5028],{"name":5024,"type":3737},"MailMessage","Представляє один електронний лист. Містить відправника, одержувачів, тему, тіло, вкладення та альтернативні подання. Реалізує ",[3440,5027,5010],{}," — звільняє ресурси вкладень (потоки файлів).",[3616,5030,5032,5033,5036,5037,5040],{"name":5031,"type":3737},"MailAddress","Представляє поштову адресу із необов'язковим ім'ям. ",[3440,5034,5035],{},"new MailAddress(\"alice@example.com\", \"Alice\")"," → ",[3440,5038,5039],{},"Alice \u003Calice@example.com>",". Виконує базову валідацію формату адреси.",[3616,5042,5044,5045,5048,5049,5007,5052,3692],{"name":5043,"type":3737},"Attachment","Представляє вкладення листа. Може бути створений із файлу (",[3440,5046,5047],{},"new Attachment(\"path\u002Fto\u002Ffile.pdf\")",") або потоку (",[3440,5050,5051],{},"new Attachment(stream, \"report.pdf\", \"application\u002Fpdf\")",[3440,5053,5010],{},[3616,5055,5057,5058,5060,5061,5063,5064,5067],{"name":5056,"type":3737},"AlternateView","Альтернативне подання тіла листа. Використовується для ",[3440,5059,4898],{}," (текст + HTML) та ",[3440,5062,4908],{}," (HTML із inline-зображеннями через ",[3440,5065,5066],{},"LinkedResource",").",[3605,5069,5071],{"id":5070},"базове-надсилання-листа","Базове надсилання листа",[3317,5073,5074],{},"Розпочнемо із найпростішого сценарію — надсилання текстового листа через SMTP із аутентифікацією та STARTTLS:",[5076,5077,5078,5567,6182],"tabs",{},[5079,5080,5082],"tabs-item",{"label":5081},"Простий текстовий лист",[3433,5083,5088],{"className":5084,"code":5085,"language":5086,"meta":5087,"style":3438},"language-csharp shiki shiki-themes light-plus dark-plus dark-plus","using System.Net;\nusing System.Net.Mail;\n\n\u002F\u002F SmtpClient налаштовується один раз і може надсилати кілька листів\nusing var smtpClient = new SmtpClient(\"smtp.gmail.com\")\n{\n    Port = 587,                        \u002F\u002F Submission port (STARTTLS)\n    EnableSsl = true,                  \u002F\u002F STARTTLS: спочатку з'єднання, потім TLS upgrade\n    DeliveryMethod = SmtpDeliveryMethod.Network,\n    UseDefaultCredentials = false,\n    Credentials = new NetworkCredential(\n        userName: \"alice@gmail.com\",\n        password: \"app-specific-password\" \u002F\u002F Gmail: App Password (не основний пароль!)\n    )\n};\n\n\u002F\u002F MailMessage реалізує IDisposable — звільняє потоки вкладень\nusing var message = new MailMessage\n{\n    From = new MailAddress(\"alice@gmail.com\", \"Alice\"),\n    Subject = \"Тестовий лист із .NET 10\",\n    Body = \"\"\"\n        Привіт, Боб!\n        \n        Це тестовий лист, надісланий через System.Net.Mail у .NET 10.\n        \n        З повагою,\n        Alice\n        \"\"\",\n    IsBodyHtml = false,          \u002F\u002F false = text\u002Fplain, true = text\u002Fhtml\n    BodyEncoding = System.Text.Encoding.UTF8,\n    SubjectEncoding = System.Text.Encoding.UTF8\n};\n\nmessage.To.Add(new MailAddress(\"bob@example.com\", \"Bob\"));\nmessage.Cc.Add(\"carol@example.com\");   \u002F\u002F Копія (видима в заголовках)\n\n\u002F\u002F Синхронне надсилання (блокуюче) — для простих сценаріїв\nsmtpClient.Send(message);\nConsole.WriteLine(\"Лист надіслано успішно.\");\n","csharp","showLineNumbers",[3440,5089,5090,5109,5126,5130,5136,5167,5172,5188,5204,5221,5233,5248,5261,5274,5279,5284,5288,5293,5309,5313,5337,5349,5359,5364,5369,5374,5378,5383,5388,5395,5410,5437,5459,5463,5467,5501,5524,5528,5533,5550],{"__ignoreMap":3438},[3443,5091,5092,5096,5100,5103,5106],{"class":3445,"line":3446},[3443,5093,5095],{"class":5094},"s8xlr","using",[3443,5097,5099],{"class":5098},"sN1BT"," System",[3443,5101,3692],{"class":5102},"sHH4Y",[3443,5104,5105],{"class":5098},"Net",[3443,5107,5108],{"class":5102},";\n",[3443,5110,5111,5113,5115,5117,5119,5121,5124],{"class":3445,"line":3452},[3443,5112,5095],{"class":5094},[3443,5114,5099],{"class":5098},[3443,5116,3692],{"class":5102},[3443,5118,5105],{"class":5098},[3443,5120,3692],{"class":5102},[3443,5122,5123],{"class":5098},"Mail",[3443,5125,5108],{"class":5102},[3443,5127,5128],{"class":3445,"line":3458},[3443,5129,3468],{"emptyLinePlaceholder":3467},[3443,5131,5132],{"class":3445,"line":3464},[3443,5133,5135],{"class":5134},"spJ8K","\u002F\u002F SmtpClient налаштовується один раз і може надсилати кілька листів\n",[3443,5137,5138,5140,5144,5148,5151,5154,5157,5160,5164],{"class":3445,"line":3471},[3443,5139,5095],{"class":5094},[3443,5141,5143],{"class":5142},"su1O8"," var",[3443,5145,5147],{"class":5146},"siwwj"," smtpClient",[3443,5149,5150],{"class":5102}," = ",[3443,5152,5153],{"class":5142},"new",[3443,5155,5156],{"class":5098}," SmtpClient",[3443,5158,5159],{"class":5102},"(",[3443,5161,5163],{"class":5162},"sbdoH","\"smtp.gmail.com\"",[3443,5165,5166],{"class":5102},")\n",[3443,5168,5169],{"class":3445,"line":3477},[3443,5170,5171],{"class":5102},"{\n",[3443,5173,5174,5177,5179,5182,5185],{"class":3445,"line":3483},[3443,5175,5176],{"class":5146},"    Port",[3443,5178,5150],{"class":5102},[3443,5180,3896],{"class":5181},"sJj4R",[3443,5183,5184],{"class":5102},",                        ",[3443,5186,5187],{"class":5134},"\u002F\u002F Submission port (STARTTLS)\n",[3443,5189,5190,5193,5195,5198,5201],{"class":3445,"line":3489},[3443,5191,5192],{"class":5146},"    EnableSsl",[3443,5194,5150],{"class":5102},[3443,5196,5197],{"class":5142},"true",[3443,5199,5200],{"class":5102},",                  ",[3443,5202,5203],{"class":5134},"\u002F\u002F STARTTLS: спочатку з'єднання, потім TLS upgrade\n",[3443,5205,5206,5209,5211,5214,5216,5218],{"class":3445,"line":3495},[3443,5207,5208],{"class":5146},"    DeliveryMethod",[3443,5210,5150],{"class":5102},[3443,5212,5213],{"class":5146},"SmtpDeliveryMethod",[3443,5215,3692],{"class":5102},[3443,5217,1929],{"class":5146},[3443,5219,5220],{"class":5102},",\n",[3443,5222,5223,5226,5228,5231],{"class":3445,"line":3501},[3443,5224,5225],{"class":5146},"    UseDefaultCredentials",[3443,5227,5150],{"class":5102},[3443,5229,5230],{"class":5142},"false",[3443,5232,5220],{"class":5102},[3443,5234,5235,5238,5240,5242,5245],{"class":3445,"line":3507},[3443,5236,5237],{"class":5146},"    Credentials",[3443,5239,5150],{"class":5102},[3443,5241,5153],{"class":5142},[3443,5243,5244],{"class":5098}," NetworkCredential",[3443,5246,5247],{"class":5102},"(\n",[3443,5249,5250,5253,5256,5259],{"class":3445,"line":3513},[3443,5251,5252],{"class":5146},"        userName",[3443,5254,5255],{"class":5102},": ",[3443,5257,5258],{"class":5162},"\"alice@gmail.com\"",[3443,5260,5220],{"class":5102},[3443,5262,5263,5266,5268,5271],{"class":3445,"line":3518},[3443,5264,5265],{"class":5146},"        password",[3443,5267,5255],{"class":5102},[3443,5269,5270],{"class":5162},"\"app-specific-password\"",[3443,5272,5273],{"class":5134}," \u002F\u002F Gmail: App Password (не основний пароль!)\n",[3443,5275,5276],{"class":3445,"line":3524},[3443,5277,5278],{"class":5102},"    )\n",[3443,5280,5281],{"class":3445,"line":3530},[3443,5282,5283],{"class":5102},"};\n",[3443,5285,5286],{"class":3445,"line":3536},[3443,5287,3468],{"emptyLinePlaceholder":3467},[3443,5289,5290],{"class":3445,"line":3542},[3443,5291,5292],{"class":5134},"\u002F\u002F MailMessage реалізує IDisposable — звільняє потоки вкладень\n",[3443,5294,5295,5297,5299,5302,5304,5306],{"class":3445,"line":3548},[3443,5296,5095],{"class":5094},[3443,5298,5143],{"class":5142},[3443,5300,5301],{"class":5146}," message",[3443,5303,5150],{"class":5102},[3443,5305,5153],{"class":5142},[3443,5307,5308],{"class":5098}," MailMessage\n",[3443,5310,5311],{"class":3445,"line":3554},[3443,5312,5171],{"class":5102},[3443,5314,5315,5318,5320,5322,5325,5327,5329,5331,5334],{"class":3445,"line":3559},[3443,5316,5317],{"class":5146},"    From",[3443,5319,5150],{"class":5102},[3443,5321,5153],{"class":5142},[3443,5323,5324],{"class":5098}," MailAddress",[3443,5326,5159],{"class":5102},[3443,5328,5258],{"class":5162},[3443,5330,3668],{"class":5102},[3443,5332,5333],{"class":5162},"\"Alice\"",[3443,5335,5336],{"class":5102},"),\n",[3443,5338,5339,5342,5344,5347],{"class":3445,"line":3565},[3443,5340,5341],{"class":5146},"    Subject",[3443,5343,5150],{"class":5102},[3443,5345,5346],{"class":5162},"\"Тестовий лист із .NET 10\"",[3443,5348,5220],{"class":5102},[3443,5350,5351,5354,5356],{"class":3445,"line":3571},[3443,5352,5353],{"class":5146},"    Body",[3443,5355,5150],{"class":5102},[3443,5357,5358],{"class":5162},"\"\"\"\n",[3443,5360,5361],{"class":3445,"line":3577},[3443,5362,5363],{"class":5162},"        Привіт, Боб!\n",[3443,5365,5366],{"class":3445,"line":3583},[3443,5367,5368],{"class":5162},"        \n",[3443,5370,5371],{"class":3445,"line":3589},[3443,5372,5373],{"class":5162},"        Це тестовий лист, надісланий через System.Net.Mail у .NET 10.\n",[3443,5375,5376],{"class":3445,"line":3595},[3443,5377,5368],{"class":5162},[3443,5379,5380],{"class":3445,"line":3600},[3443,5381,5382],{"class":5162},"        З повагою,\n",[3443,5384,5385],{"class":3445,"line":4077},[3443,5386,5387],{"class":5162},"        Alice\n",[3443,5389,5390,5393],{"class":3445,"line":4083},[3443,5391,5392],{"class":5162},"        \"\"\"",[3443,5394,5220],{"class":5102},[3443,5396,5397,5400,5402,5404,5407],{"class":3445,"line":4089},[3443,5398,5399],{"class":5146},"    IsBodyHtml",[3443,5401,5150],{"class":5102},[3443,5403,5230],{"class":5142},[3443,5405,5406],{"class":5102},",          ",[3443,5408,5409],{"class":5134},"\u002F\u002F false = text\u002Fplain, true = text\u002Fhtml\n",[3443,5411,5412,5415,5417,5420,5422,5425,5427,5430,5432,5435],{"class":3445,"line":4094},[3443,5413,5414],{"class":5146},"    BodyEncoding",[3443,5416,5150],{"class":5102},[3443,5418,5419],{"class":5146},"System",[3443,5421,3692],{"class":5102},[3443,5423,5424],{"class":5146},"Text",[3443,5426,3692],{"class":5102},[3443,5428,5429],{"class":5146},"Encoding",[3443,5431,3692],{"class":5102},[3443,5433,5434],{"class":5146},"UTF8",[3443,5436,5220],{"class":5102},[3443,5438,5439,5442,5444,5446,5448,5450,5452,5454,5456],{"class":3445,"line":4100},[3443,5440,5441],{"class":5146},"    SubjectEncoding",[3443,5443,5150],{"class":5102},[3443,5445,5419],{"class":5146},[3443,5447,3692],{"class":5102},[3443,5449,5424],{"class":5146},[3443,5451,3692],{"class":5102},[3443,5453,5429],{"class":5146},[3443,5455,3692],{"class":5102},[3443,5457,5458],{"class":5146},"UTF8\n",[3443,5460,5461],{"class":3445,"line":4106},[3443,5462,5283],{"class":5102},[3443,5464,5465],{"class":3445,"line":4111},[3443,5466,3468],{"emptyLinePlaceholder":3467},[3443,5468,5469,5472,5474,5476,5478,5482,5484,5486,5488,5490,5493,5495,5498],{"class":3445,"line":4117},[3443,5470,5471],{"class":5146},"message",[3443,5473,3692],{"class":5102},[3443,5475,4630],{"class":5146},[3443,5477,3692],{"class":5102},[3443,5479,5481],{"class":5480},"s8Opu","Add",[3443,5483,5159],{"class":5102},[3443,5485,5153],{"class":5142},[3443,5487,5324],{"class":5098},[3443,5489,5159],{"class":5102},[3443,5491,5492],{"class":5162},"\"bob@example.com\"",[3443,5494,3668],{"class":5102},[3443,5496,5497],{"class":5162},"\"Bob\"",[3443,5499,5500],{"class":5102},"));\n",[3443,5502,5503,5505,5507,5509,5511,5513,5515,5518,5521],{"class":3445,"line":4122},[3443,5504,5471],{"class":5146},[3443,5506,3692],{"class":5102},[3443,5508,4634],{"class":5146},[3443,5510,3692],{"class":5102},[3443,5512,5481],{"class":5480},[3443,5514,5159],{"class":5102},[3443,5516,5517],{"class":5162},"\"carol@example.com\"",[3443,5519,5520],{"class":5102},");   ",[3443,5522,5523],{"class":5134},"\u002F\u002F Копія (видима в заголовках)\n",[3443,5525,5526],{"class":3445,"line":4127},[3443,5527,3468],{"emptyLinePlaceholder":3467},[3443,5529,5530],{"class":3445,"line":4133},[3443,5531,5532],{"class":5134},"\u002F\u002F Синхронне надсилання (блокуюче) — для простих сценаріїв\n",[3443,5534,5535,5538,5540,5543,5545,5547],{"class":3445,"line":4139},[3443,5536,5537],{"class":5146},"smtpClient",[3443,5539,3692],{"class":5102},[3443,5541,5542],{"class":5480},"Send",[3443,5544,5159],{"class":5102},[3443,5546,5471],{"class":5146},[3443,5548,5549],{"class":5102},");\n",[3443,5551,5552,5555,5557,5560,5562,5565],{"class":3445,"line":4145},[3443,5553,5554],{"class":5146},"Console",[3443,5556,3692],{"class":5102},[3443,5558,5559],{"class":5480},"WriteLine",[3443,5561,5159],{"class":5102},[3443,5563,5564],{"class":5162},"\"Лист надіслано успішно.\"",[3443,5566,5549],{"class":5102},[5079,5568,5570],{"label":5569},"Async надсилання",[3433,5571,5573],{"className":5084,"code":5572,"language":5086,"meta":5087,"style":3438},"using System.Net;\nusing System.Net.Mail;\n\n\u002F\u002F SmtpClient.SendMailAsync — рекомендований підхід для async контексту\nasync Task SendEmailAsync(string toEmail, string subject, string body)\n{\n    using var smtpClient = new SmtpClient(\"smtp.gmail.com\")\n    {\n        Port = 587,\n        EnableSsl = true,\n        UseDefaultCredentials = false,\n        Credentials = new NetworkCredential(\"alice@gmail.com\", \"app-password\")\n    };\n\n    using var message = new MailMessage(\n        from: \"alice@gmail.com\",\n        to: toEmail,\n        subject: subject,\n        body: body\n    );\n\n    message.BodyEncoding = System.Text.Encoding.UTF8;\n    message.SubjectEncoding = System.Text.Encoding.UTF8;\n\n    try\n    {\n        \u002F\u002F SendMailAsync повертає Task — не блокує потік\n        await smtpClient.SendMailAsync(message);\n        Console.WriteLine($\"Лист надіслано на {toEmail}\");\n    }\n    catch (SmtpException ex) when (ex.StatusCode == SmtpStatusCode.MailboxUnavailable)\n    {\n        \u002F\u002F 550: Ящик не існує — постійна помилка, не повторювати\n        Console.Error.WriteLine($\"Ящик не знайдено: {ex.Message}\");\n    }\n    catch (SmtpException ex) when ((int)ex.StatusCode >= 400 && (int)ex.StatusCode \u003C 500)\n    {\n        \u002F\u002F 4xx: Тимчасова помилка — можна повторити через деякий час\n        Console.Error.WriteLine($\"Тимчасова помилка SMTP ({ex.StatusCode}): {ex.Message}\");\n        throw; \u002F\u002F Перекидаємо для retry-логіки вище\n    }\n}\n\n\u002F\u002F Виклик:\nawait SendEmailAsync(\"bob@example.com\", \"Привіт від .NET 10\", \"Тіло листа...\");\n",[3440,5574,5575,5587,5603,5607,5612,5647,5651,5672,5677,5688,5699,5710,5732,5737,5741,5758,5769,5781,5793,5803,5808,5812,5840,5867,5871,5876,5880,5885,5903,5931,5935,5977,5981,5986,6019,6023,6078,6082,6087,6131,6142,6146,6150,6154,6159],{"__ignoreMap":3438},[3443,5576,5577,5579,5581,5583,5585],{"class":3445,"line":3446},[3443,5578,5095],{"class":5094},[3443,5580,5099],{"class":5098},[3443,5582,3692],{"class":5102},[3443,5584,5105],{"class":5098},[3443,5586,5108],{"class":5102},[3443,5588,5589,5591,5593,5595,5597,5599,5601],{"class":3445,"line":3452},[3443,5590,5095],{"class":5094},[3443,5592,5099],{"class":5098},[3443,5594,3692],{"class":5102},[3443,5596,5105],{"class":5098},[3443,5598,3692],{"class":5102},[3443,5600,5123],{"class":5098},[3443,5602,5108],{"class":5102},[3443,5604,5605],{"class":3445,"line":3458},[3443,5606,3468],{"emptyLinePlaceholder":3467},[3443,5608,5609],{"class":3445,"line":3464},[3443,5610,5611],{"class":5134},"\u002F\u002F SmtpClient.SendMailAsync — рекомендований підхід для async контексту\n",[3443,5613,5614,5617,5620,5623,5625,5628,5631,5633,5635,5638,5640,5642,5645],{"class":3445,"line":3471},[3443,5615,5616],{"class":5142},"async",[3443,5618,5619],{"class":5098}," Task",[3443,5621,5622],{"class":5480}," SendEmailAsync",[3443,5624,5159],{"class":5102},[3443,5626,5627],{"class":5142},"string",[3443,5629,5630],{"class":5146}," toEmail",[3443,5632,3668],{"class":5102},[3443,5634,5627],{"class":5142},[3443,5636,5637],{"class":5146}," subject",[3443,5639,3668],{"class":5102},[3443,5641,5627],{"class":5142},[3443,5643,5644],{"class":5146}," body",[3443,5646,5166],{"class":5102},[3443,5648,5649],{"class":3445,"line":3477},[3443,5650,5171],{"class":5102},[3443,5652,5653,5656,5658,5660,5662,5664,5666,5668,5670],{"class":3445,"line":3483},[3443,5654,5655],{"class":5094},"    using",[3443,5657,5143],{"class":5142},[3443,5659,5147],{"class":5146},[3443,5661,5150],{"class":5102},[3443,5663,5153],{"class":5142},[3443,5665,5156],{"class":5098},[3443,5667,5159],{"class":5102},[3443,5669,5163],{"class":5162},[3443,5671,5166],{"class":5102},[3443,5673,5674],{"class":3445,"line":3489},[3443,5675,5676],{"class":5102},"    {\n",[3443,5678,5679,5682,5684,5686],{"class":3445,"line":3495},[3443,5680,5681],{"class":5146},"        Port",[3443,5683,5150],{"class":5102},[3443,5685,3896],{"class":5181},[3443,5687,5220],{"class":5102},[3443,5689,5690,5693,5695,5697],{"class":3445,"line":3501},[3443,5691,5692],{"class":5146},"        EnableSsl",[3443,5694,5150],{"class":5102},[3443,5696,5197],{"class":5142},[3443,5698,5220],{"class":5102},[3443,5700,5701,5704,5706,5708],{"class":3445,"line":3507},[3443,5702,5703],{"class":5146},"        UseDefaultCredentials",[3443,5705,5150],{"class":5102},[3443,5707,5230],{"class":5142},[3443,5709,5220],{"class":5102},[3443,5711,5712,5715,5717,5719,5721,5723,5725,5727,5730],{"class":3445,"line":3513},[3443,5713,5714],{"class":5146},"        Credentials",[3443,5716,5150],{"class":5102},[3443,5718,5153],{"class":5142},[3443,5720,5244],{"class":5098},[3443,5722,5159],{"class":5102},[3443,5724,5258],{"class":5162},[3443,5726,3668],{"class":5102},[3443,5728,5729],{"class":5162},"\"app-password\"",[3443,5731,5166],{"class":5102},[3443,5733,5734],{"class":3445,"line":3518},[3443,5735,5736],{"class":5102},"    };\n",[3443,5738,5739],{"class":3445,"line":3524},[3443,5740,3468],{"emptyLinePlaceholder":3467},[3443,5742,5743,5745,5747,5749,5751,5753,5756],{"class":3445,"line":3530},[3443,5744,5655],{"class":5094},[3443,5746,5143],{"class":5142},[3443,5748,5301],{"class":5146},[3443,5750,5150],{"class":5102},[3443,5752,5153],{"class":5142},[3443,5754,5755],{"class":5098}," MailMessage",[3443,5757,5247],{"class":5102},[3443,5759,5760,5763,5765,5767],{"class":3445,"line":3536},[3443,5761,5762],{"class":5146},"        from",[3443,5764,5255],{"class":5102},[3443,5766,5258],{"class":5162},[3443,5768,5220],{"class":5102},[3443,5770,5771,5774,5776,5779],{"class":3445,"line":3542},[3443,5772,5773],{"class":5146},"        to",[3443,5775,5255],{"class":5102},[3443,5777,5778],{"class":5146},"toEmail",[3443,5780,5220],{"class":5102},[3443,5782,5783,5786,5788,5791],{"class":3445,"line":3548},[3443,5784,5785],{"class":5146},"        subject",[3443,5787,5255],{"class":5102},[3443,5789,5790],{"class":5146},"subject",[3443,5792,5220],{"class":5102},[3443,5794,5795,5798,5800],{"class":3445,"line":3554},[3443,5796,5797],{"class":5146},"        body",[3443,5799,5255],{"class":5102},[3443,5801,5802],{"class":5146},"body\n",[3443,5804,5805],{"class":3445,"line":3559},[3443,5806,5807],{"class":5102},"    );\n",[3443,5809,5810],{"class":3445,"line":3565},[3443,5811,3468],{"emptyLinePlaceholder":3467},[3443,5813,5814,5817,5819,5822,5824,5826,5828,5830,5832,5834,5836,5838],{"class":3445,"line":3571},[3443,5815,5816],{"class":5146},"    message",[3443,5818,3692],{"class":5102},[3443,5820,5821],{"class":5146},"BodyEncoding",[3443,5823,5150],{"class":5102},[3443,5825,5419],{"class":5146},[3443,5827,3692],{"class":5102},[3443,5829,5424],{"class":5146},[3443,5831,3692],{"class":5102},[3443,5833,5429],{"class":5146},[3443,5835,3692],{"class":5102},[3443,5837,5434],{"class":5146},[3443,5839,5108],{"class":5102},[3443,5841,5842,5844,5846,5849,5851,5853,5855,5857,5859,5861,5863,5865],{"class":3445,"line":3577},[3443,5843,5816],{"class":5146},[3443,5845,3692],{"class":5102},[3443,5847,5848],{"class":5146},"SubjectEncoding",[3443,5850,5150],{"class":5102},[3443,5852,5419],{"class":5146},[3443,5854,3692],{"class":5102},[3443,5856,5424],{"class":5146},[3443,5858,3692],{"class":5102},[3443,5860,5429],{"class":5146},[3443,5862,3692],{"class":5102},[3443,5864,5434],{"class":5146},[3443,5866,5108],{"class":5102},[3443,5868,5869],{"class":3445,"line":3583},[3443,5870,3468],{"emptyLinePlaceholder":3467},[3443,5872,5873],{"class":3445,"line":3589},[3443,5874,5875],{"class":5094},"    try\n",[3443,5877,5878],{"class":3445,"line":3595},[3443,5879,5676],{"class":5102},[3443,5881,5882],{"class":3445,"line":3600},[3443,5883,5884],{"class":5134},"        \u002F\u002F SendMailAsync повертає Task — не блокує потік\n",[3443,5886,5887,5890,5892,5894,5897,5899,5901],{"class":3445,"line":4077},[3443,5888,5889],{"class":5142},"        await",[3443,5891,5147],{"class":5146},[3443,5893,3692],{"class":5102},[3443,5895,5896],{"class":5480},"SendMailAsync",[3443,5898,5159],{"class":5102},[3443,5900,5471],{"class":5146},[3443,5902,5549],{"class":5102},[3443,5904,5905,5908,5910,5912,5914,5917,5921,5923,5926,5929],{"class":3445,"line":4083},[3443,5906,5907],{"class":5146},"        Console",[3443,5909,3692],{"class":5102},[3443,5911,5559],{"class":5480},[3443,5913,5159],{"class":5102},[3443,5915,5916],{"class":5162},"$\"Лист надіслано на ",[3443,5918,5920],{"class":5919},"sD7JJ","{",[3443,5922,5778],{"class":5146},[3443,5924,5925],{"class":5919},"}",[3443,5927,5928],{"class":5162},"\"",[3443,5930,5549],{"class":5102},[3443,5932,5933],{"class":3445,"line":4089},[3443,5934,4804],{"class":5102},[3443,5936,5937,5940,5942,5945,5948,5951,5954,5956,5959,5961,5964,5967,5970,5972,5975],{"class":3445,"line":4094},[3443,5938,5939],{"class":5094},"    catch",[3443,5941,4611],{"class":5102},[3443,5943,5944],{"class":5098},"SmtpException",[3443,5946,5947],{"class":5146}," ex",[3443,5949,5950],{"class":5102},") ",[3443,5952,5953],{"class":5094},"when",[3443,5955,4611],{"class":5102},[3443,5957,5958],{"class":5146},"ex",[3443,5960,3692],{"class":5102},[3443,5962,5963],{"class":5146},"StatusCode",[3443,5965,5966],{"class":5102}," == ",[3443,5968,5969],{"class":5146},"SmtpStatusCode",[3443,5971,3692],{"class":5102},[3443,5973,5974],{"class":5146},"MailboxUnavailable",[3443,5976,5166],{"class":5102},[3443,5978,5979],{"class":3445,"line":4100},[3443,5980,5676],{"class":5102},[3443,5982,5983],{"class":3445,"line":4106},[3443,5984,5985],{"class":5134},"        \u002F\u002F 550: Ящик не існує — постійна помилка, не повторювати\n",[3443,5987,5988,5990,5992,5995,5997,5999,6001,6004,6006,6008,6010,6013,6015,6017],{"class":3445,"line":4111},[3443,5989,5907],{"class":5146},[3443,5991,3692],{"class":5102},[3443,5993,5994],{"class":5146},"Error",[3443,5996,3692],{"class":5102},[3443,5998,5559],{"class":5480},[3443,6000,5159],{"class":5102},[3443,6002,6003],{"class":5162},"$\"Ящик не знайдено: ",[3443,6005,5920],{"class":5919},[3443,6007,5958],{"class":5146},[3443,6009,3692],{"class":5919},[3443,6011,6012],{"class":5146},"Message",[3443,6014,5925],{"class":5919},[3443,6016,5928],{"class":5162},[3443,6018,5549],{"class":5102},[3443,6020,6021],{"class":3445,"line":4117},[3443,6022,4804],{"class":5102},[3443,6024,6025,6027,6029,6031,6033,6035,6037,6040,6043,6045,6047,6049,6051,6054,6057,6060,6062,6064,6066,6068,6070,6073,6076],{"class":3445,"line":4122},[3443,6026,5939],{"class":5094},[3443,6028,4611],{"class":5102},[3443,6030,5944],{"class":5098},[3443,6032,5947],{"class":5146},[3443,6034,5950],{"class":5102},[3443,6036,5953],{"class":5094},[3443,6038,6039],{"class":5102}," ((",[3443,6041,6042],{"class":5142},"int",[3443,6044,4915],{"class":5102},[3443,6046,5958],{"class":5146},[3443,6048,3692],{"class":5102},[3443,6050,5963],{"class":5146},[3443,6052,6053],{"class":5102}," >= ",[3443,6055,6056],{"class":5181},"400",[3443,6058,6059],{"class":5102}," && (",[3443,6061,6042],{"class":5142},[3443,6063,4915],{"class":5102},[3443,6065,5958],{"class":5146},[3443,6067,3692],{"class":5102},[3443,6069,5963],{"class":5146},[3443,6071,6072],{"class":5102}," \u003C ",[3443,6074,6075],{"class":5181},"500",[3443,6077,5166],{"class":5102},[3443,6079,6080],{"class":3445,"line":4127},[3443,6081,5676],{"class":5102},[3443,6083,6084],{"class":3445,"line":4133},[3443,6085,6086],{"class":5134},"        \u002F\u002F 4xx: Тимчасова помилка — можна повторити через деякий час\n",[3443,6088,6089,6091,6093,6095,6097,6099,6101,6104,6106,6108,6110,6112,6114,6117,6119,6121,6123,6125,6127,6129],{"class":3445,"line":4139},[3443,6090,5907],{"class":5146},[3443,6092,3692],{"class":5102},[3443,6094,5994],{"class":5146},[3443,6096,3692],{"class":5102},[3443,6098,5559],{"class":5480},[3443,6100,5159],{"class":5102},[3443,6102,6103],{"class":5162},"$\"Тимчасова помилка SMTP (",[3443,6105,5920],{"class":5919},[3443,6107,5958],{"class":5146},[3443,6109,3692],{"class":5919},[3443,6111,5963],{"class":5146},[3443,6113,5925],{"class":5919},[3443,6115,6116],{"class":5162},"): ",[3443,6118,5920],{"class":5919},[3443,6120,5958],{"class":5146},[3443,6122,3692],{"class":5919},[3443,6124,6012],{"class":5146},[3443,6126,5925],{"class":5919},[3443,6128,5928],{"class":5162},[3443,6130,5549],{"class":5102},[3443,6132,6133,6136,6139],{"class":3445,"line":4145},[3443,6134,6135],{"class":5094},"        throw",[3443,6137,6138],{"class":5102},"; ",[3443,6140,6141],{"class":5134},"\u002F\u002F Перекидаємо для retry-логіки вище\n",[3443,6143,6144],{"class":3445,"line":4150},[3443,6145,4804],{"class":5102},[3443,6147,6148],{"class":3445,"line":4156},[3443,6149,4809],{"class":5102},[3443,6151,6152],{"class":3445,"line":4162},[3443,6153,3468],{"emptyLinePlaceholder":3467},[3443,6155,6156],{"class":3445,"line":4168},[3443,6157,6158],{"class":5134},"\u002F\u002F Виклик:\n",[3443,6160,6161,6164,6166,6168,6170,6172,6175,6177,6180],{"class":3445,"line":4174},[3443,6162,6163],{"class":5142},"await",[3443,6165,5622],{"class":5480},[3443,6167,5159],{"class":5102},[3443,6169,5492],{"class":5162},[3443,6171,3668],{"class":5102},[3443,6173,6174],{"class":5162},"\"Привіт від .NET 10\"",[3443,6176,3668],{"class":5102},[3443,6178,6179],{"class":5162},"\"Тіло листа...\"",[3443,6181,5549],{"class":5102},[5079,6183,6185],{"label":6184},"Кілька одержувачів та BCC",[3433,6186,6188],{"className":5084,"code":6187,"language":5086,"meta":5087,"style":3438},"using System.Net;\nusing System.Net.Mail;\n\nusing var smtp = new SmtpClient(\"smtp.office365.com\")\n{\n    Port = 587,\n    EnableSsl = true,\n    Credentials = new NetworkCredential(\"noreply@company.com\", \"password\")\n};\n\nusing var message = new MailMessage\n{\n    From = new MailAddress(\"noreply@company.com\", \"Компанія ABC\"),\n    Subject = \"Щомісячний звіт\",\n    Body = \"Шановні колеги, у вкладенні звіт за травень.\",\n    IsBodyHtml = false\n};\n\n\u002F\u002F Кілька основних одержувачів\nmessage.To.Add(new MailAddress(\"ceo@company.com\", \"Директор\"));\nmessage.To.Add(new MailAddress(\"cfo@company.com\", \"Фінансовий директор\"));\n\n\u002F\u002F Копія (Cc) — видима всім одержувачам у заголовках\nmessage.CC.Add(new MailAddress(\"assistant@company.com\", \"Асистент\"));\n\n\u002F\u002F Прихована копія (Bcc) — одержувачі не бачать один одного\n\u002F\u002F Бухгалтер отримає лист, але To\u002FCc-одержувачі його не побачать\nmessage.Bcc.Add(new MailAddress(\"accountant@company.com\", \"Бухгалтер\"));\n\n\u002F\u002F ReplyTo — куди надсилати відповідь (може відрізнятися від From)\nmessage.ReplyToList.Add(new MailAddress(\"support@company.com\", \"Підтримка\"));\n\nawait smtp.SendMailAsync(message);\n",[3440,6189,6190,6202,6218,6222,6244,6248,6258,6268,6290,6294,6298,6312,6316,6337,6348,6359,6368,6372,6376,6381,6411,6441,6445,6450,6481,6485,6490,6495,6525,6529,6534,6565,6569],{"__ignoreMap":3438},[3443,6191,6192,6194,6196,6198,6200],{"class":3445,"line":3446},[3443,6193,5095],{"class":5094},[3443,6195,5099],{"class":5098},[3443,6197,3692],{"class":5102},[3443,6199,5105],{"class":5098},[3443,6201,5108],{"class":5102},[3443,6203,6204,6206,6208,6210,6212,6214,6216],{"class":3445,"line":3452},[3443,6205,5095],{"class":5094},[3443,6207,5099],{"class":5098},[3443,6209,3692],{"class":5102},[3443,6211,5105],{"class":5098},[3443,6213,3692],{"class":5102},[3443,6215,5123],{"class":5098},[3443,6217,5108],{"class":5102},[3443,6219,6220],{"class":3445,"line":3458},[3443,6221,3468],{"emptyLinePlaceholder":3467},[3443,6223,6224,6226,6228,6231,6233,6235,6237,6239,6242],{"class":3445,"line":3464},[3443,6225,5095],{"class":5094},[3443,6227,5143],{"class":5142},[3443,6229,6230],{"class":5146}," smtp",[3443,6232,5150],{"class":5102},[3443,6234,5153],{"class":5142},[3443,6236,5156],{"class":5098},[3443,6238,5159],{"class":5102},[3443,6240,6241],{"class":5162},"\"smtp.office365.com\"",[3443,6243,5166],{"class":5102},[3443,6245,6246],{"class":3445,"line":3471},[3443,6247,5171],{"class":5102},[3443,6249,6250,6252,6254,6256],{"class":3445,"line":3477},[3443,6251,5176],{"class":5146},[3443,6253,5150],{"class":5102},[3443,6255,3896],{"class":5181},[3443,6257,5220],{"class":5102},[3443,6259,6260,6262,6264,6266],{"class":3445,"line":3483},[3443,6261,5192],{"class":5146},[3443,6263,5150],{"class":5102},[3443,6265,5197],{"class":5142},[3443,6267,5220],{"class":5102},[3443,6269,6270,6272,6274,6276,6278,6280,6283,6285,6288],{"class":3445,"line":3489},[3443,6271,5237],{"class":5146},[3443,6273,5150],{"class":5102},[3443,6275,5153],{"class":5142},[3443,6277,5244],{"class":5098},[3443,6279,5159],{"class":5102},[3443,6281,6282],{"class":5162},"\"noreply@company.com\"",[3443,6284,3668],{"class":5102},[3443,6286,6287],{"class":5162},"\"password\"",[3443,6289,5166],{"class":5102},[3443,6291,6292],{"class":3445,"line":3495},[3443,6293,5283],{"class":5102},[3443,6295,6296],{"class":3445,"line":3501},[3443,6297,3468],{"emptyLinePlaceholder":3467},[3443,6299,6300,6302,6304,6306,6308,6310],{"class":3445,"line":3507},[3443,6301,5095],{"class":5094},[3443,6303,5143],{"class":5142},[3443,6305,5301],{"class":5146},[3443,6307,5150],{"class":5102},[3443,6309,5153],{"class":5142},[3443,6311,5308],{"class":5098},[3443,6313,6314],{"class":3445,"line":3513},[3443,6315,5171],{"class":5102},[3443,6317,6318,6320,6322,6324,6326,6328,6330,6332,6335],{"class":3445,"line":3518},[3443,6319,5317],{"class":5146},[3443,6321,5150],{"class":5102},[3443,6323,5153],{"class":5142},[3443,6325,5324],{"class":5098},[3443,6327,5159],{"class":5102},[3443,6329,6282],{"class":5162},[3443,6331,3668],{"class":5102},[3443,6333,6334],{"class":5162},"\"Компанія ABC\"",[3443,6336,5336],{"class":5102},[3443,6338,6339,6341,6343,6346],{"class":3445,"line":3524},[3443,6340,5341],{"class":5146},[3443,6342,5150],{"class":5102},[3443,6344,6345],{"class":5162},"\"Щомісячний звіт\"",[3443,6347,5220],{"class":5102},[3443,6349,6350,6352,6354,6357],{"class":3445,"line":3530},[3443,6351,5353],{"class":5146},[3443,6353,5150],{"class":5102},[3443,6355,6356],{"class":5162},"\"Шановні колеги, у вкладенні звіт за травень.\"",[3443,6358,5220],{"class":5102},[3443,6360,6361,6363,6365],{"class":3445,"line":3536},[3443,6362,5399],{"class":5146},[3443,6364,5150],{"class":5102},[3443,6366,6367],{"class":5142},"false\n",[3443,6369,6370],{"class":3445,"line":3542},[3443,6371,5283],{"class":5102},[3443,6373,6374],{"class":3445,"line":3548},[3443,6375,3468],{"emptyLinePlaceholder":3467},[3443,6377,6378],{"class":3445,"line":3554},[3443,6379,6380],{"class":5134},"\u002F\u002F Кілька основних одержувачів\n",[3443,6382,6383,6385,6387,6389,6391,6393,6395,6397,6399,6401,6404,6406,6409],{"class":3445,"line":3559},[3443,6384,5471],{"class":5146},[3443,6386,3692],{"class":5102},[3443,6388,4630],{"class":5146},[3443,6390,3692],{"class":5102},[3443,6392,5481],{"class":5480},[3443,6394,5159],{"class":5102},[3443,6396,5153],{"class":5142},[3443,6398,5324],{"class":5098},[3443,6400,5159],{"class":5102},[3443,6402,6403],{"class":5162},"\"ceo@company.com\"",[3443,6405,3668],{"class":5102},[3443,6407,6408],{"class":5162},"\"Директор\"",[3443,6410,5500],{"class":5102},[3443,6412,6413,6415,6417,6419,6421,6423,6425,6427,6429,6431,6434,6436,6439],{"class":3445,"line":3565},[3443,6414,5471],{"class":5146},[3443,6416,3692],{"class":5102},[3443,6418,4630],{"class":5146},[3443,6420,3692],{"class":5102},[3443,6422,5481],{"class":5480},[3443,6424,5159],{"class":5102},[3443,6426,5153],{"class":5142},[3443,6428,5324],{"class":5098},[3443,6430,5159],{"class":5102},[3443,6432,6433],{"class":5162},"\"cfo@company.com\"",[3443,6435,3668],{"class":5102},[3443,6437,6438],{"class":5162},"\"Фінансовий директор\"",[3443,6440,5500],{"class":5102},[3443,6442,6443],{"class":3445,"line":3571},[3443,6444,3468],{"emptyLinePlaceholder":3467},[3443,6446,6447],{"class":3445,"line":3577},[3443,6448,6449],{"class":5134},"\u002F\u002F Копія (Cc) — видима всім одержувачам у заголовках\n",[3443,6451,6452,6454,6456,6459,6461,6463,6465,6467,6469,6471,6474,6476,6479],{"class":3445,"line":3583},[3443,6453,5471],{"class":5146},[3443,6455,3692],{"class":5102},[3443,6457,6458],{"class":5146},"CC",[3443,6460,3692],{"class":5102},[3443,6462,5481],{"class":5480},[3443,6464,5159],{"class":5102},[3443,6466,5153],{"class":5142},[3443,6468,5324],{"class":5098},[3443,6470,5159],{"class":5102},[3443,6472,6473],{"class":5162},"\"assistant@company.com\"",[3443,6475,3668],{"class":5102},[3443,6477,6478],{"class":5162},"\"Асистент\"",[3443,6480,5500],{"class":5102},[3443,6482,6483],{"class":3445,"line":3589},[3443,6484,3468],{"emptyLinePlaceholder":3467},[3443,6486,6487],{"class":3445,"line":3595},[3443,6488,6489],{"class":5134},"\u002F\u002F Прихована копія (Bcc) — одержувачі не бачать один одного\n",[3443,6491,6492],{"class":3445,"line":3600},[3443,6493,6494],{"class":5134},"\u002F\u002F Бухгалтер отримає лист, але To\u002FCc-одержувачі його не побачать\n",[3443,6496,6497,6499,6501,6503,6505,6507,6509,6511,6513,6515,6518,6520,6523],{"class":3445,"line":4077},[3443,6498,5471],{"class":5146},[3443,6500,3692],{"class":5102},[3443,6502,4638],{"class":5146},[3443,6504,3692],{"class":5102},[3443,6506,5481],{"class":5480},[3443,6508,5159],{"class":5102},[3443,6510,5153],{"class":5142},[3443,6512,5324],{"class":5098},[3443,6514,5159],{"class":5102},[3443,6516,6517],{"class":5162},"\"accountant@company.com\"",[3443,6519,3668],{"class":5102},[3443,6521,6522],{"class":5162},"\"Бухгалтер\"",[3443,6524,5500],{"class":5102},[3443,6526,6527],{"class":3445,"line":4083},[3443,6528,3468],{"emptyLinePlaceholder":3467},[3443,6530,6531],{"class":3445,"line":4089},[3443,6532,6533],{"class":5134},"\u002F\u002F ReplyTo — куди надсилати відповідь (може відрізнятися від From)\n",[3443,6535,6536,6538,6540,6543,6545,6547,6549,6551,6553,6555,6558,6560,6563],{"class":3445,"line":4094},[3443,6537,5471],{"class":5146},[3443,6539,3692],{"class":5102},[3443,6541,6542],{"class":5146},"ReplyToList",[3443,6544,3692],{"class":5102},[3443,6546,5481],{"class":5480},[3443,6548,5159],{"class":5102},[3443,6550,5153],{"class":5142},[3443,6552,5324],{"class":5098},[3443,6554,5159],{"class":5102},[3443,6556,6557],{"class":5162},"\"support@company.com\"",[3443,6559,3668],{"class":5102},[3443,6561,6562],{"class":5162},"\"Підтримка\"",[3443,6564,5500],{"class":5102},[3443,6566,6567],{"class":3445,"line":4100},[3443,6568,3468],{"emptyLinePlaceholder":3467},[3443,6570,6571,6573,6575,6577,6579,6581,6583],{"class":3445,"line":4106},[3443,6572,6163],{"class":5142},[3443,6574,6230],{"class":5146},[3443,6576,3692],{"class":5102},[3443,6578,5896],{"class":5480},[3443,6580,5159],{"class":5102},[3443,6582,5471],{"class":5146},[3443,6584,5549],{"class":5102},[3645,6586],{},[3605,6588,6590],{"id":6589},"html-листи-та-вкладення","HTML-листи та вкладення",[3317,6592,6593,6594,6596,6597,3668,6600,3727,6603,3692],{},"Більшість реальних листів використовують HTML для форматування та можуть містити файлові вкладення. ",[3440,6595,5024],{}," підтримує обидва сценарії через ",[3440,6598,6599],{},"IsBodyHtml",[3440,6601,6602],{},"Attachments",[3440,6604,6605],{},"AlternateViews",[5076,6607,6608,6957,7446],{},[5079,6609,6611],{"label":6610},"HTML-лист (IsBodyHtml)",[3433,6612,6614],{"className":5084,"code":6613,"language":5086,"meta":5087,"style":3438},"using System.Net;\nusing System.Net.Mail;\nusing System.Text;\n\nusing var smtp = new SmtpClient(\"smtp.gmail.com\")\n{\n    Port = 587,\n    EnableSsl = true,\n    Credentials = new NetworkCredential(\"alice@gmail.com\", \"app-password\")\n};\n\n\u002F\u002F HTML-тіло листа — SmtpClient встановить Content-Type: text\u002Fhtml; charset=utf-8\nstring htmlBody = \"\"\"\n    \u003C!DOCTYPE html>\n    \u003Chtml lang=\"uk\">\n    \u003Chead>\u003Cmeta charset=\"UTF-8\">\u003C\u002Fhead>\n    \u003Cbody style=\"font-family: Arial, sans-serif; color: #333;\">\n        \u003Ch2 style=\"color: #1a73e8;\">Привіт, Боб!\u003C\u002Fh2>\n        \u003Cp>Це \u003Cstrong>HTML-лист\u003C\u002Fstrong>, надісланий через \u003Cem>.NET 10\u003C\u002Fem>.\u003C\u002Fp>\n        \u003Ctable border=\"1\" cellpadding=\"8\" style=\"border-collapse: collapse;\">\n            \u003Ctr>\u003Cth>Продукт\u003C\u002Fth>\u003Cth>Кількість\u003C\u002Fth>\u003Cth>Ціна\u003C\u002Fth>\u003C\u002Ftr>\n            \u003Ctr>\u003Ctd>Товар A\u003C\u002Ftd>\u003Ctd>5\u003C\u002Ftd>\u003Ctd>250 грн\u003C\u002Ftd>\u003C\u002Ftr>\n            \u003Ctr>\u003Ctd>Товар B\u003C\u002Ftd>\u003Ctd>2\u003C\u002Ftd>\u003Ctd>180 грн\u003C\u002Ftd>\u003C\u002Ftr>\n        \u003C\u002Ftable>\n        \u003Cp style=\"color: #888; font-size: 12px;\">Цей лист згенеровано автоматично.\u003C\u002Fp>\n    \u003C\u002Fbody>\n    \u003C\u002Fhtml>\n    \"\"\";\n\nusing var message = new MailMessage\n{\n    From = new MailAddress(\"alice@gmail.com\", \"Alice\"),\n    Subject = \"Замовлення #12345\",\n    Body = htmlBody,\n    IsBodyHtml = true,    \u002F\u002F Content-Type: text\u002Fhtml\n    BodyEncoding = Encoding.UTF8\n};\n\nmessage.To.Add(\"bob@example.com\");\nawait smtp.SendMailAsync(message);\n",[3440,6615,6616,6628,6644,6656,6660,6680,6684,6694,6704,6724,6728,6732,6737,6748,6753,6758,6763,6768,6773,6778,6783,6788,6793,6798,6803,6808,6813,6818,6825,6829,6843,6847,6867,6878,6889,6903,6915,6919,6923,6941],{"__ignoreMap":3438},[3443,6617,6618,6620,6622,6624,6626],{"class":3445,"line":3446},[3443,6619,5095],{"class":5094},[3443,6621,5099],{"class":5098},[3443,6623,3692],{"class":5102},[3443,6625,5105],{"class":5098},[3443,6627,5108],{"class":5102},[3443,6629,6630,6632,6634,6636,6638,6640,6642],{"class":3445,"line":3452},[3443,6631,5095],{"class":5094},[3443,6633,5099],{"class":5098},[3443,6635,3692],{"class":5102},[3443,6637,5105],{"class":5098},[3443,6639,3692],{"class":5102},[3443,6641,5123],{"class":5098},[3443,6643,5108],{"class":5102},[3443,6645,6646,6648,6650,6652,6654],{"class":3445,"line":3458},[3443,6647,5095],{"class":5094},[3443,6649,5099],{"class":5098},[3443,6651,3692],{"class":5102},[3443,6653,5424],{"class":5098},[3443,6655,5108],{"class":5102},[3443,6657,6658],{"class":3445,"line":3464},[3443,6659,3468],{"emptyLinePlaceholder":3467},[3443,6661,6662,6664,6666,6668,6670,6672,6674,6676,6678],{"class":3445,"line":3471},[3443,6663,5095],{"class":5094},[3443,6665,5143],{"class":5142},[3443,6667,6230],{"class":5146},[3443,6669,5150],{"class":5102},[3443,6671,5153],{"class":5142},[3443,6673,5156],{"class":5098},[3443,6675,5159],{"class":5102},[3443,6677,5163],{"class":5162},[3443,6679,5166],{"class":5102},[3443,6681,6682],{"class":3445,"line":3477},[3443,6683,5171],{"class":5102},[3443,6685,6686,6688,6690,6692],{"class":3445,"line":3483},[3443,6687,5176],{"class":5146},[3443,6689,5150],{"class":5102},[3443,6691,3896],{"class":5181},[3443,6693,5220],{"class":5102},[3443,6695,6696,6698,6700,6702],{"class":3445,"line":3489},[3443,6697,5192],{"class":5146},[3443,6699,5150],{"class":5102},[3443,6701,5197],{"class":5142},[3443,6703,5220],{"class":5102},[3443,6705,6706,6708,6710,6712,6714,6716,6718,6720,6722],{"class":3445,"line":3495},[3443,6707,5237],{"class":5146},[3443,6709,5150],{"class":5102},[3443,6711,5153],{"class":5142},[3443,6713,5244],{"class":5098},[3443,6715,5159],{"class":5102},[3443,6717,5258],{"class":5162},[3443,6719,3668],{"class":5102},[3443,6721,5729],{"class":5162},[3443,6723,5166],{"class":5102},[3443,6725,6726],{"class":3445,"line":3501},[3443,6727,5283],{"class":5102},[3443,6729,6730],{"class":3445,"line":3507},[3443,6731,3468],{"emptyLinePlaceholder":3467},[3443,6733,6734],{"class":3445,"line":3513},[3443,6735,6736],{"class":5134},"\u002F\u002F HTML-тіло листа — SmtpClient встановить Content-Type: text\u002Fhtml; charset=utf-8\n",[3443,6738,6739,6741,6744,6746],{"class":3445,"line":3518},[3443,6740,5627],{"class":5142},[3443,6742,6743],{"class":5146}," htmlBody",[3443,6745,5150],{"class":5102},[3443,6747,5358],{"class":5162},[3443,6749,6750],{"class":3445,"line":3524},[3443,6751,6752],{"class":5162},"    \u003C!DOCTYPE html>\n",[3443,6754,6755],{"class":3445,"line":3530},[3443,6756,6757],{"class":5162},"    \u003Chtml lang=\"uk\">\n",[3443,6759,6760],{"class":3445,"line":3536},[3443,6761,6762],{"class":5162},"    \u003Chead>\u003Cmeta charset=\"UTF-8\">\u003C\u002Fhead>\n",[3443,6764,6765],{"class":3445,"line":3542},[3443,6766,6767],{"class":5162},"    \u003Cbody style=\"font-family: Arial, sans-serif; color: #333;\">\n",[3443,6769,6770],{"class":3445,"line":3548},[3443,6771,6772],{"class":5162},"        \u003Ch2 style=\"color: #1a73e8;\">Привіт, Боб!\u003C\u002Fh2>\n",[3443,6774,6775],{"class":3445,"line":3554},[3443,6776,6777],{"class":5162},"        \u003Cp>Це \u003Cstrong>HTML-лист\u003C\u002Fstrong>, надісланий через \u003Cem>.NET 10\u003C\u002Fem>.\u003C\u002Fp>\n",[3443,6779,6780],{"class":3445,"line":3559},[3443,6781,6782],{"class":5162},"        \u003Ctable border=\"1\" cellpadding=\"8\" style=\"border-collapse: collapse;\">\n",[3443,6784,6785],{"class":3445,"line":3565},[3443,6786,6787],{"class":5162},"            \u003Ctr>\u003Cth>Продукт\u003C\u002Fth>\u003Cth>Кількість\u003C\u002Fth>\u003Cth>Ціна\u003C\u002Fth>\u003C\u002Ftr>\n",[3443,6789,6790],{"class":3445,"line":3571},[3443,6791,6792],{"class":5162},"            \u003Ctr>\u003Ctd>Товар A\u003C\u002Ftd>\u003Ctd>5\u003C\u002Ftd>\u003Ctd>250 грн\u003C\u002Ftd>\u003C\u002Ftr>\n",[3443,6794,6795],{"class":3445,"line":3577},[3443,6796,6797],{"class":5162},"            \u003Ctr>\u003Ctd>Товар B\u003C\u002Ftd>\u003Ctd>2\u003C\u002Ftd>\u003Ctd>180 грн\u003C\u002Ftd>\u003C\u002Ftr>\n",[3443,6799,6800],{"class":3445,"line":3583},[3443,6801,6802],{"class":5162},"        \u003C\u002Ftable>\n",[3443,6804,6805],{"class":3445,"line":3589},[3443,6806,6807],{"class":5162},"        \u003Cp style=\"color: #888; font-size: 12px;\">Цей лист згенеровано автоматично.\u003C\u002Fp>\n",[3443,6809,6810],{"class":3445,"line":3595},[3443,6811,6812],{"class":5162},"    \u003C\u002Fbody>\n",[3443,6814,6815],{"class":3445,"line":3600},[3443,6816,6817],{"class":5162},"    \u003C\u002Fhtml>\n",[3443,6819,6820,6823],{"class":3445,"line":4077},[3443,6821,6822],{"class":5162},"    \"\"\"",[3443,6824,5108],{"class":5102},[3443,6826,6827],{"class":3445,"line":4083},[3443,6828,3468],{"emptyLinePlaceholder":3467},[3443,6830,6831,6833,6835,6837,6839,6841],{"class":3445,"line":4089},[3443,6832,5095],{"class":5094},[3443,6834,5143],{"class":5142},[3443,6836,5301],{"class":5146},[3443,6838,5150],{"class":5102},[3443,6840,5153],{"class":5142},[3443,6842,5308],{"class":5098},[3443,6844,6845],{"class":3445,"line":4094},[3443,6846,5171],{"class":5102},[3443,6848,6849,6851,6853,6855,6857,6859,6861,6863,6865],{"class":3445,"line":4100},[3443,6850,5317],{"class":5146},[3443,6852,5150],{"class":5102},[3443,6854,5153],{"class":5142},[3443,6856,5324],{"class":5098},[3443,6858,5159],{"class":5102},[3443,6860,5258],{"class":5162},[3443,6862,3668],{"class":5102},[3443,6864,5333],{"class":5162},[3443,6866,5336],{"class":5102},[3443,6868,6869,6871,6873,6876],{"class":3445,"line":4106},[3443,6870,5341],{"class":5146},[3443,6872,5150],{"class":5102},[3443,6874,6875],{"class":5162},"\"Замовлення #12345\"",[3443,6877,5220],{"class":5102},[3443,6879,6880,6882,6884,6887],{"class":3445,"line":4111},[3443,6881,5353],{"class":5146},[3443,6883,5150],{"class":5102},[3443,6885,6886],{"class":5146},"htmlBody",[3443,6888,5220],{"class":5102},[3443,6890,6891,6893,6895,6897,6900],{"class":3445,"line":4117},[3443,6892,5399],{"class":5146},[3443,6894,5150],{"class":5102},[3443,6896,5197],{"class":5142},[3443,6898,6899],{"class":5102},",    ",[3443,6901,6902],{"class":5134},"\u002F\u002F Content-Type: text\u002Fhtml\n",[3443,6904,6905,6907,6909,6911,6913],{"class":3445,"line":4122},[3443,6906,5414],{"class":5146},[3443,6908,5150],{"class":5102},[3443,6910,5429],{"class":5146},[3443,6912,3692],{"class":5102},[3443,6914,5458],{"class":5146},[3443,6916,6917],{"class":3445,"line":4127},[3443,6918,5283],{"class":5102},[3443,6920,6921],{"class":3445,"line":4133},[3443,6922,3468],{"emptyLinePlaceholder":3467},[3443,6924,6925,6927,6929,6931,6933,6935,6937,6939],{"class":3445,"line":4139},[3443,6926,5471],{"class":5146},[3443,6928,3692],{"class":5102},[3443,6930,4630],{"class":5146},[3443,6932,3692],{"class":5102},[3443,6934,5481],{"class":5480},[3443,6936,5159],{"class":5102},[3443,6938,5492],{"class":5162},[3443,6940,5549],{"class":5102},[3443,6942,6943,6945,6947,6949,6951,6953,6955],{"class":3445,"line":4145},[3443,6944,6163],{"class":5142},[3443,6946,6230],{"class":5146},[3443,6948,3692],{"class":5102},[3443,6950,5896],{"class":5480},[3443,6952,5159],{"class":5102},[3443,6954,5471],{"class":5146},[3443,6956,5549],{"class":5102},[5079,6958,6960],{"label":6959},"Вкладення файлів",[3433,6961,6963],{"className":5084,"code":6962,"language":5086,"meta":5087,"style":3438},"using System.Net;\nusing System.Net.Mail;\n\nusing var smtp = new SmtpClient(\"smtp.gmail.com\")\n{\n    Port = 587,\n    EnableSsl = true,\n    Credentials = new NetworkCredential(\"alice@gmail.com\", \"app-password\")\n};\n\n\u002F\u002F Attachment реалізує IDisposable — явно звільняємо ресурси\nusing var pdfAttachment = new Attachment(\n    fileName: \"\u002Freports\u002Fmonthly_report.pdf\",\n    mediaType: \"application\u002Fpdf\"\n);\n\n\u002F\u002F Налаштовуємо ім'я файлу у заголовках MIME (Content-Disposition)\npdfAttachment.ContentDisposition!.FileName = \"Звіт_травень_2025.pdf\";\npdfAttachment.ContentDisposition.Inline = false; \u002F\u002F false = вкладення, true = inline\n\n\u002F\u002F Attachment із потоку (для динамічно згенерованих файлів)\nbyte[] csvData = System.Text.Encoding.UTF8.GetBytes(\"Name,Value\\nA,1\\nB,2\");\nusing var csvStream = new MemoryStream(csvData);\nusing var csvAttachment = new Attachment(csvStream, \"data.csv\", \"text\u002Fcsv\");\n\nusing var message = new MailMessage\n{\n    From = new MailAddress(\"alice@gmail.com\", \"Alice\"),\n    Subject = \"Місячний звіт — травень 2025\",\n    Body = \"Привіт! У вкладенні — звіт та таблиця даних.\",\n    IsBodyHtml = false\n};\n\nmessage.To.Add(\"ceo@company.com\");\nmessage.Attachments.Add(pdfAttachment);\nmessage.Attachments.Add(csvAttachment);\n\nawait smtp.SendMailAsync(message);\n\u002F\u002F Після відправки: Attachment та MemoryStream ще живі до виходу з using-блоку\n",[3440,6964,6965,6977,6993,6997,7017,7021,7031,7041,7061,7065,7069,7074,7092,7104,7114,7118,7122,7127,7150,7172,7176,7181,7232,7254,7286,7290,7304,7308,7328,7339,7350,7358,7362,7366,7384,7402,7421,7425,7441],{"__ignoreMap":3438},[3443,6966,6967,6969,6971,6973,6975],{"class":3445,"line":3446},[3443,6968,5095],{"class":5094},[3443,6970,5099],{"class":5098},[3443,6972,3692],{"class":5102},[3443,6974,5105],{"class":5098},[3443,6976,5108],{"class":5102},[3443,6978,6979,6981,6983,6985,6987,6989,6991],{"class":3445,"line":3452},[3443,6980,5095],{"class":5094},[3443,6982,5099],{"class":5098},[3443,6984,3692],{"class":5102},[3443,6986,5105],{"class":5098},[3443,6988,3692],{"class":5102},[3443,6990,5123],{"class":5098},[3443,6992,5108],{"class":5102},[3443,6994,6995],{"class":3445,"line":3458},[3443,6996,3468],{"emptyLinePlaceholder":3467},[3443,6998,6999,7001,7003,7005,7007,7009,7011,7013,7015],{"class":3445,"line":3464},[3443,7000,5095],{"class":5094},[3443,7002,5143],{"class":5142},[3443,7004,6230],{"class":5146},[3443,7006,5150],{"class":5102},[3443,7008,5153],{"class":5142},[3443,7010,5156],{"class":5098},[3443,7012,5159],{"class":5102},[3443,7014,5163],{"class":5162},[3443,7016,5166],{"class":5102},[3443,7018,7019],{"class":3445,"line":3471},[3443,7020,5171],{"class":5102},[3443,7022,7023,7025,7027,7029],{"class":3445,"line":3477},[3443,7024,5176],{"class":5146},[3443,7026,5150],{"class":5102},[3443,7028,3896],{"class":5181},[3443,7030,5220],{"class":5102},[3443,7032,7033,7035,7037,7039],{"class":3445,"line":3483},[3443,7034,5192],{"class":5146},[3443,7036,5150],{"class":5102},[3443,7038,5197],{"class":5142},[3443,7040,5220],{"class":5102},[3443,7042,7043,7045,7047,7049,7051,7053,7055,7057,7059],{"class":3445,"line":3489},[3443,7044,5237],{"class":5146},[3443,7046,5150],{"class":5102},[3443,7048,5153],{"class":5142},[3443,7050,5244],{"class":5098},[3443,7052,5159],{"class":5102},[3443,7054,5258],{"class":5162},[3443,7056,3668],{"class":5102},[3443,7058,5729],{"class":5162},[3443,7060,5166],{"class":5102},[3443,7062,7063],{"class":3445,"line":3495},[3443,7064,5283],{"class":5102},[3443,7066,7067],{"class":3445,"line":3501},[3443,7068,3468],{"emptyLinePlaceholder":3467},[3443,7070,7071],{"class":3445,"line":3507},[3443,7072,7073],{"class":5134},"\u002F\u002F Attachment реалізує IDisposable — явно звільняємо ресурси\n",[3443,7075,7076,7078,7080,7083,7085,7087,7090],{"class":3445,"line":3513},[3443,7077,5095],{"class":5094},[3443,7079,5143],{"class":5142},[3443,7081,7082],{"class":5146}," pdfAttachment",[3443,7084,5150],{"class":5102},[3443,7086,5153],{"class":5142},[3443,7088,7089],{"class":5098}," Attachment",[3443,7091,5247],{"class":5102},[3443,7093,7094,7097,7099,7102],{"class":3445,"line":3518},[3443,7095,7096],{"class":5146},"    fileName",[3443,7098,5255],{"class":5102},[3443,7100,7101],{"class":5162},"\"\u002Freports\u002Fmonthly_report.pdf\"",[3443,7103,5220],{"class":5102},[3443,7105,7106,7109,7111],{"class":3445,"line":3524},[3443,7107,7108],{"class":5146},"    mediaType",[3443,7110,5255],{"class":5102},[3443,7112,7113],{"class":5162},"\"application\u002Fpdf\"\n",[3443,7115,7116],{"class":3445,"line":3530},[3443,7117,5549],{"class":5102},[3443,7119,7120],{"class":3445,"line":3536},[3443,7121,3468],{"emptyLinePlaceholder":3467},[3443,7123,7124],{"class":3445,"line":3542},[3443,7125,7126],{"class":5134},"\u002F\u002F Налаштовуємо ім'я файлу у заголовках MIME (Content-Disposition)\n",[3443,7128,7129,7132,7134,7137,7140,7143,7145,7148],{"class":3445,"line":3548},[3443,7130,7131],{"class":5146},"pdfAttachment",[3443,7133,3692],{"class":5102},[3443,7135,7136],{"class":5146},"ContentDisposition",[3443,7138,7139],{"class":5102},"!.",[3443,7141,7142],{"class":5146},"FileName",[3443,7144,5150],{"class":5102},[3443,7146,7147],{"class":5162},"\"Звіт_травень_2025.pdf\"",[3443,7149,5108],{"class":5102},[3443,7151,7152,7154,7156,7158,7160,7163,7165,7167,7169],{"class":3445,"line":3554},[3443,7153,7131],{"class":5146},[3443,7155,3692],{"class":5102},[3443,7157,7136],{"class":5146},[3443,7159,3692],{"class":5102},[3443,7161,7162],{"class":5146},"Inline",[3443,7164,5150],{"class":5102},[3443,7166,5230],{"class":5142},[3443,7168,6138],{"class":5102},[3443,7170,7171],{"class":5134},"\u002F\u002F false = вкладення, true = inline\n",[3443,7173,7174],{"class":3445,"line":3559},[3443,7175,3468],{"emptyLinePlaceholder":3467},[3443,7177,7178],{"class":3445,"line":3565},[3443,7179,7180],{"class":5134},"\u002F\u002F Attachment із потоку (для динамічно згенерованих файлів)\n",[3443,7182,7183,7186,7189,7192,7194,7196,7198,7200,7202,7204,7206,7208,7210,7213,7215,7218,7222,7225,7227,7230],{"class":3445,"line":3571},[3443,7184,7185],{"class":5142},"byte",[3443,7187,7188],{"class":5102},"[] ",[3443,7190,7191],{"class":5146},"csvData",[3443,7193,5150],{"class":5102},[3443,7195,5419],{"class":5146},[3443,7197,3692],{"class":5102},[3443,7199,5424],{"class":5146},[3443,7201,3692],{"class":5102},[3443,7203,5429],{"class":5146},[3443,7205,3692],{"class":5102},[3443,7207,5434],{"class":5146},[3443,7209,3692],{"class":5102},[3443,7211,7212],{"class":5480},"GetBytes",[3443,7214,5159],{"class":5102},[3443,7216,7217],{"class":5162},"\"Name,Value",[3443,7219,7221],{"class":7220},"sjcCO","\\n",[3443,7223,7224],{"class":5162},"A,1",[3443,7226,7221],{"class":7220},[3443,7228,7229],{"class":5162},"B,2\"",[3443,7231,5549],{"class":5102},[3443,7233,7234,7236,7238,7241,7243,7245,7248,7250,7252],{"class":3445,"line":3577},[3443,7235,5095],{"class":5094},[3443,7237,5143],{"class":5142},[3443,7239,7240],{"class":5146}," csvStream",[3443,7242,5150],{"class":5102},[3443,7244,5153],{"class":5142},[3443,7246,7247],{"class":5098}," MemoryStream",[3443,7249,5159],{"class":5102},[3443,7251,7191],{"class":5146},[3443,7253,5549],{"class":5102},[3443,7255,7256,7258,7260,7263,7265,7267,7269,7271,7274,7276,7279,7281,7284],{"class":3445,"line":3583},[3443,7257,5095],{"class":5094},[3443,7259,5143],{"class":5142},[3443,7261,7262],{"class":5146}," csvAttachment",[3443,7264,5150],{"class":5102},[3443,7266,5153],{"class":5142},[3443,7268,7089],{"class":5098},[3443,7270,5159],{"class":5102},[3443,7272,7273],{"class":5146},"csvStream",[3443,7275,3668],{"class":5102},[3443,7277,7278],{"class":5162},"\"data.csv\"",[3443,7280,3668],{"class":5102},[3443,7282,7283],{"class":5162},"\"text\u002Fcsv\"",[3443,7285,5549],{"class":5102},[3443,7287,7288],{"class":3445,"line":3589},[3443,7289,3468],{"emptyLinePlaceholder":3467},[3443,7291,7292,7294,7296,7298,7300,7302],{"class":3445,"line":3595},[3443,7293,5095],{"class":5094},[3443,7295,5143],{"class":5142},[3443,7297,5301],{"class":5146},[3443,7299,5150],{"class":5102},[3443,7301,5153],{"class":5142},[3443,7303,5308],{"class":5098},[3443,7305,7306],{"class":3445,"line":3600},[3443,7307,5171],{"class":5102},[3443,7309,7310,7312,7314,7316,7318,7320,7322,7324,7326],{"class":3445,"line":4077},[3443,7311,5317],{"class":5146},[3443,7313,5150],{"class":5102},[3443,7315,5153],{"class":5142},[3443,7317,5324],{"class":5098},[3443,7319,5159],{"class":5102},[3443,7321,5258],{"class":5162},[3443,7323,3668],{"class":5102},[3443,7325,5333],{"class":5162},[3443,7327,5336],{"class":5102},[3443,7329,7330,7332,7334,7337],{"class":3445,"line":4083},[3443,7331,5341],{"class":5146},[3443,7333,5150],{"class":5102},[3443,7335,7336],{"class":5162},"\"Місячний звіт — травень 2025\"",[3443,7338,5220],{"class":5102},[3443,7340,7341,7343,7345,7348],{"class":3445,"line":4089},[3443,7342,5353],{"class":5146},[3443,7344,5150],{"class":5102},[3443,7346,7347],{"class":5162},"\"Привіт! У вкладенні — звіт та таблиця даних.\"",[3443,7349,5220],{"class":5102},[3443,7351,7352,7354,7356],{"class":3445,"line":4094},[3443,7353,5399],{"class":5146},[3443,7355,5150],{"class":5102},[3443,7357,6367],{"class":5142},[3443,7359,7360],{"class":3445,"line":4100},[3443,7361,5283],{"class":5102},[3443,7363,7364],{"class":3445,"line":4106},[3443,7365,3468],{"emptyLinePlaceholder":3467},[3443,7367,7368,7370,7372,7374,7376,7378,7380,7382],{"class":3445,"line":4111},[3443,7369,5471],{"class":5146},[3443,7371,3692],{"class":5102},[3443,7373,4630],{"class":5146},[3443,7375,3692],{"class":5102},[3443,7377,5481],{"class":5480},[3443,7379,5159],{"class":5102},[3443,7381,6403],{"class":5162},[3443,7383,5549],{"class":5102},[3443,7385,7386,7388,7390,7392,7394,7396,7398,7400],{"class":3445,"line":4117},[3443,7387,5471],{"class":5146},[3443,7389,3692],{"class":5102},[3443,7391,6602],{"class":5146},[3443,7393,3692],{"class":5102},[3443,7395,5481],{"class":5480},[3443,7397,5159],{"class":5102},[3443,7399,7131],{"class":5146},[3443,7401,5549],{"class":5102},[3443,7403,7404,7406,7408,7410,7412,7414,7416,7419],{"class":3445,"line":4122},[3443,7405,5471],{"class":5146},[3443,7407,3692],{"class":5102},[3443,7409,6602],{"class":5146},[3443,7411,3692],{"class":5102},[3443,7413,5481],{"class":5480},[3443,7415,5159],{"class":5102},[3443,7417,7418],{"class":5146},"csvAttachment",[3443,7420,5549],{"class":5102},[3443,7422,7423],{"class":3445,"line":4127},[3443,7424,3468],{"emptyLinePlaceholder":3467},[3443,7426,7427,7429,7431,7433,7435,7437,7439],{"class":3445,"line":4133},[3443,7428,6163],{"class":5142},[3443,7430,6230],{"class":5146},[3443,7432,3692],{"class":5102},[3443,7434,5896],{"class":5480},[3443,7436,5159],{"class":5102},[3443,7438,5471],{"class":5146},[3443,7440,5549],{"class":5102},[3443,7442,7443],{"class":3445,"line":4139},[3443,7444,7445],{"class":5134},"\u002F\u002F Після відправки: Attachment та MemoryStream ще живі до виходу з using-блоку\n",[5079,7447,7449],{"label":7448},"Inline-зображення (CID)",[3433,7450,7452],{"className":5084,"code":7451,"language":5086,"meta":5087,"style":3438},"using System.Net;\nusing System.Net.Mail;\nusing System.Net.Mime;\n\n\u002F\u002F Inline-зображення: вбудовані у HTML через Content-ID (cid:)\n\u002F\u002F MIME-структура: multipart\u002Frelated → [text\u002Fhtml + image\u002Fpng]\nusing var smtp = new SmtpClient(\"smtp.gmail.com\")\n{\n    Port = 587,\n    EnableSsl = true,\n    Credentials = new NetworkCredential(\"alice@gmail.com\", \"app-password\")\n};\n\n\u002F\u002F 1. Створюємо HTML-подання із посиланням cid:logo\nstring htmlBody = \"\"\"\n    \u003Chtml>\u003Cbody>\n        \u003Cimg src=\"cid:logo_image\" alt=\"Логотип\" width=\"200\"\u002F>\u003Cbr\u002F>\n        \u003Ch2>Ласкаво просимо!\u003C\u002Fh2>\n        \u003Cp>Цей лист містить вбудоване зображення.\u003C\u002Fp>\n    \u003C\u002Fbody>\u003C\u002Fhtml>\n    \"\"\";\n\n\u002F\u002F 2. AlternateView для HTML-частини\nAlternateView htmlView = AlternateView.CreateAlternateViewFromString(\n    htmlBody,\n    encoding: System.Text.Encoding.UTF8,\n    mediaType: \"text\u002Fhtml\"\n);\n\n\u002F\u002F 3. LinkedResource — прив'язуємо зображення через ContentId\nusing var logoResource = new LinkedResource(\"\u002Fassets\u002Flogo.png\", \"image\u002Fpng\")\n{\n    ContentId = \"logo_image\",    \u002F\u002F Відповідає cid:logo_image у HTML\n    TransferEncoding = TransferEncoding.Base64\n};\n\nhtmlView.LinkedResources.Add(logoResource);\n\n\u002F\u002F 4. Текстова альтернатива (для клієнтів без HTML)\nAlternateView plainView = AlternateView.CreateAlternateViewFromString(\n    \"Ласкаво просимо! Ваш поштовий клієнт не підтримує HTML.\",\n    encoding: System.Text.Encoding.UTF8,\n    mediaType: \"text\u002Fplain\"\n);\n\nusing var message = new MailMessage\n{\n    From = new MailAddress(\"alice@gmail.com\", \"Alice\"),\n    Subject = \"Лист із вбудованим логотипом\"\n};\n\nmessage.To.Add(\"bob@example.com\");\n\n\u002F\u002F Порядок: plain перед html — клієнт обирає останній підтримуваний\nmessage.AlternateViews.Add(plainView);\nmessage.AlternateViews.Add(htmlView);\n\nawait smtp.SendMailAsync(message);\n",[3440,7453,7454,7466,7482,7499,7503,7508,7513,7533,7537,7547,7557,7577,7581,7585,7590,7600,7605,7610,7615,7620,7625,7631,7635,7640,7658,7665,7688,7697,7701,7705,7710,7738,7742,7757,7772,7776,7780,7801,7805,7810,7827,7834,7856,7865,7869,7873,7887,7891,7911,7920,7924,7928,7946,7950,7955,7974,7992,7997],{"__ignoreMap":3438},[3443,7455,7456,7458,7460,7462,7464],{"class":3445,"line":3446},[3443,7457,5095],{"class":5094},[3443,7459,5099],{"class":5098},[3443,7461,3692],{"class":5102},[3443,7463,5105],{"class":5098},[3443,7465,5108],{"class":5102},[3443,7467,7468,7470,7472,7474,7476,7478,7480],{"class":3445,"line":3452},[3443,7469,5095],{"class":5094},[3443,7471,5099],{"class":5098},[3443,7473,3692],{"class":5102},[3443,7475,5105],{"class":5098},[3443,7477,3692],{"class":5102},[3443,7479,5123],{"class":5098},[3443,7481,5108],{"class":5102},[3443,7483,7484,7486,7488,7490,7492,7494,7497],{"class":3445,"line":3458},[3443,7485,5095],{"class":5094},[3443,7487,5099],{"class":5098},[3443,7489,3692],{"class":5102},[3443,7491,5105],{"class":5098},[3443,7493,3692],{"class":5102},[3443,7495,7496],{"class":5098},"Mime",[3443,7498,5108],{"class":5102},[3443,7500,7501],{"class":3445,"line":3464},[3443,7502,3468],{"emptyLinePlaceholder":3467},[3443,7504,7505],{"class":3445,"line":3471},[3443,7506,7507],{"class":5134},"\u002F\u002F Inline-зображення: вбудовані у HTML через Content-ID (cid:)\n",[3443,7509,7510],{"class":3445,"line":3477},[3443,7511,7512],{"class":5134},"\u002F\u002F MIME-структура: multipart\u002Frelated → [text\u002Fhtml + image\u002Fpng]\n",[3443,7514,7515,7517,7519,7521,7523,7525,7527,7529,7531],{"class":3445,"line":3483},[3443,7516,5095],{"class":5094},[3443,7518,5143],{"class":5142},[3443,7520,6230],{"class":5146},[3443,7522,5150],{"class":5102},[3443,7524,5153],{"class":5142},[3443,7526,5156],{"class":5098},[3443,7528,5159],{"class":5102},[3443,7530,5163],{"class":5162},[3443,7532,5166],{"class":5102},[3443,7534,7535],{"class":3445,"line":3489},[3443,7536,5171],{"class":5102},[3443,7538,7539,7541,7543,7545],{"class":3445,"line":3495},[3443,7540,5176],{"class":5146},[3443,7542,5150],{"class":5102},[3443,7544,3896],{"class":5181},[3443,7546,5220],{"class":5102},[3443,7548,7549,7551,7553,7555],{"class":3445,"line":3501},[3443,7550,5192],{"class":5146},[3443,7552,5150],{"class":5102},[3443,7554,5197],{"class":5142},[3443,7556,5220],{"class":5102},[3443,7558,7559,7561,7563,7565,7567,7569,7571,7573,7575],{"class":3445,"line":3507},[3443,7560,5237],{"class":5146},[3443,7562,5150],{"class":5102},[3443,7564,5153],{"class":5142},[3443,7566,5244],{"class":5098},[3443,7568,5159],{"class":5102},[3443,7570,5258],{"class":5162},[3443,7572,3668],{"class":5102},[3443,7574,5729],{"class":5162},[3443,7576,5166],{"class":5102},[3443,7578,7579],{"class":3445,"line":3513},[3443,7580,5283],{"class":5102},[3443,7582,7583],{"class":3445,"line":3518},[3443,7584,3468],{"emptyLinePlaceholder":3467},[3443,7586,7587],{"class":3445,"line":3524},[3443,7588,7589],{"class":5134},"\u002F\u002F 1. Створюємо HTML-подання із посиланням cid:logo\n",[3443,7591,7592,7594,7596,7598],{"class":3445,"line":3530},[3443,7593,5627],{"class":5142},[3443,7595,6743],{"class":5146},[3443,7597,5150],{"class":5102},[3443,7599,5358],{"class":5162},[3443,7601,7602],{"class":3445,"line":3536},[3443,7603,7604],{"class":5162},"    \u003Chtml>\u003Cbody>\n",[3443,7606,7607],{"class":3445,"line":3542},[3443,7608,7609],{"class":5162},"        \u003Cimg src=\"cid:logo_image\" alt=\"Логотип\" width=\"200\"\u002F>\u003Cbr\u002F>\n",[3443,7611,7612],{"class":3445,"line":3548},[3443,7613,7614],{"class":5162},"        \u003Ch2>Ласкаво просимо!\u003C\u002Fh2>\n",[3443,7616,7617],{"class":3445,"line":3554},[3443,7618,7619],{"class":5162},"        \u003Cp>Цей лист містить вбудоване зображення.\u003C\u002Fp>\n",[3443,7621,7622],{"class":3445,"line":3559},[3443,7623,7624],{"class":5162},"    \u003C\u002Fbody>\u003C\u002Fhtml>\n",[3443,7626,7627,7629],{"class":3445,"line":3565},[3443,7628,6822],{"class":5162},[3443,7630,5108],{"class":5102},[3443,7632,7633],{"class":3445,"line":3571},[3443,7634,3468],{"emptyLinePlaceholder":3467},[3443,7636,7637],{"class":3445,"line":3577},[3443,7638,7639],{"class":5134},"\u002F\u002F 2. AlternateView для HTML-частини\n",[3443,7641,7642,7644,7647,7649,7651,7653,7656],{"class":3445,"line":3583},[3443,7643,5056],{"class":5098},[3443,7645,7646],{"class":5146}," htmlView",[3443,7648,5150],{"class":5102},[3443,7650,5056],{"class":5146},[3443,7652,3692],{"class":5102},[3443,7654,7655],{"class":5480},"CreateAlternateViewFromString",[3443,7657,5247],{"class":5102},[3443,7659,7660,7663],{"class":3445,"line":3589},[3443,7661,7662],{"class":5146},"    htmlBody",[3443,7664,5220],{"class":5102},[3443,7666,7667,7670,7672,7674,7676,7678,7680,7682,7684,7686],{"class":3445,"line":3595},[3443,7668,7669],{"class":5146},"    encoding",[3443,7671,5255],{"class":5102},[3443,7673,5419],{"class":5146},[3443,7675,3692],{"class":5102},[3443,7677,5424],{"class":5146},[3443,7679,3692],{"class":5102},[3443,7681,5429],{"class":5146},[3443,7683,3692],{"class":5102},[3443,7685,5434],{"class":5146},[3443,7687,5220],{"class":5102},[3443,7689,7690,7692,7694],{"class":3445,"line":3600},[3443,7691,7108],{"class":5146},[3443,7693,5255],{"class":5102},[3443,7695,7696],{"class":5162},"\"text\u002Fhtml\"\n",[3443,7698,7699],{"class":3445,"line":4077},[3443,7700,5549],{"class":5102},[3443,7702,7703],{"class":3445,"line":4083},[3443,7704,3468],{"emptyLinePlaceholder":3467},[3443,7706,7707],{"class":3445,"line":4089},[3443,7708,7709],{"class":5134},"\u002F\u002F 3. LinkedResource — прив'язуємо зображення через ContentId\n",[3443,7711,7712,7714,7716,7719,7721,7723,7726,7728,7731,7733,7736],{"class":3445,"line":4094},[3443,7713,5095],{"class":5094},[3443,7715,5143],{"class":5142},[3443,7717,7718],{"class":5146}," logoResource",[3443,7720,5150],{"class":5102},[3443,7722,5153],{"class":5142},[3443,7724,7725],{"class":5098}," LinkedResource",[3443,7727,5159],{"class":5102},[3443,7729,7730],{"class":5162},"\"\u002Fassets\u002Flogo.png\"",[3443,7732,3668],{"class":5102},[3443,7734,7735],{"class":5162},"\"image\u002Fpng\"",[3443,7737,5166],{"class":5102},[3443,7739,7740],{"class":3445,"line":4100},[3443,7741,5171],{"class":5102},[3443,7743,7744,7747,7749,7752,7754],{"class":3445,"line":4106},[3443,7745,7746],{"class":5146},"    ContentId",[3443,7748,5150],{"class":5102},[3443,7750,7751],{"class":5162},"\"logo_image\"",[3443,7753,6899],{"class":5102},[3443,7755,7756],{"class":5134},"\u002F\u002F Відповідає cid:logo_image у HTML\n",[3443,7758,7759,7762,7764,7767,7769],{"class":3445,"line":4111},[3443,7760,7761],{"class":5146},"    TransferEncoding",[3443,7763,5150],{"class":5102},[3443,7765,7766],{"class":5146},"TransferEncoding",[3443,7768,3692],{"class":5102},[3443,7770,7771],{"class":5146},"Base64\n",[3443,7773,7774],{"class":3445,"line":4117},[3443,7775,5283],{"class":5102},[3443,7777,7778],{"class":3445,"line":4122},[3443,7779,3468],{"emptyLinePlaceholder":3467},[3443,7781,7782,7785,7787,7790,7792,7794,7796,7799],{"class":3445,"line":4127},[3443,7783,7784],{"class":5146},"htmlView",[3443,7786,3692],{"class":5102},[3443,7788,7789],{"class":5146},"LinkedResources",[3443,7791,3692],{"class":5102},[3443,7793,5481],{"class":5480},[3443,7795,5159],{"class":5102},[3443,7797,7798],{"class":5146},"logoResource",[3443,7800,5549],{"class":5102},[3443,7802,7803],{"class":3445,"line":4133},[3443,7804,3468],{"emptyLinePlaceholder":3467},[3443,7806,7807],{"class":3445,"line":4139},[3443,7808,7809],{"class":5134},"\u002F\u002F 4. Текстова альтернатива (для клієнтів без HTML)\n",[3443,7811,7812,7814,7817,7819,7821,7823,7825],{"class":3445,"line":4145},[3443,7813,5056],{"class":5098},[3443,7815,7816],{"class":5146}," plainView",[3443,7818,5150],{"class":5102},[3443,7820,5056],{"class":5146},[3443,7822,3692],{"class":5102},[3443,7824,7655],{"class":5480},[3443,7826,5247],{"class":5102},[3443,7828,7829,7832],{"class":3445,"line":4150},[3443,7830,7831],{"class":5162},"    \"Ласкаво просимо! Ваш поштовий клієнт не підтримує HTML.\"",[3443,7833,5220],{"class":5102},[3443,7835,7836,7838,7840,7842,7844,7846,7848,7850,7852,7854],{"class":3445,"line":4156},[3443,7837,7669],{"class":5146},[3443,7839,5255],{"class":5102},[3443,7841,5419],{"class":5146},[3443,7843,3692],{"class":5102},[3443,7845,5424],{"class":5146},[3443,7847,3692],{"class":5102},[3443,7849,5429],{"class":5146},[3443,7851,3692],{"class":5102},[3443,7853,5434],{"class":5146},[3443,7855,5220],{"class":5102},[3443,7857,7858,7860,7862],{"class":3445,"line":4162},[3443,7859,7108],{"class":5146},[3443,7861,5255],{"class":5102},[3443,7863,7864],{"class":5162},"\"text\u002Fplain\"\n",[3443,7866,7867],{"class":3445,"line":4168},[3443,7868,5549],{"class":5102},[3443,7870,7871],{"class":3445,"line":4174},[3443,7872,3468],{"emptyLinePlaceholder":3467},[3443,7874,7875,7877,7879,7881,7883,7885],{"class":3445,"line":4180},[3443,7876,5095],{"class":5094},[3443,7878,5143],{"class":5142},[3443,7880,5301],{"class":5146},[3443,7882,5150],{"class":5102},[3443,7884,5153],{"class":5142},[3443,7886,5308],{"class":5098},[3443,7888,7889],{"class":3445,"line":4186},[3443,7890,5171],{"class":5102},[3443,7892,7893,7895,7897,7899,7901,7903,7905,7907,7909],{"class":3445,"line":4192},[3443,7894,5317],{"class":5146},[3443,7896,5150],{"class":5102},[3443,7898,5153],{"class":5142},[3443,7900,5324],{"class":5098},[3443,7902,5159],{"class":5102},[3443,7904,5258],{"class":5162},[3443,7906,3668],{"class":5102},[3443,7908,5333],{"class":5162},[3443,7910,5336],{"class":5102},[3443,7912,7913,7915,7917],{"class":3445,"line":4198},[3443,7914,5341],{"class":5146},[3443,7916,5150],{"class":5102},[3443,7918,7919],{"class":5162},"\"Лист із вбудованим логотипом\"\n",[3443,7921,7922],{"class":3445,"line":4204},[3443,7923,5283],{"class":5102},[3443,7925,7926],{"class":3445,"line":4210},[3443,7927,3468],{"emptyLinePlaceholder":3467},[3443,7929,7930,7932,7934,7936,7938,7940,7942,7944],{"class":3445,"line":4215},[3443,7931,5471],{"class":5146},[3443,7933,3692],{"class":5102},[3443,7935,4630],{"class":5146},[3443,7937,3692],{"class":5102},[3443,7939,5481],{"class":5480},[3443,7941,5159],{"class":5102},[3443,7943,5492],{"class":5162},[3443,7945,5549],{"class":5102},[3443,7947,7948],{"class":3445,"line":4221},[3443,7949,3468],{"emptyLinePlaceholder":3467},[3443,7951,7952],{"class":3445,"line":4227},[3443,7953,7954],{"class":5134},"\u002F\u002F Порядок: plain перед html — клієнт обирає останній підтримуваний\n",[3443,7956,7957,7959,7961,7963,7965,7967,7969,7972],{"class":3445,"line":4233},[3443,7958,5471],{"class":5146},[3443,7960,3692],{"class":5102},[3443,7962,6605],{"class":5146},[3443,7964,3692],{"class":5102},[3443,7966,5481],{"class":5480},[3443,7968,5159],{"class":5102},[3443,7970,7971],{"class":5146},"plainView",[3443,7973,5549],{"class":5102},[3443,7975,7976,7978,7980,7982,7984,7986,7988,7990],{"class":3445,"line":4238},[3443,7977,5471],{"class":5146},[3443,7979,3692],{"class":5102},[3443,7981,6605],{"class":5146},[3443,7983,3692],{"class":5102},[3443,7985,5481],{"class":5480},[3443,7987,5159],{"class":5102},[3443,7989,7784],{"class":5146},[3443,7991,5549],{"class":5102},[3443,7993,7995],{"class":3445,"line":7994},57,[3443,7996,3468],{"emptyLinePlaceholder":3467},[3443,7998,8000,8002,8004,8006,8008,8010,8012],{"class":3445,"line":7999},58,[3443,8001,6163],{"class":5142},[3443,8003,6230],{"class":5146},[3443,8005,3692],{"class":5102},[3443,8007,5896],{"class":5480},[3443,8009,5159],{"class":5102},[3443,8011,5471],{"class":5146},[3443,8013,5549],{"class":5102},[3321,8015,8016,8017,8019,8020,8023,8024,8027,8028,8030,8031,8034,8035,8037,8038,8040,8041,8023,8043,5067],{},"При використанні ",[3440,8018,6605],{}," не встановлюйте ",[3440,8021,8022],{},"message.Body"," і ",[3440,8025,8026],{},"message.IsBodyHtml"," — вони конфліктують із ",[3440,8029,6605],{},". Або використовуйте ",[3440,8032,8033],{},"Body","\u002F",[3440,8036,6599],{}," (для простих HTML без inline-зображень), або ",[3440,8039,6605],{}," (для ",[3440,8042,4898],{},[3440,8044,4908],{},[3645,8046],{},[3605,8048,8050],{"id":8049},"конфігурація-smtpclient-через-appsettings","Конфігурація SmtpClient через appsettings",[3317,8052,8053],{},"У реальних застосунках параметри SMTP зберігаються у конфігурації, а не хардкодяться у коді:",[3433,8055,8059],{"className":8056,"code":8057,"language":8058,"meta":3438,"style":3438},"language-json shiki shiki-themes light-plus dark-plus dark-plus","{\n  \"SmtpSettings\": {\n    \"Host\": \"smtp.gmail.com\",\n    \"Port\": 587,\n    \"EnableSsl\": true,\n    \"Username\": \"alice@gmail.com\",\n    \"Password\": \"app-password\",\n    \"FromName\": \"Alice\",\n    \"FromEmail\": \"alice@gmail.com\"\n  }\n}\n","json",[3440,8060,8061,8065,8074,8085,8096,8107,8118,8129,8140,8150,8155],{"__ignoreMap":3438},[3443,8062,8063],{"class":3445,"line":3446},[3443,8064,5171],{"class":5102},[3443,8066,8067,8071],{"class":3445,"line":3452},[3443,8068,8070],{"class":8069},"sLwNe","  \"SmtpSettings\"",[3443,8072,8073],{"class":5102},": {\n",[3443,8075,8076,8079,8081,8083],{"class":3445,"line":3458},[3443,8077,8078],{"class":8069},"    \"Host\"",[3443,8080,5255],{"class":5102},[3443,8082,5163],{"class":5162},[3443,8084,5220],{"class":5102},[3443,8086,8087,8090,8092,8094],{"class":3445,"line":3464},[3443,8088,8089],{"class":8069},"    \"Port\"",[3443,8091,5255],{"class":5102},[3443,8093,3896],{"class":5181},[3443,8095,5220],{"class":5102},[3443,8097,8098,8101,8103,8105],{"class":3445,"line":3471},[3443,8099,8100],{"class":8069},"    \"EnableSsl\"",[3443,8102,5255],{"class":5102},[3443,8104,5197],{"class":5142},[3443,8106,5220],{"class":5102},[3443,8108,8109,8112,8114,8116],{"class":3445,"line":3477},[3443,8110,8111],{"class":8069},"    \"Username\"",[3443,8113,5255],{"class":5102},[3443,8115,5258],{"class":5162},[3443,8117,5220],{"class":5102},[3443,8119,8120,8123,8125,8127],{"class":3445,"line":3483},[3443,8121,8122],{"class":8069},"    \"Password\"",[3443,8124,5255],{"class":5102},[3443,8126,5729],{"class":5162},[3443,8128,5220],{"class":5102},[3443,8130,8131,8134,8136,8138],{"class":3445,"line":3489},[3443,8132,8133],{"class":8069},"    \"FromName\"",[3443,8135,5255],{"class":5102},[3443,8137,5333],{"class":5162},[3443,8139,5220],{"class":5102},[3443,8141,8142,8145,8147],{"class":3445,"line":3495},[3443,8143,8144],{"class":8069},"    \"FromEmail\"",[3443,8146,5255],{"class":5102},[3443,8148,8149],{"class":5162},"\"alice@gmail.com\"\n",[3443,8151,8152],{"class":3445,"line":3501},[3443,8153,8154],{"class":5102},"  }\n",[3443,8156,8157],{"class":3445,"line":3507},[3443,8158,4809],{"class":5102},[3433,8160,8162],{"className":5084,"code":8161,"language":5086,"meta":5087,"style":3438},"using Microsoft.Extensions.Configuration;\nusing System.Net;\nusing System.Net.Mail;\n\n\u002F\u002F Клас налаштувань (зв'язується з секцією SmtpSettings)\npublic record SmtpSettings(\n    string Host,\n    int Port,\n    bool EnableSsl,\n    string Username,\n    string Password,\n    string FromName,\n    string FromEmail\n);\n\n\u002F\u002F Реєстрація у DI-контейнері (Program.cs або Startup.cs)\nbuilder.Services.Configure\u003CSmtpSettings>(\n    builder.Configuration.GetSection(\"SmtpSettings\")\n);\nbuilder.Services.AddTransient\u003CIEmailSender, SmtpEmailSender>();\n\n\u002F\u002F Реалізація сервісу відправки\npublic class SmtpEmailSender(IOptions\u003CSmtpSettings> options) : IEmailSender\n{\n    private readonly SmtpSettings _settings = options.Value;\n\n    public async Task SendAsync(string to, string subject, string htmlBody,\n        CancellationToken ct = default)\n    {\n        using var smtp = new SmtpClient(_settings.Host)\n        {\n            Port = _settings.Port,\n            EnableSsl = _settings.EnableSsl,\n            Credentials = new NetworkCredential(_settings.Username, _settings.Password)\n        };\n\n        using var message = new MailMessage\n        {\n            From = new MailAddress(_settings.FromEmail, _settings.FromName),\n            Subject = subject,\n            Body = htmlBody,\n            IsBodyHtml = true,\n            BodyEncoding = System.Text.Encoding.UTF8\n        };\n\n        message.To.Add(to);\n        await smtp.SendMailAsync(message, ct);\n    }\n}\n",[3440,8163,8164,8183,8195,8211,8215,8220,8233,8243,8253,8263,8272,8281,8290,8297,8301,8305,8310,8334,8355,8359,8385,8389,8394,8425,8429,8453,8457,8491,8506,8510,8537,8542,8558,8574,8605,8610,8614,8628,8632,8663,8674,8685,8696,8717,8721,8725,8745,8766,8770],{"__ignoreMap":3438},[3443,8165,8166,8168,8171,8173,8176,8178,8181],{"class":3445,"line":3446},[3443,8167,5095],{"class":5094},[3443,8169,8170],{"class":5098}," Microsoft",[3443,8172,3692],{"class":5102},[3443,8174,8175],{"class":5098},"Extensions",[3443,8177,3692],{"class":5102},[3443,8179,8180],{"class":5098},"Configuration",[3443,8182,5108],{"class":5102},[3443,8184,8185,8187,8189,8191,8193],{"class":3445,"line":3452},[3443,8186,5095],{"class":5094},[3443,8188,5099],{"class":5098},[3443,8190,3692],{"class":5102},[3443,8192,5105],{"class":5098},[3443,8194,5108],{"class":5102},[3443,8196,8197,8199,8201,8203,8205,8207,8209],{"class":3445,"line":3458},[3443,8198,5095],{"class":5094},[3443,8200,5099],{"class":5098},[3443,8202,3692],{"class":5102},[3443,8204,5105],{"class":5098},[3443,8206,3692],{"class":5102},[3443,8208,5123],{"class":5098},[3443,8210,5108],{"class":5102},[3443,8212,8213],{"class":3445,"line":3464},[3443,8214,3468],{"emptyLinePlaceholder":3467},[3443,8216,8217],{"class":3445,"line":3471},[3443,8218,8219],{"class":5134},"\u002F\u002F Клас налаштувань (зв'язується з секцією SmtpSettings)\n",[3443,8221,8222,8225,8228,8231],{"class":3445,"line":3477},[3443,8223,8224],{"class":5142},"public",[3443,8226,8227],{"class":5142}," record",[3443,8229,8230],{"class":5098}," SmtpSettings",[3443,8232,5247],{"class":5102},[3443,8234,8235,8238,8241],{"class":3445,"line":3483},[3443,8236,8237],{"class":5142},"    string",[3443,8239,8240],{"class":5146}," Host",[3443,8242,5220],{"class":5102},[3443,8244,8245,8248,8251],{"class":3445,"line":3489},[3443,8246,8247],{"class":5142},"    int",[3443,8249,8250],{"class":5146}," Port",[3443,8252,5220],{"class":5102},[3443,8254,8255,8258,8261],{"class":3445,"line":3495},[3443,8256,8257],{"class":5142},"    bool",[3443,8259,8260],{"class":5146}," EnableSsl",[3443,8262,5220],{"class":5102},[3443,8264,8265,8267,8270],{"class":3445,"line":3501},[3443,8266,8237],{"class":5142},[3443,8268,8269],{"class":5146}," Username",[3443,8271,5220],{"class":5102},[3443,8273,8274,8276,8279],{"class":3445,"line":3507},[3443,8275,8237],{"class":5142},[3443,8277,8278],{"class":5146}," Password",[3443,8280,5220],{"class":5102},[3443,8282,8283,8285,8288],{"class":3445,"line":3513},[3443,8284,8237],{"class":5142},[3443,8286,8287],{"class":5146}," FromName",[3443,8289,5220],{"class":5102},[3443,8291,8292,8294],{"class":3445,"line":3518},[3443,8293,8237],{"class":5142},[3443,8295,8296],{"class":5146}," FromEmail\n",[3443,8298,8299],{"class":3445,"line":3524},[3443,8300,5549],{"class":5102},[3443,8302,8303],{"class":3445,"line":3530},[3443,8304,3468],{"emptyLinePlaceholder":3467},[3443,8306,8307],{"class":3445,"line":3536},[3443,8308,8309],{"class":5134},"\u002F\u002F Реєстрація у DI-контейнері (Program.cs або Startup.cs)\n",[3443,8311,8312,8315,8317,8320,8322,8325,8328,8331],{"class":3445,"line":3542},[3443,8313,8314],{"class":5146},"builder",[3443,8316,3692],{"class":5102},[3443,8318,8319],{"class":5146},"Services",[3443,8321,3692],{"class":5102},[3443,8323,8324],{"class":5480},"Configure",[3443,8326,8327],{"class":5102},"\u003C",[3443,8329,8330],{"class":5098},"SmtpSettings",[3443,8332,8333],{"class":5102},">(\n",[3443,8335,8336,8339,8341,8343,8345,8348,8350,8353],{"class":3445,"line":3548},[3443,8337,8338],{"class":5146},"    builder",[3443,8340,3692],{"class":5102},[3443,8342,8180],{"class":5146},[3443,8344,3692],{"class":5102},[3443,8346,8347],{"class":5480},"GetSection",[3443,8349,5159],{"class":5102},[3443,8351,8352],{"class":5162},"\"SmtpSettings\"",[3443,8354,5166],{"class":5102},[3443,8356,8357],{"class":3445,"line":3554},[3443,8358,5549],{"class":5102},[3443,8360,8361,8363,8365,8367,8369,8372,8374,8377,8379,8382],{"class":3445,"line":3559},[3443,8362,8314],{"class":5146},[3443,8364,3692],{"class":5102},[3443,8366,8319],{"class":5146},[3443,8368,3692],{"class":5102},[3443,8370,8371],{"class":5480},"AddTransient",[3443,8373,8327],{"class":5102},[3443,8375,8376],{"class":5098},"IEmailSender",[3443,8378,3668],{"class":5102},[3443,8380,8381],{"class":5098},"SmtpEmailSender",[3443,8383,8384],{"class":5102},">();\n",[3443,8386,8387],{"class":3445,"line":3565},[3443,8388,3468],{"emptyLinePlaceholder":3467},[3443,8390,8391],{"class":3445,"line":3571},[3443,8392,8393],{"class":5134},"\u002F\u002F Реалізація сервісу відправки\n",[3443,8395,8396,8398,8401,8404,8406,8409,8411,8413,8416,8419,8422],{"class":3445,"line":3577},[3443,8397,8224],{"class":5142},[3443,8399,8400],{"class":5142}," class",[3443,8402,8403],{"class":5098}," SmtpEmailSender",[3443,8405,5159],{"class":5102},[3443,8407,8408],{"class":5098},"IOptions",[3443,8410,8327],{"class":5102},[3443,8412,8330],{"class":5098},[3443,8414,8415],{"class":5102},"> ",[3443,8417,8418],{"class":5146},"options",[3443,8420,8421],{"class":5102},") : ",[3443,8423,8424],{"class":5098},"IEmailSender\n",[3443,8426,8427],{"class":3445,"line":3583},[3443,8428,5171],{"class":5102},[3443,8430,8431,8434,8437,8439,8442,8444,8446,8448,8451],{"class":3445,"line":3589},[3443,8432,8433],{"class":5142},"    private",[3443,8435,8436],{"class":5142}," readonly",[3443,8438,8230],{"class":5098},[3443,8440,8441],{"class":5146}," _settings",[3443,8443,5150],{"class":5102},[3443,8445,8418],{"class":5146},[3443,8447,3692],{"class":5102},[3443,8449,8450],{"class":5146},"Value",[3443,8452,5108],{"class":5102},[3443,8454,8455],{"class":3445,"line":3595},[3443,8456,3468],{"emptyLinePlaceholder":3467},[3443,8458,8459,8462,8465,8467,8470,8472,8474,8477,8479,8481,8483,8485,8487,8489],{"class":3445,"line":3600},[3443,8460,8461],{"class":5142},"    public",[3443,8463,8464],{"class":5142}," async",[3443,8466,5619],{"class":5098},[3443,8468,8469],{"class":5480}," SendAsync",[3443,8471,5159],{"class":5102},[3443,8473,5627],{"class":5142},[3443,8475,8476],{"class":5146}," to",[3443,8478,3668],{"class":5102},[3443,8480,5627],{"class":5142},[3443,8482,5637],{"class":5146},[3443,8484,3668],{"class":5102},[3443,8486,5627],{"class":5142},[3443,8488,6743],{"class":5146},[3443,8490,5220],{"class":5102},[3443,8492,8493,8496,8499,8501,8504],{"class":3445,"line":4077},[3443,8494,8495],{"class":5098},"        CancellationToken",[3443,8497,8498],{"class":5146}," ct",[3443,8500,5150],{"class":5102},[3443,8502,8503],{"class":5142},"default",[3443,8505,5166],{"class":5102},[3443,8507,8508],{"class":3445,"line":4083},[3443,8509,5676],{"class":5102},[3443,8511,8512,8515,8517,8519,8521,8523,8525,8527,8530,8532,8535],{"class":3445,"line":4089},[3443,8513,8514],{"class":5094},"        using",[3443,8516,5143],{"class":5142},[3443,8518,6230],{"class":5146},[3443,8520,5150],{"class":5102},[3443,8522,5153],{"class":5142},[3443,8524,5156],{"class":5098},[3443,8526,5159],{"class":5102},[3443,8528,8529],{"class":5146},"_settings",[3443,8531,3692],{"class":5102},[3443,8533,8534],{"class":5146},"Host",[3443,8536,5166],{"class":5102},[3443,8538,8539],{"class":3445,"line":4094},[3443,8540,8541],{"class":5102},"        {\n",[3443,8543,8544,8547,8549,8551,8553,8556],{"class":3445,"line":4100},[3443,8545,8546],{"class":5146},"            Port",[3443,8548,5150],{"class":5102},[3443,8550,8529],{"class":5146},[3443,8552,3692],{"class":5102},[3443,8554,8555],{"class":5146},"Port",[3443,8557,5220],{"class":5102},[3443,8559,8560,8563,8565,8567,8569,8572],{"class":3445,"line":4106},[3443,8561,8562],{"class":5146},"            EnableSsl",[3443,8564,5150],{"class":5102},[3443,8566,8529],{"class":5146},[3443,8568,3692],{"class":5102},[3443,8570,8571],{"class":5146},"EnableSsl",[3443,8573,5220],{"class":5102},[3443,8575,8576,8579,8581,8583,8585,8587,8589,8591,8594,8596,8598,8600,8603],{"class":3445,"line":4111},[3443,8577,8578],{"class":5146},"            Credentials",[3443,8580,5150],{"class":5102},[3443,8582,5153],{"class":5142},[3443,8584,5244],{"class":5098},[3443,8586,5159],{"class":5102},[3443,8588,8529],{"class":5146},[3443,8590,3692],{"class":5102},[3443,8592,8593],{"class":5146},"Username",[3443,8595,3668],{"class":5102},[3443,8597,8529],{"class":5146},[3443,8599,3692],{"class":5102},[3443,8601,8602],{"class":5146},"Password",[3443,8604,5166],{"class":5102},[3443,8606,8607],{"class":3445,"line":4117},[3443,8608,8609],{"class":5102},"        };\n",[3443,8611,8612],{"class":3445,"line":4122},[3443,8613,3468],{"emptyLinePlaceholder":3467},[3443,8615,8616,8618,8620,8622,8624,8626],{"class":3445,"line":4127},[3443,8617,8514],{"class":5094},[3443,8619,5143],{"class":5142},[3443,8621,5301],{"class":5146},[3443,8623,5150],{"class":5102},[3443,8625,5153],{"class":5142},[3443,8627,5308],{"class":5098},[3443,8629,8630],{"class":3445,"line":4133},[3443,8631,8541],{"class":5102},[3443,8633,8634,8637,8639,8641,8643,8645,8647,8649,8652,8654,8656,8658,8661],{"class":3445,"line":4139},[3443,8635,8636],{"class":5146},"            From",[3443,8638,5150],{"class":5102},[3443,8640,5153],{"class":5142},[3443,8642,5324],{"class":5098},[3443,8644,5159],{"class":5102},[3443,8646,8529],{"class":5146},[3443,8648,3692],{"class":5102},[3443,8650,8651],{"class":5146},"FromEmail",[3443,8653,3668],{"class":5102},[3443,8655,8529],{"class":5146},[3443,8657,3692],{"class":5102},[3443,8659,8660],{"class":5146},"FromName",[3443,8662,5336],{"class":5102},[3443,8664,8665,8668,8670,8672],{"class":3445,"line":4145},[3443,8666,8667],{"class":5146},"            Subject",[3443,8669,5150],{"class":5102},[3443,8671,5790],{"class":5146},[3443,8673,5220],{"class":5102},[3443,8675,8676,8679,8681,8683],{"class":3445,"line":4150},[3443,8677,8678],{"class":5146},"            Body",[3443,8680,5150],{"class":5102},[3443,8682,6886],{"class":5146},[3443,8684,5220],{"class":5102},[3443,8686,8687,8690,8692,8694],{"class":3445,"line":4156},[3443,8688,8689],{"class":5146},"            IsBodyHtml",[3443,8691,5150],{"class":5102},[3443,8693,5197],{"class":5142},[3443,8695,5220],{"class":5102},[3443,8697,8698,8701,8703,8705,8707,8709,8711,8713,8715],{"class":3445,"line":4162},[3443,8699,8700],{"class":5146},"            BodyEncoding",[3443,8702,5150],{"class":5102},[3443,8704,5419],{"class":5146},[3443,8706,3692],{"class":5102},[3443,8708,5424],{"class":5146},[3443,8710,3692],{"class":5102},[3443,8712,5429],{"class":5146},[3443,8714,3692],{"class":5102},[3443,8716,5458],{"class":5146},[3443,8718,8719],{"class":3445,"line":4168},[3443,8720,8609],{"class":5102},[3443,8722,8723],{"class":3445,"line":4174},[3443,8724,3468],{"emptyLinePlaceholder":3467},[3443,8726,8727,8730,8732,8734,8736,8738,8740,8743],{"class":3445,"line":4180},[3443,8728,8729],{"class":5146},"        message",[3443,8731,3692],{"class":5102},[3443,8733,4630],{"class":5146},[3443,8735,3692],{"class":5102},[3443,8737,5481],{"class":5480},[3443,8739,5159],{"class":5102},[3443,8741,8742],{"class":5146},"to",[3443,8744,5549],{"class":5102},[3443,8746,8747,8749,8751,8753,8755,8757,8759,8761,8764],{"class":3445,"line":4186},[3443,8748,5889],{"class":5142},[3443,8750,6230],{"class":5146},[3443,8752,3692],{"class":5102},[3443,8754,5896],{"class":5480},[3443,8756,5159],{"class":5102},[3443,8758,5471],{"class":5146},[3443,8760,3668],{"class":5102},[3443,8762,8763],{"class":5146},"ct",[3443,8765,5549],{"class":5102},[3443,8767,8768],{"class":3445,"line":4192},[3443,8769,4804],{"class":5102},[3443,8771,8772],{"class":3445,"line":4198},[3443,8773,4809],{"class":5102},[3645,8775],{},[3605,8777,8779],{"id":8778},"обробка-помилок-smtpclient","Обробка помилок SmtpClient",[3317,8781,8782],{},"Детальна обробка помилок є критично важливою у поштових системах — частина помилок є тимчасовими (слід повторити), частина постійними (слід зафіксувати й не повторювати):",[3433,8784,8786],{"className":5084,"code":8785,"language":5086,"meta":5087,"style":3438},"using System.Net;\nusing System.Net.Mail;\nusing System.Net.Sockets;\n\nasync Task SendWithRetryAsync(MailMessage message, int maxRetries = 3)\n{\n    using var smtp = new SmtpClient(\"smtp.gmail.com\")\n    {\n        Port = 587,\n        EnableSsl = true,\n        Credentials = new NetworkCredential(\"alice@gmail.com\", \"app-password\"),\n        Timeout = 30_000 \u002F\u002F Таймаут 30 секунд на операцію\n    };\n\n    for (int attempt = 1; attempt \u003C= maxRetries; attempt++)\n    {\n        try\n        {\n            await smtp.SendMailAsync(message);\n            Console.WriteLine($\"Лист надіслано (спроба {attempt})\");\n            return; \u002F\u002F Успіх — виходимо з циклу\n        }\n        catch (SmtpException ex)\n        {\n            int code = (int)ex.StatusCode;\n\n            \u002F\u002F 5xx — постійна помилка: не повторювати\n            if (code >= 500)\n            {\n                Console.Error.WriteLine($\"Постійна SMTP-помилка {code}: {ex.Message}\");\n                \u002F\u002F 550 = Mailbox unavailable, 552 = Too large, 554 = Transaction failed\n                throw;\n            }\n\n            \u002F\u002F 4xx — тимчасова помилка: повторити з паузою\n            if (code >= 400 && attempt \u003C maxRetries)\n            {\n                \u002F\u002F Exponential backoff: 2s, 4s, 8s...\n                var delay = TimeSpan.FromSeconds(Math.Pow(2, attempt));\n                Console.Warning($\"Тимчасова помилка {code}. Повтор через {delay.TotalSeconds}с...\");\n                await Task.Delay(delay);\n                continue;\n            }\n\n            throw; \u002F\u002F Вичерпали спроби або невідомий код\n        }\n        catch (SmtpFailedRecipientException ex)\n        {\n            \u002F\u002F Один або кілька одержувачів відхилені\n            \u002F\u002F ex.FailedRecipient — адреса, що спричинила помилку\n            Console.Error.WriteLine($\"Одержувача відхилено: {ex.FailedRecipient}\");\n            Console.Error.WriteLine($\"Код: {ex.StatusCode}, Деталі: {ex.Message}\");\n            throw;\n        }\n        catch (SmtpFailedRecipientsException ex)\n        {\n            \u002F\u002F Всі одержувачі відхилені (при масовому відправленні)\n            foreach (SmtpFailedRecipientException inner in ex.InnerExceptions)\n                Console.Error.WriteLine($\"  Відхилено: {inner.FailedRecipient} ({inner.StatusCode})\");\n            throw;\n        }\n        catch (SocketException ex)\n        {\n            \u002F\u002F Мережева помилка: сервер недоступний, DNS-помилка\n            Console.Error.WriteLine($\"Помилка мережі: {ex.Message}\");\n            if (attempt \u003C maxRetries)\n            {\n                await Task.Delay(TimeSpan.FromSeconds(5));\n                continue;\n            }\n            throw;\n        }\n    }\n}\n",[3440,8787,8788,8800,8816,8833,8837,8866,8870,8890,8894,8904,8914,8934,8947,8951,8955,8990,8994,8999,9003,9020,9045,9055,9059,9072,9076,9099,9103,9108,9123,9128,9168,9173,9180,9185,9189,9194,9217,9221,9226,9265,9305,9323,9330,9334,9338,9348,9352,9365,9369,9374,9379,9411,9455,9461,9465,9478,9482,9487,9511,9556,9563,9568,9582,9587,9593,9625,9640,9645,9671,9678,9683,9690,9695,9700],{"__ignoreMap":3438},[3443,8789,8790,8792,8794,8796,8798],{"class":3445,"line":3446},[3443,8791,5095],{"class":5094},[3443,8793,5099],{"class":5098},[3443,8795,3692],{"class":5102},[3443,8797,5105],{"class":5098},[3443,8799,5108],{"class":5102},[3443,8801,8802,8804,8806,8808,8810,8812,8814],{"class":3445,"line":3452},[3443,8803,5095],{"class":5094},[3443,8805,5099],{"class":5098},[3443,8807,3692],{"class":5102},[3443,8809,5105],{"class":5098},[3443,8811,3692],{"class":5102},[3443,8813,5123],{"class":5098},[3443,8815,5108],{"class":5102},[3443,8817,8818,8820,8822,8824,8826,8828,8831],{"class":3445,"line":3458},[3443,8819,5095],{"class":5094},[3443,8821,5099],{"class":5098},[3443,8823,3692],{"class":5102},[3443,8825,5105],{"class":5098},[3443,8827,3692],{"class":5102},[3443,8829,8830],{"class":5098},"Sockets",[3443,8832,5108],{"class":5102},[3443,8834,8835],{"class":3445,"line":3464},[3443,8836,3468],{"emptyLinePlaceholder":3467},[3443,8838,8839,8841,8843,8846,8848,8850,8852,8854,8856,8859,8861,8864],{"class":3445,"line":3471},[3443,8840,5616],{"class":5142},[3443,8842,5619],{"class":5098},[3443,8844,8845],{"class":5480}," SendWithRetryAsync",[3443,8847,5159],{"class":5102},[3443,8849,5024],{"class":5098},[3443,8851,5301],{"class":5146},[3443,8853,3668],{"class":5102},[3443,8855,6042],{"class":5142},[3443,8857,8858],{"class":5146}," maxRetries",[3443,8860,5150],{"class":5102},[3443,8862,8863],{"class":5181},"3",[3443,8865,5166],{"class":5102},[3443,8867,8868],{"class":3445,"line":3477},[3443,8869,5171],{"class":5102},[3443,8871,8872,8874,8876,8878,8880,8882,8884,8886,8888],{"class":3445,"line":3483},[3443,8873,5655],{"class":5094},[3443,8875,5143],{"class":5142},[3443,8877,6230],{"class":5146},[3443,8879,5150],{"class":5102},[3443,8881,5153],{"class":5142},[3443,8883,5156],{"class":5098},[3443,8885,5159],{"class":5102},[3443,8887,5163],{"class":5162},[3443,8889,5166],{"class":5102},[3443,8891,8892],{"class":3445,"line":3489},[3443,8893,5676],{"class":5102},[3443,8895,8896,8898,8900,8902],{"class":3445,"line":3495},[3443,8897,5681],{"class":5146},[3443,8899,5150],{"class":5102},[3443,8901,3896],{"class":5181},[3443,8903,5220],{"class":5102},[3443,8905,8906,8908,8910,8912],{"class":3445,"line":3501},[3443,8907,5692],{"class":5146},[3443,8909,5150],{"class":5102},[3443,8911,5197],{"class":5142},[3443,8913,5220],{"class":5102},[3443,8915,8916,8918,8920,8922,8924,8926,8928,8930,8932],{"class":3445,"line":3507},[3443,8917,5714],{"class":5146},[3443,8919,5150],{"class":5102},[3443,8921,5153],{"class":5142},[3443,8923,5244],{"class":5098},[3443,8925,5159],{"class":5102},[3443,8927,5258],{"class":5162},[3443,8929,3668],{"class":5102},[3443,8931,5729],{"class":5162},[3443,8933,5336],{"class":5102},[3443,8935,8936,8939,8941,8944],{"class":3445,"line":3513},[3443,8937,8938],{"class":5146},"        Timeout",[3443,8940,5150],{"class":5102},[3443,8942,8943],{"class":5181},"30_000",[3443,8945,8946],{"class":5134}," \u002F\u002F Таймаут 30 секунд на операцію\n",[3443,8948,8949],{"class":3445,"line":3518},[3443,8950,5736],{"class":5102},[3443,8952,8953],{"class":3445,"line":3524},[3443,8954,3468],{"emptyLinePlaceholder":3467},[3443,8956,8957,8960,8962,8964,8967,8969,8972,8974,8977,8980,8983,8985,8987],{"class":3445,"line":3530},[3443,8958,8959],{"class":5094},"    for",[3443,8961,4611],{"class":5102},[3443,8963,6042],{"class":5142},[3443,8965,8966],{"class":5146}," attempt",[3443,8968,5150],{"class":5102},[3443,8970,8971],{"class":5181},"1",[3443,8973,6138],{"class":5102},[3443,8975,8976],{"class":5146},"attempt",[3443,8978,8979],{"class":5102}," \u003C= ",[3443,8981,8982],{"class":5146},"maxRetries",[3443,8984,6138],{"class":5102},[3443,8986,8976],{"class":5146},[3443,8988,8989],{"class":5102},"++)\n",[3443,8991,8992],{"class":3445,"line":3536},[3443,8993,5676],{"class":5102},[3443,8995,8996],{"class":3445,"line":3542},[3443,8997,8998],{"class":5094},"        try\n",[3443,9000,9001],{"class":3445,"line":3548},[3443,9002,8541],{"class":5102},[3443,9004,9005,9008,9010,9012,9014,9016,9018],{"class":3445,"line":3554},[3443,9006,9007],{"class":5142},"            await",[3443,9009,6230],{"class":5146},[3443,9011,3692],{"class":5102},[3443,9013,5896],{"class":5480},[3443,9015,5159],{"class":5102},[3443,9017,5471],{"class":5146},[3443,9019,5549],{"class":5102},[3443,9021,9022,9025,9027,9029,9031,9034,9036,9038,9040,9043],{"class":3445,"line":3559},[3443,9023,9024],{"class":5146},"            Console",[3443,9026,3692],{"class":5102},[3443,9028,5559],{"class":5480},[3443,9030,5159],{"class":5102},[3443,9032,9033],{"class":5162},"$\"Лист надіслано (спроба ",[3443,9035,5920],{"class":5919},[3443,9037,8976],{"class":5146},[3443,9039,5925],{"class":5919},[3443,9041,9042],{"class":5162},")\"",[3443,9044,5549],{"class":5102},[3443,9046,9047,9050,9052],{"class":3445,"line":3565},[3443,9048,9049],{"class":5094},"            return",[3443,9051,6138],{"class":5102},[3443,9053,9054],{"class":5134},"\u002F\u002F Успіх — виходимо з циклу\n",[3443,9056,9057],{"class":3445,"line":3571},[3443,9058,4794],{"class":5102},[3443,9060,9061,9064,9066,9068,9070],{"class":3445,"line":3577},[3443,9062,9063],{"class":5094},"        catch",[3443,9065,4611],{"class":5102},[3443,9067,5944],{"class":5098},[3443,9069,5947],{"class":5146},[3443,9071,5166],{"class":5102},[3443,9073,9074],{"class":3445,"line":3583},[3443,9075,8541],{"class":5102},[3443,9077,9078,9081,9084,9087,9089,9091,9093,9095,9097],{"class":3445,"line":3589},[3443,9079,9080],{"class":5142},"            int",[3443,9082,9083],{"class":5146}," code",[3443,9085,9086],{"class":5102}," = (",[3443,9088,6042],{"class":5142},[3443,9090,4915],{"class":5102},[3443,9092,5958],{"class":5146},[3443,9094,3692],{"class":5102},[3443,9096,5963],{"class":5146},[3443,9098,5108],{"class":5102},[3443,9100,9101],{"class":3445,"line":3595},[3443,9102,3468],{"emptyLinePlaceholder":3467},[3443,9104,9105],{"class":3445,"line":3600},[3443,9106,9107],{"class":5134},"            \u002F\u002F 5xx — постійна помилка: не повторювати\n",[3443,9109,9110,9113,9115,9117,9119,9121],{"class":3445,"line":4077},[3443,9111,9112],{"class":5094},"            if",[3443,9114,4611],{"class":5102},[3443,9116,3440],{"class":5146},[3443,9118,6053],{"class":5102},[3443,9120,6075],{"class":5181},[3443,9122,5166],{"class":5102},[3443,9124,9125],{"class":3445,"line":4083},[3443,9126,9127],{"class":5102},"            {\n",[3443,9129,9130,9133,9135,9137,9139,9141,9143,9146,9148,9150,9152,9154,9156,9158,9160,9162,9164,9166],{"class":3445,"line":4089},[3443,9131,9132],{"class":5146},"                Console",[3443,9134,3692],{"class":5102},[3443,9136,5994],{"class":5146},[3443,9138,3692],{"class":5102},[3443,9140,5559],{"class":5480},[3443,9142,5159],{"class":5102},[3443,9144,9145],{"class":5162},"$\"Постійна SMTP-помилка ",[3443,9147,5920],{"class":5919},[3443,9149,3440],{"class":5146},[3443,9151,5925],{"class":5919},[3443,9153,5255],{"class":5162},[3443,9155,5920],{"class":5919},[3443,9157,5958],{"class":5146},[3443,9159,3692],{"class":5919},[3443,9161,6012],{"class":5146},[3443,9163,5925],{"class":5919},[3443,9165,5928],{"class":5162},[3443,9167,5549],{"class":5102},[3443,9169,9170],{"class":3445,"line":4094},[3443,9171,9172],{"class":5134},"                \u002F\u002F 550 = Mailbox unavailable, 552 = Too large, 554 = Transaction failed\n",[3443,9174,9175,9178],{"class":3445,"line":4100},[3443,9176,9177],{"class":5094},"                throw",[3443,9179,5108],{"class":5102},[3443,9181,9182],{"class":3445,"line":4106},[3443,9183,9184],{"class":5102},"            }\n",[3443,9186,9187],{"class":3445,"line":4111},[3443,9188,3468],{"emptyLinePlaceholder":3467},[3443,9190,9191],{"class":3445,"line":4117},[3443,9192,9193],{"class":5134},"            \u002F\u002F 4xx — тимчасова помилка: повторити з паузою\n",[3443,9195,9196,9198,9200,9202,9204,9206,9209,9211,9213,9215],{"class":3445,"line":4122},[3443,9197,9112],{"class":5094},[3443,9199,4611],{"class":5102},[3443,9201,3440],{"class":5146},[3443,9203,6053],{"class":5102},[3443,9205,6056],{"class":5181},[3443,9207,9208],{"class":5102}," && ",[3443,9210,8976],{"class":5146},[3443,9212,6072],{"class":5102},[3443,9214,8982],{"class":5146},[3443,9216,5166],{"class":5102},[3443,9218,9219],{"class":3445,"line":4127},[3443,9220,9127],{"class":5102},[3443,9222,9223],{"class":3445,"line":4133},[3443,9224,9225],{"class":5134},"                \u002F\u002F Exponential backoff: 2s, 4s, 8s...\n",[3443,9227,9228,9231,9234,9236,9239,9241,9244,9246,9249,9251,9254,9256,9259,9261,9263],{"class":3445,"line":4139},[3443,9229,9230],{"class":5142},"                var",[3443,9232,9233],{"class":5146}," delay",[3443,9235,5150],{"class":5102},[3443,9237,9238],{"class":5146},"TimeSpan",[3443,9240,3692],{"class":5102},[3443,9242,9243],{"class":5480},"FromSeconds",[3443,9245,5159],{"class":5102},[3443,9247,9248],{"class":5146},"Math",[3443,9250,3692],{"class":5102},[3443,9252,9253],{"class":5480},"Pow",[3443,9255,5159],{"class":5102},[3443,9257,9258],{"class":5181},"2",[3443,9260,3668],{"class":5102},[3443,9262,8976],{"class":5146},[3443,9264,5500],{"class":5102},[3443,9266,9267,9269,9271,9274,9276,9279,9281,9283,9285,9288,9290,9293,9295,9298,9300,9303],{"class":3445,"line":4145},[3443,9268,9132],{"class":5146},[3443,9270,3692],{"class":5102},[3443,9272,9273],{"class":5480},"Warning",[3443,9275,5159],{"class":5102},[3443,9277,9278],{"class":5162},"$\"Тимчасова помилка ",[3443,9280,5920],{"class":5919},[3443,9282,3440],{"class":5146},[3443,9284,5925],{"class":5919},[3443,9286,9287],{"class":5162},". Повтор через ",[3443,9289,5920],{"class":5919},[3443,9291,9292],{"class":5146},"delay",[3443,9294,3692],{"class":5919},[3443,9296,9297],{"class":5146},"TotalSeconds",[3443,9299,5925],{"class":5919},[3443,9301,9302],{"class":5162},"с...\"",[3443,9304,5549],{"class":5102},[3443,9306,9307,9310,9312,9314,9317,9319,9321],{"class":3445,"line":4150},[3443,9308,9309],{"class":5142},"                await",[3443,9311,5619],{"class":5146},[3443,9313,3692],{"class":5102},[3443,9315,9316],{"class":5480},"Delay",[3443,9318,5159],{"class":5102},[3443,9320,9292],{"class":5146},[3443,9322,5549],{"class":5102},[3443,9324,9325,9328],{"class":3445,"line":4156},[3443,9326,9327],{"class":5094},"                continue",[3443,9329,5108],{"class":5102},[3443,9331,9332],{"class":3445,"line":4162},[3443,9333,9184],{"class":5102},[3443,9335,9336],{"class":3445,"line":4168},[3443,9337,3468],{"emptyLinePlaceholder":3467},[3443,9339,9340,9343,9345],{"class":3445,"line":4174},[3443,9341,9342],{"class":5094},"            throw",[3443,9344,6138],{"class":5102},[3443,9346,9347],{"class":5134},"\u002F\u002F Вичерпали спроби або невідомий код\n",[3443,9349,9350],{"class":3445,"line":4180},[3443,9351,4794],{"class":5102},[3443,9353,9354,9356,9358,9361,9363],{"class":3445,"line":4186},[3443,9355,9063],{"class":5094},[3443,9357,4611],{"class":5102},[3443,9359,9360],{"class":5098},"SmtpFailedRecipientException",[3443,9362,5947],{"class":5146},[3443,9364,5166],{"class":5102},[3443,9366,9367],{"class":3445,"line":4192},[3443,9368,8541],{"class":5102},[3443,9370,9371],{"class":3445,"line":4198},[3443,9372,9373],{"class":5134},"            \u002F\u002F Один або кілька одержувачів відхилені\n",[3443,9375,9376],{"class":3445,"line":4204},[3443,9377,9378],{"class":5134},"            \u002F\u002F ex.FailedRecipient — адреса, що спричинила помилку\n",[3443,9380,9381,9383,9385,9387,9389,9391,9393,9396,9398,9400,9402,9405,9407,9409],{"class":3445,"line":4210},[3443,9382,9024],{"class":5146},[3443,9384,3692],{"class":5102},[3443,9386,5994],{"class":5146},[3443,9388,3692],{"class":5102},[3443,9390,5559],{"class":5480},[3443,9392,5159],{"class":5102},[3443,9394,9395],{"class":5162},"$\"Одержувача відхилено: ",[3443,9397,5920],{"class":5919},[3443,9399,5958],{"class":5146},[3443,9401,3692],{"class":5919},[3443,9403,9404],{"class":5146},"FailedRecipient",[3443,9406,5925],{"class":5919},[3443,9408,5928],{"class":5162},[3443,9410,5549],{"class":5102},[3443,9412,9413,9415,9417,9419,9421,9423,9425,9428,9430,9432,9434,9436,9438,9441,9443,9445,9447,9449,9451,9453],{"class":3445,"line":4215},[3443,9414,9024],{"class":5146},[3443,9416,3692],{"class":5102},[3443,9418,5994],{"class":5146},[3443,9420,3692],{"class":5102},[3443,9422,5559],{"class":5480},[3443,9424,5159],{"class":5102},[3443,9426,9427],{"class":5162},"$\"Код: ",[3443,9429,5920],{"class":5919},[3443,9431,5958],{"class":5146},[3443,9433,3692],{"class":5919},[3443,9435,5963],{"class":5146},[3443,9437,5925],{"class":5919},[3443,9439,9440],{"class":5162},", Деталі: ",[3443,9442,5920],{"class":5919},[3443,9444,5958],{"class":5146},[3443,9446,3692],{"class":5919},[3443,9448,6012],{"class":5146},[3443,9450,5925],{"class":5919},[3443,9452,5928],{"class":5162},[3443,9454,5549],{"class":5102},[3443,9456,9457,9459],{"class":3445,"line":4221},[3443,9458,9342],{"class":5094},[3443,9460,5108],{"class":5102},[3443,9462,9463],{"class":3445,"line":4227},[3443,9464,4794],{"class":5102},[3443,9466,9467,9469,9471,9474,9476],{"class":3445,"line":4233},[3443,9468,9063],{"class":5094},[3443,9470,4611],{"class":5102},[3443,9472,9473],{"class":5098},"SmtpFailedRecipientsException",[3443,9475,5947],{"class":5146},[3443,9477,5166],{"class":5102},[3443,9479,9480],{"class":3445,"line":4238},[3443,9481,8541],{"class":5102},[3443,9483,9484],{"class":3445,"line":7994},[3443,9485,9486],{"class":5134},"            \u002F\u002F Всі одержувачі відхилені (при масовому відправленні)\n",[3443,9488,9489,9492,9494,9496,9499,9502,9504,9506,9509],{"class":3445,"line":7999},[3443,9490,9491],{"class":5094},"            foreach",[3443,9493,4611],{"class":5102},[3443,9495,9360],{"class":5098},[3443,9497,9498],{"class":5146}," inner",[3443,9500,9501],{"class":5094}," in",[3443,9503,5947],{"class":5146},[3443,9505,3692],{"class":5102},[3443,9507,9508],{"class":5146},"InnerExceptions",[3443,9510,5166],{"class":5102},[3443,9512,9514,9516,9518,9520,9522,9524,9526,9529,9531,9534,9536,9538,9540,9542,9544,9546,9548,9550,9552,9554],{"class":3445,"line":9513},59,[3443,9515,9132],{"class":5146},[3443,9517,3692],{"class":5102},[3443,9519,5994],{"class":5146},[3443,9521,3692],{"class":5102},[3443,9523,5559],{"class":5480},[3443,9525,5159],{"class":5102},[3443,9527,9528],{"class":5162},"$\"  Відхилено: ",[3443,9530,5920],{"class":5919},[3443,9532,9533],{"class":5146},"inner",[3443,9535,3692],{"class":5919},[3443,9537,9404],{"class":5146},[3443,9539,5925],{"class":5919},[3443,9541,4611],{"class":5162},[3443,9543,5920],{"class":5919},[3443,9545,9533],{"class":5146},[3443,9547,3692],{"class":5919},[3443,9549,5963],{"class":5146},[3443,9551,5925],{"class":5919},[3443,9553,9042],{"class":5162},[3443,9555,5549],{"class":5102},[3443,9557,9559,9561],{"class":3445,"line":9558},60,[3443,9560,9342],{"class":5094},[3443,9562,5108],{"class":5102},[3443,9564,9566],{"class":3445,"line":9565},61,[3443,9567,4794],{"class":5102},[3443,9569,9571,9573,9575,9578,9580],{"class":3445,"line":9570},62,[3443,9572,9063],{"class":5094},[3443,9574,4611],{"class":5102},[3443,9576,9577],{"class":5098},"SocketException",[3443,9579,5947],{"class":5146},[3443,9581,5166],{"class":5102},[3443,9583,9585],{"class":3445,"line":9584},63,[3443,9586,8541],{"class":5102},[3443,9588,9590],{"class":3445,"line":9589},64,[3443,9591,9592],{"class":5134},"            \u002F\u002F Мережева помилка: сервер недоступний, DNS-помилка\n",[3443,9594,9596,9598,9600,9602,9604,9606,9608,9611,9613,9615,9617,9619,9621,9623],{"class":3445,"line":9595},65,[3443,9597,9024],{"class":5146},[3443,9599,3692],{"class":5102},[3443,9601,5994],{"class":5146},[3443,9603,3692],{"class":5102},[3443,9605,5559],{"class":5480},[3443,9607,5159],{"class":5102},[3443,9609,9610],{"class":5162},"$\"Помилка мережі: ",[3443,9612,5920],{"class":5919},[3443,9614,5958],{"class":5146},[3443,9616,3692],{"class":5919},[3443,9618,6012],{"class":5146},[3443,9620,5925],{"class":5919},[3443,9622,5928],{"class":5162},[3443,9624,5549],{"class":5102},[3443,9626,9628,9630,9632,9634,9636,9638],{"class":3445,"line":9627},66,[3443,9629,9112],{"class":5094},[3443,9631,4611],{"class":5102},[3443,9633,8976],{"class":5146},[3443,9635,6072],{"class":5102},[3443,9637,8982],{"class":5146},[3443,9639,5166],{"class":5102},[3443,9641,9643],{"class":3445,"line":9642},67,[3443,9644,9127],{"class":5102},[3443,9646,9648,9650,9652,9654,9656,9658,9660,9662,9664,9666,9669],{"class":3445,"line":9647},68,[3443,9649,9309],{"class":5142},[3443,9651,5619],{"class":5146},[3443,9653,3692],{"class":5102},[3443,9655,9316],{"class":5480},[3443,9657,5159],{"class":5102},[3443,9659,9238],{"class":5146},[3443,9661,3692],{"class":5102},[3443,9663,9243],{"class":5480},[3443,9665,5159],{"class":5102},[3443,9667,9668],{"class":5181},"5",[3443,9670,5500],{"class":5102},[3443,9672,9674,9676],{"class":3445,"line":9673},69,[3443,9675,9327],{"class":5094},[3443,9677,5108],{"class":5102},[3443,9679,9681],{"class":3445,"line":9680},70,[3443,9682,9184],{"class":5102},[3443,9684,9686,9688],{"class":3445,"line":9685},71,[3443,9687,9342],{"class":5094},[3443,9689,5108],{"class":5102},[3443,9691,9693],{"class":3445,"line":9692},72,[3443,9694,4794],{"class":5102},[3443,9696,9698],{"class":3445,"line":9697},73,[3443,9699,4804],{"class":5102},[3443,9701,9703],{"class":3445,"line":9702},74,[3443,9704,4809],{"class":5102},[3645,9706],{},[3605,9708,9710],{"id":9709},"локальне-тестування-specifiedpickupdirectory","Локальне тестування: SpecifiedPickupDirectory",[3317,9712,9713,9714,9717,9718,9721],{},"При розробці та тестуванні небажано надсилати реальні листи. ",[3440,9715,9716],{},"SmtpDeliveryMethod.SpecifiedPickupDirectory"," зберігає листи як ",[3440,9719,9720],{},".eml"," файли у вказану директорію — без жодного мережевого з'єднання:",[3433,9723,9725],{"className":5084,"code":9724,"language":5086,"meta":5087,"style":3438},"using System.Net.Mail;\n\n\u002F\u002F Зберігає листи як .eml файли — ідеально для unit-тестів та розробки\nusing var smtp = new SmtpClient\n{\n    DeliveryMethod = SmtpDeliveryMethod.SpecifiedPickupDirectory,\n    PickupDirectoryLocation = \"\u002Ftmp\u002Femail-outbox\",  \u002F\u002F Директорія для .eml файлів\n    EnableSsl = false                               \u002F\u002F TLS не потрібен для файлового збереження\n};\n\nusing var message = new MailMessage\n{\n    From = new MailAddress(\"test@myapp.com\", \"Test App\"),\n    Subject = \"Тестовий лист\",\n    Body = \"\u003Ch1>Тест\u003C\u002Fh1>\",\n    IsBodyHtml = true\n};\n\nmessage.To.Add(\"user@example.com\");\n\nsmtp.Send(message);\n\u002F\u002F Лист збережено у \u002Ftmp\u002Femail-outbox\u002Fxxxxxxxx.eml\n\u002F\u002F Відкрийте у Outlook або Thunderbird для перегляду\n",[3440,9726,9727,9743,9747,9752,9767,9771,9786,9802,9813,9817,9821,9835,9839,9861,9872,9883,9892,9896,9900,9919,9923,9938,9943],{"__ignoreMap":3438},[3443,9728,9729,9731,9733,9735,9737,9739,9741],{"class":3445,"line":3446},[3443,9730,5095],{"class":5094},[3443,9732,5099],{"class":5098},[3443,9734,3692],{"class":5102},[3443,9736,5105],{"class":5098},[3443,9738,3692],{"class":5102},[3443,9740,5123],{"class":5098},[3443,9742,5108],{"class":5102},[3443,9744,9745],{"class":3445,"line":3452},[3443,9746,3468],{"emptyLinePlaceholder":3467},[3443,9748,9749],{"class":3445,"line":3458},[3443,9750,9751],{"class":5134},"\u002F\u002F Зберігає листи як .eml файли — ідеально для unit-тестів та розробки\n",[3443,9753,9754,9756,9758,9760,9762,9764],{"class":3445,"line":3464},[3443,9755,5095],{"class":5094},[3443,9757,5143],{"class":5142},[3443,9759,6230],{"class":5146},[3443,9761,5150],{"class":5102},[3443,9763,5153],{"class":5142},[3443,9765,9766],{"class":5098}," SmtpClient\n",[3443,9768,9769],{"class":3445,"line":3471},[3443,9770,5171],{"class":5102},[3443,9772,9773,9775,9777,9779,9781,9784],{"class":3445,"line":3477},[3443,9774,5208],{"class":5146},[3443,9776,5150],{"class":5102},[3443,9778,5213],{"class":5146},[3443,9780,3692],{"class":5102},[3443,9782,9783],{"class":5146},"SpecifiedPickupDirectory",[3443,9785,5220],{"class":5102},[3443,9787,9788,9791,9793,9796,9799],{"class":3445,"line":3483},[3443,9789,9790],{"class":5146},"    PickupDirectoryLocation",[3443,9792,5150],{"class":5102},[3443,9794,9795],{"class":5162},"\"\u002Ftmp\u002Femail-outbox\"",[3443,9797,9798],{"class":5102},",  ",[3443,9800,9801],{"class":5134},"\u002F\u002F Директорія для .eml файлів\n",[3443,9803,9804,9806,9808,9810],{"class":3445,"line":3489},[3443,9805,5192],{"class":5146},[3443,9807,5150],{"class":5102},[3443,9809,5230],{"class":5142},[3443,9811,9812],{"class":5134},"                               \u002F\u002F TLS не потрібен для файлового збереження\n",[3443,9814,9815],{"class":3445,"line":3495},[3443,9816,5283],{"class":5102},[3443,9818,9819],{"class":3445,"line":3501},[3443,9820,3468],{"emptyLinePlaceholder":3467},[3443,9822,9823,9825,9827,9829,9831,9833],{"class":3445,"line":3507},[3443,9824,5095],{"class":5094},[3443,9826,5143],{"class":5142},[3443,9828,5301],{"class":5146},[3443,9830,5150],{"class":5102},[3443,9832,5153],{"class":5142},[3443,9834,5308],{"class":5098},[3443,9836,9837],{"class":3445,"line":3513},[3443,9838,5171],{"class":5102},[3443,9840,9841,9843,9845,9847,9849,9851,9854,9856,9859],{"class":3445,"line":3518},[3443,9842,5317],{"class":5146},[3443,9844,5150],{"class":5102},[3443,9846,5153],{"class":5142},[3443,9848,5324],{"class":5098},[3443,9850,5159],{"class":5102},[3443,9852,9853],{"class":5162},"\"test@myapp.com\"",[3443,9855,3668],{"class":5102},[3443,9857,9858],{"class":5162},"\"Test App\"",[3443,9860,5336],{"class":5102},[3443,9862,9863,9865,9867,9870],{"class":3445,"line":3524},[3443,9864,5341],{"class":5146},[3443,9866,5150],{"class":5102},[3443,9868,9869],{"class":5162},"\"Тестовий лист\"",[3443,9871,5220],{"class":5102},[3443,9873,9874,9876,9878,9881],{"class":3445,"line":3530},[3443,9875,5353],{"class":5146},[3443,9877,5150],{"class":5102},[3443,9879,9880],{"class":5162},"\"\u003Ch1>Тест\u003C\u002Fh1>\"",[3443,9882,5220],{"class":5102},[3443,9884,9885,9887,9889],{"class":3445,"line":3536},[3443,9886,5399],{"class":5146},[3443,9888,5150],{"class":5102},[3443,9890,9891],{"class":5142},"true\n",[3443,9893,9894],{"class":3445,"line":3542},[3443,9895,5283],{"class":5102},[3443,9897,9898],{"class":3445,"line":3548},[3443,9899,3468],{"emptyLinePlaceholder":3467},[3443,9901,9902,9904,9906,9908,9910,9912,9914,9917],{"class":3445,"line":3554},[3443,9903,5471],{"class":5146},[3443,9905,3692],{"class":5102},[3443,9907,4630],{"class":5146},[3443,9909,3692],{"class":5102},[3443,9911,5481],{"class":5480},[3443,9913,5159],{"class":5102},[3443,9915,9916],{"class":5162},"\"user@example.com\"",[3443,9918,5549],{"class":5102},[3443,9920,9921],{"class":3445,"line":3559},[3443,9922,3468],{"emptyLinePlaceholder":3467},[3443,9924,9925,9928,9930,9932,9934,9936],{"class":3445,"line":3565},[3443,9926,9927],{"class":5146},"smtp",[3443,9929,3692],{"class":5102},[3443,9931,5542],{"class":5480},[3443,9933,5159],{"class":5102},[3443,9935,5471],{"class":5146},[3443,9937,5549],{"class":5102},[3443,9939,9940],{"class":3445,"line":3571},[3443,9941,9942],{"class":5134},"\u002F\u002F Лист збережено у \u002Ftmp\u002Femail-outbox\u002Fxxxxxxxx.eml\n",[3443,9944,9945],{"class":3445,"line":3577},[3443,9946,9947],{"class":5134},"\u002F\u002F Відкрийте у Outlook або Thunderbird для перегляду\n",[4960,9949,9950,9951,9960,9961,9964,9965,9967,9968,3692],{},"Для локального тестування поштових функцій також чудово підходить ",[9952,9953,9957],"a",{"href":9954,"rel":9955},"https:\u002F\u002Fgithub.com\u002Fmailhog\u002FMailHog",[9956],"nofollow",[3324,9958,9959],{},"MailHog"," — SMTP-сервер із веб-інтерфейсом, що перехоплює всі листи і відображає їх у браузері. Запуск: ",[3440,9962,9963],{},"docker run -p 1025:1025 -p 8025:8025 mailhog\u002Fmailhog",". Налаштовуйте ",[3440,9966,4671],{}," на ",[3440,9969,9970],{},"Host = \"localhost\", Port = 1025",[3645,9972],{},[3312,9974,9976],{"id":9975},"безпека-поштових-систем-spf-dkim-dmarc","Безпека поштових систем: SPF, DKIM, DMARC",[3317,9978,9979,9980,9983,9984,9987],{},"Сучасна поштова безпека базується на трьох стандартах, що разом забезпечують ",[3324,9981,9982],{},"автентифікацію"," відправника та ",[3324,9985,9986],{},"захист від підробки",":",[3430,9989,9990],{},[3433,9991,9993],{"className":3435,"code":9992,"language":3437,"meta":3438,"style":3438},"@startuml\nskinparam style plain\nskinparam backgroundColor #ffffff\n\nparticipant \"Відправник\\nalice@myapp.com\" as sender #e3f2fd\nparticipant \"MTA відправника\\nsmtp.myapp.com\" as mta_s #e8f5e9\nparticipant \"DNS\\nmyapp.com\" as dns #fff3e0\nparticipant \"MTA одержувача\\nsmtp.gmail.com\" as mta_r #e8f5e9\n\nsender -> mta_s : Надсилає лист\nmta_s -> mta_s : Підписує листа\\nDKIM-підписом\n\nmta_r -> dns : DNS TXT?\\nmyapp.com SPF\ndns --> mta_r : v=spf1 include:_spf.myapp.com ~all\nmta_r -> mta_r : SPF: smtp.myapp.com\\nдозволений? ✅\n\nmta_r -> dns : DNS TXT?\\nmail._domainkey.myapp.com\ndns --> mta_r : v=DKIM1; k=rsa; p=MIGfMA...\nmta_r -> mta_r : DKIM: перевіряємо\\nпідпис заголовків ✅\n\nmta_r -> dns : DNS TXT?\\n_dmarc.myapp.com\ndns --> mta_r : v=DMARC1; p=reject;\\nrua=mailto:dmarc@myapp.com\nmta_r -> mta_r : DMARC: SPF✅ + DKIM✅\\nFrom:=SPF domain? ✅\\nДоставити!\n\nmta_s --> mta_r : Лист доставлено\n\n@enduml\n",[3440,9994,9995,9999,10003,10007,10011,10016,10021,10026,10031,10035,10040,10045,10049,10054,10059,10064,10068,10073,10078,10083,10087,10092,10097,10102,10106,10111,10115],{"__ignoreMap":3438},[3443,9996,9997],{"class":3445,"line":3446},[3443,9998,3449],{},[3443,10000,10001],{"class":3445,"line":3452},[3443,10002,3455],{},[3443,10004,10005],{"class":3445,"line":3458},[3443,10006,3461],{},[3443,10008,10009],{"class":3445,"line":3464},[3443,10010,3468],{"emptyLinePlaceholder":3467},[3443,10012,10013],{"class":3445,"line":3471},[3443,10014,10015],{},"participant \"Відправник\\nalice@myapp.com\" as sender #e3f2fd\n",[3443,10017,10018],{"class":3445,"line":3477},[3443,10019,10020],{},"participant \"MTA відправника\\nsmtp.myapp.com\" as mta_s #e8f5e9\n",[3443,10022,10023],{"class":3445,"line":3483},[3443,10024,10025],{},"participant \"DNS\\nmyapp.com\" as dns #fff3e0\n",[3443,10027,10028],{"class":3445,"line":3489},[3443,10029,10030],{},"participant \"MTA одержувача\\nsmtp.gmail.com\" as mta_r #e8f5e9\n",[3443,10032,10033],{"class":3445,"line":3495},[3443,10034,3468],{"emptyLinePlaceholder":3467},[3443,10036,10037],{"class":3445,"line":3501},[3443,10038,10039],{},"sender -> mta_s : Надсилає лист\n",[3443,10041,10042],{"class":3445,"line":3507},[3443,10043,10044],{},"mta_s -> mta_s : Підписує листа\\nDKIM-підписом\n",[3443,10046,10047],{"class":3445,"line":3513},[3443,10048,3468],{"emptyLinePlaceholder":3467},[3443,10050,10051],{"class":3445,"line":3518},[3443,10052,10053],{},"mta_r -> dns : DNS TXT?\\nmyapp.com SPF\n",[3443,10055,10056],{"class":3445,"line":3524},[3443,10057,10058],{},"dns --> mta_r : v=spf1 include:_spf.myapp.com ~all\n",[3443,10060,10061],{"class":3445,"line":3530},[3443,10062,10063],{},"mta_r -> mta_r : SPF: smtp.myapp.com\\nдозволений? ✅\n",[3443,10065,10066],{"class":3445,"line":3536},[3443,10067,3468],{"emptyLinePlaceholder":3467},[3443,10069,10070],{"class":3445,"line":3542},[3443,10071,10072],{},"mta_r -> dns : DNS TXT?\\nmail._domainkey.myapp.com\n",[3443,10074,10075],{"class":3445,"line":3548},[3443,10076,10077],{},"dns --> mta_r : v=DKIM1; k=rsa; p=MIGfMA...\n",[3443,10079,10080],{"class":3445,"line":3554},[3443,10081,10082],{},"mta_r -> mta_r : DKIM: перевіряємо\\nпідпис заголовків ✅\n",[3443,10084,10085],{"class":3445,"line":3559},[3443,10086,3468],{"emptyLinePlaceholder":3467},[3443,10088,10089],{"class":3445,"line":3565},[3443,10090,10091],{},"mta_r -> dns : DNS TXT?\\n_dmarc.myapp.com\n",[3443,10093,10094],{"class":3445,"line":3571},[3443,10095,10096],{},"dns --> mta_r : v=DMARC1; p=reject;\\nrua=mailto:dmarc@myapp.com\n",[3443,10098,10099],{"class":3445,"line":3577},[3443,10100,10101],{},"mta_r -> mta_r : DMARC: SPF✅ + DKIM✅\\nFrom:=SPF domain? ✅\\nДоставити!\n",[3443,10103,10104],{"class":3445,"line":3583},[3443,10105,3468],{"emptyLinePlaceholder":3467},[3443,10107,10108],{"class":3445,"line":3589},[3443,10109,10110],{},"mta_s --> mta_r : Лист доставлено\n",[3443,10112,10113],{"class":3445,"line":3595},[3443,10114,3468],{"emptyLinePlaceholder":3467},[3443,10116,10117],{"class":3445,"line":3600},[3443,10118,3603],{},[10120,10121,10122,10192,10229],"accordion",{},[10123,10124,10126,10136,10147,10178],"accordion-item",{"icon":793,"label":10125},"SPF — Sender Policy Framework (RFC 7208)",[3317,10127,10128,10131,10132,10135],{},[3324,10129,10130],{},"SPF"," — DNS-запис типу ",[3440,10133,10134],{},"TXT",", що перераховує IP-адреси та сервери, яким дозволено надсилати пошту від імені домену.",[3433,10137,10141],{"className":10138,"code":10139,"language":10140,"meta":3438,"style":3438},"language-dns shiki shiki-themes light-plus dark-plus dark-plus","myapp.com. IN TXT \"v=spf1 ip4:203.0.113.10 include:sendgrid.net -all\"\n","dns",[3440,10142,10143],{"__ignoreMap":3438},[3443,10144,10145],{"class":3445,"line":3446},[3443,10146,10139],{},[3764,10148,10149,10155,10161],{},[3767,10150,10151,10154],{},[3440,10152,10153],{},"ip4:203.0.113.10"," — дозволена конкретна IP-адреса",[3767,10156,10157,10160],{},[3440,10158,10159],{},"include:sendgrid.net"," — дозволено всі IP із SPF-запису sendgrid.net",[3767,10162,10163,10166,10167,10169,10170,10173,10174,10177],{},[3440,10164,10165],{},"-all"," — всі решта відхиляються (",[3440,10168,10165],{}," = жорстко, ",[3440,10171,10172],{},"~all"," = м'яко, ",[3440,10175,10176],{},"?all"," = нейтрально)",[3317,10179,10180,10183,10184,4611,10186,10188,10189,10191],{},[3324,10181,10182],{},"Обмеження SPF:"," перевіряє лише ",[3324,10185,4268],{},[3440,10187,4614],{},"), не заголовок ",[3440,10190,4278],{},". Тому SPF недостатньо без DKIM\u002FDMARC.",[10123,10193,10196,10202,10211,10217,10223],{"icon":10194,"label":10195},"i-lucide-key","DKIM — DomainKeys Identified Mail (RFC 6376)",[3317,10197,10198,10201],{},[3324,10199,10200],{},"DKIM"," — криптографічний підпис листа. MTA відправника підписує вибрані заголовки та тіло листа RSA або Ed25519 приватним ключем. Публічний ключ публікується у DNS.",[3433,10203,10205],{"className":10138,"code":10204,"language":10140,"meta":3438,"style":3438},"mail._domainkey.myapp.com. IN TXT \"v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA...\"\n",[3440,10206,10207],{"__ignoreMap":3438},[3443,10208,10209],{"class":3445,"line":3446},[3443,10210,10204],{},[3317,10212,10213,10214,9987],{},"Підпис додається у заголовок ",[3440,10215,10216],{},"DKIM-Signature:",[3433,10218,10221],{"className":10219,"code":10220,"language":4594},[4592],"DKIM-Signature: v=1; a=rsa-sha256; d=myapp.com; s=mail;\n  h=from:to:subject:date:message-id;\n  bh=base64(SHA256(тіло));\n  b=base64(RSA-підпис-заголовків)\n",[3440,10222,10220],{"__ignoreMap":3438},[3317,10224,10225,10228],{},[3324,10226,10227],{},"Переваги DKIM:"," підпис проходить через будь-яку кількість relay-серверів незмінним, оскільки перевіряє вміст, а не IP-адресу.",[10123,10230,10233,10239,10248,10280],{"icon":10231,"label":10232},"i-lucide-shield-alert","DMARC — Domain-based Message Authentication (RFC 7489)",[3317,10234,10235,10238],{},[3324,10236,10237],{},"DMARC"," — політика, що об'єднує SPF і DKIM. Визначає, що робити із листами, які провалили автентифікацію.",[3433,10240,10242],{"className":10138,"code":10241,"language":10140,"meta":3438,"style":3438},"_dmarc.myapp.com. IN TXT \"v=DMARC1; p=reject; rua=mailto:dmarc-reports@myapp.com; pct=100\"\n",[3440,10243,10244],{"__ignoreMap":3438},[3443,10245,10246],{"class":3445,"line":3446},[3443,10247,10241],{},[3764,10249,10250,10256,10262,10268,10274],{},[3767,10251,10252,10255],{},[3440,10253,10254],{},"p=none"," — тільки моніторинг (не відхиляти)",[3767,10257,10258,10261],{},[3440,10259,10260],{},"p=quarantine"," — помістити у спам",[3767,10263,10264,10267],{},[3440,10265,10266],{},"p=reject"," — повністю відхилити",[3767,10269,10270,10273],{},[3440,10271,10272],{},"rua="," — адреса для aggregate-звітів (щоденні JSON\u002FXML-звіти)",[3767,10275,10276,10279],{},[3440,10277,10278],{},"pct=100"," — застосовувати до 100% листів",[3317,10281,10282,10285,10286,10288,10289,3692],{},[3324,10283,10284],{},"DMARC alignment:"," вимагає, щоб домен ",[3440,10287,4278],{}," збігався з доменом, що пройшов SPF або DKIM-перевірку — саме це закриває дірку підробки заголовка ",[3440,10290,4278],{},[10292,10293,10294],"caution",{},"Без SPF\u002FDKIM\u002FDMARC ваші листи будуть потрапляти до спаму або відхилятися більшістю сучасних поштових провайдерів. Gmail та Microsoft відхиляють листи від доменів без SPF із серпня 2024 року.",[3645,10296],{},[3312,10298,10300],{"id":10299},"налаштування-популярних-smtp-провайдерів","Налаштування популярних SMTP-провайдерів",[5076,10302,10303,10445,10630,10908],{},[5079,10304,10306,10422,10425],{"label":10305},"Gmail",[3433,10307,10309],{"className":5084,"code":10308,"language":5086,"meta":5087,"style":3438},"\u002F\u002F Gmail SMTP — ВАЖЛИВО: потрібен App Password, не основний пароль!\n\u002F\u002F Google вимкнув \"Less secure apps\" з травня 2022 року.\n\u002F\u002F Налаштування: Google Account → Security → 2-Step Verification → App Passwords\n\u002F\u002F Або використовуйте OAuth 2.0 Bearer через XOAUTH2 (MailKit)\n\nusing var smtp = new SmtpClient(\"smtp.gmail.com\")\n{\n    Port = 587,           \u002F\u002F Або 465 для Implicit TLS (SSL від початку)\n    EnableSsl = true,     \u002F\u002F STARTTLS для port 587\n    Credentials = new NetworkCredential(\n        \"yourname@gmail.com\",\n        \"xxxx xxxx xxxx xxxx\"   \u002F\u002F App Password (16 символів із пробілами)\n    )\n};\n",[3440,10310,10311,10316,10321,10326,10331,10335,10355,10359,10373,10387,10399,10406,10414,10418],{"__ignoreMap":3438},[3443,10312,10313],{"class":3445,"line":3446},[3443,10314,10315],{"class":5134},"\u002F\u002F Gmail SMTP — ВАЖЛИВО: потрібен App Password, не основний пароль!\n",[3443,10317,10318],{"class":3445,"line":3452},[3443,10319,10320],{"class":5134},"\u002F\u002F Google вимкнув \"Less secure apps\" з травня 2022 року.\n",[3443,10322,10323],{"class":3445,"line":3458},[3443,10324,10325],{"class":5134},"\u002F\u002F Налаштування: Google Account → Security → 2-Step Verification → App Passwords\n",[3443,10327,10328],{"class":3445,"line":3464},[3443,10329,10330],{"class":5134},"\u002F\u002F Або використовуйте OAuth 2.0 Bearer через XOAUTH2 (MailKit)\n",[3443,10332,10333],{"class":3445,"line":3471},[3443,10334,3468],{"emptyLinePlaceholder":3467},[3443,10336,10337,10339,10341,10343,10345,10347,10349,10351,10353],{"class":3445,"line":3477},[3443,10338,5095],{"class":5094},[3443,10340,5143],{"class":5142},[3443,10342,6230],{"class":5146},[3443,10344,5150],{"class":5102},[3443,10346,5153],{"class":5142},[3443,10348,5156],{"class":5098},[3443,10350,5159],{"class":5102},[3443,10352,5163],{"class":5162},[3443,10354,5166],{"class":5102},[3443,10356,10357],{"class":3445,"line":3483},[3443,10358,5171],{"class":5102},[3443,10360,10361,10363,10365,10367,10370],{"class":3445,"line":3489},[3443,10362,5176],{"class":5146},[3443,10364,5150],{"class":5102},[3443,10366,3896],{"class":5181},[3443,10368,10369],{"class":5102},",           ",[3443,10371,10372],{"class":5134},"\u002F\u002F Або 465 для Implicit TLS (SSL від початку)\n",[3443,10374,10375,10377,10379,10381,10384],{"class":3445,"line":3495},[3443,10376,5192],{"class":5146},[3443,10378,5150],{"class":5102},[3443,10380,5197],{"class":5142},[3443,10382,10383],{"class":5102},",     ",[3443,10385,10386],{"class":5134},"\u002F\u002F STARTTLS для port 587\n",[3443,10388,10389,10391,10393,10395,10397],{"class":3445,"line":3501},[3443,10390,5237],{"class":5146},[3443,10392,5150],{"class":5102},[3443,10394,5153],{"class":5142},[3443,10396,5244],{"class":5098},[3443,10398,5247],{"class":5102},[3443,10400,10401,10404],{"class":3445,"line":3507},[3443,10402,10403],{"class":5162},"        \"yourname@gmail.com\"",[3443,10405,5220],{"class":5102},[3443,10407,10408,10411],{"class":3445,"line":3513},[3443,10409,10410],{"class":5162},"        \"xxxx xxxx xxxx xxxx\"",[3443,10412,10413],{"class":5134},"   \u002F\u002F App Password (16 символів із пробілами)\n",[3443,10415,10416],{"class":3445,"line":3518},[3443,10417,5278],{"class":5102},[3443,10419,10420],{"class":3445,"line":3524},[3443,10421,5283],{"class":5102},[3317,10423,10424],{},"Обмеження Gmail SMTP:",[3764,10426,10427,10433,10439],{},[3767,10428,10429,10432],{},[3324,10430,10431],{},"500 листів\u002Fдень"," для звичайних акаунтів",[3767,10434,10435,10438],{},[3324,10436,10437],{},"2000 листів\u002Fдень"," для Google Workspace",[3767,10440,10441,10442],{},"Максимальний розмір листа: ",[3324,10443,10444],{},"25 MB",[5079,10446,10448],{"label":10447},"Outlook \u002F Office 365",[3433,10449,10451],{"className":5084,"code":10450,"language":5086,"meta":5087,"style":3438},"\u002F\u002F Microsoft\u002FOutlook SMTP\n\u002F\u002F З жовтня 2022: Basic Auth вимкнено для Exchange Online\n\u002F\u002F Для продакшну — Modern Authentication (OAuth 2.0)\n\u002F\u002F Для тестування — smtp-mail.outlook.com ще підтримує Basic Auth\n\nusing var smtp = new SmtpClient(\"smtp-mail.outlook.com\")  \u002F\u002F Особисті @outlook.com\u002F@hotmail.com\n{\n    Port = 587,\n    EnableSsl = true,\n    Credentials = new NetworkCredential(\"yourname@outlook.com\", \"password\")\n};\n\n\u002F\u002F Для Office 365 \u002F Exchange Online (корпоративні акаунти):\nusing var office365Smtp = new SmtpClient(\"smtp.office365.com\")\n{\n    Port = 587,\n    EnableSsl = true,\n    Credentials = new NetworkCredential(\"user@company.onmicrosoft.com\", \"password\")\n};\n",[3440,10452,10453,10458,10463,10468,10473,10477,10502,10506,10516,10526,10547,10551,10555,10560,10581,10585,10595,10605,10626],{"__ignoreMap":3438},[3443,10454,10455],{"class":3445,"line":3446},[3443,10456,10457],{"class":5134},"\u002F\u002F Microsoft\u002FOutlook SMTP\n",[3443,10459,10460],{"class":3445,"line":3452},[3443,10461,10462],{"class":5134},"\u002F\u002F З жовтня 2022: Basic Auth вимкнено для Exchange Online\n",[3443,10464,10465],{"class":3445,"line":3458},[3443,10466,10467],{"class":5134},"\u002F\u002F Для продакшну — Modern Authentication (OAuth 2.0)\n",[3443,10469,10470],{"class":3445,"line":3464},[3443,10471,10472],{"class":5134},"\u002F\u002F Для тестування — smtp-mail.outlook.com ще підтримує Basic Auth\n",[3443,10474,10475],{"class":3445,"line":3471},[3443,10476,3468],{"emptyLinePlaceholder":3467},[3443,10478,10479,10481,10483,10485,10487,10489,10491,10493,10496,10499],{"class":3445,"line":3477},[3443,10480,5095],{"class":5094},[3443,10482,5143],{"class":5142},[3443,10484,6230],{"class":5146},[3443,10486,5150],{"class":5102},[3443,10488,5153],{"class":5142},[3443,10490,5156],{"class":5098},[3443,10492,5159],{"class":5102},[3443,10494,10495],{"class":5162},"\"smtp-mail.outlook.com\"",[3443,10497,10498],{"class":5102},")  ",[3443,10500,10501],{"class":5134},"\u002F\u002F Особисті @outlook.com\u002F@hotmail.com\n",[3443,10503,10504],{"class":3445,"line":3483},[3443,10505,5171],{"class":5102},[3443,10507,10508,10510,10512,10514],{"class":3445,"line":3489},[3443,10509,5176],{"class":5146},[3443,10511,5150],{"class":5102},[3443,10513,3896],{"class":5181},[3443,10515,5220],{"class":5102},[3443,10517,10518,10520,10522,10524],{"class":3445,"line":3495},[3443,10519,5192],{"class":5146},[3443,10521,5150],{"class":5102},[3443,10523,5197],{"class":5142},[3443,10525,5220],{"class":5102},[3443,10527,10528,10530,10532,10534,10536,10538,10541,10543,10545],{"class":3445,"line":3501},[3443,10529,5237],{"class":5146},[3443,10531,5150],{"class":5102},[3443,10533,5153],{"class":5142},[3443,10535,5244],{"class":5098},[3443,10537,5159],{"class":5102},[3443,10539,10540],{"class":5162},"\"yourname@outlook.com\"",[3443,10542,3668],{"class":5102},[3443,10544,6287],{"class":5162},[3443,10546,5166],{"class":5102},[3443,10548,10549],{"class":3445,"line":3507},[3443,10550,5283],{"class":5102},[3443,10552,10553],{"class":3445,"line":3513},[3443,10554,3468],{"emptyLinePlaceholder":3467},[3443,10556,10557],{"class":3445,"line":3518},[3443,10558,10559],{"class":5134},"\u002F\u002F Для Office 365 \u002F Exchange Online (корпоративні акаунти):\n",[3443,10561,10562,10564,10566,10569,10571,10573,10575,10577,10579],{"class":3445,"line":3524},[3443,10563,5095],{"class":5094},[3443,10565,5143],{"class":5142},[3443,10567,10568],{"class":5146}," office365Smtp",[3443,10570,5150],{"class":5102},[3443,10572,5153],{"class":5142},[3443,10574,5156],{"class":5098},[3443,10576,5159],{"class":5102},[3443,10578,6241],{"class":5162},[3443,10580,5166],{"class":5102},[3443,10582,10583],{"class":3445,"line":3530},[3443,10584,5171],{"class":5102},[3443,10586,10587,10589,10591,10593],{"class":3445,"line":3536},[3443,10588,5176],{"class":5146},[3443,10590,5150],{"class":5102},[3443,10592,3896],{"class":5181},[3443,10594,5220],{"class":5102},[3443,10596,10597,10599,10601,10603],{"class":3445,"line":3542},[3443,10598,5192],{"class":5146},[3443,10600,5150],{"class":5102},[3443,10602,5197],{"class":5142},[3443,10604,5220],{"class":5102},[3443,10606,10607,10609,10611,10613,10615,10617,10620,10622,10624],{"class":3445,"line":3548},[3443,10608,5237],{"class":5146},[3443,10610,5150],{"class":5102},[3443,10612,5153],{"class":5142},[3443,10614,5244],{"class":5098},[3443,10616,5159],{"class":5102},[3443,10618,10619],{"class":5162},"\"user@company.onmicrosoft.com\"",[3443,10621,3668],{"class":5102},[3443,10623,6287],{"class":5162},[3443,10625,5166],{"class":5102},[3443,10627,10628],{"class":3445,"line":3554},[3443,10629,5283],{"class":5102},[5079,10631,10633],{"label":10632},"SendGrid",[3433,10634,10636],{"className":5084,"code":10635,"language":5086,"meta":5087,"style":3438},"\u002F\u002F SendGrid — один із найпопулярніших транзакційних поштових сервісів\n\u002F\u002F Безкоштовний план: 100 листів\u002Fдень. Платні плани: від 40 000\u002Fмісяць.\n\u002F\u002F Автоматично налаштовує DKIM для вашого домену.\n\n\u002F\u002F SMTP-спосіб (простіший, але обмеженіший за HTTP API):\nusing var smtp = new SmtpClient(\"smtp.sendgrid.net\")\n{\n    Port = 587,           \u002F\u002F Або 465\n    EnableSsl = true,\n    Credentials = new NetworkCredential(\n        userName: \"apikey\",    \u002F\u002F Літерально рядок \"apikey\"\n        password: \"SG.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\"  \u002F\u002F Ваш SendGrid API Key\n    )\n};\n\nusing var message = new MailMessage\n{\n    From = new MailAddress(\"sender@yourdomain.com\", \"Your App\"),\n    Subject = \"Транзакційний лист\",\n    Body = \"\u003Ch1>Hello!\u003C\u002Fh1>\",\n    IsBodyHtml = true\n};\n\nmessage.To.Add(\"user@example.com\");\n\u002F\u002F Заголовки для SendGrid-аналітики (необов'язково):\nmessage.Headers.Add(\"X-SMTPAPI\",\n    \"\"\"{\"category\": [\"welcome_email\"], \"unique_args\": {\"user_id\": \"12345\"}}\"\"\");\n\nawait smtp.SendMailAsync(message);\n",[3440,10637,10638,10643,10648,10653,10657,10662,10683,10687,10700,10710,10722,10736,10748,10752,10756,10760,10774,10778,10800,10811,10822,10830,10834,10838,10856,10861,10881,10888,10892],{"__ignoreMap":3438},[3443,10639,10640],{"class":3445,"line":3446},[3443,10641,10642],{"class":5134},"\u002F\u002F SendGrid — один із найпопулярніших транзакційних поштових сервісів\n",[3443,10644,10645],{"class":3445,"line":3452},[3443,10646,10647],{"class":5134},"\u002F\u002F Безкоштовний план: 100 листів\u002Fдень. Платні плани: від 40 000\u002Fмісяць.\n",[3443,10649,10650],{"class":3445,"line":3458},[3443,10651,10652],{"class":5134},"\u002F\u002F Автоматично налаштовує DKIM для вашого домену.\n",[3443,10654,10655],{"class":3445,"line":3464},[3443,10656,3468],{"emptyLinePlaceholder":3467},[3443,10658,10659],{"class":3445,"line":3471},[3443,10660,10661],{"class":5134},"\u002F\u002F SMTP-спосіб (простіший, але обмеженіший за HTTP API):\n",[3443,10663,10664,10666,10668,10670,10672,10674,10676,10678,10681],{"class":3445,"line":3477},[3443,10665,5095],{"class":5094},[3443,10667,5143],{"class":5142},[3443,10669,6230],{"class":5146},[3443,10671,5150],{"class":5102},[3443,10673,5153],{"class":5142},[3443,10675,5156],{"class":5098},[3443,10677,5159],{"class":5102},[3443,10679,10680],{"class":5162},"\"smtp.sendgrid.net\"",[3443,10682,5166],{"class":5102},[3443,10684,10685],{"class":3445,"line":3483},[3443,10686,5171],{"class":5102},[3443,10688,10689,10691,10693,10695,10697],{"class":3445,"line":3489},[3443,10690,5176],{"class":5146},[3443,10692,5150],{"class":5102},[3443,10694,3896],{"class":5181},[3443,10696,10369],{"class":5102},[3443,10698,10699],{"class":5134},"\u002F\u002F Або 465\n",[3443,10701,10702,10704,10706,10708],{"class":3445,"line":3495},[3443,10703,5192],{"class":5146},[3443,10705,5150],{"class":5102},[3443,10707,5197],{"class":5142},[3443,10709,5220],{"class":5102},[3443,10711,10712,10714,10716,10718,10720],{"class":3445,"line":3501},[3443,10713,5237],{"class":5146},[3443,10715,5150],{"class":5102},[3443,10717,5153],{"class":5142},[3443,10719,5244],{"class":5098},[3443,10721,5247],{"class":5102},[3443,10723,10724,10726,10728,10731,10733],{"class":3445,"line":3507},[3443,10725,5252],{"class":5146},[3443,10727,5255],{"class":5102},[3443,10729,10730],{"class":5162},"\"apikey\"",[3443,10732,6899],{"class":5102},[3443,10734,10735],{"class":5134},"\u002F\u002F Літерально рядок \"apikey\"\n",[3443,10737,10738,10740,10742,10745],{"class":3445,"line":3513},[3443,10739,5265],{"class":5146},[3443,10741,5255],{"class":5102},[3443,10743,10744],{"class":5162},"\"SG.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\"",[3443,10746,10747],{"class":5134},"  \u002F\u002F Ваш SendGrid API Key\n",[3443,10749,10750],{"class":3445,"line":3518},[3443,10751,5278],{"class":5102},[3443,10753,10754],{"class":3445,"line":3524},[3443,10755,5283],{"class":5102},[3443,10757,10758],{"class":3445,"line":3530},[3443,10759,3468],{"emptyLinePlaceholder":3467},[3443,10761,10762,10764,10766,10768,10770,10772],{"class":3445,"line":3536},[3443,10763,5095],{"class":5094},[3443,10765,5143],{"class":5142},[3443,10767,5301],{"class":5146},[3443,10769,5150],{"class":5102},[3443,10771,5153],{"class":5142},[3443,10773,5308],{"class":5098},[3443,10775,10776],{"class":3445,"line":3542},[3443,10777,5171],{"class":5102},[3443,10779,10780,10782,10784,10786,10788,10790,10793,10795,10798],{"class":3445,"line":3548},[3443,10781,5317],{"class":5146},[3443,10783,5150],{"class":5102},[3443,10785,5153],{"class":5142},[3443,10787,5324],{"class":5098},[3443,10789,5159],{"class":5102},[3443,10791,10792],{"class":5162},"\"sender@yourdomain.com\"",[3443,10794,3668],{"class":5102},[3443,10796,10797],{"class":5162},"\"Your App\"",[3443,10799,5336],{"class":5102},[3443,10801,10802,10804,10806,10809],{"class":3445,"line":3554},[3443,10803,5341],{"class":5146},[3443,10805,5150],{"class":5102},[3443,10807,10808],{"class":5162},"\"Транзакційний лист\"",[3443,10810,5220],{"class":5102},[3443,10812,10813,10815,10817,10820],{"class":3445,"line":3559},[3443,10814,5353],{"class":5146},[3443,10816,5150],{"class":5102},[3443,10818,10819],{"class":5162},"\"\u003Ch1>Hello!\u003C\u002Fh1>\"",[3443,10821,5220],{"class":5102},[3443,10823,10824,10826,10828],{"class":3445,"line":3565},[3443,10825,5399],{"class":5146},[3443,10827,5150],{"class":5102},[3443,10829,9891],{"class":5142},[3443,10831,10832],{"class":3445,"line":3571},[3443,10833,5283],{"class":5102},[3443,10835,10836],{"class":3445,"line":3577},[3443,10837,3468],{"emptyLinePlaceholder":3467},[3443,10839,10840,10842,10844,10846,10848,10850,10852,10854],{"class":3445,"line":3583},[3443,10841,5471],{"class":5146},[3443,10843,3692],{"class":5102},[3443,10845,4630],{"class":5146},[3443,10847,3692],{"class":5102},[3443,10849,5481],{"class":5480},[3443,10851,5159],{"class":5102},[3443,10853,9916],{"class":5162},[3443,10855,5549],{"class":5102},[3443,10857,10858],{"class":3445,"line":3589},[3443,10859,10860],{"class":5134},"\u002F\u002F Заголовки для SendGrid-аналітики (необов'язково):\n",[3443,10862,10863,10865,10867,10870,10872,10874,10876,10879],{"class":3445,"line":3595},[3443,10864,5471],{"class":5146},[3443,10866,3692],{"class":5102},[3443,10868,10869],{"class":5146},"Headers",[3443,10871,3692],{"class":5102},[3443,10873,5481],{"class":5480},[3443,10875,5159],{"class":5102},[3443,10877,10878],{"class":5162},"\"X-SMTPAPI\"",[3443,10880,5220],{"class":5102},[3443,10882,10883,10886],{"class":3445,"line":3600},[3443,10884,10885],{"class":5162},"    \"\"\"{\"category\": [\"welcome_email\"], \"unique_args\": {\"user_id\": \"12345\"}}\"\"\"",[3443,10887,5549],{"class":5102},[3443,10889,10890],{"class":3445,"line":4077},[3443,10891,3468],{"emptyLinePlaceholder":3467},[3443,10893,10894,10896,10898,10900,10902,10904,10906],{"class":3445,"line":4083},[3443,10895,6163],{"class":5142},[3443,10897,6230],{"class":5146},[3443,10899,3692],{"class":5102},[3443,10901,5896],{"class":5480},[3443,10903,5159],{"class":5102},[3443,10905,5471],{"class":5146},[3443,10907,5549],{"class":5102},[5079,10909,10911],{"label":10910},"Локальний (Mailpit \u002F MailHog)",[3433,10912,10914],{"className":5084,"code":10913,"language":5086,"meta":5087,"style":3438},"\u002F\u002F Mailpit (сучасна альтернатива MailHog) або MailHog\n\u002F\u002F Для локального розробки: перехоплює всі листи, відображає у веб-UI\n\u002F\u002F Встановлення: docker run -p 1025:1025 -p 8025:8025 axllent\u002Fmailpit\n\u002F\u002F Веб-інтерфейс: http:\u002F\u002Flocalhost:8025\n\nusing var smtp = new SmtpClient(\"localhost\")\n{\n    Port = 1025,          \u002F\u002F SMTP порт Mailpit\u002FMailHog\n    EnableSsl = false,    \u002F\u002F Без TLS — лише локально\n    DeliveryMethod = SmtpDeliveryMethod.Network\n    \u002F\u002F Credentials не потрібні — Mailpit\u002FMailHog приймає без auth\n};\n\nusing var message = new MailMessage\n{\n    From = new MailAddress(\"test@myapp.local\", \"Test App\"),\n    Subject = \"Тест відправки\",\n    Body = \"\u003Ch2>Перевірка!\u003C\u002Fh2>\u003Cp>Листа перехоплено у Mailpit.\u003C\u002Fp>\",\n    IsBodyHtml = true\n};\n\nmessage.To.Add(\"developer@example.com\");\nawait smtp.SendMailAsync(message);\n\u002F\u002F Відкрийте http:\u002F\u002Flocalhost:8025 для перегляду листа\n",[3440,10915,10916,10921,10926,10931,10936,10940,10961,10965,10979,10992,11005,11010,11014,11018,11032,11036,11057,11068,11079,11087,11091,11095,11114,11130],{"__ignoreMap":3438},[3443,10917,10918],{"class":3445,"line":3446},[3443,10919,10920],{"class":5134},"\u002F\u002F Mailpit (сучасна альтернатива MailHog) або MailHog\n",[3443,10922,10923],{"class":3445,"line":3452},[3443,10924,10925],{"class":5134},"\u002F\u002F Для локального розробки: перехоплює всі листи, відображає у веб-UI\n",[3443,10927,10928],{"class":3445,"line":3458},[3443,10929,10930],{"class":5134},"\u002F\u002F Встановлення: docker run -p 1025:1025 -p 8025:8025 axllent\u002Fmailpit\n",[3443,10932,10933],{"class":3445,"line":3464},[3443,10934,10935],{"class":5134},"\u002F\u002F Веб-інтерфейс: http:\u002F\u002Flocalhost:8025\n",[3443,10937,10938],{"class":3445,"line":3471},[3443,10939,3468],{"emptyLinePlaceholder":3467},[3443,10941,10942,10944,10946,10948,10950,10952,10954,10956,10959],{"class":3445,"line":3477},[3443,10943,5095],{"class":5094},[3443,10945,5143],{"class":5142},[3443,10947,6230],{"class":5146},[3443,10949,5150],{"class":5102},[3443,10951,5153],{"class":5142},[3443,10953,5156],{"class":5098},[3443,10955,5159],{"class":5102},[3443,10957,10958],{"class":5162},"\"localhost\"",[3443,10960,5166],{"class":5102},[3443,10962,10963],{"class":3445,"line":3483},[3443,10964,5171],{"class":5102},[3443,10966,10967,10969,10971,10974,10976],{"class":3445,"line":3489},[3443,10968,5176],{"class":5146},[3443,10970,5150],{"class":5102},[3443,10972,10973],{"class":5181},"1025",[3443,10975,5406],{"class":5102},[3443,10977,10978],{"class":5134},"\u002F\u002F SMTP порт Mailpit\u002FMailHog\n",[3443,10980,10981,10983,10985,10987,10989],{"class":3445,"line":3495},[3443,10982,5192],{"class":5146},[3443,10984,5150],{"class":5102},[3443,10986,5230],{"class":5142},[3443,10988,6899],{"class":5102},[3443,10990,10991],{"class":5134},"\u002F\u002F Без TLS — лише локально\n",[3443,10993,10994,10996,10998,11000,11002],{"class":3445,"line":3501},[3443,10995,5208],{"class":5146},[3443,10997,5150],{"class":5102},[3443,10999,5213],{"class":5146},[3443,11001,3692],{"class":5102},[3443,11003,11004],{"class":5146},"Network\n",[3443,11006,11007],{"class":3445,"line":3507},[3443,11008,11009],{"class":5134},"    \u002F\u002F Credentials не потрібні — Mailpit\u002FMailHog приймає без auth\n",[3443,11011,11012],{"class":3445,"line":3513},[3443,11013,5283],{"class":5102},[3443,11015,11016],{"class":3445,"line":3518},[3443,11017,3468],{"emptyLinePlaceholder":3467},[3443,11019,11020,11022,11024,11026,11028,11030],{"class":3445,"line":3524},[3443,11021,5095],{"class":5094},[3443,11023,5143],{"class":5142},[3443,11025,5301],{"class":5146},[3443,11027,5150],{"class":5102},[3443,11029,5153],{"class":5142},[3443,11031,5308],{"class":5098},[3443,11033,11034],{"class":3445,"line":3530},[3443,11035,5171],{"class":5102},[3443,11037,11038,11040,11042,11044,11046,11048,11051,11053,11055],{"class":3445,"line":3536},[3443,11039,5317],{"class":5146},[3443,11041,5150],{"class":5102},[3443,11043,5153],{"class":5142},[3443,11045,5324],{"class":5098},[3443,11047,5159],{"class":5102},[3443,11049,11050],{"class":5162},"\"test@myapp.local\"",[3443,11052,3668],{"class":5102},[3443,11054,9858],{"class":5162},[3443,11056,5336],{"class":5102},[3443,11058,11059,11061,11063,11066],{"class":3445,"line":3542},[3443,11060,5341],{"class":5146},[3443,11062,5150],{"class":5102},[3443,11064,11065],{"class":5162},"\"Тест відправки\"",[3443,11067,5220],{"class":5102},[3443,11069,11070,11072,11074,11077],{"class":3445,"line":3548},[3443,11071,5353],{"class":5146},[3443,11073,5150],{"class":5102},[3443,11075,11076],{"class":5162},"\"\u003Ch2>Перевірка!\u003C\u002Fh2>\u003Cp>Листа перехоплено у Mailpit.\u003C\u002Fp>\"",[3443,11078,5220],{"class":5102},[3443,11080,11081,11083,11085],{"class":3445,"line":3554},[3443,11082,5399],{"class":5146},[3443,11084,5150],{"class":5102},[3443,11086,9891],{"class":5142},[3443,11088,11089],{"class":3445,"line":3559},[3443,11090,5283],{"class":5102},[3443,11092,11093],{"class":3445,"line":3565},[3443,11094,3468],{"emptyLinePlaceholder":3467},[3443,11096,11097,11099,11101,11103,11105,11107,11109,11112],{"class":3445,"line":3571},[3443,11098,5471],{"class":5146},[3443,11100,3692],{"class":5102},[3443,11102,4630],{"class":5146},[3443,11104,3692],{"class":5102},[3443,11106,5481],{"class":5480},[3443,11108,5159],{"class":5102},[3443,11110,11111],{"class":5162},"\"developer@example.com\"",[3443,11113,5549],{"class":5102},[3443,11115,11116,11118,11120,11122,11124,11126,11128],{"class":3445,"line":3577},[3443,11117,6163],{"class":5142},[3443,11119,6230],{"class":5146},[3443,11121,3692],{"class":5102},[3443,11123,5896],{"class":5480},[3443,11125,5159],{"class":5102},[3443,11127,5471],{"class":5146},[3443,11129,5549],{"class":5102},[3443,11131,11132],{"class":3445,"line":3583},[3443,11133,11134],{"class":5134},"\u002F\u002F Відкрийте http:\u002F\u002Flocalhost:8025 для перегляду листа\n",[3613,11136,11137,11142,11147,11156,11161],{},[3616,11138,11141],{"name":11139,"type":11140},"smtp.gmail.com","Google Gmail","Порт 587 (STARTTLS) або 465 (Implicit TLS). Вимагає App Password або OAuth 2.0. Ліміт: 500\u002Fдень (звичайний), 2000\u002Fдень (Workspace).",[3616,11143,11146],{"name":11144,"type":11145},"smtp.office365.com","Microsoft Office 365","Порт 587 (STARTTLS). Basic Auth вимкнено з 2022 — потрібен OAuth 2.0 для Exchange Online.",[3616,11148,11151,11152,11155],{"name":11149,"type":11150},"smtp.sendgrid.net","SendGrid (Twilio)","Порт 587 або 465. Username завжди ",[3440,11153,11154],{},"apikey",", password — SendGrid API Key. Безкоштовно: 100 листів\u002Fдень.",[3616,11157,11160],{"name":11158,"type":11159},"email-smtp.eu-west-1.amazonaws.com","Amazon SES","Порт 587 або 465. Credentials: SMTP credentials із консолі SES (не IAM!). Від 0.10$ за 1000 листів.",[3616,11162,11165],{"name":11163,"type":11164},"smtp.mailersend.com","MailerSend","Порт 587 або 465. Безкоштовно: 3000 листів\u002Fмісяць. Підтримує шаблони, аналітику, webhooks.",[3645,11167],{},[3312,11169,11171],{"id":11170},"підсумок","Підсумок",[3317,11173,11174],{},"Електронна пошта — це складна екосистема взаємодіючих протоколів. У цьому розділі ми вивчили:",[3764,11176,11177,11183,11189,11198,11212,11218],{},[3767,11178,11179,11182],{},[3324,11180,11181],{},"Архітектуру"," поштової інфраструктури: ролі MUA, MTA, MDA, DNS MX-записів",[3767,11184,11185,11188],{},[3324,11186,11187],{},"SMTP-протокол"," (RFC 5321): команди, відповіді, сесія, порти 25\u002F465\u002F587",[3767,11190,11191,11194,11195],{},[3324,11192,11193],{},"MIME-стандарт"," (RFC 2045–2049): структуру листа, заголовки, типи ",[3440,11196,11197],{},"multipart",[3767,11199,11200,5255,11202,3668,11204,3668,11206,3668,11208,3668,11210],{},[3324,11201,3737],{},[3440,11203,4671],{},[3440,11205,5024],{},[3440,11207,5043],{},[3440,11209,5056],{},[3440,11211,5066],{},[3767,11213,11214,11217],{},[3324,11215,11216],{},"Безпеку",": SPF, DKIM, DMARC — три рівні захисту від підробки адреси відправника",[3767,11219,11220,11223],{},[3324,11221,11222],{},"Практику",": налаштування Gmail, Office 365, SendGrid, локального тестування",[3321,11225,11226,11227,11229],{},"Для продакшн-систем із великим обсягом листів або потребою OAuth 2.0 розгляньте бібліотеку ",[3324,11228,3741],{}," — вона забезпечує повну підтримку IMAP4, POP3, SMTP, MIME, OAuth 2.0 та NTLM, і є рекомендованою Microsoft для нових .NET-проектів.",[11231,11232,11233],"style",{},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s8xlr, html code.shiki .s8xlr{--shiki-light:#AF00DB;--shiki-default:#C586C0;--shiki-dark:#C586C0}html pre.shiki code .sN1BT, html code.shiki .sN1BT{--shiki-light:#267F99;--shiki-default:#4EC9B0;--shiki-dark:#4EC9B0}html pre.shiki code .sHH4Y, html code.shiki .sHH4Y{--shiki-light:#000000;--shiki-default:#D4D4D4;--shiki-dark:#D4D4D4}html pre.shiki code .spJ8K, html code.shiki .spJ8K{--shiki-light:#008000;--shiki-default:#6A9955;--shiki-dark:#6A9955}html pre.shiki code .su1O8, html code.shiki .su1O8{--shiki-light:#0000FF;--shiki-default:#569CD6;--shiki-dark:#569CD6}html pre.shiki code .siwwj, html code.shiki .siwwj{--shiki-light:#001080;--shiki-default:#9CDCFE;--shiki-dark:#9CDCFE}html pre.shiki code .sbdoH, html code.shiki .sbdoH{--shiki-light:#A31515;--shiki-default:#CE9178;--shiki-dark:#CE9178}html pre.shiki code .sJj4R, html code.shiki .sJj4R{--shiki-light:#098658;--shiki-default:#B5CEA8;--shiki-dark:#B5CEA8}html pre.shiki code .s8Opu, html code.shiki .s8Opu{--shiki-light:#795E26;--shiki-default:#DCDCAA;--shiki-dark:#DCDCAA}html pre.shiki code .sD7JJ, html code.shiki .sD7JJ{--shiki-light:#000000FF;--shiki-default:#D4D4D4;--shiki-dark:#D4D4D4}html pre.shiki code .sjcCO, html code.shiki .sjcCO{--shiki-light:#EE0000;--shiki-default:#D7BA7D;--shiki-dark:#D7BA7D}html pre.shiki code .sLwNe, html code.shiki .sLwNe{--shiki-light:#0451A5;--shiki-default:#9CDCFE;--shiki-dark:#9CDCFE}",{"title":3438,"searchDepth":3452,"depth":3452,"links":11235},[11236,11239,11243,11247,11251,11256,11263,11264,11265],{"id":3314,"depth":3452,"text":3315,"children":11237},[11238],{"id":3607,"depth":3458,"text":3608},{"id":3649,"depth":3452,"text":3650,"children":11240},[11241,11242],{"id":3656,"depth":3458,"text":3657},{"id":3702,"depth":3458,"text":3703},{"id":3747,"depth":3452,"text":3748,"children":11244},[11245,11246],{"id":3761,"depth":3458,"text":3762},{"id":3837,"depth":3458,"text":3838},{"id":3925,"depth":3452,"text":3926,"children":11248},[11249,11250],{"id":4243,"depth":3458,"text":4244},{"id":4389,"depth":3458,"text":4390},{"id":4562,"depth":3452,"text":4563,"children":11252},[11253,11254,11255],{"id":4572,"depth":3458,"text":4573},{"id":4599,"depth":3458,"text":4600},{"id":4735,"depth":3458,"text":4736},{"id":4991,"depth":3452,"text":4992,"children":11257},[11258,11259,11260,11261,11262],{"id":5070,"depth":3458,"text":5071},{"id":6589,"depth":3458,"text":6590},{"id":8049,"depth":3458,"text":8050},{"id":8778,"depth":3458,"text":8779},{"id":9709,"depth":3458,"text":9710},{"id":9975,"depth":3452,"text":9976},{"id":10299,"depth":3452,"text":10300},{"id":11170,"depth":3452,"text":11171},"Детальне вивчення SMTP-протоколу — сесія, команди, аутентифікація, MIME, STARTTLS\u002FSMTPS; відправлення листів через System.Net.Mail у .NET 10; огляд суміжних протоколів IMAP та POP3.","md",null,{},{"title":1692,"description":11266},"FKSCJWQbqhIyY0Q1jWo1DJhYnC0yvFEjoeYIKxA7j7A",[11273,11275],{"title":1688,"path":1689,"stem":1690,"description":11274,"children":-1},"Глибоке вивчення механізмів стану в HTTP — cookies, атаки XSS\u002FCSRF\u002Fsession-fixation, Basic\u002FDigest\u002FBearer аутентифікація, JWT алгоритми, OAuth 2.0 з усіма grant-types, PKCE, TLS Handshake, HSTS, HTTP Security Headers, кешування ETag\u002FLast-Modified\u002Fstale-while-revalidate, CORS з credentialed-запитами та content negotiation.",{"title":1696,"path":1697,"stem":1698,"description":11276,"children":-1},"Детальне вивчення протоколу WebSocket — відкриття з'єднання, фреймування, opcodes, ping\u002Fpong, закриття, порівняння з Long Polling та SSE; безпека WSS; практичний проєкт чату на HttpListener та ClientWebSocket без сторонніх бібліотек.",1781795352413]