namespace PendingEmails { using System; using System.Collections.Generic; using System.Configuration; using System.Data; using System.Data.SqlClient; using System.IO; using System.Linq; using System.Net.Mail; using System.Threading; using System.Timers; using SystemTimersTimer = System.Timers.Timer; public static class Program { private static readonly SystemTimersTimer timer = new SystemTimersTimer(); private static void Main() { Console.WriteLine("Pending emails ...."); try { timer.AutoReset = true; timer.Interval = 600_000; timer.Elapsed += Timer_Elapsed; while (true) { Timer_Elapsed(null, null); timer.Start(); var awaiter = new ManualResetEventSlim(); awaiter.Wait(); timer.Stop(); } } catch (Exception e) { LogToFile(e.Message); } } public class Ready { public string Source { get; set; } public string Subject { get; set; } public string Body { get; set; } } private static void Timer_Elapsed(Object _, ElapsedEventArgs _1) { LogToFile($"loading pending emails"); var connectionString = ConfigurationManager.ConnectionStrings["Auftrag"].ConnectionString; using (var connection = new SqlConnection(connectionString)) { connection.FireInfoMessageEventOnUserErrors = true; connection.InfoMessage += (_2, args) => LogToFile(args.Message); connection.Open(); var ready = new List(); using (var command = connection.CreateCommand()) { command.CommandTimeout = 60000; command.CommandText = @" SELECT [Pruefstation] , [Pruefdatum] , [Mitarbaiter] , [Auftrag] , [Position] , [Fertigungsauftrag] , [Merkmal] , [Bezeichnung] , [Menge] , [SerienNrVon] , [SerienNrBis] , [Kunde] , [Kundenort] FROM [AlleAuftraegeMitGarantieAusLetzte13Min] ORDER BY [Pruefdatum]"; using (var reader = command.ExecuteReader()) { while (reader.Read()) { reader.AddToPendingMessages(); } } } var updated = new HashSet(); var countAll = 0; using (var command = connection.CreateCommand()) { command.CommandText = @" SELECT [Sender] , [Subject] , [Body] , [Recipients] , [CC] , [Id] FROM [Messages] WHERE [OutDate] IS NULL ORDER BY [InDate] DESC"; using (var reader = command.ExecuteReader()) { while (reader.Read()) { try { var email = new MailMessage(); var from = ConfigurationManager.AppSettings["DefaultSender"]; email.From = new MailAddress(from); email.Subject = $"{reader.GetValue(1)}"; email.Body = $"{reader.GetValue(2)}"; $"{reader.GetValue(3)}" .Split(new[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries) .Select(x => new MailAddress(x)) .ToList() .ForEach(email.To.Add); $"{reader.GetValue(4)}" .Split(new[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries) .Select(x => new MailAddress(x)) .ToList() .ForEach(email.CC.Add); var messageId = reader.GetValue(5); if (SendEmail(email)) { updated.Add(messageId); } } catch (Exception e) { LogToFile(e); } countAll++; } } } var updatedCount = updated.Count; if (updatedCount > 0) { try { LogToFile($"updating: {string.Join(", ", updated)}"); using (var command = connection.CreateCommand()) { command.CommandText = $@" UPDATE [Messages] SET [OutDate] = GETDATE() WHERE [Id] IN ({string.Join(", ", updated)})"; command.ExecuteNonQuery(); } Console.WriteLine($"{updatedCount}/{countAll} email{(updatedCount == 1 ? null : "s")} sent."); LogToFile($"{updatedCount}/{countAll} emails sent."); } catch (Exception e) { LogToFile(e); } } else { LogToFile($"there are no pending emails to send"); } } } private static Boolean SendEmail(MailMessage email) { try { using (var smtpClient = new SmtpClient("smtp.xylem.com", 587)) { smtpClient.UseDefaultCredentials = true; smtpClient.Send(email); } return true; } catch (Exception e) { LogToFile(e); } return false; } private static void LogToFile(Object e) => File.AppendAllText(GetOrCreateFile(), $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] {e}{Environment.NewLine}"); private static String GetOrCreateFile() { var logFolder = ConfigurationManager.AppSettings["LogFolder"]; var logPath = Directory.CreateDirectory(logFolder).FullName; return Path.Combine(logPath, $"{DateTime.Now:yyyy-MM-dd}.txt"); } private static void AddToPendingMessages(this SqlDataReader reader) { var psno = reader.GetValue(0); var date = reader.GetValue(1); var empl = reader.GetValue(2); var orderno = reader.GetValue(3); var posno = reader.GetValue(4); var pono = reader.GetValue(5); var vako = reader.GetValue(6); var desc = reader.GetValue(7); var count = reader.GetValue(8); var snfrom = reader.GetValue(9); var snto = reader.GetValue(10); var client = reader.GetValue(11); var ort = reader.GetValue(12); var source = $"{orderno}/{posno}"; var subject = $"{ort} - {orderno}/{posno} erfolgreich geprüft - bitte Garantiescheine drucken und bereitlegen!"; var body = $"Auftrag: {orderno}/{posno}{Environment.NewLine}" + $"FertigungsauftragNr: {pono}{Environment.NewLine}" + $"{Environment.NewLine}" + $"{count} Stück {desc}{Environment.NewLine}" + $"wurde an der Prüfstation: {psno}{Environment.NewLine}" + $"am {date:dd-MM-yyyy} um {date:HH:mm} Uhr{Environment.NewLine}" + $"von {empl} vollständig geprüft.{Environment.NewLine}" + $"{Environment.NewLine}" + $"Seriennummern: {snfrom} - {snto}{Environment.NewLine}" + $"{Environment.NewLine}" + $"{vako}{Environment.NewLine}"; var connectionString = ConfigurationManager.ConnectionStrings["Auftrag"].ConnectionString; using (var connection = new SqlConnection(connectionString)) { connection.FireInfoMessageEventOnUserErrors = true; connection.InfoMessage += (_2, args) => LogToFile(args.Message); connection.Open(); var ready = new List(); using (var command = connection.CreateCommand()) { command.CommandText = $@" IF (SELECT COUNT(1) FROM [Messages] WHERE [Source] = @{nameof(source)}) = 0 BEGIN INSERT INTO [Messages] ( [Source] , [InDate] , [StationNr] , [PCName] , [IPAddress] , [Trace] , [Sender] , [Subject] , [Body] , [IsHtml] , [Recipients] , [CC] , [OutDate] , [State]) VALUES (@{nameof(source)} , GETDATE() , @{nameof(psno)} , 'localhost' , '127.0.0.1' , 'Xylem.Common.Service.PendingMails.Timer_Elapsed(Object, ElapsedEventArgs))' , 'noreplay@xylem.com' , @{nameof(subject)} , @{nameof(body)} , 0 , 'uwe.kubon@xylem.com' , 'stoyan.zlatev@xylem.com' , NULL , 'Automatische fertigmeldung für garantiescheine') END"; command.Parameters.AddWithValue(nameof(source), source); command.Parameters.AddWithValue(nameof(subject), subject); command.Parameters.AddWithValue(nameof(body), body); command.Parameters.AddWithValue(nameof(psno), psno); LogToFile($"Inserted: {command.ExecuteNonQuery()}"); command.Parameters.Clear(); } } } private static T GetValue(this SqlDataReader sqlDataReader, Int32 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) { LogToFile(e); } } return value; } } }