using InABox.Clients;
using InABox.Core;
using InABox.Reports;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net.Mail;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls;
using System.Windows;
using System.Windows.Forms;
using System.Drawing;
using InABox.WPF;
using MessageBox = System.Windows.Forms.MessageBox;
using Comal.Classes;
using TextBox = System.Windows.Controls.TextBox;
using InABox.Wpf.Reports;
namespace PRSDesktop
{
public class EmailUtils
{
///
/// Creates and opens an email with the default email app - selected by the user.
/// This method is for emails with a PDF attachment. Provide the file name and data.
/// Optionally provide from, subject and body.
/// If from is not provided, an attempt will be made to find the User's email address - if empty it will throw an error (cannot be empty)
///
///
///
///
///
///
public static void CreateEMLFile(string attachmentname, byte[] attachmentdata, string from = "", string subject = "", string body = "", string to = "")
{
var message = CreateMessage(from, subject, body, to);
message = AddAttachment(message, attachmentname, attachmentdata);
OpenEmail(message, attachmentname);
}
///
/// Creates and opens an email with the default email app - selected by the user.
/// This method is for emails with multiple PDF attachments. Provide the a Dictionary of names and byte arrays
/// Optionally provide from, subject and body.
/// If from is not provided, an attempt will be made to find the User's email address - if empty it will throw an error (cannot be empty)
///
///
///
///
///
///
public static void CreateEMLFile(Dictionary attachments, string from = "", string subject = "", string body = "", string to = "")
{
var message = CreateMessage(from, subject, body, to);
foreach (var key in attachments.Keys)
AddAttachment(message, key, attachments[key]);
OpenEmail(message);
}
///
/// Creates and opens an email with the default email app - selected by the user.
/// This method is for emails with no attachments.
/// Optionally provide from, subject and body.
/// If from is not provided, an attempt will be made to find the User's email address - if empty it will throw an error (cannot be empty)
///
///
///
///
public static void CreateEMLFile(string from = "", string subject = "", string body = "")
{
var message = CreateMessage(from, subject, body);
OpenEmail(message, "Message from " + from);
}
private static void OpenEmail(MailMessage message, string name = null)
{
var filename = Path.Combine(
Path.GetTempPath(),
Path.ChangeExtension(String.IsNullOrWhiteSpace(name) ? Guid.NewGuid().ToString() : name, ".eml")
);
using (var filestream = File.Open(filename, FileMode.Create))
{
var binaryWriter = new BinaryWriter(filestream);
//Write the Unsent header to the file so the mail client knows this mail must be presented in "New message" mode
binaryWriter.Write(Encoding.UTF8.GetBytes("X-Unsent: 1" + Environment.NewLine));
var assembly = typeof(SmtpClient).Assembly;
var mailWriterType = assembly.GetType("System.Net.Mail.MailWriter")!;
// Get reflection info for MailWriter contructor
var mailWriterConstructor =
mailWriterType.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, new Type[] { typeof(Stream), typeof(bool) }, null)!;
// Construct MailWriter object with our FileStream
var mailWriter = mailWriterConstructor.Invoke(new object[] { filestream, true });
// Get reflection info for Send() method on MailMessage
var sendMethod = typeof(MailMessage).GetMethod("Send", BindingFlags.Instance | BindingFlags.NonPublic)!;
sendMethod.Invoke(message, BindingFlags.Instance | BindingFlags.NonPublic, null, new[] { mailWriter, true, true }, null);
// Finally get reflection info for Close() method on our MailWriter
var closeMethod = mailWriter.GetType().GetMethod("Close", BindingFlags.Instance | BindingFlags.NonPublic)!;
// Call close method
closeMethod.Invoke(mailWriter, BindingFlags.Instance | BindingFlags.NonPublic, null, new object[] { }, null);
}
// Open the file with the default associated application registered on the local machine
Process.Start(new ProcessStartInfo(filename) { UseShellExecute = true });
}
private static MailMessage CreateMessage(string from, string subject, string body, string to = "")
{
if (string.IsNullOrWhiteSpace(to))
to = "example@outlook.com.au";
if (string.IsNullOrWhiteSpace(from))
from = GetAddressFromUser();
if (string.IsNullOrWhiteSpace(subject))
subject = "Enter subject";
if (string.IsNullOrWhiteSpace(body))
body = "Enter message";
var message = new MailMessage(from, to, subject, body);
message.IsBodyHtml = false;
return message;
}
private static string GetAddressFromUser()
{
CoreTable table = new Client().Query(new Filter(x => x.ID).IsEqualTo(ClientFactory.UserGuid)
, new Columns(x => x.EmailAddress));
User user = table.Rows.FirstOrDefault().ToObject();
if (!string.IsNullOrWhiteSpace(user.EmailAddress))
return user.EmailAddress;
else
MessageBox.Show("Current User Email Address is blank - please fill in (Human Resources -> User Accounts -> Choose your User -> Email Settings -> Email Address", "Error");
return "";
}
private static MailMessage AddAttachment(MailMessage message, string attachmentname, byte[] attachmentdata)
{
var attachment = Path.Combine(
Path.GetTempPath(),
String.IsNullOrWhiteSpace(Path.GetExtension(attachmentname))
? Path.ChangeExtension(attachmentname, ".pdf")
: attachmentname
);
File.WriteAllBytes(attachment, attachmentdata);
message.Attachments.Add(new Attachment(attachment));
return message;
}
public static IEnumerable CreateTemplateDefinitions(DataModel model)
{
var templates = new Client().Query(new Filter(x => x.Model).IsEqualTo(model.Name)
.And(x => x.Visible).IsEqualTo(true));
if (templates.Rows.Any())
{
List list = new List();
foreach (CoreRow row in templates.Rows)
{
Action action = new Action((model, data) =>
{
DoEmailAction(model, data, row.Get(x => x.Name));
});
list.Add(
new ReportExportDefinition(
"Email Report",
ImageUtils.CreatePreviewWindowButtonContent(row.Get(x => x.Name),PRSDesktop.Resources.emailreport),
ReportExportType.PDF,
action));
}
return list;
}
else
return new List()
{
new ReportExportDefinition(
"Email Report",
ImageUtils.CreatePreviewWindowButtonContent("Email",PRSDesktop.Resources.emailreport),
ReportExportType.PDF,
DoEmailReport)
};
}
private static void DoEmailAction(DataModel model, byte[] data, string templateName)
{
var template = new Client().Query(new Filter(x => x.Name).IsEqualTo(templateName)).Rows.FirstOrDefault();
ParseTemplateAndCreateEmail(template, model, data);
}
private static void ParseTemplateAndCreateEmail(CoreRow row, DataModel model, byte[] data)
{
var to = DataModelUtils.ParseTemplate(model, row.Get(x => x.To)).Replace("\n", "").Replace("\r", "");
var Subject = DataModelUtils.ParseTemplate(model, row.Get(x => x.Subject)).Replace("\n", "").Replace("\r", "");
var attachmentName = DataModelUtils.ParseTemplate(model, row.Get(x => x.AttachmentName)).Replace("\n", "").Replace("\r", "");
var body = DataModelUtils.ParseTemplate(model, row.Get(x => x.Template));
if (string.IsNullOrWhiteSpace(attachmentName))
attachmentName = model.Name;
EmailUtils.CreateEMLFile(attachmentName, data, App.EmployeeEmail, Subject, body, to);
}
public static void DoEmailReport(DataModel model, byte[] data)
{
string attachmentName = DetermineName(model);
EmailUtils.CreateEMLFile(attachmentName, data, App.EmployeeEmail, "Emailing report for " + attachmentName);
}
private static string DetermineName(DataModel model)
{
string title = model.Name;
if (model.HasTable())
{
CoreTable table = model.GetTable();
title = title + " - " + table.Rows.FirstOrDefault().Get(x => x.Title);
}
else if (model.HasTable())
{
title = "Purchase Order ";
CoreTable table = model.GetTable();
if (table.Rows.Count == 1)
title += table.Rows.FirstOrDefault().Get(x => x.PONumber);
else if (table.Rows.Count > 1)
{
foreach (CoreRow row in table.Rows)
{
title = title + row.Get(x => x.PONumber) + ", ";
}
title = title.Substring(0, title.Length - 2);
}
}
return title;
}
}
}