GitHub
Tests: 12 • Commercial: 2 • Pet projects: 4 • Legacy: 4
Total: 22

.NET Framework

Test
2021

Project Request

ASP.NET MVC • C# • SQL Server
Idea of the project: if someone wants to order a project development, here you can send an application.
Test
2020

ProjectC

ASP.NET MVC • C# • JSON • jQuery
JSON data processing.
Test
2020

Vehicle Maintenance

ASP.NET MVC • VB.NET • JSON
Idea of the project: if someone wants to order a project development, here you can send an application.
Test
2019

Movie Navigator

ASP.NET MVC • VB.NET
Request information about movie from IMDB.
Test
2018

Customers Exchange

ASP.NET MVC • C# • SQL Server
Automated teller machine emulation.
Test
2016

ATM

ASP.NET MVC • C#
Automated teller machine emulation.

.NET Core

Pet project
2022

Mail Daemon

.NET 9 • Console • JSON • Serilog
Utility to send mails with customizable settings.

Custom

Code
2024

Buns of code

.NET Framework • C# • JavaScript
Code snippets from my projects, ready to use; tiny tests; code examples.

PHP

Test
2024

Mediabox

PHP 8 • Laravel 11 • Vue.js • Composer • SQLite
Test project for media files management.
Test
2020

Loan Castle

PHP • MariaDB
Jums jāizstrādā kāda lielāk projekta prototips. Izstrādājot prototipu, paturiet prātā, ka projektam attīstoties, šo prototipu varētu vajadzēt pilnveidot.
Test
2020

Content Management

PHP • MySQL • AJAX
Создать простой сайт, где будет страница с формой для авторизации и страница для авторизованного пользователя.
Test
2019

Laravel

PHP • Laravel • Vue.js • Composer • SQLite
Izveidot aplikāciju, kura ik pēc noteikta intervāla (60 sekundes) veic ierakstu datubāzē izmantojot Laravel freimworka iebūvēto funkcionalitāti.
Test
2019

Phone Check

PHP • JavaScript • JSON • Docker
Implement application to detect country by phone number.

Frontend

Test
2021

Forex Wall

npm • React • Angular • Vue • Svelte
For this exercise, what we need is a simple live wall for tracking currencies.

Business projects

Commercial
2008

Certification Center

.NET Framework 4.8 • ASP.NET Web Forms • C# • LINQ • SQL Server • ADO.NET • Dapper • JavaScript • jQuery • Git
Transport registration and certification services in Latvia, Customer Relationship Management.
Commercial
2000

Amerikas Auto

.NET Framework 4.8 • ASP.NET Web Forms • C# • LINQ • SQL Server • ADO.NET • Entity Framework • JavaScript • jQuery • Git
Car service and spare parts for all USA and European car models, Customer Relationship Management.

Pet projects

Pet project
2023

Geolocation Assistant

.NET 8 • ASP.NET Core • C# • Web API • JSON • Git
Website for determining geolocation by IP or geotagged photo.
Pet project
2008

Web Dynamics

.NET Framework 4.8 • ASP.NET Web Forms • C# • LINQ • Web API • JSON • SQL Server • Dapper • JavaScript • jQuery • SVG • Git
Software development blog. Articles, books, videos, content management.
Pet project
2000

Blackball

.NET Framework 4.8 • ASP.NET Web Forms • C# • LINQ • Web API • JSON • XML • SQL Server • Dapper • JavaScript • jQuery • SVG • Git
My entertainment portal created from scratch.

Good old times

Legacy
2000

DOS Clock

Turbo Pascal • Assembler
Digital clock.
Legacy
2000

BrainOut

Turbo Pascal • Assembler
Tank battle game.
Legacy
1999

Airport Administrator

Turbo Pascal
Курсовая работа в институте.
Legacy
1998

Atomizer

Turbo Pascal • Assembler
Atomizer, aka «Studio2D». Graphic raster editor. AGI is my own «Atomizer Generated Image» file format.

Mail Daemon

2022-2025 Pet project

Utility to send mails with customizable settings.

.NET 9 Console JSON Serilog
Information
Source code
Root / MailDaemon.ConsoleApp / Program.cs
using Microsoft.Extensions.Configuration; using System; using System.IO; using System.Linq; using System.Net.Mail; using System.Security.Cryptography.X509Certificates; using System.Text; using System.Threading; using MailDaemon.Core; using MailDaemon.Lib; using Serilog; using Serilog.Events; using Serilog.Formatting.Json; using System.Diagnostics; namespace MailDaemon.ConsoleApp { internal class Program { private static SettingsInfo SettingsInfo; private static IMailDaemonService mailDaemonService; private static IMailProfileService mailProfileService; private static IMailMessageService mailMessageService; private static MailProfile mailProfile; private static MailAgent mailAgent = new(); private static bool DisplayHelp;         private static string PreviewsDirPath { get; set; }         private static string ReportsDirPath { get; set; }         //private static string AppDir { get; set; } private static void Main(string[] args) { var configBuilder = new ConfigurationBuilder()                 .SetBasePath(AppContext.BaseDirectory)                 .AddJsonFile("appSettings.json", optional: false); var config = configBuilder.Build(); Log.Logger = new LoggerConfiguration() .WriteTo.File("logs\\log.txt", restrictedToMinimumLevel: LogEventLevel.Debug, rollingInterval: RollingInterval.Day) .MinimumLevel.Debug() .ReadFrom.Configuration(config) .CreateLogger(); Log.Information("Start application.");             SettingsInfo = new SettingsInfo();             mailDaemonService = new MailDaemonService();             mailProfileService = new JsonMailProfileService(); mailMessageService = new MailMessageService(); mailAgent = new MailAgent(); SettingsInfo.AppDirectory = AppDomain.CurrentDomain.BaseDirectory; mailProfile = new MailProfile(); try { // settings can be loaded from another source, e.g. database. SettingsInfo.MailProfile = config["App:MailProfile"]; mailProfile.MailBodyTemplateFileName = SettingsInfo.MailProfile; Log.Information($"Profile template: \"{mailProfile.MailBodyTemplateFileName}\""); SettingsInfo.SmtpHost = config["MailServer:SmtpHost"]; SettingsInfo.SmtpPort = Convert.ToInt32(config["MailServer:SmtpPort"]); SettingsInfo.SmtpUsername = config["MailServer:SmtpUsername"]; SettingsInfo.SmtpPassword = config["MailServer:SmtpPassword"]; SettingsInfo.SmtpEnableSSL = Convert.ToBoolean(config["MailServer:SmtpEnableSSL"]); if (mailProfile.Operator is not null && !string.IsNullOrEmpty(mailProfile.Operator.Address)) { SettingsInfo.Operator = new SenderInfo { Address = mailProfile.Operator.Address, Name = mailProfile.Operator.Name }; } else { SettingsInfo.Operator = new SenderInfo { Address = config["Operator:address"], Name = config["Operator:name"] }; } // set SMTP server information mailAgent.SmtpHost = SettingsInfo.SmtpHost; mailAgent.SmtpPort = SettingsInfo.SmtpPort; mailAgent.SmtpUsername = SettingsInfo.SmtpUsername; mailAgent.SmtpPassword = SettingsInfo.SmtpPassword; mailAgent.SmtpEnableSSL = SettingsInfo.SmtpEnableSSL; } catch (Exception ex) { Log.Fatal(GenerateExceptionDetails(ex)); } if (args.Length > 0)             { Log.Information($"Command line args: mail-daemon {string.Join(" ", args)}");                 try { var argIndex = 0; foreach (var arg in args) { switch (arg.ToLower()) { case "-v": mailDaemonService.JustValidate = true; break; case "-d": mailDaemonService.SendDemo = true; break; case "-gp": mailDaemonService.GeneratePreview = true; break; case "-p": //mailProfileService.MailProfilePath = Path.Combine(AppDir, "MailProfiles", args[argIndex + 1]); // TBD: remove mailDaemonService.MailProfileFilename assignment //mailDaemonService.MailProfileFilename = Path.Combine(AppDir, "MailProfiles", args[argIndex + 1]); mailProfile.MailBodyTemplateFileName = Path.Combine(SettingsInfo.AppDirectory, SettingsInfo.MailProfilesDirectory, args[argIndex + 1]); Log.Information($"Profile new template: \"{mailProfile.MailBodyTemplateFileName}\""); break; case "-h": DisplayHelp = true; break; } argIndex++; } }                 catch (Exception ex)                 {                     DisplayErrorMessage(ex.Message);                     return;                 }             } if (DisplayHelp) { Console.WriteLine("Description:"); Console.WriteLine("-v\t\tValidation mode to verify mail profile integrity. With this argument mails not sending to recipients."); Console.WriteLine("-d\t\tSend demo mail only to sender. With this argument mails not sending to recipients."); Console.WriteLine("-gp\t\tCreate files on disk with generated mails for each recipient."); Console.WriteLine("-p\t\tSet name of the mail profile."); WaitForExit(); return; } //if (!string.IsNullOrEmpty(mailDaemonService.MailProfileFilename) && !File.Exists(mailDaemonService.MailProfileFilename)) //{ // DisplayErrorMessage($"Mail profile \"{mailDaemonService.MailProfileFilename}\" not exists."); // return; //} // TBD: Think about whether someone needs this information //Console.WriteLine("=== Mail Daemon 0.8 ==="); //Console.WriteLine("Author:\t\tSergey Drozdov"); //Console.WriteLine("Email:\t\tsergey.drozdov.0305@gmail.com"); //Console.WriteLine("Website:\thttps://sd.blackball.lv/sergey-drozdov"); //Console.Write(Environment.NewLine); if (mailDaemonService.JustValidate)             {                 Console.ForegroundColor = ConsoleColor.Yellow;                 Console.WriteLine("--- Validation mode: do not send any mail. Just validate mail profile and recipients.");                 Console.WriteLine("");                 Console.ResetColor();             } Log.Information($"AppDir: {SettingsInfo.AppDirectory}"); // if (string.IsNullOrEmpty(mailProfileService.MailProfilePath)) // mailProfileService.MailProfilePath = Path.Combine(AppDir, "MailProfiles", settingsInfo.MailProfile); //Console.ForegroundColor = ConsoleColor.Yellow; //Console.WriteLine($"--- Mail profile: \"{mailProfileService.MailProfilePath}\""); //Console.ResetColor(); //if (string.IsNullOrEmpty(mailProfile.MailBodyTemplateFileName)) //{ // mailProfile.MailBodyTemplateFileName = SettingsInfo.MailProfile; //} try { //mailDaemonService.MailProfile = mailProfileService.ReadProfile(); mailProfile = mailProfileService.ReadProfile(Path.Combine(SettingsInfo.AppDirectory, SettingsInfo.MailProfilesDirectory, SettingsInfo.MailProfile)); } catch (Exception ex) { Log.Fatal(GenerateExceptionDetails(ex)); DisplayErrorMessage(ex.Message); WaitForExit(); return; } if (mailProfile.MailBodyTemplateFileName.StartsWith(".\\")) mailProfile.MailBodyTemplateFullPath = Path.Combine(SettingsInfo.AppDirectory, mailProfile.MailBodyTemplateFileName.Replace(".\\", "")); else mailProfile.MailBodyTemplateFullPath = Path.Combine(SettingsInfo.AppDirectory, SettingsInfo.MailProfilesDirectory, mailProfile.MailBodyTemplateFileName); var profileValidation = mailProfileService.ValidateMailProfile(mailProfile); if (profileValidation.Count > 0) { // show errors if (profileValidation.Any(x => x.Level == ValidationLevel.Error)) { SetErrorMessagesStyle(); Console.WriteLine(""); Console.WriteLine("Errors:"); foreach (var item in profileValidation.Where(x => x.Level == ValidationLevel.Error)) { DisplayErrorMessage(item.Message); } } // show warnings if (profileValidation.Any(x => x.Level == ValidationLevel.Warning)) { SetWarningMessagesStyle(); Console.WriteLine(""); Console.WriteLine("Warnings:"); foreach (var item in profileValidation.Where(x => x.Level == ValidationLevel.Warning)) { DisplayWarningMessage(item.Message); } } // if mail profile contains errors - stop execution if (mailDaemonService.Errors.Count > 0) { WaitForExit(); return; } // if mail profile contains warnings - ask user to continue or not if (profileValidation.Any(x => x.Level == ValidationLevel.Warning)) { Console.WriteLine(""); Console.Write("Continue? [Y/N]"); var confirmed = false; string key; while (!confirmed) { key = Console.ReadLine().ToLower(); if (key == "y") { confirmed = true; } if (key == "n") { WaitForExit(); return; } } } } //mailDaemonService.ValidateMailProfile(); //ReportsDirPath = Path.Combine(AppDir, "reports"); //if (!Directory.Exists(ReportsDirPath)) // Directory.CreateDirectory(ReportsDirPath); if (mailDaemonService.GeneratePreview) { try { PreviewsDirPath = Path.Combine(SettingsInfo.AppDirectory, "previews", Path.GetFileName(SettingsInfo.MailProfile)); if (!Directory.Exists(PreviewsDirPath)) Directory.CreateDirectory(PreviewsDirPath); else { foreach (var filePath in Directory.EnumerateFiles(PreviewsDirPath)) { File.Delete(filePath); } } } catch (Exception ex) { Log.Fatal(GenerateExceptionDetails(ex)); DisplayErrorMessage(ex.Message); WaitForExit(); return; } } // mailDaemonService.Operator.Address = config["Operator:address"]; // mailDaemonService.Operator.Name = config["Operator:name"]; // if (mailDaemonService.MailProfile.MailBodyTemplateFileName.StartsWith(".\\"))             //    mailDaemonService.MailProfile.MailBodyTemplateFileName = Path.Combine(AppDir, mailDaemonService.MailProfile.MailBodyTemplateFileName.Replace(".\\", "")); try { mailProfile.MailBody = mailProfileService.ReadMailBodyTemplate(mailProfile.MailBodyTemplateFullPath); } catch (Exception ex) { Log.Fatal(GenerateExceptionDetails(ex)); WaitForExit(); return; } // perform recipients var counter = 0;             var recipientsReport = new StringBuilder();             foreach (var recipient in mailProfile.Recipients)             {                 var recipientReportInfo = new StringBuilder();                 try { recipient.MailBodyTemplateFileName = mailProfile.MailBodyTemplateFileName; recipient.MailBody = mailProfile.MailBody; // TBD: add support for HTML and plain text files if (!string.IsNullOrEmpty(recipient.MailBodyTemplateFullPath)) { recipient.MailBodyTemplateFileName = mailProfile.MailBodyTemplateFullPath; recipient.MailBody = mailDaemonService.ReadMailBodyTemplate(recipient.MailBodyTemplateFullPath); } var mailMessage = mailMessageService.GenerateMailMessage(SettingsInfo.Operator, mailProfile, recipient); // display mail sending process counter++; if (recipient.Skip.GetValueOrDefault()) Console.ForegroundColor = ConsoleColor.DarkGray;                     else Console.ForegroundColor = ConsoleColor.White; //Console.WriteLine($"({counter}) {recipient.Company?.ToUpper()} {recipient.Name}"); Console.WriteLine($"({counter}) {recipient.Name}"); Console.WriteLine($"Mail: {recipient.Address}");                     Console.WriteLine($"Subject: {mailMessage.Subject}");                     Console.WriteLine($"Template: {(!string.IsNullOrEmpty(recipient.MailBodyTemplateFileName) ? recipient.MailBodyTemplateFileName : mailDaemonService.MailProfile.MailBodyTemplateFileName)}"); if (recipient.Skip.GetValueOrDefault()) recipientReportInfo.AppendLine("<div style=\"color: #999\">"); //recipientReportInfo.AppendLine($"({counter}) {recipient.Company?.ToUpper()} {recipient.Name} <a href=\"mailto:{recipient.Address}\">{recipient.Address}</a>"); recipientReportInfo.AppendLine($"({counter}) {recipient.Name} <a href=\"mailto:{recipient.Address}\">{recipient.Address}</a>");                     recipientReportInfo.AppendLine($"<div>Subject: {mailMessage.Subject}</div>");                     if (!string.IsNullOrEmpty(recipient.MailBodyTemplateFileName) && recipient.MailBodyTemplateFileName != mailDaemonService.MailProfile.MailBodyTemplateFileName)                     recipientReportInfo.AppendLine($"<div>Template: {recipient.MailBodyTemplateFileName}</div>"); // recipient related attachments use at first if (recipient.Attachments != null) { foreach (var attachment in recipient.Attachments) { if (File.Exists(attachment.Path)) { Console.WriteLine($"\tAttachment: \"{attachment.Path}\""); recipientReportInfo.AppendLine($"<div style=\"padding-left: 40px\">Attachment: \"{attachment.Path}\"</div>"); } else { DisplayWarningMessage($"\tAttachment: file \"{attachment.Path}\" not exists."); recipientReportInfo.AppendLine($"<div style=\"padding-left: 40px; color: #aa0000\">Attachment: file \"{attachment.Path}\" not exists.</div>"); } } } // attachments if (mailDaemonService.MailProfile.Attachments != null)                     {                         foreach (var attachment in mailDaemonService.MailProfile.Attachments)                         {                             if (File.Exists(attachment.Path))                             {                                 Console.WriteLine($"\tAttachment: \"{attachment.Path}\"");                                 recipientReportInfo.AppendLine($"<div style=\"padding-left: 40px\">Attachment: \"{attachment.Path}\"</div>");                             }                             else                             {                                 DisplayWarningMessage($"\tAttachment: file \"{attachment.Path}\" not exists.");                                 recipientReportInfo.AppendLine($"<div style=\"padding-left: 40px\">Attachment: file \"{attachment.Path}\" not exists.</div>");                             }                         }                     } if (recipient.Skip.GetValueOrDefault()) { recipientReportInfo.AppendLine("--- Skipped ---"); recipientReportInfo.AppendLine("</div>"); } if (mailDaemonService.SendDemo)                     {                         Console.ForegroundColor = ConsoleColor.Cyan;                         Console.WriteLine($"--- Send demo to sender address: {mailDaemonService.MailProfile.Sender.Address} ---");                         Console.ResetColor(); } if (mailDaemonService.GeneratePreview) { Console.ForegroundColor = ConsoleColor.Cyan; Console.WriteLine($"--- Create file \"{recipient.Address}.html\" with preview ---"); Console.ResetColor(); try { var fileNamePrefix = "";                             if (recipient.Skip.GetValueOrDefault()) fileNamePrefix = "(skipped)_"; var previewFilePath = Path.Combine(PreviewsDirPath, $"{fileNamePrefix}{recipient.Address}{Path.GetExtension(recipient.MailBodyTemplateFileName)}"); File.WriteAllText(previewFilePath, mailMessage.Body); } catch (Exception ex) { Log.Error(GenerateExceptionDetails(ex)); DisplayErrorMessage(ex.Message); } } if (!mailDaemonService.JustValidate)                     { if (recipient.Skip.GetValueOrDefault()) { Console.ForegroundColor = ConsoleColor.Cyan; Console.WriteLine("--- Skipped ---"); Console.ResetColor(); Console.WriteLine(""); } else { var mailSendResult = mailAgent.Send(mailMessage);                          if (!mailSendResult.Success)                          {                              DisplayErrorMessage(mailSendResult.Message);                          }                          else                          {                              Console.ForegroundColor = ConsoleColor.Green;                              Console.WriteLine("--- Sent ---");                              Console.ResetColor();                              Console.WriteLine("");                          } }                     } else { if (recipient.Skip.GetValueOrDefault()) { Console.ForegroundColor = ConsoleColor.Cyan; Console.WriteLine("--- Skipped ---"); Console.ResetColor(); }                         Console.WriteLine(""); } }                 catch (Exception ex)                 {                     DisplayErrorMessage(ex.InnerException != null ? ex.InnerException.Message : ex.Message);                     Console.WriteLine("--- Error ---");                     Console.WriteLine("");                 }                 recipientReportInfo.AppendLine("<br/>");                 recipientsReport.AppendLine(recipientReportInfo.ToString());                 Thread.Sleep(mailDaemonService.SendSleep);             } var report = GenerateReport(mailDaemonService, recipientsReport); try { var reportFilePath = Path.Combine(ReportsDirPath, $"report_{Path.GetFileName(mailDaemonService.MailProfileFilename)}_{DateTime.Now:dd.MM.yyyy_HH-mm}.html"); File.WriteAllText(reportFilePath, report); } catch (Exception ex) { Log.Error(GenerateExceptionDetails(ex));          DisplayWarningMessage(ex.Message); Console.Write("Press any key to continue..."); Console.ReadKey(); } if (!mailDaemonService.JustValidate)             {                 // send status report to sender                 try                 { var mailMessage = new MailMessage(); mailMessage.To.Add(mailDaemonService.GetMailAddress(SettingsInfo.Operator.Address, SettingsInfo.Operator.Name)); mailMessage.From = mailDaemonService.GetMailAddress(mailDaemonService.MailProfile.Sender.Address, mailDaemonService.MailProfile.Sender.Name); mailMessage.ReplyToList.Add(mailMessage.From); mailMessage.Headers.Add("Reply-To", mailDaemonService.MailProfile.Sender.Address); mailMessage.Subject = "Mail Daemon: mails has been sent"; mailMessage.SubjectEncoding = Encoding.UTF8; mailMessage.IsBodyHtml = true; mailMessage.BodyEncoding = Encoding.UTF8; mailMessage.Body = report; mailAgent.Send(mailMessage); Console.ForegroundColor = ConsoleColor.Yellow;                     Console.WriteLine("--- Mails has been sent ---");                     Console.ForegroundColor = ConsoleColor.White;                 }                 catch (Exception ex)                 {                     DisplayErrorMessage(ex.InnerException != null ? ex.InnerException.Message : ex.Message);                     Console.WriteLine("--- Error ---");                 }                 Thread.Sleep(5000);             }             else             {                 WaitForExit();             }             if (mailDaemonService.SendDemo) WaitForExit();         } private static string GenerateExceptionDetails(Exception ex) { var st = new StackTrace(ex, true); var frame = st.GetFrame(0); var fileName = frame.GetFileName(); var methodName = frame.GetMethod().Name; var line = frame.GetFileLineNumber(); var col = frame.GetFileColumnNumber(); return $"File name: {fileName}{Environment.NewLine}Method: {methodName}{Environment.NewLine}Line: {line}{Environment.NewLine}Columns: {col}{Environment.NewLine}{ex}"; } private static string GenerateReport(IMailDaemonService mailDaemonService, StringBuilder recipientsReport) { var report = new StringBuilder(); report.AppendLine("<!DOCTYPE html>"); report.AppendLine("<html>"); report.AppendLine("<head>"); report.AppendLine("<meta charset=\"utf-8\" />"); report.AppendLine("<title>Mail Daemon report</title>"); report.AppendLine("</head>"); report.AppendLine("<body>"); report.AppendLine($"<div>{mailDaemonService.MailProfile.Recipients.Count} mails has been sent.</div>"); report.AppendLine($"<div>Mail profile: \"{mailDaemonService.MailProfileFilename}\"</div>"); report.AppendLine($"<div>Mail template: \"{mailDaemonService.MailProfile.MailBodyTemplateFileName}\"</div>"); report.AppendLine("<br/>"); report.AppendLine($"<div><strong>Recipients:</strong></div>"); report.AppendLine($"<div>{recipientsReport}</div>"); report.AppendLine("</body>"); report.AppendLine("</html>"); return report.ToString(); } private static void SetErrorMessagesStyle()         {             Console.ForegroundColor = ConsoleColor.Red;         }         private static void SetWarningMessagesStyle()         {             Console.ForegroundColor = ConsoleColor.Magenta;         }         private static void DisplayErrorMessage(string message)         {             Console.ForegroundColor = ConsoleColor.Red;             Console.WriteLine(message);             Console.ResetColor();         }         private static void DisplayWarningMessage(string message)         {             Console.ForegroundColor = ConsoleColor.Magenta;             Console.WriteLine(message);             Console.ResetColor();         }         private static void WaitForExit()         {             Console.ForegroundColor = ConsoleColor.White;             Console.WriteLine("");             Console.Write("Press any key to exit...");             Console.ReadKey();         }     } }