using Amazon.Lambda.Core; using Amazon.S3; using Amazon.S3.Model; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.IO; using System.Net; using System.Net.Http; using System.Net.Mail; using System.Text; using System.Threading; using System.Threading.Tasks; using Model.ResponseModel; using classes; public class PaymentReceiptService { Logger logger; SesUserModel smtpUser; string pdfBaseUrl = string.Empty; string invoiceBucket = string.Empty; string fromEmail = string.Empty; public ILambdaContext context { get; } public PaymentReceiptService(Logger logger, ILambdaContext context) { this.logger = logger; this.context = context; var secretManager = new SecretsManagerService(); this.smtpUser = secretManager.GetSesUser(); pdfBaseUrl = secretManager.GetPdfServer().IP; invoiceBucket = secretManager.GetBucket().Invoice_Bucket; fromEmail = secretManager.GetTMTEmail().TMT_MAIL; } public async Task GenerateReceipt(List infringements, double convenience, string email, string transactionId, string reference) { try { var html = GetReceiptHTMLString(infringements, convenience, reference); var httpClient = new HttpClient { Timeout = TimeSpan.FromSeconds(Constants.TimeDefaultValue) }; var body = new Dictionary { { "html", html} }; var json = JsonConvert.SerializeObject(body); var content = new StringContent(json, Encoding.UTF8, "application/json"); var result = httpClient.PostAsync(pdfBaseUrl, content).Result; if (result.IsSuccessStatusCode) { var response = await result.Content.ReadAsStringAsync(); var PdfMicro = JsonConvert.DeserializeObject(response); try { logger.LogMessage(context, $"path returned : {PdfMicro.path} Linked email: {email} Filename: {PdfMicro.filename}"); logger.WriteLog("path", PdfMicro.path, $"Linked email:{email}", "TMT"); CancellationTokenSource source = new CancellationTokenSource(); // //small delay so that the pdf is created await Task.Delay(TimeSpan.FromSeconds(1.5), source.Token); var stream = await ReadFromS3(PdfMicro.filename); var mailSentSuccess = SendMail(email, stream); logger.LogMessage(context, "mail sent:" + mailSentSuccess.ToString()); if (!mailSentSuccess) { logger.LogMessage(context, $"mail not set: {email}. S3 Path: {PdfMicro.path}"); return false; } } catch (Exception) { //Send only hmtl if pdf server has issues if (PdfMicro.path != null) { logger.LogMessage(context, $"cannot access: {PdfMicro.path} attachement for {email}"); logger.WriteLog(email, $"cannot access: {PdfMicro.path} attachement for {email}", "hmtl mail only", "TMT"); var mail = SendMail(email, html); if (!mail) { logger.LogMessage(context, $"unable to send html mail to {email} for attachment {PdfMicro.path}"); logger.WriteLog("sending html mail", $"unable to send html mail to {email} for attachment {PdfMicro.path}", "test", "TMT"); } } } return true; } else { logger.WriteLog(email, $"pdf server error status code: {result.StatusCode.ToString()}.", "Exception", "TMT"); logger.LogMessage(context, $"pdf server error status code: {result.StatusCode.ToString()}."); return false; //mail not sent; } } catch (Exception ex) { logger.WriteLog(email, "Error from PDF Server", $"Exception: {ex.Message}", "TMT"); logger.LogMessage(context, "pdf not reached:" + ex.Message.ToString()); return false; } } private bool SendMail(string email, MemoryStream pdfattachment) { SmtpClient client = new SmtpClient() { Host = Constants.TMT_MAIL_HOST, Port = 587, EnableSsl = true, DeliveryMethod = SmtpDeliveryMethod.Network, UseDefaultCredentials = false, Credentials = new NetworkCredential() { UserName = smtpUser.SMTP_Username, Password = smtpUser.SMTP_Password } }; MailAddress from = new MailAddress(fromEmail, "PMF"); MailAddress to = new MailAddress(email); MailMessage message = new MailMessage(); message.From = from; message.To.Add(to); message.Subject = "PMF Online Payment Receipt"; message.IsBodyHtml = true; message.Body = "A payment has been made on PMF website"; message.Attachments.Add(new Attachment(pdfattachment, "PMF_Payment_Receipt.pdf")); try { client.Send(message); return true; } catch (Exception ex) { logger.WriteLog(email, "Smtp Mail error", $"Exception: {ex.Message}", "TMT"); logger.LogMessage(context, $"function sending mail threw an exception + {email}"); return false; } } private bool SendMail(string email, string body) { SmtpClient client = new SmtpClient() { Host = Constants.TMT_MAIL_HOST, Port = 587, EnableSsl = true, DeliveryMethod = SmtpDeliveryMethod.Network, UseDefaultCredentials = false, Credentials = new NetworkCredential() { UserName = smtpUser.SMTP_Username, Password = smtpUser.SMTP_Password } }; MailAddress from = new MailAddress(fromEmail, "PMF"); MailAddress to = new MailAddress(email); MailMessage message = new MailMessage(); message.From = from; message.To.Add(to); message.Subject = "PMF Online Payment Receipt"; message.IsBodyHtml = true; message.Body = body; try { client.Send(message); return true; } catch (Exception ex) { logger.WriteLog(email, "SMTP error second attempt failed", ex.Message, "TMT"); return false; } } // private async Task SaveToS3(MemoryStream data, string email) // { // try // { // string keyName = DateTime.Now.ToString("yyyy-MM-dd h:mm:ss") + email; //find naming format // using (var client = new AmazonS3Client(Amazon.RegionEndpoint.EUWest1)) // { // var request = new PutObjectRequest // { // InputStream = data, // BucketName = "tmt-pmf-prod-invoices", // Key = keyName, // ContentType = "application/pdf" // }; // var response = await client.PutObjectAsync(request); // if ((int)response.HttpStatusCode == 200) // { // return true; // } // } // return false; // } // catch (Exception) // { // return false; // } // } private async Task ReadFromS3(string bucketKey) { try { var client = new AmazonS3Client(Amazon.RegionEndpoint.EUWest1); GetObjectRequest request = new GetObjectRequest(); logger.LogMessage(context, $"error reading from S3 bucket for key: {bucketKey}"); request.BucketName = invoiceBucket; request.Key = bucketKey; GetObjectResponse response = await client.GetObjectAsync(request); var result = response.ResponseStream; MemoryStream pdfStream = new MemoryStream(); result.CopyTo(pdfStream); pdfStream.Position = 0; logger.LogMessage(context, $"successfully read from s3 bucket"); //logger.WriteLog("S3", "Read from S3", bucketKey, "TMT"); return pdfStream; } catch (Exception ex) { logger.LogMessage(context, $"error reading from S3: Error:{ex.Message}"); logger.WriteLog("S3", "Read from S3", ex.Message, "TMT"); throw ex; } } private string GetReceiptHTMLString(List paidInfringements, double convenience, string receiptNumber) { double total = default(double); string open = "{"; string close = "}"; var serverTime = DateTime.Now; var paymentdate = serverTime.AddHours(2).ToString("dd MMMM yyyy, h:mm tt"); //string cssFilePath = Path.Combine(Directory.GetCurrentDirectory(), "Assets", "pmf_logo.svg"); //avoid using external style sheets for the convertor. Include the css into html. An old design is in ./Assets/mystyle.css var sb = new StringBuilder(); sb.Append(@$"

Payment Receipt

Payment Enquiries: 010 500 0077 or payment@paymyfines.co.za

Other Enquiries: help@paymyfines.co.za

Date: {paymentdate}

Receipt Number: {receiptNumber}


"); foreach (var infringement in paidInfringements) { var InfringementAmount = infringement.Amount.ToString(); sb.AppendFormat(@"", infringement.Infringement, infringement.IdNumber, infringement.VechicleRegistration, InfringementAmount); total += infringement.Amount; } double totalConvenience = convenience * paidInfringements.Count; total += totalConvenience; sb.Append(@$" "); sb.Append(@"
INFRINGEMENT NUMBER ID NUMBER VEHICLE REGISTRATION AMOUNT
{0} {1} {2} R {3}
Convenience Fee(R{convenience} per Infringement) R {totalConvenience}
TOTAL R {total}
"); return sb.ToString(); } }