Skip to content
Snippets Groups Projects
process.js 9.52 KiB
Newer Older
S.Listl's avatar
S.Listl committed
import("Document_lib");
import("system.logging");
Johannes Hörmann's avatar
Johannes Hörmann committed
import("system.translate");
import("system.text");
import("system.db");
import("system.util");
import("Communication_lib");
import("DocumentTemplate_lib");
import("system.neon");
import("system.mail");
S.Listl's avatar
S.Listl committed
import("Bulkmail_lib")
Johannes Hörmann's avatar
Johannes Hörmann committed

Johannes Hörmann's avatar
Johannes Hörmann committed

/**
 * 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
S.Listl's avatar
S.Listl committed
 * @return {Array} the eml document as array with [filename, base64]
Johannes Hörmann's avatar
Johannes Hörmann committed
 */
S.Listl's avatar
S.Listl committed
EmailWritingUtils.openMailTemplate = function (pToRecipients, pSenderContactId, pTemplateId, pRecipientContactId, pBindata)
Johannes Hörmann's avatar
Johannes Hörmann committed
{
    if (pToRecipients && typeof(pToRecipients) == "string")
        pToRecipients = [pToRecipients];
    
    var email;
S.Listl's avatar
S.Listl committed
    if (pTemplateId || pBindata)
        email = Email.fromTemplate(pTemplateId, pRecipientContactId, pBindata)
    else
        email = new Email();
    email.setSender(pSenderContactId);
Johannes Hörmann's avatar
Johannes Hörmann committed

    if (pToRecipients)
        email.toRecipients = pToRecipients;
   
    email.bccRecipients = [EmailWritingUtils.getMailbridgeAddress()];

S.Listl's avatar
S.Listl committed
    return email.downloadEML();
Johannes Hörmann's avatar
Johannes Hörmann committed
}

/**
 * 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
Johannes Hörmann's avatar
Johannes Hörmann committed
 */
EmailWritingUtils.openNewMail = function (pToContactId, pToEmailAddress)
Johannes Hörmann's avatar
Johannes Hörmann committed
{
    var params = {
        "ContactId_param" : pToContactId
    };
    if (pToEmailAddress)
        params.Recipient_param = pToEmailAddress;
        
Johannes Hörmann's avatar
Johannes Hörmann committed
    neon.openContext("Email", "EmailEdit_view", null, neon.OPERATINGSTATE_NEW, params);
}

S.Listl's avatar
S.Listl committed
EmailWritingUtils.getMailbridgeAddress = function ()
{
    return "mailbridge@domain.local"; //TODO: not hardcoded
}

Johannes Hörmann's avatar
Johannes Hörmann committed
/**
 * object for handling emails
 * @param {String} [pBody=null] if given, the body is set to this text
Johannes Hörmann's avatar
Johannes Hörmann committed
 * @class
 */
Johannes Hörmann's avatar
Johannes Hörmann committed
{
    this.sender = null;
    this.subject = null;
    this.toRecipients = [];
    this.ccRecipients = [];
    this.bccRecipients = [];
    this.emlFile = null;
S.Listl's avatar
S.Listl committed
 * makes an Email object from a RFC
 * NOTE: body is not editable if comming from a eml. Use it only for preview!
S.Listl's avatar
S.Listl committed
 * 
 * @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.subject = mailData[mail.MAIL_SUBJECT];
    newMail.emlFile = decoded;
    return newMail;
Email.fromTemplate = function (pTemplateId, pContactId, pBindata)
Johannes Hörmann's avatar
Johannes Hörmann committed
{
S.Listl's avatar
S.Listl committed
    var template;
    if (pBindata && pBindata.isFilled())
    {
        if (BulkMailUtils.isValidMimeType(pBindata.mimeType))
        {
Johannes Hörmann's avatar
Johannes Hörmann committed
            template = new DocumentTemplate(pBindata.bindata, DocumentTemplate.types.fromMimeType(pBindata.mimeType), pBindata.filename, true);
S.Listl's avatar
S.Listl committed
        }
    }
    else
        template = DocumentTemplate.loadTemplate(pTemplateId);
    return Email.getReplacedBulkEmails(template, [pContactId])[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) 
{
    var emailObjects = {};
    var isEML = pTemplate.type == DocumentTemplate.types.EML;
    var emailContents = pTemplate.getReplacedContentByContactIds(pContactIds, isEML);
    
    for (contactId in emailContents)
        if (isEML)
        {
            emailObjects[contactId] = Email.fromRFC(emailContents[contactId]);
        }
        else
        {
            // convert to HTML if needed
            if (pTemplate.type == DocumentTemplate.types.TXT || pTemplate.type == DocumentTemplate.types.PLAIN)
                emailContents[contactId] = text.text2html(emailContents[contactId], false);
            
            emailObjects[contactId] = new Email(emailContents[contactId]);
        }
Johannes Hörmann's avatar
Johannes Hörmann committed
}

/**
 * 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()
Johannes Hörmann's avatar
Johannes Hörmann committed
{
    var ENCODING = "UTF-8";
    var emlFile = this.emlFile ? this.emlFile : null;
        
        if (emlFile)
            mailId = mail.newMail(emlFile, mail.FORMAT_MIME);
    }
    catch(ex)
    {
        //TODO: fix this dirty workaround [waiting for #1038963], since newMail causes an error on the first call after a user logged in
        logging.log(ex);
        util.sleep(1500);
        if (emlFile)
            mailId = mail.newMail(emlFile, mail.FORMAT_MIME);
    {
        mail.clearRecipients(mailId, mail.RECIPIENT_TO);
        mail.clearRecipients(mailId, mail.RECIPIENT_CC);
        mail.clearRecipients(mailId, mail.RECIPIENT_BCC);
S.Listl's avatar
S.Listl committed
    
Johannes Hörmann's avatar
Johannes Hörmann committed
    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);
    }
    
    return mailId;
}

/**
 * generates a eml-element from the email object
 */
Email.prototype.getRFCmail = function ()
{
    var ENCODING = "UTF-8";
    var mailId = this._newMailObject()
Johannes Hörmann's avatar
Johannes Hörmann committed
    
    //"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;
Johannes Hörmann's avatar
Johannes Hörmann committed
}

/**
 * opens the email
 */
Email.prototype.openMail = function ()
{
    neon.openUrl(this.getMailtoUrl(), false);
}

/**
 * ask for a download of the email
S.Listl's avatar
S.Listl committed
 * 
 * @return {Array} array of [filename, EML (base64)]
Johannes Hörmann's avatar
Johannes Hörmann committed
 */
S.Listl's avatar
S.Listl committed
Email.prototype.downloadEML = function ()
{
    var eml = this.getEML();
    var filename = (this.subject || translate.text("Email Template")) + ".eml";
    neon.download(eml, filename);
    return [filename, eml];
}

/**
S.Listl's avatar
S.Listl committed
 * @return {String} RFC mail (base64 encoded)
S.Listl's avatar
S.Listl committed
 */
S.Listl's avatar
S.Listl committed
Email.prototype.getEML = function ()
S.Listl's avatar
S.Listl committed
    return util.encodeBase64String(this.getRFCmail(), null);
Johannes Hörmann's avatar
Johannes Hörmann committed
}

/**
 * sends the email object
 * 
 * @return {boolean} true, if the mail was sent sucessfully
 */
S.Listl's avatar
S.Listl committed
Email.prototype.send = function (pUser)
        mailId = this._newMailObject();
S.Listl's avatar
S.Listl committed
        
        if (this.sender)
            mail.setSender(mailId, this.sender);
        var sentMails = mail.sendMailAs(pUser || "mailbridge", mailId)
        // remove from cache
        mail.deleteMail(mailId)
        return sentMails > 0;
        logging.log(ex);
        return false;
    }
}