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; SesUser smtpUser; public ILambdaContext context { get; } public PaymentReceiptService(Logger logger, ILambdaContext context) { this.logger = logger; this.context = context; this.smtpUser = SecretsManager.GetSesUser(); } 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(); 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"); logger.LogMessage(context, "posting to" + Constants.PDF_MICRO_BASE_URL); var result = httpClient.PostAsync(Constants.PDF_MICRO_BASE_URL, 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()}.", "Mail error", "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", 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(Constants.TMT_MAIL, "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 { logger.WriteLog(email, "calling send mail", "mail", "TMT"); client.Send(message); return true; } catch (Exception ex) { logger.WriteLog(email, "Smtp Mail error", 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(Constants.TMT_MAIL, "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 = "tmt-pmf-prod-invoices"; 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 - convenience).ToString(); sb.AppendFormat(@"", infringement.Infringement, infringement.IdNumber, infringement.VechicleRegistration, InfringementAmount); total = total + (infringement.Amount - convenience); } double totalConvenience = convenience * paidInfringements.Count; total = 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(); } }