EmailUtils.cs 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. using InABox.Clients;
  2. using InABox.Core;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Diagnostics;
  6. using System.IO;
  7. using System.Linq;
  8. using System.Net.Mail;
  9. using System.Reflection;
  10. using System.Text;
  11. using System.Threading.Tasks;
  12. using System.Windows.Controls;
  13. using System.Windows;
  14. using System.Windows.Forms;
  15. using System.Drawing;
  16. using InABox.WPF;
  17. using MessageBox = System.Windows.Forms.MessageBox;
  18. using TextBox = System.Windows.Controls.TextBox;
  19. using InABox.Wpf.Reports;
  20. namespace InABox.Wpf;
  21. public static class EmailUtils
  22. {
  23. /// <summary>
  24. /// Creates and opens an email with the default email app - selected by the user.
  25. /// This method is for emails with a PDF attachment. Provide the file name and data.
  26. /// Optionally provide from, subject and body.
  27. /// 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)
  28. /// </summary>
  29. /// <param name="attachmentname"></param>
  30. /// <param name="attachmentdata"></param>
  31. /// <param name="from"></param>
  32. /// <param name="subject"></param>
  33. /// <param name="body"></param>
  34. public static void CreateEMLFile(string attachmentname, byte[] attachmentdata, string from = "", string subject = "", string body = "", string to = "")
  35. {
  36. var message = CreateMessage(from, subject, body, to);
  37. message = AddAttachment(message, attachmentname, attachmentdata);
  38. OpenEmail(message, attachmentname);
  39. }
  40. /// <summary>
  41. /// Creates and opens an email with the default email app - selected by the user.
  42. /// This method is for emails with multiple PDF attachments. Provide the a Dictionary of names and byte arrays
  43. /// Optionally provide from, subject and body.
  44. /// 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)
  45. /// </summary>
  46. /// <param name="attachmentname"></param>
  47. /// <param name="attachmentdata"></param>
  48. /// <param name="from"></param>
  49. /// <param name="subject"></param>
  50. /// <param name="body"></param>
  51. public static void CreateEMLFile(Dictionary<string,byte[]> attachments, string from = "", string subject = "", string body = "", string to = "")
  52. {
  53. var message = CreateMessage(from, subject, body, to);
  54. foreach (var key in attachments.Keys)
  55. AddAttachment(message, key, attachments[key]);
  56. OpenEmail(message);
  57. }
  58. /// <summary>
  59. /// Creates and opens an email with the default email app - selected by the user.
  60. /// This method is for emails with no attachments.
  61. /// Optionally provide from, subject and body.
  62. /// 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)
  63. /// </summary>
  64. /// <param name="from"></param>
  65. /// <param name="subject"></param>
  66. /// <param name="body"></param>
  67. public static void CreateEMLFile(string? from, string? subject, string? body)
  68. {
  69. var message = CreateMessage(from, subject, body);
  70. OpenEmail(message, "Message from " + message.From);
  71. }
  72. public static void OpenEmail(MailMessage message, string? name = null)
  73. {
  74. var filename = Path.Combine(
  75. Path.GetTempPath(),
  76. Path.ChangeExtension(String.IsNullOrWhiteSpace(name) ? Guid.NewGuid().ToString() : name, ".eml")
  77. );
  78. using (var filestream = File.Open(filename, FileMode.Create))
  79. {
  80. var binaryWriter = new BinaryWriter(filestream);
  81. //Write the Unsent header to the file so the mail client knows this mail must be presented in "New message" mode
  82. binaryWriter.Write(Encoding.UTF8.GetBytes("X-Unsent: 1" + Environment.NewLine));
  83. var assembly = typeof(SmtpClient).Assembly;
  84. var mailWriterType = assembly.GetType("System.Net.Mail.MailWriter")!;
  85. // Get reflection info for MailWriter contructor
  86. var mailWriterConstructor =
  87. mailWriterType.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, new Type[] { typeof(Stream), typeof(bool) }, null)!;
  88. // Construct MailWriter object with our FileStream
  89. var mailWriter = mailWriterConstructor.Invoke(new object[] { filestream, true });
  90. // Get reflection info for Send() method on MailMessage
  91. var sendMethod = typeof(MailMessage).GetMethod("Send", BindingFlags.Instance | BindingFlags.NonPublic)!;
  92. sendMethod.Invoke(message, BindingFlags.Instance | BindingFlags.NonPublic, null, new[] { mailWriter, true, true }, null);
  93. // Finally get reflection info for Close() method on our MailWriter
  94. var closeMethod = mailWriter.GetType().GetMethod("Close", BindingFlags.Instance | BindingFlags.NonPublic)!;
  95. // Call close method
  96. closeMethod.Invoke(mailWriter, BindingFlags.Instance | BindingFlags.NonPublic, null, new object[] { }, null);
  97. }
  98. // Open the file with the default associated application registered on the local machine
  99. Process.Start(new ProcessStartInfo(filename) { UseShellExecute = true });
  100. }
  101. public static MailMessage CreateMessage(string? from = null, string? subject = null, string? body = null, string? to = null)
  102. {
  103. return new MailMessage(
  104. from.NotWhiteSpaceOr(GetAddressFromUser()).NotWhiteSpaceOr("example@outlook.com.au"),
  105. to.NotWhiteSpaceOr("example@outlook.com.au"),
  106. subject.NotWhiteSpaceOr("Enter subject"),
  107. body.NotWhiteSpaceOr("Enter message"))
  108. {
  109. IsBodyHtml = false
  110. };
  111. }
  112. private static string GetAddressFromUser()
  113. {
  114. CoreTable table = new Client<User>().Query(new Filter<User>(x => x.ID).IsEqualTo(ClientFactory.UserGuid)
  115. , new Columns<User>(x => x.EmailAddress));
  116. User user = table.Rows.FirstOrDefault().ToObject<User>();
  117. if (!string.IsNullOrWhiteSpace(user.EmailAddress))
  118. return user.EmailAddress;
  119. else
  120. MessageWindow.ShowMessage("Current User Email Address is blank - please fill in (Human Resources -> User Accounts -> Choose your User -> Email Settings -> Email Address", "Error");
  121. return "";
  122. }
  123. public static MailMessage AddAttachment(this MailMessage message, string attachmentname, byte[] attachmentdata)
  124. {
  125. var attachment = Path.Combine(
  126. Path.GetTempPath(),
  127. String.IsNullOrWhiteSpace(Path.GetExtension(attachmentname))
  128. ? Path.ChangeExtension(attachmentname, ".pdf")
  129. : attachmentname
  130. );
  131. File.WriteAllBytes(attachment, attachmentdata);
  132. message.Attachments.Add(new Attachment(attachment));
  133. return message;
  134. }
  135. }