In my .net core hosted service console application, I am reading a database table, retrieving some values, and based on a status, I am sending emails. It is working as it is expected, I wonder if there are any improvements to make it better. So I would be glad if you can share your comments.
Thanks in advance.
Program.cs
using System.IO;
using System.Net;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Serilog;
using Serilog.Events;
using Serilog.Sinks.Email;
namespace SendEmail
{
class Program
{
static async Task Main(string[] args)
{
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Information()
.Enrich.FromLogContext()
.WriteTo.Console()
.WriteTo.File("log-.txt", rollingInterval: RollingInterval.Day)
.WriteTo.Email(new EmailConnectionInfo
{
FromEmail = "[email protected]",
ToEmail = "[email protected]",
MailServer = "smtp.yandex.com.tr",
NetworkCredentials = new NetworkCredential
{
UserName = "[email protected]",
Password = "123456"
},
EnableSsl = false,
Port = 587,
EmailSubject = "Send Email Service Error"
}, restrictedToMinimumLevel: LogEventLevel.Error, batchPostingLimit: 1)
.CreateLogger();
var builder = new HostBuilder()
.ConfigureServices((hostContext, services) =>
{
//Serilog
services.AddLogging(loggingBuilder =>
loggingBuilder.AddSerilog(dispose: true));
services.AddSingleton<IHostedService, BusinessService>();
//Setting up app settings configuration
var config = LoadConfiguration();
services.AddSingleton(config);
});
await builder.RunConsoleAsync();
}
private static IConfiguration LoadConfiguration()
{
var builder = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile(path: "serilog.json", optional: false, reloadOnChange: true);
return builder.Build();
}
}
}
BusinessService.cs
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using MailKit.Net.Smtp;
using MailKit.Security;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using MimeKit;
namespace SendEmail
{
public class BusinessService : IHostedService
{
private readonly IHostApplicationLifetime _applicationLifetime;
private readonly IConfiguration _configuration;
private readonly ILogger _logger;
public BusinessService(IHostApplicationLifetime applicationLifetime, IConfiguration configuration, ILogger<BusinessService> logger)
{
_applicationLifetime = applicationLifetime;
_configuration = configuration;
_logger = logger;
}
public async Task StartAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("Application starts: ");
await GetData();
//Stop Application
_applicationLifetime.StopApplication();
_logger.LogInformation("Application stops: ");
}
private async Task SendEmailAsync(string email, string serial, string pin, long id)
{
var emailMessage = new MimeMessage();
emailMessage.From.Add(new MailboxAddress("Test","[email protected]" ));
emailMessage.To.Add(new MailboxAddress("", email));
emailMessage.Subject = "Test Codes";
emailMessage.Body = new TextPart("html") { Text = serial +" " + pin };
try
{
var client = new SmtpClient();
await client.ConnectAsync("smtp.gmail.com", 465, true);
await client.AuthenticateAsync("[email protected]", "12345");
await client.SendAsync(emailMessage);
await client.DisconnectAsync(true);
//Update Table
await UpdateData(id);
}
catch (Exception ex)
{
_logger.LogError("Error: {Error} ", ex.Message);
throw; // Throw exception if this exception is unexpected
}
}
private async Task GetData()
{
var connString = _configuration["ConnectionStrings:Development"];
await using var sqlConnection = new SqlConnection(connString);
sqlConnection.Open();
await using var command = new SqlCommand {Connection = sqlConnection};
const string sql = @"Select ID, Email, Serial, Pin from Orders where status = 1";
command.CommandText = sql;
try
{
await using var reader = await command.ExecuteReaderAsync();
while (reader.Read())
{
_logger.LogInformation("Order {ID} , {Email}, {Serial}, {Pin} ", reader.GetInt32(0).ToString(), reader.GetString(1), reader.GetString(2), reader.GetString(3));
await SendEmailAsync(reader.GetString(1).Trim(), reader.GetString(2).Trim(), reader.GetString(3).Trim(), reader.GetInt32(0));
}
}
catch (SqlException exception)
{
_logger.LogError("Error: {Error} ", exception.Message);
throw; // Throw exception if this exception is unexpected
}
}
private async Task UpdateData(long id)
{
var connString = _configuration["ConnectionStrings:Development"];
await using var sqlConnection = new SqlConnection(connString);
sqlConnection.Open();
await using var command = new SqlCommand {Connection = sqlConnection};
const string sql = @"Update Orders set status = 2, Date = GetDate() where id = @id";
command.CommandText = sql;
command.Parameters.Add(new SqlParameter("id", id));
try
{
await command.ExecuteNonQueryAsync();
}
catch (SqlException exception)
{
_logger.LogError("Error: {Error} ", exception.Message);
throw; // Throw exception if this exception is unexpected
}
}
public Task StopAsync(CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
}
}