Newer
Older
Martin Groppe
committed
import("JditoFilter_lib");
import("CommunicationBlacklist_lib");
import("EmailFilterHandling_lib");
import("system.logging");
import("system.entities");
Martin Groppe
committed
import("system.fileIO");
import("system.project");
import("system.translate");
import("ActivityTask_lib");
import("system.util");
import("Contact_lib");
import("system.datetime");
import("system.neon");
import("Employee_lib");
import("system.vars");
import("KeywordRegistry_basic");
import("Sql_lib");
import("system.db");
import("DocumentTemplate_lib");
import("Communication_lib");
import("Email_lib");
import("system.process");
import("system.notification");
Martin Groppe
committed
import("system.db");
Martin Groppe
committed
import("system.workflow");
Martin Groppe
committed
import("system.text");
* Functions for bulk mails.
*/
function BulkMailUtils () {}
/**
* Executes a process to send bulk mails on the server and creates a notification when finished.
*
* @param {String} pBulkMailId <p>
* Id of the bulk mail.<br>
Martin Groppe
committed
* @param {Bool} pTestRun (optional) <p>
* True indicates a Testrun<br>
* @param {String} pUser=currentUser (optional) <p>
* User that will get the notification, <br>
* if null (not undefined!), no notification<br>
* will be created.<br>
Martin Groppe
committed
BulkMailUtils.sendBulkMailOnServer = function (pBulkMailId, pTestRun, pUser)
{
if (pUser === undefined)
pUser = EmployeeUtils.getCurrentUserId();
var processConfig = process.createStartAsyncConfig()
.setName("sendBulkMail_serverProcess")
.setLocalVariables({
Martin Groppe
committed
testRun : pTestRun,
Martin Groppe
committed
.setUser(pUser||"mailbridge")
}
/**
* Sends a bulk mail. You should only call this function on the server because it
* can take some time to execute, use BulkMailUtils.sendBulkMailOnServer instead.
*
* @param {String} pBulkMailId <p>
* Id of the bulk mail.<br>
Martin Groppe
committed
* True indicates a Testrun<br>
* @param {Bool} pUser (optional) <p>
* If there are no test recipients or no recipients marked for a test replacement in a test run
* we send an email to this user instead<br>
* @param {Object} pAdditionalLinkParameters(optional)<p>
* Additional parameters that get put into the weblinks for the redirect webservice.
* Expects object of key value pairs. <br>
* @param {String} pAdHochMailingRecipientId (optional) <p>
* The id of a recipient added to a adhoc mailing list. The mailing ignores all other recipients if this parameter is set<br>
* @param {String} pOriginUrl (optional) <p>
* Base URL for link replacement. Only needed when sending an Ad-Hoc Mailing without a configured baseReplacementURL in the Configuration <br>
* since sys.origin does not exist during workflowactions.
* @return {Object} <p>
* Count of sucessful and failed mails.<br>
BulkMailUtils.sendBulkMail = function (pBulkMailId, pIsTestRun, pUser, pAdditionalLinkParameters, pAdHochMailingRecipientId, pOriginUrl)
if (pIsTestRun == undefined)
{
pIsTestRun = false;
}
Martin Groppe
committed
try
{
var sendUserTitle = project.getInstanceConfigValue("custom.bulkmail.user");
Martin Groppe
committed
var [templateId, subject, emailSender, createActivity, bulkMailName, useTemplateAttachments, mosaicoTemplateId] =
newSelect("DOCUMENTTEMPLATE_ID, SUBJECT, SENDER_EMAIL_ADDRESS, CREATEACTIVITIES, NAME, USE_TEMPLATE_ATTACHMENTS, MOSAICOTEMPLATE_ID")
.from("BULKMAIL")
.where("BULKMAIL.BULKMAILID", pBulkMailId)
.arrayRow();
useTemplateAttachments = Utils.toBoolean(useTemplateAttachments);

Vinzent Broens
committed
var template = BulkMailUtils.getBulkMailTemplate(pBulkMailId, templateId, true, useTemplateAttachments, null, mosaicoTemplateId);
Martin Groppe
committed
var testRecipientData;
var recipientLoadConfig = entities.createConfigForLoadingRows()
.fields(["BULKMAILRECIPIENTID", "CONTACT_ID", "EMAIL_ADDRESS", "PERSON_ID", "ORGANISATION_ID", "HASCOMMUNICATIONREJECTION"])
.provider("RecipientsToBeMailed")
.addParameter("BulkMailId_param", pBulkMailId)
.addParameter("IsTestMail_param", pIsTestRun);
if(pAdHochMailingRecipientId)
{
recipientLoadConfig.uid(pAdHochMailingRecipientId);
}
recipientData = entities.getRows(recipientLoadConfig);
var blacklist = new CommunicationBlacklist().loadBlacklistRecipients(pBulkMailId);
Martin Groppe
committed
testRecipientData = newSelect("BULKMAILTESTRECIPIENT.CONTACT_ID, BULKMAILTESTRECIPIENT.EMAIL_ADDRESS")
.from("BULKMAILTESTRECIPIENT")
.where("BULKMAILTESTRECIPIENT.BULKMAIL_ID", pBulkMailId)
Martin Groppe
committed
.table();
if (testRecipientData.length == 0 || recipientData.length == 0 && pUser)
{
var userData = tools.getUserByAttribute(tools.NAME,pUser,tools.PROFILE_DEFAULT);
if (userData)
{
testRecipientData = [userData[tools.PARAMS][tools.CONTACTID],userData[tools.PARAMS][tools.EMAIL]];
recipientData = [{"CONTACT_ID":userData[tools.PARAMS][tools.CONTACTID],"EMAIL":userData[tools.PARAMS][tools.EMAIL]}];
}
}
Martin Groppe
committed
var mailrunId = util.getNewUUID();
new SqlBuilder()
.tableName("MAIL_RUN")
.insertFields({
"MAIL_RUNID": mailrunId,
"OBJECT_ROWID": pBulkMailId,
"OBJECT_TYPE": "Bulkmail",
"DATE_RUN_START": vars.get("$sys.date"),
"STATUS": $KeywordRegistry.bulkMailStatus$beingSent(),
"TESTRUN": pIsTestRun ? 1 : 0
});
Martin Groppe
committed
var mailLogIds = new Map();
var contactIds = recipientData.map(function (recipient)
{
var contactId = recipient["CONTACT_ID"];
mailLogIds.set(contactId, util.getNewUUID());
return contactId;
});
var baseUrl = (pOriginUrl || project.getInstanceConfigValue("custom.bulkmail.baseReplacementURL", vars.get("$sys.origin"))) + "/services/rest/redirect_rest?";
var additionalParameterString = "";
if (pAdditionalLinkParameters)
{
additionalParameterString = "&" + Object.keys(pAdditionalLinkParameters)
.map(function (key)
{
return key + "=" + pAdditionalLinkParameters[key]
})
.join("&");
}
var linkPlaceholders = newSelect(["PLACEHOLDER", "WEBLINKID", "URL", "ISREDIRECT"])
.from("WEBLINK")
.table()
.map(function ([placeholder, weblinkId, url, isRedirect])
{
Martin Groppe
committed
var linkFn
Martin Groppe
committed
linkFn = function (pContactId)
Martin Groppe
committed
{
return baseUrl + "link=" + weblinkId + "&log=" + mailLogIds.get(pContactId) + additionalParameterString;
Martin Groppe
committed
}
return new Placeholder(placeholder, Placeholder.types.CALLBACKFUNCTION, linkFn);
}
Martin Groppe
committed
else
{
linkFn = function (pContactId)
{
return StringUtils.replaceAll(url, "{@contactid@}", pContactId);
}
return new Placeholder(placeholder, Placeholder.types.CALLBACKFUNCTION, linkFn);
}
Martin Groppe
committed
Martin Groppe
committed
var webviewFn = function(pContactId)
{
return (pOriginUrl || project.getInstanceConfigValue("custom.bulkmail.baseReplacementURL", vars.get("$sys.origin"))) + "/services/rest/webview_rest?" + "log=" + mailLogIds.get(pContactId);
Martin Groppe
committed
}
var webviewPlaceholder = new Placeholder("webview", Placeholder.types.CALLBACKFUNCTION, webviewFn);
var additionalPlaceholders = [webviewPlaceholder].concat(linkPlaceholders);
var bouncedSoftIds = [];
var bouncedHardIds = [];
Martin Groppe
committed
var mails = template.getReplacedEmailsByContactIds(contactIds, additionalPlaceholders);
var subjectTemplate = new DocumentTemplate(subject, DocumentTemplate.types.PLAIN);
var subjects = subjectTemplate.getReplacedContentByContactIds(contactIds);
var bulkMailLink = [["BulkMail", pBulkMailId]];
var activitySubject = translate.withArguments("Bulk mail \"%0\" sent", [bulkMailName]);
var emailFilterProcessor = new IncomingEmailFilterProcessor().loadFilters();
if (!pIsTestRun)
{
recipientData.forEach(function (recipient)
{
let isSuccess = false;
Martin Groppe
committed
var errorMessage = "";
let recipientId = recipient["BULKMAILRECIPIENTID"];
let contactId = recipient["CONTACT_ID"];
let emailAddress = recipient["EMAIL_ADDRESS"];
let personId = recipient["PERSON_ID"];
let organisationId = recipient["ORGANISATION_ID"];
Martin Groppe
committed
let hasCommunicationRejection = Utils.toBoolean(recipient["HASCOMMUNICATIONREJECTION"]);
Martin Groppe
committed
let recipientStatus = $KeywordRegistry.bulkMailRecipientStatus$failed();
Martin Groppe
committed
if (email !== undefined && emailAddress && !blacklist.hasContactId(contactId) && !hasCommunicationRejection)
Martin Groppe
committed
{
Martin Groppe
committed
try
{
email.toRecipients = [emailAddress];
email.sender = emailSender;
email.subject = subjects[contactId];
BulkMailUtils.storeEmlFile(pBulkMailId, mailrunId, mailLogId,email.getEML());
isSuccess = email.send(sendUserTitle);
if (!isSuccess)
{
errorMessage = logging.toLogString(email.getMailError(), true);
var filterType = emailFilterProcessor.processError(errorMessage, contactId, emailAddress);
if (filterType == $KeywordRegistry.emailFilterType$bounceHard())
bouncedStatus = $KeywordRegistry.bulkMailRecipientStatus$hardBounce();
else if (filterType == $KeywordRegistry.emailFilterType$bounceSoft())
bouncedStatus = $KeywordRegistry.bulkMailRecipientStatus$softBounce();
Martin Groppe
committed
recipientStatus = bouncedStatus || $KeywordRegistry.bulkMailRecipientStatus$failed();
}
else
{
recipientStatus = $KeywordRegistry.bulkMailRecipientStatus$sent();
}
}
catch (ex)
Martin Groppe
committed
errorMessage = logging.toLogString(ex, true);
//set the recipient status to 'sent' or 'failed'
new SqlBuilder()
.tableName("MAIL_LOG")
.insertFields({
"MAIL_LOGID": mailLogId,
"MAIL_RUN_ID": mailrunId,
"CONTACT_ID": contactId,
Martin Groppe
committed
"ERRORMESSAGE": errorMessage,
"SENDER_EMAIL": emailSender,
"RECIPIENT_EMAIL": emailAddress,
"MAILING_SUBJECT": subjects[contactId],
"DATE_SEND": vars.get("$sys.date")
});
Martin Groppe
committed
//TODO: Klären was von alter Logik noch bleiben soll. Status macht nur Sinn wenn jede Bulkmail nur einmal gesendet wird. Bleiben Activitys?
successIds.push(recipientId);
}
else if (bouncedStatus == $KeywordRegistry.bulkMailRecipientStatus$softBounce())
{
bouncedSoftIds.push(recipientId);
}
else if (bouncedStatus == $KeywordRegistry.bulkMailRecipientStatus$hardBounce())
{
bouncedHardIds.push(recipientId);
}
else
{
failedIds.push(recipientId);
}
if (isSuccess && createActivity == "1")
{
let activityData = {
categoryKeywordId : $KeywordRegistry.activityCategory$mail(),
directionKeywordId : $KeywordRegistry.activityDirection$outgoing(),
subject : activitySubject,
content : email.body
};
let contactLink = [[ContactUtils.getContextByPersOrg(personId, organisationId), contactId]];
ActivityUtils.insertNewActivity(activityData, bulkMailLink.concat(contactLink));
}
});
newWhere("MAIL_RUN.MAIL_RUNID", mailrunId)
.updateFields({
"STATUS": $KeywordRegistry.bulkMailStatus$sent(),
"DATE_RUN_FINISHED": vars.get("$sys.date")
});
if(!pAdHochMailingRecipientId)
{
newWhere("BULKMAIL.BULKMAILID", pBulkMailId)
.updateFields({
"STATUS": $KeywordRegistry.bulkMailStatus$sent()
}
else
{
for (let i = 0, l = recipientData.length; i < l; i++)
{
let isSuccess = false;
Martin Groppe
committed
let errorMessage = "";
let contactId = recipientData[i]["CONTACT_ID"];
Martin Groppe
committed
let currentMailLogId = mailLogIds.get(contactId);
if (email !== undefined)
{
email.sender = emailSender;
email.subject = "Test: "+subjects[contactId];
for (let j =0; j<testRecipientData.length;j++)
{
if(testRecipientData[j][1])
{
Martin Groppe
committed
let nextMailLogId = util.getNewUUID();
Martin Groppe
committed
try
{
email.toRecipients = [testRecipientData[j][1]];
email.body = StringUtils.replaceAll(email.body,currentMailLogId,nextMailLogId);
currentMailLogId = nextMailLogId;
this.storeEmlFile(pBulkMailId, mailrunId, nextMailLogId,email.getEML());
isSuccess = email.send(sendUserTitle);
}
catch(ex)
{
errorMessage = logging.toLogString(ex, true);
}
Array.prototype.push.call(isSuccess ? successIds : failedIds, recipientData[i]["BULKMAILRECIPIENTID"]);
Martin Groppe
committed
new SqlBuilder()
.tableName("MAIL_LOG")
.insertFields({
"MAIL_LOGID":nextMailLogId,
"MAIL_RUN_ID":mailrunId,
"CONTACT_ID":testRecipientData[j][0],
Martin Groppe
committed
"ERRORMESSAGE": errorMessage || logging.toLogString(email.getMailError(), true) || "",
Martin Groppe
committed
"STATUS":(isSuccess ?$KeywordRegistry.bulkMailRecipientStatus$sent(): $KeywordRegistry.bulkMailRecipientStatus$failed()),
"SENDER_EMAIL":emailSender,
"RECIPIENT_EMAIL":testRecipientData[j][1],
"MAILING_SUBJECT":email.subject,
"DATE_SEND":vars.get("$sys.date")
Martin Groppe
committed
});
Martin Groppe
committed
}
}
Martin Groppe
committed
}
newWhere("MAIL_RUN.MAIL_RUNID",mailrunId)
.updateData(true,"MAIL_RUN",["STATUS","DATE_RUN_FINISHED"],null,[$KeywordRegistry.bulkMailStatus$sent(),vars.get("$sys.date")]);
}
Martin Groppe
committed
}
catch(ex)
{
logging.log(ex);
Martin Groppe
committed
.updateData(true,"MAIL_RUN",["STATUS","DATE_RUN_FINISHED"],null,[$KeywordRegistry.bulkMailStatus$failed(),vars.get("$sys.date")]);
if(!pIsTestRun)
{
newWhere("BULKMAIL.BULKMAILID", pBulkMailId)
.updateFields({
"STATUS": $KeywordRegistry.bulkMailStatus$failed()
});
}
}
finally
{
if(successIds && failedIds && bouncedSoftIds && bouncedHardIds)
{
var updates = [];
Martin Groppe
committed
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
updates = updates.concat(successIds.map(function (successId)
{
return newWhere("BULKMAILRECIPIENT.BULKMAILRECIPIENTID",successId)
.buildUpdateStatement({
"STATUS": $KeywordRegistry.bulkMailRecipientStatus$sent(),
"SENTDATE": sentDate
});
}));
updates = updates.concat(failedIds.map(function (failedId)
{
return newWhere("BULKMAILRECIPIENT.BULKMAILRECIPIENTID",failedId)
.buildUpdateStatement({
"STATUS": $KeywordRegistry.bulkMailRecipientStatus$failed(),
"SENTDATE": sentDate
});
}));
updates = updates.concat(bouncedSoftIds.map(function (bouncedSoftId)
{
return newWhere("BULKMAILRECIPIENT.BULKMAILRECIPIENTID",bouncedSoftId)
.buildUpdateStatement({
"STATUS": $KeywordRegistry.bulkMailRecipientStatus$softBounce(),
"SENTDATE": sentDate
});
}));
Martin Groppe
committed
updates = updates.concat(bouncedHardIds.map(function (bouncedHardId)
{
return newWhere("BULKMAILRECIPIENT.BULKMAILRECIPIENTID",bouncedHardId)
.buildUpdateStatement({
"STATUS": $KeywordRegistry.bulkMailRecipientStatus$hardBounce(),
"SENTDATE": sentDate
});
}));
db.updates(updates);
return {
sucessful : successIds.length,
failed : failedIds.length
};
}
* Opens a context to select a bulk mail to add recipients to.<br>
* @param {String} pContext the context of the contacts (Person or Organisation)
Martin Groppe
committed
* @param {String[]} pIds Ids that should be added.<br>
* @param {String|Object} pFilter the filter for the contacts that should be used if no Ids are selected
* @param {String|Object} pParameters the relevant parameters that are needed to get the Ids from entities.loadrows in the form:{parametername:parametervalue}
Martin Groppe
committed
BulkMailUtils.openAddRecipientView = function (pContext, pIds, pFilter, pParameters)
Martin Groppe
committed
if (!Utils.isString(pParameters))
pParameters = JSON.stringify(pParameters);
if (!Utils.isString(pIds))
pIds = JSON.stringify(pIds);
if (Utils.isString(pFilter))
pFilter = JSON.parse(pFilter);
Martin Groppe
committed
if(Utils.isNullOrEmpty(pFilter.filter))
pFilter.filter= JSON.parse(JditoFilterUtils.getEmptyFilter()).filter;
pFilter = JSON.stringify(pFilter);
var recipe = neonFilter.createEntityRecordsRecipeBuilder().parameters({
"ObjectType_param": pContext,
Martin Groppe
committed
"Ids_param": pIds,
"Filter_param": pFilter,
"Parameters_param": pParameters

Florian Maier
committed
neon.openContextWithRecipe("BulkMailAddRecipients", "BulkMailAddRecipientsEdit_view", recipe, neon.OPERATINGSTATE_VIEW);
/**
* Opens a context to select a bulk mail to add recipients to.<br>
*
* @param {String} pRecordsRecipe RecordsRecipe for the selection that should be added
*/
BulkMailUtils.openAddRecipientViewWithRecipe = function (pRecordsRecipe)
{
logging.log(pRecordsRecipe);
var recipe = neonFilter.createEntityRecordsRecipeBuilder().parameters({
"RecordsRecipe_param": pRecordsRecipe
}).toString();
neon.openContextWithRecipe("BulkMailAddRecipients", "BulkMailAddRecipientsEdit_view", recipe, neon.OPERATINGSTATE_VIEW);
}
* Deletes all bulk mail recipients that have a commrestriction for emails.<br>
* @param {String} pBulkMailId <p>
* The mail id.<br>
*/
BulkMailUtils.removeCommRestrictionRecipients = function (pBulkMailId)
{
var recipientIds = newSelect("BULKMAILRECIPIENTID")
.join("CONTACT", "BULKMAILRECIPIENT.CONTACT_ID = CONTACT.CONTACTID")
.where("BULKMAILRECIPIENT.BULKMAIL_ID", pBulkMailId)
.and(new CommunicationSettingsCondition()
.emails("BULKMAILRECIPIENT.EMAIL_ADDRESS")
.rejected()
.existSettings()
.buildCondition())
newWhereIfSet("BULKMAILRECIPIENT.BULKMAILRECIPIENTID", recipientIds, SqlBuilder.IN())
* Adds recipients to a bulkmail.<br>
* @param {String} pBulkMailId <p>
* Bulk mail id.<br>
* @param {String[]} pContactIds <p>
* Contact ids of the recipients.<br>
*/
BulkMailUtils.addRecipients = function (pBulkMailId, pContactIds)
{
if (pContactIds.length > 0)
var sqlBuilder = new SqlBuilder();

Vinzent Broens
committed
var inserts = [];
var contactData;

Vinzent Broens
committed
while (pContactIds.length > 0){
var ContactIdsChunk = pContactIds.splice(0, 1000);
contactData = newSelect(["CONTACTID", "(" + CommUtil.getStandardSubSqlMail(newWhere("COMMUNICATION.OBJECT_ROWID = CONTACTID").and("COMMUNICATION.OBJECT_TYPE", "Contact")) + ")"])
.from("CONTACT")
.where("CONTACT.CONTACTID", ContactIdsChunk, SqlBuilder.IN())
.table();
inserts = inserts.concat(contactData.map(function([contactId, standardMail])
{
return sqlBuilder.buildInsertStatement({
"BULKMAIL_ID": pBulkMailId,
"CONTACT_ID": contactId,
"STATUS": $KeywordRegistry.bulkMailRecipientStatus$added(),
"IS_TEST_RECIPIENT" : 0,
"EMAIL_ADDRESS": standardMail
}, "BULKMAILRECIPIENT", "BULKMAILRECIPIENTID");
}));
}
* Loads the document template of a bulk mail. If the bulk mail
* itself has a template, it is preferred over the documentTemplate-id.
* @param {String} pBulkMailId <p>
* The id of the bulk mail.<br>
* @param {String} pDocumentTemplateId <p>
* The id of the document template.<br>
* @param {Boolean} pResolveSubtemplates=true (optional) <p>
* If true subtemplates are resolved (if the type is html)
* @param {Boolean} pUseTemplateAttachments=false <p>
* If true the attachments from the document template is always used
* @param {FileUpload} pUpload (optional) <p>
* The upload value if a custom template is used.<br>
* @param {String} pMosaicoTemplateId (optional) <p>
* The id of the mosaico template.<br>
* @return {DocumentTemplate} <p>
* The document template, null if no content was found.<br>
BulkMailUtils.getBulkMailTemplate = function (pBulkMailId, pDocumentTemplateId, pResolveSubtemplates, pUseTemplateAttachments, pUpload, pMosaicoTemplateId)
if (pUpload && pUpload.isFilled() && BulkMailUtils.isValidMimeType(pUpload.mimeType))
{
return DocumentTemplate.fromUpload(pUpload);
}
var bulkTemplate = DocumentTemplate.loadTemplate(pBulkMailId, "BULKMAIL", pResolveSubtemplates);
var documentTemplate = DocumentTemplate.loadTemplate(pDocumentTemplateId, undefined, pResolveSubtemplates);
var mosaicoTemplate = DocumentTemplate.loadTemplate(pMosaicoTemplateId, "MOSAICOTEMPLATE", pResolveSubtemplates);
if (pMosaicoTemplateId)
{
return mosaicoTemplate;
}
else
{
return documentTemplate;
}
if (pUseTemplateAttachments)
{
bulkTemplate.setAttachments(documentTemplate.getAttachments());
}
* Checks if a contact is a recipient of a bulk mail.<br>
* @param {String} pBulkMailId <p>
* The id of the bulk mail.<br>
* @param {String} pContactId <p>
* The contact id.<br>
* @param {String} pRecipientId <p>
* The contact id of the contact where,<br>
* the bulk mail shall sent to.<br>
* @return {boolean} <p>
* True, if the contact is a recipient.<br>
*/
BulkMailUtils.isRecipient = function (pBulkMailId, pContactId, pRecipientId)
{
return newSelect("count(*)")
.from("BULKMAILRECIPIENT")
.where("BULKMAILRECIPIENT.CONTACT_ID", pContactId)
.and("BULKMAILRECIPIENT.BULKMAIL_ID", pBulkMailId)
.andIfSet("BULKMAILRECIPIENT.BULKMAILRECIPIENTID", pRecipientId, SqlBuilder.NOT_EQUAL())
.cell() != "0"; //TODO: is there a way exists could be used?
Martin Groppe
committed
/**
* Checks if a bulk mail still has pending recipients.<br>
*
* @param {String} pBulkMailId <p>
* The id of the bulk mail.<br>
* @return {boolean} <p>
* True, if the contact is a recipient.<br>
*/
BulkMailUtils.hasPendingRecipient = function (pBulkMailId)
{
return new SqlBuilder().selectCount()
.from("BULKMAILRECIPIENT")
.where("BULKMAILRECIPIENT.STATUS", $KeywordRegistry.bulkMailRecipientStatus$pending())
.and("BULKMAILRECIPIENT.BULKMAIL_ID", pBulkMailId)
.cell() != "0";
}
* Opens the BulkMail context in new mode.<br>
* @param {String[]} pRecipients (optional) <p>
* Recipients that should be added after creation.<br>
Martin Groppe
committed
* @param {String} pContext (optional) <p>
* Context the filter is coming from.<br>
* @param {Object} pFilter (optional) <p>
* sys.filter of selection that should be added to new bulkmail<br>
Martin Groppe
committed
BulkMailUtils.newBulkMail = function (pRecipients, pContext, pFilter)
Martin Groppe
committed
"PresetRecipients_param" : pRecipients?JSON.stringify(pRecipients):null,
"PresetRecipientsContext_param": pContext,
"PresetRecipientsFilter_param": pFilter?JSON.stringify(pFilter):null
var recipe = neonFilter.createEntityRecordsRecipeBuilder().parameters(params).toString();

Florian Maier
committed
neon.openContextWithRecipe("BulkMail", "BulkMailEdit_view", recipe, neon.OPERATINGSTATE_NEW);
/**
* Opens the BulkMail context in new mode.<br>
*
* @param {String} pRecordsRecipe <p>
* Recordsrecipe containing the recipients for the new Bulkmail.
* Currently supported Contexts are campaignstep, campaignparticipant, person and <br> sys.filter of selection that should be added to new bulkmail<br>
*/
BulkMailUtils.newBulkMailWithRecordsRecipe = function (pRecordsRecipe)
{
if (!Utils.isString(pRecordsRecipe))
{
pRecordsRecipe = JSON.stringify(pRecordsRecipe);
}
var params = {
"PresetRecipientsRecordsRecipe_param": pRecordsRecipe
};
var recipe = neonFilter.createEntityRecordsRecipeBuilder().parameters(params).toString();
neon.openContextWithRecipe("BulkMail", "BulkMailEdit_view", recipe, neon.OPERATINGSTATE_NEW);
}
/**
* Filters the given contactIds if they can be added as new recipients.
* Checks if a contact is already a recipient or if there is a advertising ban.
*
* @param {String} pBulkMailId id of the bulk mail the contacts should be added to
* @param {String[]} pContactIds contacts to filter
* @return {String[]} contacts that can be added as recipients
*/
BulkMailUtils.filterNewRecipients = function (pBulkMailId, pContactIds)
{
return newSelect("CONTACTID")
.from("CONTACT")
.whereIfSet("CONTACT.CONTACTID", pContactIds, SqlBuilder.IN())
// only add contacts that aren't already recipients
.and(null, newSelect("BULKMAILRECIPIENTID")
.from("BULKMAILRECIPIENT")
.where("BULKMAILRECIPIENT.CONTACT_ID = CONTACT.CONTACTID")
.and("BULKMAILRECIPIENT.BULKMAIL_ID", pBulkMailId)
, SqlBuilder.NOT_EXISTS())
// check if there's a commrestriction
.and(new CommunicationSettingsCondition()
.emails(CommUtil.getStandardSubSqlMail())
.rejected()
.existNoSettings()
.buildCondition())
Martin Groppe
committed
/**
* Filters the given contactIds if they can be added as new recipients.
* Checks if a contact is already a recipient or if there is a advertising ban.
*
* @param {String} pBulkMailId id of the bulk mail the contacts should be added to
* @param {String} pCondition Condition part of sys.filter
* @param {String} pContext Context that belongs to the filtercondition
* @return {String[]} contacts that can be added as recipients
*/
BulkMailUtils.filterNewRecipientsByCondition = function (pBulkMailId, pCondition, pContext)
{
var condition = newSelect("CONTACTID")
.from("CONTACT")

Vinzent Broens
committed
.join("ADDRESS", "ADDRESS.ADDRESSID = CONTACT.ADDRESS_ID")
.join("ORGANISATION", "ORGANISATION.ORGANISATIONID = CONTACT.ORGANISATION_ID")
Martin Groppe
committed
.whereIfSet(pCondition)
// only add contacts that aren't already recipients
.and(null, newSelect("BULKMAILRECIPIENTID")
.from("BULKMAILRECIPIENT")
.where("BULKMAILRECIPIENT.CONTACT_ID = CONTACT.CONTACTID")
.and("BULKMAILRECIPIENT.BULKMAIL_ID", pBulkMailId)
, SqlBuilder.NOT_EXISTS())
// check if there's a commrestriction
.and(new CommunicationSettingsCondition()
.emails(CommUtil.getStandardSubSqlMail())
.rejected()
.existNoSettings()
.buildCondition());
if (pContext == "Person")
{

Vinzent Broens
committed
condition.join("PERSON", "PERSON.PERSONID = CONTACT.PERSON_ID");
Martin Groppe
committed
}

Vinzent Broens
committed
if (pContext == "Organisation")
Martin Groppe
committed
{
condition.and("CONTACT.PERSON_ID is null");
}
if (pContext == "CampaignParticipant")
{
condition.join("CAMPAIGNPARTICIPANT","CAMPAIGNPARTICIPANT.CONTACT_ID = CONTACT.CONTACTID");
}
if (pContext == "CampaignStep")
{
condition.join("CAMPAIGNPARTICIPANT","CAMPAIGNPARTICIPANT.CONTACT_ID = CONTACT.CONTACTID")
.join("CAMPAIGNSTEP","CAMPAIGNSTEP.CAMPAIGNSTEPID = CAMPAIGNPARTICIPANT.CAMPAIGNSTEP_ID");
}
return condition.arrayColumn();
}
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
/*
* adds a Recipient to an ad hoc mailing list and sends the mail.
*
* @param {String} pBulkMailId id of the bulk mail the contact should be added to
* @param {String} pContactId id of the contact that gets added
* @param {String} pEmailAddress address the ad hoc mailing gets sent to.
* @param {Object} pAdditionalLinkParameters(optional)<p>
* Additional parameters that get put into the weblinks for the redirect webservice.
* Expects object of key value pairs. <br>
* @param {String} pOriginUrl Base URL for link replacement.
*/
BulkMailUtils.addToAdHocMail = function (pBulkMailId, pContactId, pEmailAddress, pAdditionalLinkParameters, pOriginUrl)
{
if(!pBulkMailId || !pContactId)
{
return;
}
var bulkMailRecipientId = util.getNewUUID();
new SqlBuilder().insertFields({
"BULKMAILRECIPIENTID": bulkMailRecipientId,
"BULKMAIL_ID": pBulkMailId,
"CONTACT_ID": pContactId,
"STATUS": $KeywordRegistry.bulkMailRecipientStatus$pending(),
"EMAIL_ADDRESS": pEmailAddress
},
"BULKMAILRECIPIENT");
this.sendBulkMail(pBulkMailId, false, false, pAdditionalLinkParameters, bulkMailRecipientId, pOriginUrl);
}
Martin Groppe
committed
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
/**
* Filters the given contactIds if they can be added as new recipients.
* Checks if a contact is already a recipient or if there is a advertising ban.
*
* @param {String} pBulkMailId id of the bulk mail the contacts should be added to
* @param {String} pRecordsRecipe recordsrecipe for the selection that should be filtered.
* @return {String[]} contacts that can be added as recipients
*/
BulkMailUtils.filterNewRecipientsByRecordsRecipe = function (pBulkMailId, pRecordsRecipe)
{
var recipients = [];
var entity = JSON.parse(pRecordsRecipe).entityName;
var loadConfig = entities.createConfigForLoadingRows()
.fromEntityRecordsRecipe(pRecordsRecipe)
.fields(["#UID"]);
var rows = entities.getRows(loadConfig);
while (rows.length > 0)
{
var currentIds = rows.splice(0,1000).map(function (row)
{
return row["#UID"];
});
var sql = newSelect("CONTACTID")
.from("CONTACT")
.join("ADDRESS", "ADDRESS.ADDRESSID = CONTACT.ADDRESS_ID")
.join("ORGANISATION", "ORGANISATION.ORGANISATIONID = CONTACT.ORGANISATION_ID")
// only add contacts that aren't already recipients
.where(null, newSelect("BULKMAILRECIPIENTID")
.from("BULKMAILRECIPIENT")
.where("BULKMAILRECIPIENT.CONTACT_ID = CONTACT.CONTACTID")
.and("BULKMAILRECIPIENT.BULKMAIL_ID", pBulkMailId)
, SqlBuilder.NOT_EXISTS())
// check if there's a commrestriction
.and(new CommunicationSettingsCondition()
.emails(CommUtil.getStandardSubSqlMail())
.rejected()
.existNoSettings()
.buildCondition());
if (entity == "Person_entity")
{
sql.join("PERSON", "PERSON.PERSONID = CONTACT.PERSON_ID")
.and("CONTACT.CONTACTID",currentIds,SqlBuilder.IN());
}
if (entity == "Organisation_entity")
{
sql.and("CONTACT.PERSON_ID is null")
.and("CONTACT.CONTACTID",currentIds,SqlBuilder.IN());
}
if (entity == "CampaignParticipant_entity")
{
sql.join("CAMPAIGNPARTICIPANT","CAMPAIGNPARTICIPANT.CONTACT_ID = CONTACT.CONTACTID")
.and("CAMPAIGNPARTICIPANT.CAMPAIGNPARTICIPANTID",currentIds,SqlBuilder.IN());
}
if (entity == "CampaignStep_entity")
{
sql.join("CAMPAIGNPARTICIPANT","CAMPAIGNPARTICIPANT.CONTACT_ID = CONTACT.CONTACTID")
.join("CAMPAIGNSTEP","CAMPAIGNSTEP.CAMPAIGNSTEPID = CAMPAIGNPARTICIPANT.CAMPAIGNSTEP_ID")
.and("CAMPAIGNSTEP.CAMPAIGNSTEPID",currentIds,SqlBuilder.IN());
}
recipients = recipients.concat(sql.arrayColumn());
}
return recipients;
}
* Opens the given bulk mail.
*
* @param {String} pBulkMailId <p>
* The id of the bulk mail.<br>
*/
BulkMailUtils.openBulkMail = function (pBulkMailId)
{
var recipe = neonFilter.createEntityRecordsRecipeBuilder().uidsIncludelist([pBulkMailId]).toString();

Florian Maier
committed
neon.openContextWithRecipe("BulkMail", "BulkMailMain_view", recipe, neon.OPERATINGSTATE_VIEW);
* Checks is the given mime type can be used for a bulk mail.<br>
* @param {String} pMimeType <p>
* The mime type.<br>
* @return {Boolean} <p>
* Whether the type is usable or not.<br>
*/
BulkMailUtils.isValidMimeType = function (pMimeType)
{
var templateType = DocumentTemplate.types.fromMimeType(pMimeType);
return BulkMailUtils.isValidTemplateType(templateType)
}
/**
* Checks is the given template type can be used for a bulk mail.<br>
* @param {String} pTemplateType <p>
* Template type.<br>
* @return {Boolean} <p>
* Whether the type is usable or not.<br>
*/
BulkMailUtils.isValidTemplateType = function (pTemplateType)
{
switch (pTemplateType)
{
case DocumentTemplate.types.EML:
case DocumentTemplate.types.HTML:
case DocumentTemplate.types.TXT:
return true;
default:
return false;
}
}
* Checks whether the given status id matches,<br>
* to the status of a bulk mail which is sent or<br>
* not.
*
* @param {String} pStatus <p>
* The key id of the current status.<br>
* @return {Boolean} <p>
Martin Groppe
committed
* True if the status is "sent","failed" or "sending".<br>
*/
BulkMailUtils.isStatusSendingOrSent = function (pStatus)
{
Martin Groppe
committed
return pStatus == $KeywordRegistry.bulkMailStatus$sent() || pStatus == $KeywordRegistry.bulkMailStatus$beingSent() || pStatus == $KeywordRegistry.bulkMailStatus$failed();
/**
* Checks whether the given status id matches,<br>
* to the status of a bulk mail which is sent or<br>
* not.
*
* @param {String} pStatus <p>
* The key id of the current status.<br>
* @return {Boolean} <p>
* True if the status is "sent" or "sending".<br>
*/
BulkMailUtils.isStatusSendingSentOrAdHoc = function (pStatus)
{
return pStatus == $KeywordRegistry.bulkMailStatus$sent() || pStatus == $KeywordRegistry.bulkMailStatus$beingSent() || pStatus == $KeywordRegistry.bulkMailStatus$adHoc()
}
/**
* Opens BulkMail context in new mode, with the given bulk mail id.<br>
*
* @param {String} pBulkMailId <p>
* The id of the bulk mail.<br>
*/
BulkMailUtils.copy = function(pBulkMailId)
{
var params = {
"CopyBulkMailId_param" : pBulkMailId
};
var recipe = neonFilter.createEntityRecordsRecipeBuilder().parameters(params).toString();

Florian Maier
committed
neon.openContextWithRecipe("BulkMail", null, recipe, neon.OPERATINGSTATE_NEW);
/**
* Opens BulkMail context in new mode, with the given template from MosaicoTemplate id.<br>
*
* @param {String} pMosaicoTemplateId <p>
* The id of the bulk mail.<br>
*/
BulkMailUtils.createFromMosaicoTemplate = function(pMosaicoTemplateId)
{
var params = {
"CreateFromMosaicoTemplateId_param" : pMosaicoTemplateId
};
var recipe = neonFilter.createEntityRecordsRecipeBuilder().parameters(params).toString();

Florian Maier
committed
neon.openContextWithRecipe("BulkMail", null, recipe, neon.OPERATINGSTATE_NEW);
}
Martin Groppe
committed
/*
*Stores the Eml file for a bulkmailrecipient in the Filesystem
*
* @param {String} pBulkMailId <p>
* The id of the bulk mail.<br>
* @param {String} pMailRunId <p>
* The id of the bulk mail run.<br>
* @param {String} pMailLogId <p>
* The id of the corresponding mail log entry.<br>
* @param {String} pFile
Martin Groppe
committed
**/
BulkMailUtils.storeEmlFile = function (pBulkMailId, pMailRunId, pMailLogId, pFile)
var locationOption = project.getInstanceConfigValue("bulkmail.fileStorage", vars.get("$sys.serverdata"));
var path = locationOption + (locationOption.substr(locationOption.length-1) == "/" ? "" : "/" )+ "bulkmailfiles/" + pBulkMailId + "/" + pMailRunId + "/";
Martin Groppe
committed
var fullPath = path + filename;
fileIO.storeData(fullPath, pFile, util.DATA_BINARY, false);
}