LogoLogo
HomePricingDocumentation
  • 💿Getting Started
    • Installation and Project Setup
    • Hello Perigee!
    • Perigee Application Design
    • Hello Configuration
    • Hello Logs
    • Hello Integration
    • Troubleshooting
    • Case Studies
  • 📃License + Notice
    • 📂Licensing
    • Notice of Third Party Agreements
  • 🚀Perigee and Beyond
    • Extending - Threads
    • Extending - Loaders
    • ⏳All about CRON
  • 🔮API Generation
    • What is API Generation?
    • API Builder
  • 🗺️Architecting YOUR App
    • Design and Requirements
    • Define Sources
    • Requirements
  • 🧩Core Modules
    • 🌐PerigeeApplication
    • 🪡Thread Registry
    • Event Sources
      • Scheduled/Logic
        • CRON Thread
        • Scheduler
        • Sync Agent
      • Watchers
        • SalesForce
        • Sharepoint
        • Directory Watch
        • Directory Notifier
        • IMAP
    • Credential Management
      • Connection Strings
      • Custom Refresh Logic
      • RestSharp Authenticator
      • Credential Store SDK
      • ⁉️Troubleshooting Credentials
    • Integration Utilities
      • HTTP(S) - RestSharp
      • Transaction Coordinator
      • Limiter
      • Watermarking
    • Alert Managers
      • SMS
      • Email
      • Discord
      • Teams
    • File Formats
      • Excel
      • CSV
    • 📁File System Storage
      • File Revision Store
      • Concurrent File Store
      • FileSync + Cache
    • Third Party
      • SmartSheets
      • Microsoft Graph
    • Perigee In Parallel
      • Parallel Processing Reference
      • Extensions
      • GroupProcessor
      • SingleProcessor
    • 🧱Utility Classes
      • Metrics
      • F(x) Expressions
      • Multi-Threaded Processor (Scatter Gather)
      • OpenAI - GPT
      • XML Converter
      • Dynamic Data Table
      • Debounce
      • Thread Conditions
      • Perigee Utility Class
      • Network Utility
      • Lists
      • FileUtil
      • Inclusive2DRange
      • Strings, Numbers, Dates
      • Nested Sets
      • Behavior Trees
      • JsonCompress
      • Topological Sorting
      • DBDownloader
    • 🈁Bit Serializer
  • 📣Examples and Demos
    • API + Perigee
    • 📰Excel Quick Load
    • SalesForce Watcher
    • Report Scheduler
    • Agent Data Synchronization
    • 📩IMAP Echo bot
    • Watch and load CSVs
    • Graph Delegated Authorization + DataVerse
    • Coordinator Demo
    • Azure Service Bus
    • QuickBooks Online
  • 📘Blueprints
    • Perigee With .NET Hosting
    • Web Host Utilities
    • 🔌Plugin Load Context
  • 🎞️Transforms
    • 🌟What is Transforms?
    • 📘Terminology
    • 🦾The Mapping Document
    • 👾Transformation Process
    • 😎Profile
    • 🎒Automation
      • 🕓Package Options
      • 🔳Configuration
    • 🔧Utilities
      • 🧹Clean
      • 📑Map File
      • 🔎File Identification
      • 🗺️Map Generation
      • 🪅Insert Statement Generation
  • 🗃️Transform SDK
    • 👋Quick Start Guide
    • 🥳MapTo
    • 🔌Authoring Plugins
      • 🔘File IO Process
      • 📢Data Quality
      • 🟢Transform Process
    • SDK Reference
      • 🔘FileIOProcessData
      • 📢DataQualityContext
      • 🎛️TransformDataContext
      • 🏅TransformResult
Powered by GitBook
On this page
  • Authentication
  • User/Pass
  • SASL
  • The SDK
  • Addresses
  • Labels and Flags
  • Replying
  • Is ?
  • Delete Mail
  • Attachments
  • Querying
  • Sent Box
  • Input Text
  • Low Level Access
  • Best practice watching
Export as PDF
  1. Core Modules
  2. Event Sources
  3. Watchers

IMAP

IMAP watcher is able to watch a single inbox and give a callback any time a new message is available to process.

There's a rich SDK that enables the IMAP client to respond to messages, attach images or HTML, get the body body, create reply messages, etc.

Authentication

There are two basic ways to authenticate with your IMAP server:

User/Pass

This is the "direct" method. If the server supports it, you can supply a username and password.

PerigeeApplication.ApplicationNoInit("EmailWatcher",  (c) => {
    c.AddIMAPWatcher("MailWatch", 
        "email@address.com", "MailBot", "password", 
        "hostImap", 993, 
        "smtphost", 587, 
        (ct, l, mail) => { 
            //Mail handler here!
    });
});

SASL

Simple Authentication Security Layer: This is for the authentication methods that require OAUTH2 or other methods.

//Direct creation
var saslDirect = new SaslMechanismOAuth2("", "");

//If using GMAIL, we built in the google auth flow
var googleSASL = MailWatcher.SASL_GoogleAPIS("email", "CredentialPath.json");

An example of the google SASL callback:

 PerigeeApplication.ApplicationNoInit("EmailWatcher",  (c) => {

    c.AddIMAPWatcher("MailWatch",
     "email@address.com", "MailBot",
     "hostImap", 993,
     "smtphost", 587, 
     () => MailWatcher.SASL_GoogleAPIS("email@address.com", "CredentialPath.json"),
     (ct, l, mail) => {
         //Mail handler here!
     });
});

The SDK

All of the SDK references below are available when a callback occurs for new mail messages to be processed.

Addresses

To get the various addresses:

mail.CCAddresses();
mail.FromAddresses();
mail.ToAddresses();

//Or to get to the message envelope
var env = mail.Message.Envelope;

Labels and Flags

//Add
mail.AddFlags(MailKit.MessageFlags.Answered | MailKit.MessageFlags.Seen);
mail.AddLabels("bot");

//Get
var labels = mail.GetLabels();
var flags = mail.GetFlags();

Replying

The Reply method automatically configures the method reply parameters including the correct message headers, subject, response addresses, and if includeReplyText is true, it will also quote the original message back as any normal client would do.

//Generate a reply with the correct message contents
 var mReply = mail.Reply(false, (bb) =>
 {
     //Set HTML, and text fallback content
     bb.TextBody = "text is supported";
     bb.HtmlBody = "<b>html</b> is supported";
     
     //Add an attachment
     //bb.Attachments.Add("MyPDF", File.ReadAllBytes("MyPDF.pdf"));
 }, includeReplyText: true);

 //Send
 mail.SendMessage(mReply);

Is ?

To see if the message is <FLAG>:

var isAnswered = mail.IsAnswered;
var isSeen = mail.IsSeen;
var isFlagged = mail.IsFlagged;
var isDeleted = mail.IsDeleted;
var isDraft = mail.IsDraft;

Delete Mail

To delete a message, issue the delete command. The parameter is for expunging the message from the server as well as issuing the deleted flag.

mail.DeleteMail(true);

Attachments

You can get a list of attachment parts, and iterate over them to get the actual content, mime type, name, etc.

//This does not pull the body or content, and is a fast way of checking how many attachments a message has
var attachcount = mail.Message.Attachments.Count();

//This iterates over the bodyparts to get additional information, it is slower and should be used after there are known messages
var attachments = mail.GetAttachments();
if (attachments.Any())
{
    var attach = attachments.ElementAt(0);
    var name = attach.FileName;
    using MemoryStream attachBytes = mail.GetAttachment(attach);
}

Querying

To query the inbox:

var uidsNotAnswered = mail.GetNotAnsweredUIDs();
if (uidsNotAnswered.Any())
{
   var ListMailSummaries = mail.FetchMessages(uidsNotAnswered);
}

var uidsNotSeen = mail.GetNotSeenUIDs();
if (uidsNotSeen.Any())
{
   var ListMailSummaries = mail.FetchMessages(uidsNotSeen);
}

//Or direct access querying:
var uids = mail.Folder.Search(MailKit.Search.SearchQuery.DeliveredAfter(DateTime.UtcNow.AddDays(-1)));

Sent Box

If you need to access the sent box, we provide an easy way to retrieve and open the sent mailbox.

var sentBox = mail.GetAndOpenSentFolder();
if (sentBox != null)
{
 var uids = sentBox.Search(MailKit.Search.SearchQuery.DeliveredAfter(DateTime.UtcNow.AddDays(-1)));

 //Fetch using the sentbox, as mail.FetchMessages uses the inbox.
 var ListMailSummaries = sentBox.FetchAsync(uids, mail.MessagePullItems).GetAwaiter().GetResult(); //make sure you're "using MailKit;"
}

IMAP only allows a single mailbox to be open at once. Don't forget to call:

mail.OpenInbox();. This verifies and prevents future issues with any subsequent calls to the mail client.

Input Text

Sometimes you just need whatever the person said, excluding their signature and reply content. This method takes several passes at retrieving just the top level user input and skipping the rest:

string textOnlyPart = mail.GetOnlyInputTextBody();

Low Level Access

var imapClient = mail.Client;
var imapInbox = mail.Folder;

Best practice watching

We highly recommend:

  1. Putting a stop gap on the mail receive handler, something like IsAnswered, as a way of preventing unwanted reprocessing of messages.

  2. Catching the exception and attempting to mark it answered and label it error if the client supports labelling.

PerigeeApplication.ApplicationNoInit("MailDemo",  (c) => {

    c.AddIMAPWatcher("MailWatch",
        "email@address.com", "MailBot",
        "hostImap", 993,
        "smtphost", 587,
        () => MailWatcher.SASL_GoogleAPIS("email@address.com", "CredentialPath.json"),
        (ct, l, mail) => 
        {
            try
            {
                if (!mail.IsAnswered)
                {
                    //Do stuff here!
                    
                    
                    //Mark it on success
                    mail.AddFlags(MessageFlags.Answered | MailKit.MessageFlags.Seen);
                    mail.AddLabels("success");
                }
            }
            catch (Exception ex)
            {
                l.LogError(ex, "Uncaught exception in mail processor");
                try
                {
                    mail.AddFlags(MessageFlags.Answered | MailKit.MessageFlags.Seen);
                    mail.AddLabels("error");
                }
                catch (Exception) { }
            }
        });
});
PreviousDirectory NotifierNextCredential Management

Last updated 1 year ago

The BodyBuilder callback is how you configure the outgoing message. You can see an of adding an image with CIDs.

There are a bunch of prebuilt methods to help with a mail client. If you want to do something specific, you can get the client and folder access as so, and use any of the available methods from :

example here
MailKit
🧩
Page cover image