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
.
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";
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) != '=')
decStr += String.fromCharCode((bits24 & 0xFF00) >> 8);
if (encStr.charAt(i + 3) != '=')
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);
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.