GPAL - Generally Positive Automation Library v1.0
GPAL The Fluent Automation LIbrary
Loading...
Searching...
No Matches
GPALMail.cs
1// =============================================================================
2// GPAL - Generally Positive Automation Library
3// Copyright © 2026 Software Decisions, Inc. All rights reserved.
4//
5// This file is part of GPAL.
6// Licensed under the Business Source License 1.1
7//
8// Primary development, architecture, and vision by Michael B. Vederman,
9// CEO of Software Decisions, Inc., Texas.
10//
11// Internal development maintained privately.
12// Public releases appear on GitHub: https://github.com/SoftwareDecisionsInc/GPAL.
13//
14// See LICENSE for full terms, including Additional Use Grant.
15// =============================================================================
16
17using System;
18using System.Collections.Generic;
19using System.Linq;
20using System.Text;
21using System.Threading.Tasks;
23
24namespace GenerallyPositive
25{
26 using System.Collections.Generic;
27 using System.IO;
28 using MailKit.Net.Imap;
29 using MailKit.Net.Pop3;
30 using MailKit;
31 using MailKit.Net.Smtp;
32 using MailKit.Search;
33 using MimeKit;
34
54 public class GPALMail : IGPALMail
55 {
56 private GPALMailSettings gPALMailSettings;
57 private static string MailSettingsFilePath { get; set; } = "./GPALMail.yaml";
62 private GPALMailSettings GPALMailSettings
63 {
64 get
65 {
66 return gPALMailSettings;
67 }
68 set
69 {
70 gPALMailSettings = value;
71 }
72 }
77 internal GPALMail()
78 {
79 GPALMailSettings = new GPALMailSettings();
80 GPALMailSettings.ToEmailAddresses = new List<MailboxAddress>();
81 GPALMailSettings.CcEmailAddresses = new List<MailboxAddress>();
82 GPALMailSettings.BccEmailAddresses = new List<MailboxAddress>();
83 GPALMailSettings.Attachments = new List<string>();
84 GPALMailSettings.ReceivedEmails = new List<ReceivedEmail>();
86 }
93 {
94 return this;
95 }
96
103 {
104 GPALMailSettings.IMAPServerName = serverName;
105 GPALMailSettings.POPServerName = null;
106 return this;
107 }
108
116 {
117 GPALMailSettings.POPServerName = serverName;
118 GPALMailSettings.IMAPServerName = null;
119 return this;
120 }
121
128 {
129 GPALMailSettings.SMTPServerName = serverName;
130 return this;
131 }
132
139 {
140 GPALMailSettings.IMAPPortNum = portNum;
141 return this;
142 }
143
149 {
150 GPALMailSettings.POPPortNum = portNum;
151 return this;
152 }
153
159 {
160 GPALMailSettings.SMTPPortNum = portNum;
161 return this;
162 }
163
170 {
171 GPALMailSettings.Credentials = credentials;
172 return this;
173 }
174
175 // what a settings file holds, readable so a form can show it. everything else about a message is the
176 // envelope, and the login is the credential's business
178 public string SMTPServerName => GPALMailSettings.SMTPServerName;
180 public int SMTPPortNum => GPALMailSettings.SMTPPortNum;
182 public string IMAPServerName => GPALMailSettings.IMAPServerName;
184 public int IMAPPortNum => GPALMailSettings.IMAPPortNum;
186 public string POPServerName => GPALMailSettings.POPServerName;
188 public int POPPortNum => GPALMailSettings.POPPortNum;
190 public string FromAddress => GPALMailSettings.FromAddress;
191
192 // the credential if there is one, otherwise whatever was set by hand
193 private string ResolvedUserName
194 {
195 get
196 {
197 return null != GPALMailSettings.Credentials ? ((Credentials)GPALMailSettings.Credentials).Username : GPALMailSettings.UserName;
198 }
199 }
200
201 private string ResolvedPassword
202 {
203 get
204 {
205 return null != GPALMailSettings.Credentials ? ((Credentials)GPALMailSettings.Credentials).Password : GPALMailSettings.Password;
206 }
207 }
208
215 {
216 GPALMailSettings.UserName = userName;
217 return this;
218 }
219
225 {
226 GPALMailSettings.Password = password;
227 return this;
228 }
229
235 // whichever address was added last, so .WithName knows which one it is naming
236 private MailboxAddress lastAddress = null;
237
238 public IAllowNameEnvelopeAndActions WithFromEmailAddress(string mailAddress)
239 {
240 GPALMailSettings.FromEmailAddress = MailboxAddress.Parse(mailAddress);
241 lastAddress = GPALMailSettings.FromEmailAddress;
242 return this;
243 }
251 {
252 foreach (MailboxAddress mailboxAddress in ParseEmailAddresses(mailAddress))
253 {
254 GPALMailSettings.ToEmailAddresses.Add(mailboxAddress);
255 lastAddress = mailboxAddress;
256 }
257 return this;
258 }
259
267 {
268 foreach (MailboxAddress mailboxAddress in ParseEmailAddresses(mailAddress))
269 {
270 GPALMailSettings.CcEmailAddresses.Add(mailboxAddress);
271 lastAddress = mailboxAddress;
272 }
273 return this;
274 }
275
283 {
284 foreach (MailboxAddress mailboxAddress in ParseEmailAddresses(mailAddress))
285 {
286 GPALMailSettings.BccEmailAddresses.Add(mailboxAddress);
287 lastAddress = mailboxAddress;
288 }
289 return this;
290 }
291
297 {
298 foreach (MailboxAddress mailboxAddress in CreateEmailAddresses(emailParts))
299 {
300 GPALMailSettings.ToEmailAddresses.Add(mailboxAddress);
301 lastAddress = mailboxAddress;
302 }
303 return this;
304 }
305
312 {
313 foreach (MailboxAddress mailboxAddress in CreateEmailAddresses(emailParts))
314 {
315 GPALMailSettings.CcEmailAddresses.Add(mailboxAddress);
316 lastAddress = mailboxAddress;
317 }
318 return this;
319 }
320
327 {
328 foreach (MailboxAddress mailboxAddress in CreateEmailAddresses(emailParts))
329 {
330 GPALMailSettings.BccEmailAddresses.Add(mailboxAddress);
331 lastAddress = mailboxAddress;
332 }
333 return this;
334 }
335
345 {
346 foreach (string filename in attachmentFile.Filenames)
347 try
348 {
349 string directory = Path.GetDirectoryName(filename);
350 string filenamepart = Path.GetFileName(filename);
351 string[] matches = Directory.GetFiles(false == string.IsNullOrEmpty(directory) ? directory : @".\", filenamepart);
352
353 // said out loud, because a name that matches no file attaches nothing and the message still sends
354 if (0 == matches.Length)
355 GPAL.PublishSimpleEvent(Enums.GPALEventType.WARNING, $"Nothing to attach at [{filename}]", attachmentFile, Enums.GPALObjectType.Other);
356
357 foreach (string filename2 in matches)
358 try
359 {
360 GPALMailSettings.Attachments.Add(filename2);
361 }
362 catch (Exception ex)
363 {
364 GPAL.PublishSimpleEvent(Enums.GPALEventType.EXCEPTION, $"Unable to add file attachments [{filename2}].", attachmentFile, Enums.GPALObjectType.Other, ex);
365 }
366 }
367 catch (Exception ex)
368 {
369 GPAL.PublishSimpleEvent(Enums.GPALEventType.EXCEPTION, $"Unable to add file attachments [{attachmentFile.Filename}].", attachmentFile, Enums.GPALObjectType.Other, ex);
370 }
371 return this;
372 }
373
381 {
382 if (true == IsHtml(body))
383 GPALMailSettings.BodyHTML = body;
384 else
385 GPALMailSettings.BodyText = body;
386 return this;
387 }
388
395 {
396 GPALMailSettings.Subject = subject;
397 return this;
398 }
399
407 {
408 // the address this follows, whether that was the from, a to, a cc or a bcc. named after the fact
409 // rather than parsed out of the address, so "Dead Mike <mike@x.com>" is not the only way to say it
410 if (null == lastAddress)
411 GPAL.PublishSimpleEvent(Enums.GPALEventType.WARNING, $"No address to put the name [{name}] on. Name an address after adding it", this, Enums.GPALObjectType.Other);
412 else
413 lastAddress.Name = name;
414
415 return this;
416 }
417
437 {
438 if (null == GPALMailSettings.FromEmailAddress)
439 {
440 // said here rather than thrown from inside MimeKit as a null argument called "address"
441 GPAL.PublishSimpleEvent(Enums.GPALEventType.ERROR, $"No from address to send with", this, Enums.GPALObjectType.Other);
442
443 return this;
444 }
445
446 var message = new MimeMessage();
447 message.From.Add(GPALMailSettings.FromEmailAddress);
448
449 if (null != GPALMailSettings.ToEmailAddresses && 0 < GPALMailSettings.ToEmailAddresses.Count)
450 foreach (var to in GPALMailSettings.ToEmailAddresses)
451 message.To.Add(to);
452
453 if (null != GPALMailSettings.CcEmailAddresses && 0 < GPALMailSettings.CcEmailAddresses.Count)
454 foreach (var cc in GPALMailSettings.CcEmailAddresses)
455 message.Cc.Add(cc);
456
457 if (null != GPALMailSettings.BccEmailAddresses && 0 < GPALMailSettings.BccEmailAddresses.Count)
458 foreach (var bcc in GPALMailSettings.BccEmailAddresses)
459 message.Bcc.Add(bcc);
460
461 message.Subject = GPALMailSettings.Subject;
462 var bodyBuilder = new BodyBuilder();
463 if (null != GPALMailSettings.BodyHTML)
464 bodyBuilder.HtmlBody = GPALMailSettings.BodyHTML;
465 else
466 bodyBuilder.TextBody = GPALMailSettings.BodyText;
467 if (null != GPALMailSettings.Attachments && 0 < GPALMailSettings.Attachments.Count)
468 {
469 foreach (var attachment in GPALMailSettings.Attachments)
470 {
471 bodyBuilder.Attachments.Add(attachment);
472 }
473 }
474 message.Body = bodyBuilder.ToMessageBody();
475
476 using (var client = new SmtpClient())
477 {
478 try
479 {
480 client.Connect(GPALMailSettings.SMTPServerName, GPALMailSettings.SMTPPortNum, false);
481 }
482 catch // a cert exception most probably
483 {
484 client.ServerCertificateValidationCallback = (s, c, h, e) => true; // Bad, but protects against bad certs we can check, or something.
485 client.DeliveryStatusNotificationType = MailKit.Net.Smtp.DeliveryStatusNotificationType.Full;
486 client.SslProtocols = System.Security.Authentication.SslProtocols.Tls11 | System.Security.Authentication.SslProtocols.Tls12;
487
488 client.Connect(GPALMailSettings.SMTPServerName, GPALMailSettings.SMTPPortNum, false);
489 }
490 // a server that wants to know who is sending. nothing to authenticate with means nothing to do,
491 // which is how an open relay on a local port has always worked here
492 if (false == string.IsNullOrEmpty(ResolvedUserName))
493 client.Authenticate(ResolvedUserName, ResolvedPassword);
494
495 client.Send(message);
496 client.Disconnect(true);
497 }
498
499 return this;
500 }
501
509 {
510 // whichever was configured. a pop server named means pop, because naming one and having it ignored
511 // is worse than either
512 if (false == string.IsNullOrWhiteSpace(GPALMailSettings.POPServerName))
513 ReceiveOverPOP();
514 else if (false == string.IsNullOrWhiteSpace(GPALMailSettings.IMAPServerName))
515 ReceiveOverIMAP();
516 else
517 GPAL.PublishSimpleEvent(Enums.GPALEventType.ERROR, $"No pop or imap server to read mail from", this, Enums.GPALObjectType.Other);
518
519 return this;
520 }
521
527 public IAllowEmailEnvelopeAndActions Receive(out List<ReceivedEmail> receivedEmails)
528 {
529 Receive();
530
531 receivedEmails = new List<ReceivedEmail>(GPALMailSettings.ReceivedEmails);
532
533 GPAL.PublishSimpleEvent(Enums.GPALEventType.INFO, $"Handing back [{receivedEmails.Count}] received emails.", this, Enums.GPALObjectType.Other);
534
535 return this;
536 }
537
545 {
546 GPALMailSettings.UnreadOnly = unreadOnly;
547 return this;
548 }
549
557 {
558 GPALMailSettings.MaxMessages = maxMessages;
559 return this;
560 }
561
562 private void ReceiveOverPOP()
563 {
564 using (var client = new Pop3Client())
565 {
566 client.Connect(GPALMailSettings.POPServerName, GPALMailSettings.POPPortNum, MailKit.Security.SecureSocketOptions.Auto);
567 client.Authenticate(ResolvedUserName, ResolvedPassword);
568
569 // pop has no notion of a read message, so unread-only cannot be honoured here
570 if (true == GPALMailSettings.UnreadOnly)
571 GPAL.PublishSimpleEvent(Enums.GPALEventType.WARNING, $"POP cannot tell read from unread, so every message is being fetched from [{GPALMailSettings.POPServerName}]", this, Enums.GPALObjectType.Other);
572
573 int first = Math.Max(0, client.Count - GPALMailSettings.MaxMessages);
574
575 for (int i = first; i < client.Count; i++)
576 Collect(client.GetMessage(i), null);
577
578 client.Disconnect(true);
579 }
580 }
581
582 private void ReceiveOverIMAP()
583 {
584 using (var client = new ImapClient())
585 {
586 client.Connect(GPALMailSettings.IMAPServerName, GPALMailSettings.IMAPPortNum, true);
587 client.Authenticate(ResolvedUserName, ResolvedPassword);
588
589 var inbox = client.Inbox;
590 inbox.Open(MailKit.FolderAccess.ReadOnly);
591
592 // ask the server which messages qualify rather than dragging the mailbox down to find out
593 IList<UniqueId> ids = inbox.Search(true == GPALMailSettings.UnreadOnly
594 ? SearchQuery.NotSeen
595 : SearchQuery.All);
596
597 int first = Math.Max(0, ids.Count - GPALMailSettings.MaxMessages);
598
599 for (int i = first; i < ids.Count; i++)
600 Collect(inbox.GetMessage(ids[i]), ids[i]);
601
602 client.Disconnect(true);
603 }
604 }
605
613 {
614 ApplyFlag(GPALMailSettings.ReceivedEmails, MessageFlags.Seen, false);
615 return this;
616 }
617
625 {
626 ApplyFlag(GPALMailSettings.ReceivedEmails, MessageFlags.Deleted, true);
627 return this;
628 }
629
638 internal void ApplyFlag(IEnumerable<ReceivedEmail> messages, MessageFlags flag, bool expunge)
639 {
640 List<UniqueId> uids = messages.Where(m => null != m?.Uid).Select(m => m.Uid.Value).ToList();
641
642 if (0 == uids.Count)
643 GPAL.PublishSimpleEvent(Enums.GPALEventType.WARNING, $"Nothing to flag: no message came from an IMAP Receive", this, Enums.GPALObjectType.Other);
644 else
645 using (var client = new ImapClient())
646 {
647 client.Connect(GPALMailSettings.IMAPServerName, GPALMailSettings.IMAPPortNum, true);
648 client.Authenticate(ResolvedUserName, ResolvedPassword);
649
650 var inbox = client.Inbox;
651 inbox.Open(MailKit.FolderAccess.ReadWrite);
652 inbox.AddFlags(uids, flag, true);
653
654 if (true == expunge)
655 inbox.Expunge(uids);
656
657 client.Disconnect(true);
658
659 GPAL.PublishSimpleEvent(Enums.GPALEventType.INFO, $"Flagged [{uids.Count}] message(s) as [{flag}].", this, Enums.GPALObjectType.Other);
660 }
661 }
662
663 private void Collect(MimeMessage message, UniqueId? uid)
664 {
665 ReceivedEmail received = new ReceivedEmail
666 {
667 Subject = message.Subject,
668 From = message.From.ToString(),
669 // transactional mail is often html with no text part at all, and an empty body is no use
670 Body = message.TextBody ?? message.HtmlBody,
671 HtmlBody = message.HtmlBody,
672 Received = message.Date.LocalDateTime,
673 MessageId = message.MessageId,
674 Uid = uid,
675 Mailbox = this
676 };
677
678 // the name each attachment arrived under, and the part itself, so the file can be written later
679 // by whoever wants it and nothing is written by the act of reading mail
680 foreach (MimeEntity attachment in message.Attachments)
681 {
682 received.Attachments.Add(attachment.ContentDisposition?.FileName ?? attachment.ContentType?.Name);
683 received.AttachmentParts.Add(attachment);
684 }
685
686 GPALMailSettings.ReceivedEmails.Add(received);
687 }
695 {
696 int written = 0;
697
698 foreach (ReceivedEmail received in GPALMailSettings.ReceivedEmails)
699 written += received.SaveTo(directory).Count;
700
701 GPAL.PublishSimpleEvent(Enums.GPALEventType.INFO, $"Wrote [{written}] attachments to [{directory.Filename}].", this, Enums.GPALObjectType.Other);
702
703 return this;
704 }
705
713 {
714 // the from address stays: it is who you send as, it is saved with the server settings, and every
715 // message after this one would have to say it again
716 GPALMailSettings.ToEmailAddresses.Clear();
717 GPALMailSettings.CcEmailAddresses.Clear();
718 GPALMailSettings.BccEmailAddresses.Clear();
719 GPALMailSettings.Subject = null;
720 GPALMailSettings.BodyText = null;
721 GPALMailSettings.Attachments.Clear();
722 GPALMailSettings.ReceivedEmails.Clear();
723 return this;
724 }
725
732 {
733 if (mailSettingsFile != null)
734 MailSettingsFilePath = mailSettingsFile.Filename;
735
736 if (true == System.IO.File.Exists(MailSettingsFilePath))
737 GPAL.Converter.WithInput((GPALFile)MailSettingsFilePath).SaveTo(ref gPALMailSettings);
738 else
739 // nothing to load, so leave a file with the settings in it to fill in. a workflow that sets them
740 // itself and saves overwrites this with the real thing
741 SaveSettings();
742
743 return this;
744 }
745
752 {
753 if (mailSettingsFile != null) MailSettingsFilePath = mailSettingsFile.Filenames[0];
754 GPAL.Converter.WithInput(gPALMailSettings).SaveTo((GPALFile)MailSettingsFilePath);
755 return this;
756 }
757 #region HELPERS
764 public static List<MailboxAddress> ParseEmailAddresses(string input)
765 {
766
767 // Split the input string based on delimiters
768 string[] emailParts = input.Split(new char[] { ',', ';', '|' });
769 return CreateEmailAddresses(emailParts);
770 }
771
776 internal static List<MailboxAddress> CreateEmailAddresses(string[] emailParts)
777 {
778 List<MailboxAddress> addresses = new List<MailboxAddress>();
779 foreach (string emailPart in emailParts)
780 {
781 string email = emailPart.Trim();
782 if (!string.IsNullOrEmpty(email))
783 {
784 // Create a MailboxAddress object
785 MailboxAddress address = MailboxAddress.Parse(email);
786 addresses.Add(address);
787 }
788 }
789 return addresses;
790 }
798 static bool IsHtml(string text)
799 {
800 //
801 // Check if the text starts with an XML declaration
802 if (text.TrimStart().StartsWith("<!DOCTYPE html>", StringComparison.OrdinalIgnoreCase))
803 return true;
804 else if (text.TrimStart().StartsWith("<?xml", StringComparison.OrdinalIgnoreCase))
805 return false;
806
807 // Define a regular expression pattern to match HTML tags
808 string pattern = @"<\s*([^ >]+)[^>]*>.*?<\s*/\s*\1\s*>";
809
810 // Use Regex to search for HTML tags in the text
811 return System.Text.RegularExpressions.Regex.IsMatch(text, pattern);
812 }
813
814 #endregion HELPERS
815 }
816
819 public class ReceivedEmail
820 {
822 public string Subject { get; set; }
824 public string From { get; set; }
826 public string Body { get; set; }
828 public string HtmlBody { get; set; }
830 public DateTime Received { get; set; }
832 public string MessageId { get; set; }
833
834 // the imap identity of the message, so MarkAsRead knows which one to flag. null over pop
835 internal UniqueId? Uid { get; set; }
836
837 // the mail object that read this message, which is who still holds the server and the login
838 internal GPALMail Mailbox { get; set; }
839
847 {
848 Mailbox.ApplyFlag(new[] { this }, MessageFlags.Seen, false);
849 return this;
850 }
851
858 {
859 Mailbox.ApplyFlag(new[] { this }, MessageFlags.Deleted, true);
860 return this;
861 }
862
863 public List<string> Attachments { get; set; } = new List<string>();
864
865 // the attachments themselves, held until someone asks for them on disk
866 internal List<MimeEntity> AttachmentParts { get; set; } = new List<MimeEntity>();
867
874 public List<GPALFile> SaveTo(GPALFile directory)
875 {
876 List<GPALFile> retVal = new List<GPALFile>();
877
878 if (0 < AttachmentParts.Count)
879 Directory.CreateDirectory(directory.Filename);
880
881 foreach (MimeEntity attachment in AttachmentParts)
882 {
883 // the name the sender chose, taken apart so nothing but a filename is used and a name like
884 // ..\..\startup.cmd cannot write outside the directory that was asked for
885 string filename = Path.GetFileName(attachment.ContentDisposition?.FileName ?? attachment.ContentType?.Name);
886 string path = Path.Combine(directory.Filename, filename);
887
888 using (FileStream stream = File.Create(path))
889 if (attachment is MimePart part)
890 part.Content.DecodeTo(stream);
891 else
892 attachment.WriteTo(stream);
893
894 retVal.Add(path);
895 }
896
897 return retVal;
898 }
899 }
900}
901
GPAL File object instantied with GPAL.File Used to load tokens into a GPALGrid [rows/columns].
Definition GPALFile.cs:36
string Filename
We have only one file, accessing it.
Definition GPALFile.cs:474
Everything starts here, all the GPAL controls and global settings using fluent syntax are here....
Definition GPAL.cs:49
static IAllowConverterInput Converter
New GPAL Convertor.
Definition GPAL.cs:560
static void PublishSimpleEvent(GPALEventType gPALEventType, string msg, dynamic gPALObject=null, Enums.GPALObjectType gPALObjectType=GPALObjectType.None, Exception ex=null)
Publish a message to either the information channel or exception channel (if exception passed in) Pub...
Definition GPAL.cs:2406
Provides a fluent API for configuring, sending, and receiving email via SMTP, IMAP,...
Definition GPALMail.cs:55
IAllowEmailEnvelopeAndActions Receive()
Connects to the configured IMAP server, authenticates with GPALMailSettings.UserName and GPALMailSett...
Definition GPALMail.cs:508
string IMAPServerName
The IMAP server mail is read from, null when a POP server is the one named.
Definition GPALMail.cs:182
IAllowEmailServerSettingsAndName WithSMTPPortNum(int portNum=465)
Sets the port number used to connect to the SMTP server.
Definition GPALMail.cs:158
IAllowEmailEnvelopeAndActions Receive(out List< ReceivedEmail > receivedEmails)
Reads the mail as Receive does and hands the messages over in one call.
Definition GPALMail.cs:527
IAllowNameEnvelopeAndActions WithToEmailAddress(string mailAddress)
Adds one or more "To" recipients, parsed from a single string that may contain multiple addresses del...
Definition GPALMail.cs:250
IAllowNameEnvelopeAndActions WithCcEmailAddress(string mailAddress)
Adds one or more "Cc" recipients, parsed from a single string that may contain multiple addresses del...
Definition GPALMail.cs:266
IAllowEmailServerSettingsAndName WithCredentials(ICredentials credentials)
The credential to authenticate with, from wherever GPAL got it: a vault, a file, or set by hand....
Definition GPALMail.cs:169
IAllowEmailEnvelopeAndActions SaveSettings(GPALFile mailSettingsFile=null)
Saves this instance's GPALMailSettings (server connection and envelope settings) to the given GPALFil...
Definition GPALMail.cs:751
IAllowEmailEnvelopeAndActions WithUnreadOnly(bool unreadOnly)
Limits Receive() to the messages the server still has as unread. Off by default, so a Receive with no...
Definition GPALMail.cs:544
IAllowNameEnvelopeAndActions WithBccEmailAddress(string[] emailParts)
Adds one or more "Bcc" recipients from an array of email address strings.
Definition GPALMail.cs:326
int SMTPPortNum
The port used to reach SMTPServerName.
Definition GPALMail.cs:180
int POPPortNum
The port used to reach POPServerName.
Definition GPALMail.cs:188
IAllowEmailServerSettingsAndName WithUserName(string userName)
Sets the username used to authenticate with the mail server(s).
Definition GPALMail.cs:214
IAllowNameEnvelopeAndActions WithCcEmailAddress(string[] emailParts)
Adds one or more "Cc" recipients from an array of email address strings.
Definition GPALMail.cs:311
IAllowEmailEnvelopeAndActions MarkAllAsRead()
Marks every message Receive() collected as read on the server, in one connection, so the next Receive...
Definition GPALMail.cs:612
IAllowEmailEnvelopeAndActions SaveTo(GPALFile directory)
Writes every attachment on every message Receive collected into the given directory,...
Definition GPALMail.cs:694
IAllowEmailServerSettingsAndName WithIMAPServerName(string serverName)
Sets the IMAP server hostname used for receiving mail, and forgets any POP server,...
Definition GPALMail.cs:102
string SMTPServerName
The SMTP server mail is sent through, as set by WithSMTPServerName or read from a settings file.
Definition GPALMail.cs:178
IGPALMail ToGPALObject()
Returns this instance cast to IGPALMail, allowing the fluent chain to be converted back to the root m...
Definition GPALMail.cs:92
string FromAddress
The address messages are sent from, as text, with the display name when there is one.
Definition GPALMail.cs:190
IAllowEmailEnvelopeAndActions WithName(string name)
Sets the display name on the address added just before this call, whether that was the from,...
Definition GPALMail.cs:406
IAllowEmailEnvelopeAndActions WithBody(string body)
Sets the message body, automatically detecting whether it is HTML or plain text via IsHtml(string) an...
Definition GPALMail.cs:380
IAllowEmailEnvelopeAndActions WithAttachment(GPALFile attachmentFile)
Adds the file(s) referenced by the given GPALFile as email attachments. Each filename in GPALFile....
Definition GPALMail.cs:344
IAllowEmailEnvelopeAndActions WithSubject(string subject)
Sets the subject line of the message.
Definition GPALMail.cs:394
string POPServerName
The POP server mail is read from, null when an IMAP server is the one named.
Definition GPALMail.cs:186
IAllowEmailServerSettingsAndName WithIMAPPortNum(int portNum=993)
Sets the port number used to connect to the IMAP server.
Definition GPALMail.cs:138
IAllowEmailEnvelopeAndActions Clear()
Resets the email envelope to a blank state: clears all recipient lists, subject, body text,...
Definition GPALMail.cs:712
IAllowEmailEnvelopeAndActions DeleteAll()
Deletes every message Receive() collected from the server, flagging and expunging them in one connect...
Definition GPALMail.cs:624
IAllowEmailServerSettingsAndName WithPassword(string password)
Sets the password used to authenticate with the mail server(s).
Definition GPALMail.cs:224
IAllowEmailEnvelopeAndActions Send()
Builds the message from the configured envelope (from/to/cc/bcc, subject, body, attachments) and send...
Definition GPALMail.cs:436
IAllowEmailServerSettingsAndName WithPOPServerName(string serverName)
Sets the POP server hostname used for receiving mail, and forgets any IMAP server,...
Definition GPALMail.cs:115
IAllowEmailEnvelopeAndActions LoadSettings(GPALFile mailSettingsFile=null)
Loads this instance's GPALMailSettings from the given GPALFile via GPAL.Converter,...
Definition GPALMail.cs:731
IAllowEmailServerSettingsAndName WithPOPPortNum(int portNum=110)
Sets the port number used to connect to the POP server.
Definition GPALMail.cs:148
IAllowNameEnvelopeAndActions WithBccEmailAddress(string mailAddress)
Adds one or more "Bcc" recipients, parsed from a single string that may contain multiple addresses de...
Definition GPALMail.cs:282
IAllowEmailEnvelopeAndActions WithMaxMessages(int maxMessages)
Caps how many messages one Receive() fetches, taking the newest first. Every message by default,...
Definition GPALMail.cs:556
IAllowEmailServerSettingsAndName WithSMTPServerName(string serverName)
Sets the SMTP server hostname used for sending mail.
Definition GPALMail.cs:127
int IMAPPortNum
The port used to reach IMAPServerName.
Definition GPALMail.cs:184
static List< MailboxAddress > ParseEmailAddresses(string input)
Splits a single string containing one or more email addresses delimited by commas,...
Definition GPALMail.cs:764
IAllowNameEnvelopeAndActions WithToEmailAddress(string[] emailParts)
Adds one or more "To" recipients from an array of email address strings.
Definition GPALMail.cs:296
A simplified representation of a single email message retrieved by GPALMail.Receive.
Definition GPALMail.cs:820
ReceivedEmail Delete()
Deletes this message from the server, flagging it and expunging it in the one call....
Definition GPALMail.cs:857
List< GPALFile > SaveTo(GPALFile directory)
Writes this message's attachments into the given directory, creating it when it is not there,...
Definition GPALMail.cs:874
ReceivedEmail MarkAsRead()
Marks this message as read on the server, so the next Receive set to unread only leaves it behind....
Definition GPALMail.cs:846
string Subject
The message's subject line.
Definition GPALMail.cs:822
List< string > Attachments
The filename of each attachment on the message, so a workflow can tell what came with it....
Definition GPALMail.cs:863
string From
The message's "From" address, as a display string.
Definition GPALMail.cs:824
string MessageId
The message id the sender stamped on it, which is how the same message is recognised across runs.
Definition GPALMail.cs:832
string Body
The plain-text body of the message, falling back to the html body when the sender wrote no text part.
Definition GPALMail.cs:826
string HtmlBody
The html body of the message, null when the sender wrote none.
Definition GPALMail.cs:828
DateTime Received
When the message was sent, in local time.
Definition GPALMail.cs:830