Search This Blog

Saturday, April 7, 2012

Client Scripts » Send To-Email Recip Workaround for XP x64 (v.2.0.1)

XP x64 is pretty damn cool, but there is still much left undone. For example, the Send To -> Email Recip shell feature -- it doesn't use Outlook to create the email, because Office is still 32 bit. OE that ships with XP x64 is a 64 bit shell extension, so it becomes the only game in town.

If you run %windir%\SysWOW64\explorer.exe, the Send To thing works from there -- but that isn't always real fucking convenient now, is it? So I wrote this script to fix the problem.

To use this script:
  1. Copy the text from the code window below, and paste it into a text editor, such as notepad;
  2. Save the file to whatever [target] directory you want, as SendToMailRecip.js;
  3. Open a console window and change directory to the [target] directory
  4. Type the following command:
   SendToMailRecip.js /register:yes

That will add it to your registry as a shell extension for all file extensions. The location of Outlook is of no consequence to this script.
Code: SendToMailRecip.js

var hdr = new Array(
"         Script: SendToMailRecip.js version 2.0.1",
"        Purpose: Work-around MS lameness ",
"                 re: Send to -> Mail Recip shell functionality on XP x64",
"         Author: Mark J. McGinty",
"           Date: 19 March 2009",
" IP Declaration: Copyright (c) Mark J. McGinty 2009, All Rights Reserved",
"    Permissions: Granted to public domain: permission to use and/or distribute,",
"                 provided this header is left intact"

var usage = new Array(
"       To register this script (using its current location) as a ",
"       SendTo shell extension, execute the following command:",
"            SendToMailRecip.js /register:yes",
"       To unregister, execute the following command:",
"            SendToMailRecip.js /register:no"

 // The subject and body text for the emails this script creates are generated using the two
// template strings below.  Needless to say, non-alpha characters must be escaped according
// to JavaScript rules (e.g., "\r\n", as is used below, will be rendered as a blank line.
// Note that it was not necessary to split-up the value assigned to bodyTemplate, it was
// done that way to help visualize the end output.)
// The token {{filename}} is replaced at runtime with the name of the attached file.
// (Inclusion of this token in either template is optional.)
var subjectTemplate =  "Emailing file: {{filename}}";
var bodyTemplate =  "See attached file: {{filename}}" +
   "\r\n" +
   "\r\n" +
   "(If in doubt, contact the sender before opening the attachment.)" +
   "\r\n" +
   "\r\n" +
   "Make XP x64 SendTo work for you!" +
   "\r\n" + +

String.prototype.Replace = function (findStr, replStr) {
 if (findStr == null)
  return this;
 if (replStr == null)
  replStr = "";
 var a = this.split(findStr);
 return a.join(replStr);

var reg = WScript.Arguments.Named("register");
if (reg != null)
 try {
  var oShell = new ActiveXObject("Wscript.Shell");
  var sendtoDir = oShell.ExpandEnvironmentStrings("%USERPROFILE%") + "\\SendTo\\";
  var shortcutName = sendtoDir + "Mail Recipient.lnk";
  var fso = new ActiveXObject("Scripting.FileSystemObject");
  var tmp = "";
  if (reg.toUpperCase() == "YES")
   var oShellLink = oShell.CreateShortcut(shortcutName);
   oShellLink.IconLocation = "%SystemRoot%\\system32\\SHELL32.dll,156";
   oShellLink.TargetPath = oShell.ExpandEnvironmentStrings("%SystemRoot%") + "\\system32\\wscript.exe";
   oShellLink.Arguments = "\"" + WScript.ScriptFullName + "\" /file:\"%1\"";
   try { fso.DeleteFile(sendtoDir + "Mail Recipient.MAPIMail", true); } catch(e) {};
   try { fso.DeleteFile(shortcutName); } catch(e) {};
   fso.CreateTextFile(sendtoDir + "Mail Recipient.MAPIMail", true);
   tmp = "un";

   WScript.Echo("\r\n\r\nSendToMailRecip: " + tmp + "registration succeeded!");

 } catch(e) {
  WScript.Echo("\r\n\r\nSendToMailRecip: " + tmp + "Registration failed. (You may lack sufficient permissions.) \r\n" +
   "Error: " + e.description);

var fullPath = WScript.Arguments.Named("file");
if (fullPath == "%1")
 fullPath = WScript.Arguments.Unnamed.item(0);
if (fullPath != null)
 var olMailItem = 0;
 var a = fullPath.split("\\");
 var fileName = a[a.length - 1];
 var oOutlook = new ActiveXObject("Outlook.Application");
 var oItem = oOutlook.CreateItem(olMailItem);
 oItem.Subject = subjectTemplate.Replace("{{filename}}", fileName);
 oItem.Body = bodyTemplate.Replace("{{filename}}", fileName);



This script supports one command line switch with two possible options: /register:[yes|no]

/register:yes creates a shortcut to the script file (using its current path location) named 'Mail Recipient.lnk' in the user's SendTo folder (under the profile folder, as obtained by expanding the environment variable %USERPROFILE%.) It also deletes the file 'Mail Recipient.MAPIMail' from the same folder, if it exists.

/register:no re-creates the file 'Mail Recipient.MAPIMail' in the SendTo folder (it is merely a zero-length file with the extension '.MAPIMail', which is registered to a MIME type handler.) It also deletes the shortcut 'Mail Recipient.lnk' from the same folder, if it exists.

Neither option alters any handler registration, including but not limited to the one invoked for files with the extension '.MAPIMail'.

Unfortunately, a simple script like this one relies on the shell to pass the selected file name as a command line argument -- and it passes only one (the file that was right-clicked, regardless of how many were selected.) In order to utilize multiple file selections, the called binary must make API calls to read the selection list from the system (via an interface defined for this purpose.)

If you wish to customize the subject and/or body text of the emails this will create, you'll find, near the top of the script (near line 35) there are two template strings that are used to render subject and body, respectively. These templates support a single case-sensitive token, {{filename}} which is replaced with the name of the attachment when the script is called.

The values assigned to these template strings can be set to any JavaScript-legal string expression of the user's choosing.

No comments:

Post a Comment