laatzen/Common/PendingEmails/Program.cs
2025-05-23 15:14:06 +02:00

270 lines
9.3 KiB
C#

namespace PendingEmails
{
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.IO;
using System.Linq;
using System.Net.Mail;
using System.Threading;
public static partial class Program
{
private static void Main()
{
try
{
var awaiter = new ManualResetEventSlim();
while (true)
{
if (!AppSettings.TryLoadExeConfiguration(out var errors))
{
WriteLine(new string('=', 50));
foreach (var error in errors)
{
WriteLine(error);
}
}
else
{
WriteLine(new string('=', 50));
using (var connection = new SqlConnection(AppSettings.MSSQLConnectionString))
{
OpenConnection(connection);
FindWarantyEmails(connection);
var messages = FindPendingEmails(connection);
if (messages.Count <= 0)
{
WriteLine($"Keine neue nachrichten gefunden.");
}
var invalidMessages = messages.Where(x => !x.IsValid).ToList();
if (invalidMessages.Count > 0)
{
WriteLine($"{invalidMessages.Count} von {messages.Count} ungültige nachrichten gefunden.");
var rowsAffected = SetOutDate(connection, invalidMessages.Select(x => x.Id));
WriteLine($"{rowsAffected} von {invalidMessages.Count} wurden als gesended markiert.");
}
else
{
WriteLine($"Keine neue ungültige nachrichten gefunden.");
}
var validMessages = messages
.Where(x => x.IsValid)
.ToList();
if (validMessages.Count > 0)
{
WriteLine($"{validMessages.Count} von {messages.Count} gültige nachrichten gefunden.");
SendEmails(connection, validMessages);
}
}
}
awaiter.Wait(AppSettings.Interval);
awaiter.Reset();
}
}
catch (Exception e)
{
WriteLine(e.ToString());
}
}
private static void OpenConnection(SqlConnection connection)
{
connection.FireInfoMessageEventOnUserErrors = true;
connection.InfoMessage += (_, args) => WriteLine(args.Message);
connection.Open();
}
private static void SendEmails(SqlConnection connection, List<Message> messages)
{
var sentEmails = new List<int>();
var excludedRecipients = AppSettings
.ExcludeRecipients
.ToEmailList();
foreach (var message in messages)
{
try
{
var recipients = message
.Recipients
.ToEmailList()
.Except(excludedRecipients)
.ToList();
if (recipients.Count <= 0)
{
break;
}
var recipientsCC = message
.RecipientsCC
.ToEmailList()
.Except(excludedRecipients)
.ToList();
var emailMessage = new MailMessage
{
From = new MailAddress(AppSettings.Sender),
Subject = message.Subject,
Body = message.Body
};
recipients.ForEach(emailMessage.To.Add);
recipientsCC.ForEach(emailMessage.CC.Add);
using (var smtpClient = new SmtpClient(AppSettings.SMTPHost, AppSettings.SMTPPort))
{
smtpClient.UseDefaultCredentials = true;
smtpClient.Send(emailMessage);
}
sentEmails.Add(message.Id);
WriteLine($"Nachricht: {message.Id} wurde gesendet.");
}
catch (Exception e)
{
WriteLine(e.ToString());
}
}
if (sentEmails.Count > 0)
{
WriteLine($"Gesendet {sentEmails.Count} von {messages.Count}");
var rowsAffected = SetOutDate(connection, sentEmails);
WriteLine($"{rowsAffected} von {messages.Count} wurden als gesended markiert.");
}
else
{
WriteLine($"Keine nachrichten gesendet.");
}
}
private static int SetOutDate(SqlConnection connection, IEnumerable<int> messageIds)
{
var rowsAffected = default(int);
using (var command = connection.CreateCommand())
{
command.CommandText = $@"
UPDATE Messages
SET OutDate = GETDATE()
WHERE Id IN ({string.Join(", ", messageIds)})";
rowsAffected = command.ExecuteNonQuery();
}
return rowsAffected;
}
private static List<Message> FindPendingEmails(SqlConnection connection)
{
var messages = new List<Message>();
using (var command = connection.CreateCommand())
{
command.CommandText = @"
SELECT Id
, Sender
, Subject
, Body
, Recipients
, CC
FROM Messages
WHERE OutDate IS NULL
ORDER BY InDate DESC";
using (var reader = command.ExecuteReader())
{
while (reader.Read())
{
var messageId = reader.GetValue<int>(0);
var sender = reader.GetValue<string>(1);
var subject = reader.GetValue<string>(2);
var body = reader.GetValue<string>(3);
var recipients = reader.GetValue<string>(4);
var recipientsCC = reader.GetValue<string>(5);
messages.Add(new Message(messageId, sender, subject, body, recipients, recipientsCC));
}
}
}
return messages;
}
private static void FindWarantyEmails(SqlConnection connection)
{
using (var command = connection.CreateCommand())
{
command.CommandTimeout = 60000;
command.CommandType = CommandType.StoredProcedure;
command.CommandText = @"SP_EMAILS_FUER_GARANTIESCHEINE_LADEN";
WriteLine($"E-Mails für Garantiescheine gefunden: {command.ExecuteNonQuery()}");
}
}
private static void WriteLine(object e)
{
var logFolder = AppSettings.LogFolder;
var logPath = Directory.CreateDirectory(logFolder).FullName;
var logFile = Path.Combine(logPath, $"{DateTime.Now:yyyy-MM-dd}.txt");
var message = $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] {e}";
File.AppendAllText(logFile, message);
Console.WriteLine(message.Trim());
}
private static T GetValue<T>(this SqlDataReader sqlDataReader, int index, T defaultValue = default(T))
{
var value = defaultValue;
if (0 <= index && index < sqlDataReader.FieldCount && !sqlDataReader.IsDBNull(index))
{
var sqlValue = sqlDataReader.GetValue(index);
var type = Nullable.GetUnderlyingType(typeof(T));
if (type is null)
{
type = typeof(T);
}
try
{
sqlValue = Convert.ChangeType(sqlValue, type);
if (sqlValue is T expectedValue)
{
value = expectedValue;
}
}
catch (Exception e)
{
WriteLine(e);
}
}
return value;
}
private static List<string> ToEmailList(this string value)
=> value
?.ToLower()
?.Split(new[] { ',', ';', ' ' }, StringSplitOptions.RemoveEmptyEntries)
?.Where(x => !string.IsNullOrWhiteSpace(x))
?.ToList()
?? new List<string>();
}
}