// ******************************************
// * $Id$
// *
// *   sendMail()
//*
// * sendMail function is used to send mail
// *         If the OrderInMailBody is set the attachment will be added to the body
// *
// * arguments:
// *           p_mailfrom: The address the mail is sent from (system if "") or must be replied to
// *             p_mailto: The address where the mail is sent to
// *            p_subject: The subject of the mail
// *               p_body: The body of the mail if the OrderInMailBody is not set
// *           p_bodyhtml: The body of the mail if the OrderInMailBody is not set
// * params:
// *     attachFileName: Filenaam van de attachment als hele body als attachement wordt gestuurd
// *       attachFolder: Folder met bij te voegen attachments
// *     attachPassword: Encrypt(zip) elke attachment met dit wachtwoord als niet leeg
// *       attachStream: Datastream waarin de attachment zit
// *       include_file: Deze file toevoegen (gezocht onder S("bdradrfiles_path"))
// *                 cc: The cc address
// *                bcc: The bcc address
// *          receiptto: The address where the receipt is sent to
// *
// ******************************************
function sendMail( p_mailfrom
                 , p_mailto
                 , p_subject
                 , p_body
                 , p_bodyhtml
                 , params
                 )
{
    Log2File(2, "*> sendMail");
    params = params || {};

    var objFso  = new ActiveXObject("Scripting.FileSystemObject");
    var objStrm = new ActiveXObject("ADODB.Stream");
    var objMail = new ActiveXObject("CDO.Message");

    // De onderstaande configuratie is ook handig voor het testen op een lokale pc.
    // Dan heb je geen lokale SMTP service nodig
	if (S("puo_sendusing") == 2) // cdoSendUsingPort
	{
        var objConf =  new ActiveXObject("CDO.Configuration");
	    var sch = "http://schemas.microsoft.com/cdo/configuration/"
	    objConf.Fields(sch + "sendusing").Value = S("puo_sendusing"); // 1=cdoSendUsingPickup, 2=cdoSendUsingPort
	    objConf.Fields(sch + "smtpserver").Value = S("puo_smtpserver"); // Wel voor ons IP-adres relay toestaan!
	    objConf.Fields(sch + "smtpserverport").Value = S("puo_smtpserverport"); //  default 25
	    objConf.Fields(sch + "smtpconnectiontimeout").Value = S("puo_smtpconnectiontimeout"); //  default 30
	    if (S("puo_smtpusessl"))
	    {
	      objConf.Fields(sch + "smtpusessl").Value = true;
	    }
	    objConf.Fields(sch + "smtpauthenticate").Value = S("puo_smtpauthenticate"); // default 0=cdoAnonymous, 1=cdoBasic, 2=cdoNTLM
	    if (S("puo_smtpauthenticate") == 1)
	    {
	        objConf.Fields(sch + "sendusername").Value = S("puo_sendusername");
	        objConf.Fields(sch + "sendpassword").Value = S("puo_sendpassword");
	    }
	    objConf.Fields.Update();
        objMail.Configuration = objConf;
	}
    //

    Log2File(3, "In SendMail sender=" + p_mailfrom);
    var Mailsend = false;

    var MailSender = S("puo_fromaddress");
    var MailReply = S("puo_replyaddress");
    if (p_mailfrom)
    {
        if (S("puo_usesenderasreplyto"))
        {
            // the sytem is the sender, but replies go to the sender
            MailSender = S("puo_fromaddress");
            MailReply = p_mailfrom;
        }
        else
        {
            // The sender is the real sender
            MailSender = p_mailfrom;
            MailReply = "";
        }
    }
    if (params.replyTo)
        MailReply = params.replyTo

    if (!p_mailto || !MailSender)
    {
        Log2File(1, "Email not sent.because from or to is empty.");
    }
    else
    {
        if (p_body)
        {
            objMail.TextBody = p_body;
            if (p_bodyhtml)
            {
                // Als attachment er bij
                var cdoBodyPart = objMail.BodyPart.AddBodyPart(-1);
                cdoBodyPart.ContentMediaType = "text/html";
                cdoBodyPart.ContentTransferEncoding = "7bit";
                objStrm = cdoBodyPart.GetDecodedContentStream();
                objStrm.WriteText(p_bodyhtml);
                objStrm.Flush();
                objStrm.Close();
                var objFlds = cdoBodyPart.Fields;
                objFlds("urn:schemas:mailheader:content-disposition").Value = "attachment; filename=\"" + params.attachFileName + "\"";
                objFlds.Update();
            }
        }
        else
        {
            // Geen p_body, dus dan moet p_bodyhtml gezet zijn.
            try
            {   // Zowel textbody als htmlbody zetten opdat default Android e-mail client
                // het euro teken goed doet.
                // NEEN: Dan zijn er mail-clients die de HTML (terecht) tonen vanwege content-type text/plain
                // objMail.TextBody = p_bodyhtml;
                // objMail.TextBodyPart.Charset = S("puo_mailbodycharset"); // default "unicode-1-1-utf-8
                objMail.BodyPart.Charset = S("puo_mailbodycharset"); // default "unicode-1-1-utf-8

                // qrc="https://aasa.facilitor.nl/?mobile=1&amp;u=opdracht&amp;k=32751" wordt omgezet naar
                // src="cid:qrc.png"
                // Ondertussen is het al HTML dus we kunnen geen XML-query doen
                // Daarom gewoon textueel opzoeken
                var nn_cid = 0;
                var startPos = p_bodyhtml.indexOf("qrc=") + 4;
                var quote = p_bodyhtml.substr(startPos, 1); // enkele of dubbele quote
                var eindPos =  p_bodyhtml.indexOf(quote, startPos + 2);
                if (startPos > 3 && eindPos > startPos)
                {
                    var qrc = p_bodyhtml.substring(startPos + 1, eindPos);
                    qrc = qrc.replace(/\&amp;/g, "&"); // Het was nog HTML/XML-encoded
                    var xc = new ActiveXObject("SLNKDWF.QRCode");
                    xc.Text = qrc;
                    Log2File(2, "Creating QRC: " + qrc);
                    var oStream = new ActiveXObject("ADODB.Stream");
                    oStream.Open;
                    oStream.Type = 1; // binary
                    oStream.Write(xc.GetAsPNG());
                    var oCrypto = new ActiveXObject("SLNKDWF.Crypto"); // Maak random naam
                    var sha1 = oCrypto.hex_sha1(qrc);
                    var tempfile = custabspath + "/../../temp/puo_qr_" + sha1 + ".png";
                    oStream.SaveToFile(tempfile, 2); // overwrite
                    nn_cid++;
                    var cidname = "qrc" + nn_cid + ".png";
                    var newbody = p_bodyhtml.substr(0, startPos - 4) + "src=\"cid:" + cidname + "\"" + p_bodyhtml.substr(eindPos + 1);
                    p_bodyhtml = newbody;
                    objMail.addRelatedBodyPart(tempfile, cidname, 0);
                    if (S("puo_loglevel") < 4)
                        objFso.DeleteFile(tempfile);
                }

                // Nu frc-codering opzoeken <img frc="M=SML:K=34417"/>
                var nn_cid = 0;
                var startPos = p_bodyhtml.indexOf("frc=") + 4;
                var quote = p_bodyhtml.substr(startPos, 1); // enkele of dubbele quote
                var eindPos =  p_bodyhtml.indexOf(quote, startPos + 2);
                while (startPos > 4 && eindPos > startPos)
                {
                    var flexcode = p_bodyhtml.substring(startPos + 1, eindPos);
                    if (flexcode.indexOf("M=") < 0)
                    {
                        Log2File(1, "<img frc=...> found in XML but invalid. Ignored: " + flexcode);
                        break;
                    }
                    if (!S("puo_fclt_web_url") || !S("puo_fclt_web_apikey"))
                    {
                        Log2File(1, "<img frc=...> found in XML but puo_fclt_web_url or puo_fclt_web_apikey not set. Ignored: " + flexcode);
                        break;
                    }

                    // om te voorkomen dat je elke klant in de hosts file moet opnemen wordt
                    // aaxx.facilitor.nl ondersteund, daarom fac_id erbij
                    var fac_web_url = S("puo_fclt_web_url") + "?fac_id=" + customerId;
                    var url = "{0}&API=GETFLEX&APIKEY={1}&flexcode={2}".format(fac_web_url, S("puo_fclt_web_apikey"), flexcode);

                    Log2File(2, url);
                    var http_request = doHTTP(url, { method: "GET", headers: { "accept": "application/json" }});

                    var props = eval('(' + http_request.responseText + ')');
                    if (props.flexlog)
                        Log2File(1, props.flexlog);
                    if (props.files.length == 0)
                    {   // Geen bestanden gevonden? Dan hele img-tag gewoon er uit halen
                        var eindPos =  p_bodyhtml.indexOf(">", startPos + 2);
                        var newbody = p_bodyhtml.substr(0, startPos - 9) + p_bodyhtml.substr(eindPos + 1);
                        p_bodyhtml = newbody;
                    }
                    else
                    {
                        var filedata =  props.files[0];
                        if (filedata.resized)
                            var file = filedata.resized;
                        else
                            var file = props.AttachPath + props.files[0].name;
                        nn_cid++;
                        var cidname = "flex" + nn_cid + ".png";
                        var newbody = p_bodyhtml.substr(0, startPos - 4) + "src=\"cid:" + cidname + "\"" + p_bodyhtml.substr(eindPos + 1);
                        p_bodyhtml = newbody;
                        objMail.addRelatedBodyPart(file, cidname, 0);
                        if (filedata.tempdelete)
                            objFso.DeleteFile(filedata.tempdelete);
                    }
                    // Volgende zoeken
                    var startPos = p_bodyhtml.indexOf("frc=", eindPos) + 4;
                    var quote = p_bodyhtml.substr(startPos, 1);
                    var eindPos =  p_bodyhtml.indexOf(quote, startPos + 2);
                }

                Log2File(2, "Before bodyHTML");
                objMail.HtmlBody = p_bodyhtml.replace(/\<br/g, "\x0D\x0A<br"); // FSN#36318 Geen afsluitende '>'
                objMail.HTMLBodyPart.Charset = S("puo_mailbodycharset");

                var startPos = p_bodyhtml.indexOf("cid:") + 4;
                var eindPos =  p_bodyhtml.indexOf(".gif", startPos) + 4;
                if (startPos >= 4 && eindPos > startPos && eindPos - startPos < 20)
                {
                    var logoFileName = p_bodyhtml.substring(startPos, eindPos);
                    var logoPathName = custabspath + "/" + logoFileName;
                    Log2File(2, logoFileName);
                    Log2File(2, "After bodyHTML");
                    try {
                        objMail.addRelatedBodyPart(logoPathName, logoFileName, 0);
                    }
                    catch (e)
                    {
                        throw new UserException(e + 1000, "PutOrders", e.description + "\nPerhaps invalid logo path: "+ logoPathName);
                    }
                }
            }
            catch(e)
            {
                throw new UserException(e + 1000, "PutOrders", e.description);
            }
        }

        if (params.include_file) // deze meesturen, bijvoorbeeld algemene voorwaarden
        {
            var safename = safe.filename(params.include_file);
            if (objFso.FileExists(S("bdradrfiles_path") + "/" + safename))
            {
                Log2File(2, "Including fixed attachment " + S("bdradrfiles_path") + "/" + safename);
                var objAttachment = objMail.AddAttachment(S("bdradrfiles_path") + "/" + safename, safename);
                objAttachment.ContentTransferEncoding = "base64";
            }
            else
            {
                Log2File(1, "Error: fixed attachment '" + S("bdradrfiles_path") + "/" + safename + "' not found. Ignoring.");
            }
        }

        if (params.attachments) // Geselecteerde bestanden uit flexfiles meesturen.
        {
            //Log2File(2, "geselecteerde attachments");
            for (i=0; i<params.attachments.length; i++)
            {
                var att = params.attachments[i];
                if (att.substr(att.length-2) == "/*")
                {   // Alle bestanden uit deze map als attachment toevoegen
                    var att_f = S("flexfilespath") + "/" + att.substr(0, att.length-2);
                    if (objFso.FolderExists(att_f))
                    {
                        var objFiles = objFso.GetFolder(att_f);
                        var allFiles = new Enumerator(objFiles.files);
                        //Log2File(1, "Adding all " + objFiles.files.count + " files as attachment from folder: " + att_f);
                        for (; !allFiles.atEnd(); allFiles.moveNext())
                        {
                            var attFile = allFiles.item();
                            Log2File(1, "Adding attachment: " + attFile.Path + " (" + attFile.Size + " bytes)");
                            var objAttachment = objMail.AddAttachment(attFile.Path);
                            objAttachment.ContentTransferEncoding = "base64";
                        }
                    }
                }
                else
                {   // Het is maar 1 attachment
                    //Log2File(2, " 1 attachment");
                    var att_f = S("flexfilespath") + "/" + params.attachments[i];
                    if (objFso.FileExists(att_f))
                    {
                        var attFile = objFso.GetFile(att_f);
                        Log2File(1, "Adding attachment: " + attFile.Path + " (" + attFile.Size + " bytes)");
                        var objAttachment = objMail.AddAttachment(attFile.Path);
                        objAttachment.ContentTransferEncoding = "base64";
                    }
                }
            }
        }
        //
        // Stuur alle flexfiles (type M(ap) en F(file)) als attachment mee (dus van meerdere kenmerken).
        //
        if (params.attachFolder)
        {
            var all_sub = (params.attachSubFolder ? false : true);
            //
            if (objFso.FolderExists(params.attachFolder))
            {
                var objFolders = objFso.GetFolder(params.attachFolder);
                var subFolders = new Enumerator(objFolders.SubFolders);
                for (; !subFolders.atEnd(); subFolders.moveNext())
                {
                    if (all_sub || (subFolders.item().name == params.attachSubFolder)) // allemaal of die ene submap.
                    {
                        var objFiles = objFso.GetFolder(subFolders.item());
                        var allFiles = new Enumerator(objFiles.files);
                        for (; !allFiles.atEnd(); allFiles.moveNext())
                        {
                            var attFile = allFiles.item();
                            Log2File(1, "Adding attachment: " + attFile.Path + " (" + attFile.Size + " bytes)");

                            if (!params.attachPassword)
                            {   // doe maar gewoon
                                var objAttachment = objMail.AddAttachment(attFile.Path, attFile.Name);
                                objAttachment.ContentTransferEncoding = "base64";
                            }
                            else
                            {
                                var ZipObjIn = new ActiveXObject("SLNKDWF.Zip");
                                var attStrm = new ActiveXObject("ADODB.Stream");
                                attStrm.Type = 1; // adTypeBinary
                                attStrm.Open();

                                var orgName = attFile.Name; // .encrypted er afhalen
                                var lastIndex = orgName.lastIndexOf(".encrypted");
                                var isEncrypted = (lastIndex != -1 ? (orgName.substring(lastIndex).toLowerCase() == ".encrypted") : false);
                                if (isEncrypted)
                                {   // decrypt
                                    orgName = orgName.substring(0, lastIndex);
                                    ZipObjIn.Open(attFile.Path);
                                    ZipObjIn.DecryptToStream(attStrm, orgName);
                                }
                                else
                                {   // Gewoon lezen
                                     attStrm.LoadFromFile(attFile.Path);
                                }
                                attStrm.Position = 0; // We gaan nu over in uitvoermode
                                var ZipObjOut = new ActiveXObject("SLNKDWF.Zip");
                                var tempfile = subFolders.item() + "\\" + orgName + ".zip";
                                ZipObjOut.New(tempfile); // Helaas niet *naar* stream
                                ZipObjOut.ZipFromStream(orgName, attStrm, params.attachPassword);
                                attStrm.Close();
                                ZipObjOut.Close();
                                var objAttachment = objMail.AddAttachment(tempfile, orgName + ".zip");
                                objAttachment.ContentTransferEncoding = "base64";
                                objFso.DeleteFile(tempfile); // objMail houdt hem nog even gelocked maar straks is hij wel weg
                            }
                        }
                    }
                }
            }
        }

        objMail.From = MailSender;
        objMail.ReplyTo = MailReply;
        objMail.To = p_mailto;
        objMail.CC = params.cc || "";
        objMail.BCC = params.bcc || "";
        objMail.subject = p_subject;
        //
        if (params.attachStream)
        {
            if (params.attachStream.Size != 0)
            {
                Log2File(2, "Before set addBodyPart");
                var cdoBodyPart = objMail.BodyPart.AddBodyPart(-1);
                cdoBodyPart.ContentMediaType = "application/octet-stream";
                cdoBodyPart.ContentTransferEncoding = "7bit";
                objStrm = cdoBodyPart.GetDecodedContentStream();
                params.attachStream.Position = 0;
                params.attachStream.copyTo(objStrm);
                objStrm.Flush();
                objStrm.Close();
                var objFlds = cdoBodyPart.Fields;
                objFlds("urn:schemas:mailheader:content-disposition").Value = "attachment; filename=\"" + params.attachFileName + "\"";
                objFlds.Update();
            }
        }

        if (params.receiptto)
        {
            // ontvangst bevestiging vragen en versturen naar dit adres
            objMail.Fields("urn:schemas:mailheader:disposition-notification-to").Value = params.receiptto;
            objMail.Fields("urn:schemas:mailheader:return-receipt-to").Value = params.receiptto;
            objMail.Fields.Update();
        }

        if (S("puo_forcemailaddress"))
        {
            objMail.To = S("puo_forcemailaddress");
        }

        if (S("puo_forcefromaddress"))
        {
            objMail.From = S("puo_forcefromaddress");
            objMail.ReplyTo = S("puo_forcefromaddress");
        }
        //
        var forcemsg = "Sending email '" + p_subject + "' from: " + MailSender + " to: " + p_mailto;
        if (S("puo_forcemailaddress") || S("puo_forcefromaddress"))
        {
            forcemsg += "\n        (effective from: " + objMail.From + " to: " + objMail.To + ")";
        }
        Log2File(1, forcemsg);

        // Handig voor intern gebruik. Komt in de e-mail headers terecht
        objMail.Fields("urn:schemas:mailheader:X-FCLT-cust").Value = customerId;
        objMail.Fields.Update();
        //
        //
        if (p_mailto)
        {
            try
            {
                objMail.Send();
            }
            catch (e)
            {
                Log2File(1, "E-mail sending failed: " + e.description);
            }
            Log2File(2, "Sent.");
        }
        else
        {
            Log2File(2, "Nobody to send to.");
        }
        Mailsend = true;
    } // !p_mailto || !MailSender)
    objMail = null;
    Log2File(2, "*< sendMail");

    return Mailsend;
}
