Getting emails from the Exchange server and closing tasks by emails
The script below does the following:
- gets all the incoming mail from a specific mailbox (Exchange server, MAPI/RPC protocol);
- identifies the task by the email subject (adding a task ID to an email subject is described below);
- closes the task by a specific transition (the transition is searched by name).
Declare the following namespaces:
using System;
using System.IO;
using System.Linq;
using Aspose.Email;
using Aspose.Email.Exchange;
using Aspose.Email.Mail;
using Aspose.Email.Outlook;
using EleWise.ELMA.API;
using EleWise.ELMA.Files;
using EleWise.ELMA.Model.Managers;
using EleWise.ELMA.Model.Services;
using EleWise.ELMA.Runtime.Managers;
using EleWise.ELMA.Services;
using EleWise.ELMA.Tasks.Models;
using EleWise.ELMA.Workflow.BPMN.Diagrams.Elements;
using EleWise.ELMA.Workflow.Models;
using EleWise.ELMA.Workflow.Services;
The script uses a context variable:
context.Initiator - User type.
Script text:
string resubject = "RE: ";// will be added to the subject when replying
string remessage = "";// reply email text
//email setup
string sendFrom = "example@example.com";
string mailboxURI = "https://mail.example.com/EWS/exchange.asmx";
string username = "User";
string password = "password";
string domain = "exapmle";
//Create IEWSClient
IEWSClient client = EWSClient.GetEWSClient (mailboxURI, username, password, domain);
ExchangeMailboxInfo mailboxInfo = client.GetMailboxInfo ();
string rootUri = client.GetMailboxInfo ().RootUri;
//Get the list of all folders
ExchangeFolderInfoCollection folderInfoCollection = client.ListSubFolders (rootUri);
//Go through folders
foreach (ExchangeFolderInfo folderInfo in folderInfoCollection)
{
//Create a filter to receive only unread emails
string resubject = "RE: ";// will be added to the subject when replying
string remessage = "";// reply email text
//email setup
string sendFrom = "example@example.com";
string mailboxURI = "https://mail.example.com/EWS/exchange.asmx";
string username = "User";
string password = "password";
string domain = "exapmle";
//Create IEWSClient
IEWSClient client = EWSClient.GetEWSClient (mailboxURI, username, password, domain);
ExchangeMailboxInfo mailboxInfo = client.GetMailboxInfo ();
string rootUri = client.GetMailboxInfo ().RootUri;
//Get the list of all folders
ExchangeFolderInfoCollection folderInfoCollection = client.ListSubFolders (rootUri);
//Go through folders
foreach (ExchangeFolderInfo folderInfo in folderInfoCollection)
{
//Create a filter for getting only unread emails
MailQuery query = new MailQuery ("’IsRead’ = ’False’");
ExchangeMessageInfoCollection msgInfoColl = client.ListMessages (folderInfo.Uri, query); // get all the unread emails from the folder
//Go through all emails
foreach (ExchangeMessageInfo mail in msgInfoColl)
{
long num = 0;
if (!mail.IsRead)//if an email is unread, process it
{
client.SetReadFlag (mail.UniqueUri, true); //mark the email as unread
resubject = resubject + mail.Subject.ToString (); //generate the reply email subject
var message = client.FetchMessage (mail.UniqueUri); //get email by uri
remessage = message.Body; //get the reply email text
string subject = mail.Subject.ToString (); //get the incoming email subject
string taskstat = ""; //a message for the recipient will be written here
//get the task ID
if (subject.Contains ("#")) //the subject contains # + number
{
int number;
var countv = subject.Split (’#’).Count () - 1;
string splitvar = subject.Split (’#’) [countv]; //get the characters after #
bool result = Int32.TryParse (splitvar, out number); //attempt parsing a string into a number
if (result)//if ID is obtained
{
num = Convert.ToInt32 (splitvar);
}
else// if ID is not obtained
{
num = 0;
}
}
else//the subject does not contain # + number
{
num = 0;
}
if (num > 0)//if ID is obtained
{
var task = EntityManager<TaskBase>.Instance.LoadOrNull (num); //get a task by ID
if (task != null) //if the task is obtained by ID
{
var workfl = task.WorkflowBookmark.Instance; //get the process instance
//check the task status
if (task.Status == TaskBaseStatus.Complete) {
taskstat = "Failed to deliver your reply: The task is already completed. Contact the addressee in another way.";
}
if (workfl != null)//if the process is not found
{
//check the process status
if (workfl.Status != WorkflowInstanceStatus.Running)
{
taskstat = "Failed to deliver your reply: The task is completed. Contact the addressee in another way.";
}
if ((workfl.Status == WorkflowInstanceStatus.Running) && (task.Status!= TaskBaseStatus.Complete))//"the process is started, the task is active"
{
//write the email text to the process instance context, EmailResponse context variable of the String type
var EmailResponse = (string)workfl.Context.GetType ().GetProperty ("EmailResponse").GetValue (workfl.Context, null);
EmailResponse += (string.IsNullOrEmpty (EmailResponse) ? "" : "\r\n") + remessage;
workfl.Context.GetType ().GetProperty ("EmailResponse").SetValue (workfl.Context, EmailResponse, null);
//get the email attachments
if (message.Attachments.Count > 0) {
for (int att = 0; att < message.Attachments.Count; att++)
{
//create an ELMA attachment
var newAtt = InterfaceActivator.Create<EleWise.ELMA.Common.Models.Attachment> ();
//create a file from stream
newAtt.File = CreateBinaryFile (message.Attachments [att].ContentStream, "Attachment №" + att.ToString ());
//and fill in the standard attachment properties
newAtt.CreationAuthor = context.Initiator;
newAtt.CreationDate = DateTime.Now;
newAtt.Save ();
//Add an attachment to the context of the EmailAttachments process instance (Attachment, list)
dynamic procContext = workfl.Context;
var itemType = procContext.EmailAttachments.GetType ().GetInterface (typeof(Iesi.Collections.Generic.ISet<>).FullName).GetGenericArguments () [0];
var item = InterfaceActivator.Create (itemType);
procContext.EmailAttachments.Add (newAtt);
}
}
//Get the process diagram element, by which the task was generated
var element = (BPMNFlowElement)task.WorkflowBookmark.Instance.Process.Diagram.Elements.Single (e => e.Uid == task.WorkflowBookmark.ElementUid);
//Find an outgoing transition by name. Since it may be one of two tasks, find a match by one of the transitions.
var connector = element.OutputConnectors.FirstOrDefault (c => (c.Name == "Email is loaded" || c.Name == "Done"));
if (connector != null)//if a transition is found
{
//Generate data for the task executor
var executeData = new WorkflowTaskExecuteData (task, connector.Uid);
//Execute the task
Locator.GetServiceNotNull<IWorkflowRuntimeService> ().Execute (executeData);
taskstat = "You reply was uploaded to the system. The task is completed.";
}
}
}
}
else
{
taskstat = "Failed to deliver your reply to the recipient: The task is not found, " + "the email subject may have been changed. Contact the recipient in another way.";
}
}
else
{
taskstat = "Failed to deliver your reply to the recipient: The task is not found, " + "the email subject may have been changed. Contact the recipient in another way.";
}
// generate the text of the reply email
remessage = taskstat + "\r\n\r\n-----Original Message-----\r\n" + "\r\nОт: " + message.From
+ "\r\nDate: " + message.Date + "\r\nTo: " + message.To + "\r\nSubject: " + message.Subject + "\r\n" + remessage;
// send the reply email
var msg = new Aspose.Email.Mail.MailMessage ();
msg.From = sendFrom;
msg.To = message.From.Address.ToString ();
msg.Subject = resubject;
msg.Body = remessage;
client.Send (msg);
}
}
}
To create a stream file, this method is used:
private BinaryFile CreateBinaryFile (Stream stream, string fileName)
{
var temp = BinaryFile.CreateContentFilePath (fileName);
using (var fs = new FileStream (temp, FileMode.CreateNew, FileAccess.Write)) {
stream.Seek (0, SeekOrigin.Begin);
stream.CopyTo (fs);
}
var mimeMappingService = Locator.GetServiceNotNull<IMimeMappingService> ();
var contractTemplate = new BinaryFile {
ContentType = mimeMappingService.GetTypeByExtension (Path.GetExtension (fileName)),
Name = Path.GetFileName (fileName),
ContentFilePath = temp,
CreateDate = DateTime.Now,
};
DataAccessManager.FileManager.SaveFile (contractTemplate);
return contractTemplate;
}
To add the task ID to the email subject, edit the notification template file. You can find the file in ELMA3-[Edition]\UserConfig\Notifications\ Workflow.Task. Add {SR(’ #’)}{$New.Id} to this line:
<Subject>
{if {$RecipientSet}=’ExecutorReplaced’}(@{$New.Executor}){end if}({SR(’New task’)}) ’{$New.Subject}’ {SR(’in the process’)} {$New.WorkflowBookmark.Instance.Name} ({$New.WorkflowBookmark.Instance.Process.Name}){SR(’ #’)}{$New.Id}
</Subject>