Something went wrong on our end
-
Benjamin Ulrich authoredBenjamin Ulrich authored
process.js 13.84 KiB
import("system.question");
import("Sql_lib");
import("MimeType_lib");
import("Document_lib");
import("system.logging");
import("system.translate");
import("system.text");
import("system.db");
import("system.util");
import("Communication_lib");
import("DocumentTemplate_lib");
import("system.neon");
import("system.mail");
import("Bulkmail_lib");
import("system.tools");
import("EmailUtil_lib");
function EmailWritingUtils () {}
/**
* creates a new E-Mail-Object and ask for a download of a eml where all fields are prefilled
* The eml can be open with a mailclient and sent via the mailclient. Each mailclient has a different behaviour:
* In Outlook the mail is automatically opened in draft-mode
* In Thunderbird the mail is opened in view mode and you've to manually "edit as new"
*
* @param {String|Array} pToRecipients mailaddresses of the recipients, can either be a 1D-Array with several addresses or a string with one address
* @param {String} pSenderContactId contactId of the sender. the standard mailadress of the contact is used as sender-address
* @param {String} [pTemplateId] if a document-template shall be used, give the templateId here
* @param {String} [pRecipientContactId] contactId of the recipient, required to fill placeholders
* @param {String} [pBindata] base64 binary data
* @param {Array} [pAttachments] attachments in a array (base64 encoded).
* @param {String} pSubject an optional subject.
* @param {String} [pEmailFilename] filename of the email.
* @param {Placeholder[]} [pAdditionalPlaceholders] additional placeholders
* @return {Array} the eml document as array with [filename, base64]
*/
EmailWritingUtils.openMailTemplate = function (pToRecipients, pSenderContactId, pTemplateId, pRecipientContactId, pBindata, pAttachments, pSubject, pEmailFilename, pAdditionalPlaceholders)
{
if (pToRecipients && typeof(pToRecipients) == "string")
pToRecipients = [pToRecipients];
var email;
if (pTemplateId || (pBindata.bindata != "" && pBindata.bindata != null))
{
email = Email.fromTemplate(pTemplateId, pRecipientContactId, pBindata, pAdditionalPlaceholders);
if (!email)
email = new Email();
}
else email = new Email();
email.setSender(pSenderContactId);
if (pToRecipients)
email.toRecipients = pToRecipients;
email.bccRecipients = [EmailWritingUtils.getMailbridgeAddress()];
if (pAttachments)
{
for (var i = 0; i < pAttachments.length; i++)
{
if (pAttachments[i] != null || pAttachments[i] != "")
email.attachmentTemplates[i] = pAttachments[i];
}
}
if (pSubject)
email.subject = pSubject;
return email.downloadEML(pEmailFilename);
}
/**
* opens a view where a new mail can be sent. In the view the use CAN select a DocumentTemplate if needed
*
* @param {String} pToContactId contactId with contacts to filter the communication-addresses
* @param {String} [pToEmailAddress] email address as string that shall be used as recipient-preset
* @param {Array} pAttachmentArray array with attachments.
* @param {String} pNotificationMsg message which will be shown after the operation is done.
* @param {String} pComingFrom source from where you started (e.g. "Person", "Organisation" )
* @param {String} pEmailFilename optional file name of the email.
* @param {String} [pAdditionalPlaceholders] additional placeholders for the email
* @param {Array[]} [pUpdateStatements] an array with update statements which will be executed after email is downloaded/sent.
* @param {String} pTypeClassification Documenttemplatetypeclassification
*/
EmailWritingUtils.openNewMail = function (pToContactId, pToEmailAddress, pComingFrom, pAttachmentArray, pNotificationMsg, pEmailFilename, pAdditionalPlaceholders, pUpdateStatements, pTypeClassification)
{
var params = {
"ContactId_param" : pToContactId,
"Attachments_param" : JSON.stringify(pAttachmentArray),
"ComingFrom_param" : pComingFrom,
"NotificationMsg_param" : pNotificationMsg,
"EmailFilename" : pEmailFilename,
"AdditionalPlaceholders_param" : JSON.stringify(pAdditionalPlaceholders),
"UpdateStatements_param" : JSON.stringify(pUpdateStatements),
"DocumentTemplateTypeClassification_param" : pTypeClassification
};
if (pToEmailAddress)
params.Recipient_param = pToEmailAddress;
neon.openContext("Email", "EmailEdit_view", null, neon.OPERATINGSTATE_VIEW, params);
}
EmailWritingUtils.getMailbridgeAddress = function ()
{
return "mailbridge@domain.local"; //TODO: not hardcoded
}
/**
* Opens a view where the email with the report(s) can be downloaded as .eml
* and after that it can be sent with e.g. Thunderbird
*
* @param {String} pRecipient Contact id of the recipient.
* @param {String} pComingFrom source from where you started (e.g. "Person", "Organisation")
* @param {Array} pReportArray array with reports.
* @param {String} pNotificationMsg message which will be shown after the operation is done.
* @param {String} pEmailFilename optional file name of the email.
* @param {String} [pAdditionalPlaceholders] additional placeholders for the email
* @param {String} [pOfferId] optional needed for the offerEmails, to change the status of the offer
* Report have to be a object with these attrs: content (base64 encoded report), contentType (mimeType of the report), filename (complete filename with filending)
*/
EmailWritingUtils.sendReportAsMail = function (pRecipient, pReportArray, pComingFrom, pNotificationMsg, pEmailFilename, pAdditionalPlaceholders, pOfferId)
{
var pRecpientEmail;
if (pRecipient)
{
pRecpientEmail = newSelect("COMMUNICATION.ADDR").from("COMMUNICATION")
.where("COMMUNICATION.CONTACT_ID", pRecipient).and("COMMUNICATION.MEDIUM_ID", "COMMEMAIL").cell();
} else{
pRecpientEmail = null;
}
EmailWritingUtils.openNewMail(pRecipient, pRecpientEmail, pComingFrom, pReportArray, pNotificationMsg, pEmailFilename, pAdditionalPlaceholders, pOfferId);
}
/**
* object for handling emails
* @param {String} [pBody=null] if given, the body is set to this text
* @class
*/
function Email(pBody)
{
if (pBody == undefined) pBody = null;
this.sender = null;
this.subject = null;
this.body = pBody;
this.mailText = null;
this.toRecipients = [];
this.ccRecipients = [];
this.bccRecipients = [];
this.attachmentTemplates = [];
this.emlFile = null;
}
/**
* makes an Email object from a RFC
* NOTE: body is not editable if comming from a eml. Use it only for preview!
*
* @param {String} pBase64RFC the RFC mail, base64 encoded
* @return {Email} a new Email object
*/
Email.fromRFC = function (pBase64RFC)
{
var decoded = util.decodeBase64String(pBase64RFC);
var mailData = mail.parseRFC(decoded);
var newMail = new Email(mailData[mail.MAIL_HTMLTEXT]);
newMail.sender = mailData[mail.MAIL_SENDER];
newMail.mailText = mailData[mail.MAIL_TEXT];
newMail.subject = mailData[mail.MAIL_SUBJECT];
newMail.toRecipients = mailData[mail.RECIPIENT_TO];
newMail.ccRecipients = mailData[mail.RECIPIENT_CC];
newMail.bccRecipients = mailData[mail.RECIPIENT_BCC];
newMail.emlFile = decoded;
return newMail;
}
/**
* Returns a object containing the contact ids as
* keys and the corresponding Email objects as values.
*
* @param {String} [pTemplateId] UUID of the explicit template which shall used. (optional)
* @param {String} [pContactId] (required)
* @param {String} [pBindata] (required)
* @param {Placeholder[]} [pAdditionalPlaceholders] additional placeholders
* @return {Email} a new Email object
*/
Email.fromTemplate = function (pTemplateId, pContactId, pBindata, pAdditionalPlaceholders)
{
var template;
if (pBindata && pBindata.isFilled() && BulkMailUtils.isValidMimeType(pBindata.mimeType))
{
template = new DocumentTemplate(pBindata.bindata, DocumentTemplate.types.fromMimeType(pBindata.mimeType), pBindata.filename, true);
}
else
{
template = DocumentTemplate.loadTemplate(pTemplateId);
if (!template)
return null;
}
return template.getReplacedEmailsByContactIds([pContactId], pAdditionalPlaceholders)[pContactId];
}
/**
* Replaces the placeholders with data from the contacts and returns the resulting Emails.
* @param {DocumentTemplate} pTemplate a document template which is used for all mails
* @param {Array} pContactIds Contact ids of all recipients
*
* @return {Object} Object containing the contact ids as keys and the corresponding Email
* objects as values
*/
Email.getReplacedBulkEmails = function(pTemplate, pContactIds)
{
return pTemplate.getReplacedEmailsByContactIds(pContactIds);
}
/**
* sets the sender of the mail
*
* @param {String} pContactId the contactId of the sender
*/
Email.prototype.setSender = function (pContactId)
{
this.sender = CommUtil.getStandardMail(pContactId);
}
/**
* generates a 'mailto:' URL from the email object
*/
Email.prototype.getMailtoUrl = function ()
{
var url = [];
if (this.toRecipients.length)
url.push("to=" + this.toRecipients.join());
if (this.ccRecipients.length)
url.push("cc=" + this.ccRecipients.join());
if (this.bccRecipients.length)
url.push("bcc=" + this.bccRecipients.join());
if (this.subject)
url.push("subject=" + this.subject);
if (this.body)
url.push("body=" + text.html2text(this.body));
url = "mailto:?" + url.join("&");
return encodeURI(url);
}
Email.prototype._newMailObject = function()
{
var ENCODING = "UTF-8";
var mailId;
var emlFile = this.emlFile ? this.emlFile : null;
if (emlFile)
mailId = mail.newMail(emlFile, mail.FORMAT_MIME);
else
mailId = mail.newMail();
if (emlFile)
{
mail.clearRecipients(mailId, mail.RECIPIENT_TO);
mail.clearRecipients(mailId, mail.RECIPIENT_CC);
mail.clearRecipients(mailId, mail.RECIPIENT_BCC);
}
if (this.sender)
mail.setSender(mailId, this.sender);
if (this.toRecipients.length)
mail.addRecipients(mailId, mail.RECIPIENT_TO, this.toRecipients);
if (this.ccRecipients.length)
mail.addRecipients(mailId, mail.RECIPIENT_CC, this.ccRecipients);
if (this.bccRecipients.length)
mail.addRecipients(mailId, mail.RECIPIENT_BCC, this.bccRecipients);
mail.setSubject(mailId, this.subject || "", ENCODING);
// only alter subject and text, if no eml is used
if (!emlFile)
{
if (this.body)
mail.addText(mailId, this.body, "text/html", ENCODING, null);
else
mail.addText(mailId, "", "text/html", ENCODING, null);
}
this.attachmentTemplates.forEach(function(pAttachment)
{
if (pAttachment.templateId)
{
mail.addBase64Attachment(mailId, pAttachment.content,
DocumentTemplateUtils.getMimeType(pAttachment.templateId), pAttachment.filename, true, null);
}
else
mail.addBase64Attachment(mailId, pAttachment.content, pAttachment.mimeType, pAttachment.filename, true, null, null)
});
return mailId;
}
/**
* generates a eml-element from the email object
*/
Email.prototype.getRFCmail = function ()
{
var mailId = this._newMailObject()
//"X-Unsent" is a very badly, non-standardised header to gently ask the mail client that the mail should open in a compose-mode
//this is mainly done for Microsoft Outlook for Windows.
//Thunderbird has a dinosaur-request (it's from the year 2002) to also support this: https://bugzilla.mozilla.org/show_bug.cgi?id=166541
mail.addHeader(mailId, "X-Unsent", "1");
//accoding to this entry: https://stackoverflow.com/questions/11330628/os-x-mail-open-eml-files-in-compose-mode/33224913
//something similar exists for OS X Mail
//X-Uniform-Type-Identifier: com.apple.mail-draft
//this could be added later if needed
var mailObj = mail.getCachedMail(mailId);
var finalMail = mail.toRFC(mailObj);
// remove from cache
mail.deleteMail(mailId)
return finalMail;
}
/**
* opens the email
*/
Email.prototype.openMail = function ()
{
neon.openUrl(this.getMailtoUrl(), false);
}
/**
* ask for a download of the email
*
* @param {String} [pFilename] the file name.
* @return {Array} array of [filename, EML (base64)]
*/
Email.prototype.downloadEML = function (pFilename)
{
var eml = this.getEML();
var filename = (pFilename || translate.text("Email Template")) + ".eml";
neon.download(eml, filename);
return [filename, eml];
}
/**
* @return {String} RFC mail (base64 encoded)
*/
Email.prototype.getEML = function ()
{
return util.encodeBase64String(this.getRFCmail(), null);
}
/**
* sends the email object
*
* @return {boolean} true, if the mail was sent sucessfully
*/
Email.prototype.send = function (pUser)
{
try
{
mailId = this._newMailObject();
if (this.sender)
mail.setSender(mailId, this.sender);
var mailbridgeTitle = "mailbridge";
var sentMails;
if(pUser)
sentMails = mail.sendMailAs(pUser, mailId)
else
{
let mailbridgeExists = tools.getUser(mailbridgeTitle);
if(mailbridgeExists)
mail.sendMailAs(mailbridgeTitle, mailId)
else //check mailbridge user if this error gets thrown
question.showMessage(translate.withArguments("Mailbridge failed: user '%0' is unknown, contact an administrator.", [mailbridgeTitle]), question.ERROR, translate.text("Error"));
}
// remove from cache
mail.deleteMail(mailId)
return sentMails > 0;
}
catch (ex)
{
logging.log(ex);
return false;
}
}