[ELMA3] Получение электронных писем с сервера Exchange и закрытие задач по письму
Приведенный ниже сценарий выполняет следующее:
- получение всех входящих писем из определенного почтового ящика (сервер Exchange, протокол MAPI/RPC);
- определение по теме письма задачи (в данной представляют интерес задачи о постановке новых задач пользователю. Как добавить Id задачи в тему письма, написано ниже);
- закрытие задачи по определенному переходу (поиск перехода по названию).
Заранее необходимо объявить следующие пространства имен:
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;
В сценарии используется контекстная переменная:
context.Initiator - переменная типа "Пользователь".
Текст сценария:
string resubject = "RE: ";// будет добавлять к теме при отправлен ответа
string remessage = "";// текст ответного письма
//настройки почты
string sendFrom = "example@example.ru";
string mailboxURI = "https://mail.example.ru/EWS/exchange.asmx";
string username = "User";
string password = "password";
string domain = "exapmle";
//Создаем IEWSClient
IEWSClient client = EWSClient.GetEWSClient (mailboxURI, username, password, domain);
ExchangeMailboxInfo mailboxInfo = client.GetMailboxInfo ();
string rootUri = client.GetMailboxInfo ().RootUri;
//Получаем список всех папок
ExchangeFolderInfoCollection folderInfoCollection = client.ListSubFolders (rootUri);
//Перебираем папки
foreach (ExchangeFolderInfo folderInfo in folderInfoCollection)
{
//Создаем фильтр - будем получать только непрочитанные письма
string resubject = "RE: ";// будет добавлять к теме при отправлен ответа
string remessage = "";// текст ответного письма
//настройки почты
string sendFrom = "example@example.ru";
string mailboxURI = "https://mail.example.ru/EWS/exchange.asmx";
string username = "User";
string password = "password";
string domain = "exapmle";
//Создаем IEWSClient
IEWSClient client = EWSClient.GetEWSClient (mailboxURI, username, password, domain);
ExchangeMailboxInfo mailboxInfo = client.GetMailboxInfo ();
string rootUri = client.GetMailboxInfo ().RootUri;
//Получаем список всех папок
ExchangeFolderInfoCollection folderInfoCollection = client.ListSubFolders (rootUri);
//Перебираем папки
foreach (ExchangeFolderInfo folderInfo in folderInfoCollection)
{
//Создаем фильтр - будем получать только непрочитанные письма
MailQuery query = new MailQuery ("’IsRead’ = ’False’");
ExchangeMessageInfoCollection msgInfoColl = client.ListMessages (folderInfo.Uri, query); // получаем все непрочитанные письма из папки
//Перебираем все письма
foreach (ExchangeMessageInfo mail in msgInfoColl)
{
long num = 0;
if (!mail.IsRead)//если письмо не прочитано - берем в обработку
{
client.SetReadFlag (mail.UniqueUri, true); //помечаем письмо как прочитанное
resubject = resubject + mail.Subject.ToString (); //формируем тему ответного письма
var message = client.FetchMessage (mail.UniqueUri); //получаем письмо по uri
remessage = message.Body; //получаем текст ответного письма
string subject = mail.Subject.ToString (); //получаем тему входящего письма
string taskstat = ""; //сюда будет записано сообщение для получателя
//получение Id задачи
if (subject.Contains ("#")) //тема содержит # + номер
{
int number;
var countv = subject.Split (’#’).Count () - 1;
string splitvar = subject.Split (’#’) [countv]; //получаем символы после #
bool result = Int32.TryParse (splitvar, out number); //пробуем преобразовать строку в число
if (result)//если удалось получить Id
{
num = Convert.ToInt32 (splitvar);
}
else// не удалось получить Id
{
num = 0;
}
}
else//тема не содержит # + номер
{
num = 0;
}
if (num > 0)//если получили Id
{
var task = EntityManager<TaskBase>.Instance.LoadOrNull (num); //получаем задачу по Id
if (task != null) //если удалось получить задачу по Id
{
var workfl = task.WorkflowBookmark.Instance; //получаем экземпляр процесса
//проверяем статус задачи
if (task.Status == TaskBaseStatus.Complete) {
taskstat = "Ваш ответ не доставлен до получателя по причине: Исходная задача уже выполнена. Обратитесь к адресату другим способом.";
}
if (workfl != null)//если процесс найден
{
//проверяем статус процесса
if (workfl.Status != WorkflowInstanceStatus.Running)
{
taskstat = "Ваш ответ не доставлен до получателя по причине: Процесс завершен. Обратитесь к адресату другим способом.";
}
if ((workfl.Status == WorkflowInstanceStatus.Running) && (task.Status!= TaskBaseStatus.Complete))//"процесс запущен, задача не завершена"
{
//записываем текст письма в контекст экземпляра процесса, контекстная переменная OtvetSEmail типа "Строка"
var OtvetSEmail = (string)workfl.Context.GetType ().GetProperty ("OtvetSEmail").GetValue (workfl.Context, null);
OtvetSEmail += (string.IsNullOrEmpty (OtvetSEmail) ? "" : "\r\n") + remessage;
workfl.Context.GetType ().GetProperty ("OtvetSEmail").SetValue (workfl.Context, OtvetSEmail, null);
//получаем вложения письма
if (message.Attachments.Count > 0) {
for (int att = 0; att < message.Attachments.Count; att++)
{
//создаем вложение ELMA
var newAtt = InterfaceActivator.Create<EleWise.ELMA.Common.Models.Attachment> ();
//создаем файл из потока
newAtt.File = CreateBinaryFile (message.Attachments [att].ContentStream, "Вложение №" + att.ToString ());
//и заполняем стандартные свойства вложения
newAtt.CreationAuthor = context.Initiator;
newAtt.CreationDate = DateTime.Now;
newAtt.Save ();
//добавляем вложение в контекст экземпляра процесса VlozheniyaSEmail (Вложение, список)
dynamic procContext = workfl.Context;
var itemType = procContext.VlozheniyaSEmail.GetType ().GetInterface (typeof(Iesi.Collections.Generic.ISet<>).FullName).GetGenericArguments () [0];
var item = InterfaceActivator.Create (itemType);
procContext.VlozheniyaSEmail.Add (newAtt);
}
}
//Получаем элемент диаграммы процесса, по которому сформирована задача
var element = (BPMNFlowElement)task.WorkflowBookmark.Instance.Process.Diagram.Elements.Single (e => e.Uid == task.WorkflowBookmark.ElementUid);
//Ищем исходящий переход по его имени. Так как может быть одна из двух задач, ищем соответсвие одному из двух переходов.
var connector = element.OutputConnectors.FirstOrDefault (c => (c.Name == "Письмо загружено" || c.Name == "Готово"));
if (connector != null)//если переход найден
{
//Формируем данные для исполнения задачи
var executeData = new WorkflowTaskExecuteData (task, connector.Uid);
//Исполняем задачу
Locator.GetServiceNotNull<IWorkflowRuntimeService> ().Execute (executeData);
taskstat = "Ваш ответ был загружен в систему. Задача выполнена.";
}
}
}
}
else
{
taskstat = "Ваш ответ не доставлен до получателя по причине: Исходная задача не найдена, " + "возможно была изменена тема письма. Обратитесь к адресату другим способом.";
}
}
else
{
taskstat = "Ваш ответ не доставлен до получателя по причине: Исходная задача не найдена, " + "возможно была изменена тема письма. Обратитесь к адресату другим способом.";
}
// формирование текста ответного письма
remessage = taskstat + "\r\n\r\n-----Original Message-----\r\n" + "\r\nОт: " + message.From
+ "\r\nДата: " + message.Date + "\r\nКому: " + message.To + "\r\nТема: " + message.Subject + "\r\n" + remessage;
// отправка ответного письма
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);
}
}
}
Внимание!
При копировании из браузера может возникнуть проблема, связанная с неправильным отображением апострофов. На рисунке ниже приведен пример того, как должны выглядеть апострофы.
![](/upload/6188/png5d5a277f772185/37929196/6188.png)
Если использовать некорректные апострофы, сценарий не будет работать. Необходимо заменить их на корректные (это можно сделать при помощи сочетания клавиш Ctrl+F, Заменить).
Для создания файла из потока используется метод:
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;
}
Для добавления Id задачи к теме письма, необходимо внести изменение в файл шаблона оповещения. Файл шаблона оповещения размещен по пути: .../<Общая папка с файлами системы ELMA>\UserConfig\Notifications\Workflow.Task. Необходимо добавить {SR(’ #’)}{$New.Id} в строку:
<Subject>
{if {$RecipientSet}=’ExecutorReplaced’}(@{$New.Executor}){end if}({SR(’Новая задача’)}) ’{$New.Subject}’ {SR(’в процессе’)} {$New.WorkflowBookmark.Instance.Name} ({$New.WorkflowBookmark.Instance.Process.Name}){SR(’ #’)}{$New.Id}
</Subject>