Click here to Skip to main content
15,886,137 members
Articles / Programming Languages / Javascript

Exsead - Sending Emails with Attachments from JScript

Rate me:
Please Sign up or sign in to vote.
3.50/5 (2 votes)
1 Mar 2007CPOL2 min read 27.9K   15   1
To futher my previous post on sending emails using Netcat and JScript, here is how to also send attachments.

Introduction

In my post: Sending Emails from the Commandline, I showed how to send plain text simple emails. Here, I extend on this to send attachments as well.

Attachments are encoded into the email body. This is done with headers and boundary separators. In the code below, I have a function called CreateEmail. This puts together the body of the email, and in this example, puts in two attachments and a plain test message.

The key header in making the email have attachments is Content-Type: multipart/mixed; boundary="_----------=_10167391557129230"';. This odd piece of boundary text, which should be anything that is very unlikely to happen accidentally in an email body, but which looks like a separator, is then used by the email client to recognize different parts of the email.

Oddly enough, when the separator is used to separate, it is prepended with --, and when it represents the end of the email body, it is prepended and postpended with --.

What is this Base64 stuff in there for

Email is, in Internet terms, pre-historic. The header Content-Transfer-Encoding: 7bit gives this away. Email is normally sent as just the bytes 0 to 127. To send 8 bit binary data (like an attached file) through a 7 bit system requires encoding it somehow. Base64 is dead simple, it just encodes two 8 bit bytes into three 6 bit chunks. 6 bit is nice because you can encode that into the ASCII letters and numbers (if you include both upper and lower case).

Once the email body has been created, the SendEmail function can send the email by just placing our nicely separated and encoded 7 bit text into the body of the email and send it the same way as in the previous post. To use this code, you call CreateEmail and pass its return value on to SendEmail. You will also need BinaryFile to read binary files from JScript. The most interesting 'new' piece of code to have a good squint at is CreateEmail.

JavaScript
function CreateEmail(fromAddress,toAddress,message,att1,att2)
{
    var content='';
    var d=new Date();
    d=d.toUTCString();
    content+='Content-Transfer-Encoding: 7bit\r\n';
    content+='Content-Type: multipart/mixed; boundary="_----------=_10167391557129230"\r\n';
    content+='MIME-Version: 1.0\r\n';
    content+='Date: '+d+'\r\n';
    content+='From: '+fromAddress+'\r\n';
    content+='To: '  +toAddress  +'\r\n';
    content+='Subject: Your Converted File\r\n'
    content+='X-Mailer: Nerds-Central JScript Daemon\r\n';
    content+='\r\n';
    content+='--_----------=_10167391557129230\r\n';
    content+='Content-Type: text/plain; charset="iso-8859-1"\r\n';
    content+='\r\n';
    content+=message+'\r\n';
    content+='\r\n';
    content+='--_----------=_10167391557129230\r\n';
    content+='Content-Transfer-Encoding: base64\r\n';
    content+='Content-Type: text/text; name="report.txt"\r\n';
    content+='\r\n';    
    content+=FileToBase64(att1)+'\r\n';
    content+='\r\n';
    content+='--_----------=_10167391557129230\r\n';
    content+='Content-Transfer-Encoding: base64\r\n';
    content+='Content-Type: text/html; name="output.html"\r\n';
    content+='\r\n';    
    content+=FileToBase64(att2)+'\r\n';
    content+='\r\n';
    content+='--_----------=_10167391557129230--';
    return content;
}

function SendEmail(body,fromAddress,toAddress)
{
    var strExe = "nc -v smtp.gotadsl.co.uk 25";
    var objShell = WScript.CreateObject("WScript.Shell");

    var strExeIn ="HELO nerds-central.com\r\n"; 
    strExeIn+="MAIL FROM: <"+fromAddress+">\r\n";
    strExeIn+="RCPT TO: <"+toAddress+">\r\n";
    strExeIn+="DATA\r\n";
    strExeIn+=body;
    strExeIn+="\r\n.\r\n";
    strExeIn+="QUIT\r\n";
    //WScript.echo(strExeIn);
    var objScriptExec = objShell.Exec(strExe);
    objScriptExec.StdIn.write(strExeIn);
    objScriptExec.StdIn.close();
    Log("Sending "+strExeIn.length+' bytes to:' + toAddress);
    Log(objScriptExec.StdOut.ReadAll());
}

function FileToBase64(fileName)
{
    try
    {
        var file=new BinaryFile(fileName);
        var b64=new Base64();
        return b64.encode(file.ReadAll());
    }
    catch(e)
    {
        return '';
    }
}

function Base64() 
{
    this.maxLineLength = 76;

    this.base64chars =  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
   
    this.decode = function(encStr) {
        var base64charToInt = {};
        for (var i = 0; i < 64; i++) base64charToInt[this.base64chars.substr(i,1)] = i;
        encStr = encStr.replace(/\s+/g, "");
        var decStr = "";
        var decArray=new Array();
        var linelen = 0
        var el=encStr.length;
        var bits24;
        for (var i = 0; i < el; i += 4) {
            bits24  = ( base64charToInt[encStr.charAt(i)] & 0xFF  ) <<  18;
            bits24 |= ( base64charToInt[encStr.charAt(i+1)] & 0xFF  ) <<  12;
            bits24 |= ( base64charToInt[encStr.charAt(i+2)] & 0xFF  ) <<   6;
            bits24 |= ( base64charToInt[encStr.charAt(i+3)] & 0xFF  ) <<   0;
            decStr += String.fromCharCode((bits24 & 0xFF0000) >> 16);
            if (encStr.charAt(i + 2) != '=')  // check for padding character =
                decStr += String.fromCharCode((bits24 &   0xFF00) >>  8);
            if (encStr.charAt(i + 3) != '=')  // check for padding character =
                decStr += String.fromCharCode((bits24 &     0xFF) >>  0);
            if(decStr.length>1024)
            {
                decArray.push(decStr);
                decStr='';
            }
        }
        if(decStr.length>0)
        {
            decArray.push(decStr);
        }
        
        var ar2=new Array();
        for(;decArray.length>1;)
        {
            var l=decArray.length;
            for(var c=0;c<l;c+=2)
            {
                if(c+1==l)
                {
                    ar2.push(decArray[c]);
                }
                else
                {
                    ar2.push(''+decArray[c]+decArray[c+1]);
                }
            }
            decArray=ar2;
            ar2=new Array();
        }
        return decArray[0];
    }
   
    this.encode = function(decStr)
    {
        var encArray=new Array();
        var bits, dual, i = 0, encOut = "";
        var linelen = 0;
        var encOut='';
        while(decStr.length >= i + 3){
            bits =    (decStr.charCodeAt(i++) & 0xff) <<16 |
                (decStr.charCodeAt(i++) & 0xff) <<8 |
                decStr.charCodeAt(i++) & 0xff;
            encOut +=
                this.base64chars.charAt((bits & 0x00fc0000) >>18) +
                this.base64chars.charAt((bits & 0x0003f000) >>12) +
                this.base64chars.charAt((bits & 0x00000fc0) >> 6) +
                this.base64chars.charAt((bits & 0x0000003f));
            linelen += 4;
            if (linelen>this.maxLineLength-3) {
                encOut += "\n";
                encArray.push(encOut);
                encOut='';
                linelen = 0;
            }
        }
        if(decStr.length -i > 0 && decStr.length -i < 3) {
            dual = Boolean(decStr.length -i -1);
            bits =
                ((decStr.charCodeAt(i++) & 0xff) <<16) |
                (dual ? (decStr.charCodeAt(i) & 0xff) <<8 : 0);
            encOut +=
                this.base64chars.charAt((bits & 0x00fc0000) >>18) +
                this.base64chars.charAt((bits & 0x0003f000) >>12) +
                      (dual ? this.base64chars.charAt((bits & 0x00000fc0) >>6) : '=') +
                      '=';
        }
       
        encArray.push(encOut);
        // this loop progressive concatonates the
        // array elements entil there is only one
        var ar2=new Array();
        for(;encArray.length>1;)
        {
            var l=encArray.length;
            for(var c=0;c<l;c+=2)
            {
                if(c+1==l)
                {
                    ar2.push(encArray[c]);
                }
                else
                {
                    ar2.push(''+encArray[c]+encArray[c+1]);
                }
            }
            encArray=ar2;
            ar2=new Array();
        }
        return encArray[0];
    }
}

There is loads more like this on Nerds-Central.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer
United Kingdom United Kingdom
I am now a Software Systems Developer - Senior Principal at Micro Focus Plc. I am honoured to work in a team developing new compiler and runtime technology for Micro Focus.

My past includes a Ph.D. in computational quantum mechanics, software consultancy and several/various software development and architecture positions.

For more - see

blog: http://nerds-central.blogspot.com

twitter: http://twitter.com/alexturner

Comments and Discussions

 
GeneralInteresting article Pin
Palm Island16-Apr-08 10:34
Palm Island16-Apr-08 10:34 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.