using InABox.Clients;
using InABox.Core;
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 TextBox = System.Windows.Controls.TextBox;
using InABox.Wpf.Reports;
using System.Diagnostics.CodeAnalysis;
namespace InABox.Wpf;
public static 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 " + message.From);
}
public 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 });
}
public static MailMessage CreateMessage(string? from = null, string? subject = null, string? body = null, string? to = null)
{
return new MailMessage(
from.NotWhiteSpaceOr(GetAddressFromUser()).NotWhiteSpaceOr("example@outlook.com.au"),
to.NotWhiteSpaceOr("example@outlook.com.au"),
subject.NotWhiteSpaceOr("Enter subject"),
body.NotWhiteSpaceOr("Enter message"))
{
IsBodyHtml = false
};
}
public static string GetAddressFromUser()
{
if(TryGetAddressFromUser(out var address))
{
return address;
}
else
{
MessageWindow.ShowMessage("Current User Email Address is blank - please fill in (Human Resources -> User Accounts -> Choose your User -> Email Settings -> Email Address", "Error");
return "";
}
}
public static string? GetAddressFromUserOrNull()
{
TryGetAddressFromUser(out var address);
return address;
}
public static bool TryGetAddressFromUser([NotNullWhen(true)] out string? address)
{
var table = Client.Query(new Filter(x => x.ID).IsEqualTo(ClientFactory.UserGuid), Columns.None().Add(x => x.EmailAddress));
var user = table.ToObjects().FirstOrDefault();
address = user?.EmailAddress.NotWhiteSpaceOr(null);
return address is not null;
}
public static MailMessage AddAttachment(this 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;
}
}