tl;dr:

To make use of outlook://msg-id style links, jump over to GitHub and grab the tools!


Update 2015-11-08: The latest Outlook updates have broken the message-id links, so please do not use this method for linking to email messages for now.


As I want to use the services over at MindMeister more excessively for creative project and task management, I was wondering how one could connect Outlook 2016 and MindMeister maps / MeisterTask tasks. This is nothing I think will be used a lot, but still, it’d be nice to have the option.

As you may know, there never was such thing in Outlook for Mac. And Outlook 2016 sadly is no exception. Even the scripting capabilities have been drastically reduced and the Scripts menu was removed completely.

I started experimenting with linking to the email with a file:// link – which seemed to work alright from anywhere but browsers. For security reasons, file:// style links are blocked in all major browsers (Safari, Chrome, Firefox) – so this wasn’t an option.

The initial idea for a custom URL handler came from the simplicity and cleverness of how they are used to link between apps on iOS (and Android?). So the idea is to create something similar for E-Mail on Outlook for Mac.

The final solution basically consists of two scripts. One is to generate the link (basically just extracting the message id) and the other is to handle the URL. AppleScripts can be saved as applications which can, in turn, provide custom URL handlers.

How to use the custom URL handler?

The code together with the ready-to-use scripts are over at GitHub – contributions welcome!

  1. Download the OutlookURLHandler.app file and place it into /Applications
  2. Run the application once for it to register the URL Handler
  3. You’re all set for outlook://msg-id style links!

To be able to quickly and easily generate the links and put them in the clipboard, I created a second script, MsgLinkToClpbrd which puts the message link that calls the handler in your clipboard.

  1. Download MsgLinkToClpbrd.scpt from GitHub
  2. Create the folder structure ~/Library/Scripts/Applications/Microsoft/Outlook and place the script there
  3. Use BetterTouchTool, FastScripts or any other tool to assign a hotkey to the script execution from within Outlook.

Now you can use direct links to your emails from anywhere on your Mac, with simple, plain-text links in the outlook://msg-id notation.

I recently tried to work with Things instead of OmniFocus, and thus trying the available AppleScripts for Things as well. One major difference between OF & Things is the inability of Things to add file attachments.

The available solutions work around this by finding the message directly inside the Outlook data directory and linking to it. (Note: This will break if you move messages between accounts, e.g. remote & local). This idea together with the fact that my Things-digression didn’t quite work out started a new round of refactoring of the Outlook-to-OmniFocus AppleScript …

Changelog:

  • New: Option to switch between file attachment and direct data-directory link to reduce library size (attachMailToOFTask)
  • New: Option to switch between the way multiple selected messages are handled (e.g. one task with multiple messages vs. one task per message) (multiSelectMultiTask)
  • New: Option to expand note in QuickEntry (expandNotes)
  • New: Option to trim message by number of characters
  • New: Option to trim subject line by keywords (e.g. Re:, Fwd:, …)
  • Changed: Task title now formatted as Sender : Subject

Update 2015-08-19:

  • New: Set attachMailToOFTask to 3 to include outlook:// style links (see OutlookURLHandler)

As said before, most of it relies on the work and all credit goes to Rainer && LuMe96.

Get the script here: Download

Ever since Microsoft decided to honor the latest changes to the way Mac Apps are built (read: Sandboxing) it’s been painful to integrate it to other apps. For me, the most crucial integration is with OmniFocus for task management. The fact that MS seems to be ditching AppleScript support – at least for new features – and completely removed the scripts menu doesn’t help either.

Yesterday I came across a comment by Brett Terpstra on Rainer Burgstaller’s site (author of one of the best Outlook-to-OmniFocus scripts as well as FocusGTD, a great way to use OF on Android) that described what location needs to be used in order to comply to sandboxing regulations and still be able to save a copy of the message alongside the task in OmniFocus.

All credit for this edit goes to Rainer & Brett, I was just pressing the keys – no brain work involved šŸ™‚ Here’s the script, together with some comments on the original post:

Download Script

I tried firing the script from both FastScripts and BetterTouchTool, both works great and substitutes the Scripts Menu reasonably well.

To license an SAP HANA instance if you’re not able to connect via HANA studio, follow this procedure:

  1. Start-Up the system
    $ HDB start
    
  2. Grab the Hardware Key via hdbsql
    $ export INSTANCE=01
    $ hdbsql -n localhost:3${INSTANCE}15 -i ${INSTANCE} -u SYSTEM -p password -m <<EOF
    SELECT * FROM M_LICENSE;
    EOF
    
    Welcome to the SAP HANA Database interactive terminal.
    
    Type:  \h for help with commands
    \q to quit
    
    HARDWARE_KEY,SYSTEM_ID,INSTALL_NO,SYSTEM_NO,PRODUCT_NAME,PRODUCT_LIMIT,PRODUCT_USAGE,START_DATE,EXPIRATION_DATE,LAST_SUCCESSFUL_CHECK,PERMANENT,VALID,ENFORCED,LOCKED_DOWN,MEASUREMENT_XML
    **THIS IS THE HARDWARE KEY**","XXXX","XXXX","XXXX","SAP-HANA",8192,2576,"2013-09-05 00:00:00.000000000","2013-09-05 00:00:00.000000000","2013-09-06 00:00:00.000000000","TRUE","TRUE","FALSE","FALSE","<?xml version=\"1.0\" encoding=\"UTF-8\"?><!DOCTYPE Measurement SYSTEM \"GLasXML1.0.dtd\"><Measurement><Header><Transfer><Version>GXML1.0</Version><Program>SAPHANA1.0</Program><Name>SYSTEM</Name></Transfer><Sender/><Receiver/></Heade
    
  3. Request a new license key

  4. Copy the license key file (in this example XX1_Standard.txt) to the target system and execute the following commands:

    $ export LICENSE=$(cat XX1_Standard.txt)
    $ export INSTANCE=01
    $ hdbsql -n localhost:3${INSTANCE}15 -i ${INSTANCE} -u SYSTEM -p password -m <<EOF
    SET SYSTEM LICENSE '${LICENSE}';
    EOF
    
    
    0 rows affected (overall time 129.122 msec; server time 115.297 msec)
    
  5. Check if the license was successfully applied by repeating step 2

Since version 10.5 ā€œLeopardā€, Mac OS X has had DTrace, a tool used for performance analysis and troubleshooting. It provides data for Apple’s Instruments tool, as well as a collection of command line tools that are implemented as DTrace scripts. I’m familiar with the latter as I wrote the originals for the DTraceToolkit, which Apple then customized and enhanced for Mac OS X where they are shipped by default (great!).

Read more

In Linux, /etc directory contains important system-related or application-specific configuration files. Especially in a server environment, it is wise to back up various server configurations in /etc directory regularly, to save trouble from any accidental changes in the directory, or to help with re-installation of necessary packages. Better yet, it is a good idea to ā€œversion controlā€ everything in /etc directory, so that you can track configuration changes, or recover from a previous configuration state if need be.

Read more

Running diskless servers sounds like a great idea – if it wasn’t for the fiddling around with auto-install scripts to finally get to a working system. I want to share and comment on my AutoYaST configuration that has served me well over the last couple of months.

The only thing this solution depends on is that the device you want to install on is connected an Lun-ID 00 – which is a prerequisite for SAN boot for most controllers anyway.

Bootloader Configuration

The initial bootloader configuration is rather straightforward. Simply setting it to (hd0), deciding to bother about selecting the right hd0 later and moving on:

<loader_type>grub</loader_type>
<sections config:type="list">
    <section>
        <append>ksdevice=bootif locale=en_US text priority=critical resume=/dev/vg_%%HOSTNAME%%/lv_swap splash=silent crashkernel=256M-:128M showopts</append>
        <image>(hd0,0)/vmlinuz-3.0.13-0.27-default</image>
        <initial>1</initial>
        <initrd>(hd0,0)/initrd-3.0.13-0.27-default</initrd>
        <lines_cache_id>0</lines_cache_id>
        <name>SLES for SAP Applications - 3.0.13-0.27</name>
        <original_name>linux</original_name>
        <root>/dev/vg_%%HOSTNAME%%/lv_root</root>
        <type>image</type>
    </section>

Pre-Scripts

Here things are getting a bit more complicated. In the Pre-Script I am doing 2 things:

  1. Renaming the volume group to incorporate the hostname
  2. Selecting the right volume to install the system on

Here is my pre-script. The magic is in assigning the $mpathvol variable. Paying attention to only use commands that are actually available at this stage of the install is crucial here.

See that I am using 2 strings to match against the /proc/scsi/scsi output – which strings you need highly depends on the SAN setup you have. I recommend checking on sn installed system to find a string that’s not too general and lets you find the device(s) safely.

<pre-scripts config:type="list">
    <script>
        <debug config:type="boolean">false</debug>
        <feedback config:type="boolean">true</feedback>
        <filename>config-hostname.sh</filename>
        <interpreter>shell</interpreter>
        <source><![CDATA[
#!/bin/bash
# Find multipathed volume on LUN ID 00
# IBM is for volumes mapped by SVC
# WD3000 is for local devices of IBM Blades
mpathvol=\$(cat /proc/scsi/scsi | egrep -B1 "IBM|WD3000" | grep "Lun: 00" | while read x1 dev x2 chan x3 id x4 lun; do echo \${dev/scsi/}\:\${chan:1}\:\${id:1}\:\${lun:1}; done | while read device; do ls -1 /sys/class/scsi_device/\$device/device/block; done | tr '\n' '|' | sed 's/|\$/\n/g' | while read search; do multipath -ll | egrep -w -B3 "\$search"; done | head -n1 | cut -d" " -f2)

# Set the correct Volume-Group Name
cat /tmp/profile/autoinst.xml | sed "s,%%HOSTNAME%%,`echo \$HOSTNAME | cut -d"." -f1`,g" > /tmp/profile/step1.xml

# Set the correct root device & LVM settings
# Check if we have a multipathed environment
if [ "_\$mpathvol" != "_" ]; then
    cat /tmp/profile/step1.xml | sed "s,/dev/sda,/dev/\${mpathvol},g" >/tmp/profile/modified.xml

    # Do not paste the "Enable all devices for LVM" snipped here as LVM will spit on the reoccurrence of devices by path
else
    mv /tmp/profile/step1.xml /tmp/profile/modified.xml

    # Enable all devices for LVM
    sed -i 's#\[ "r|/dev/\.\*/by-path/\.\*|", "a|/dev/mapper/\.\*|", "a|/dev/\.\*/by-id/\.\*|", "r/\.\*/" \]#\[ "a/\.\*/" \]#g' /etc/lvm/lvm.conf
fi

]]>
        </source>
    </script>
</pre-scripts>

As long as you assign the final autoyast configuration to /tmp/profile/modified.xml the installer will pick it up and use it instead of the autoinst.xml.

Post-Scripts

Here we are, having our system installed on the correct disk – so we should be good to go. Wrong. The system will only boot if it’s really (really) diskless. As soon as there’s another local disk we’re screwed. Grub will install on hd0, and that’s the local disk we don’t want it to install on. I am working around this with 2 post-scripts.

The reason I have 2 post scripts is actually a bit complicated. The first script doesn’t run chrooted so we can still be sure to have multipath support that’ll be crucial for getting the SCSI-ID of the device. The second script however does run chrooted to make sure we’re using the correct grub commands to install the bootloader (plus, the bootloader will install in this stage and our ‘device.map’ would get overwritten by the installer):

<chroot-scripts config:type="list">
     <script>
         <debug config:type="boolean">false</debug>
         <feedback config:type="boolean">false</feedback>
         <filename>config.sh</filename>
         <interpreter>shell</interpreter>
         <chrooted config:type="boolean">false</chrooted>
         <source><![CDATA[
#!/bin/bash
mpathid=\$(cat /proc/scsi/scsi | egrep -B1 "IBM|WD3000" | grep "Lun: 00" | while read x1 dev x2 chan x3 id x4 lun; do echo \${dev/scsi/}\:\${chan:1}\:\${id:1}\:\${lun:1}; done | while read device; do ls -1 /sys/class/scsi_device/\$device/device/block; done | tr '\n' '|' | sed 's/|\$/\n/g' | while read search; do multipath -ll | egrep -w -B3 "\$search"; done | head -n1 | cut -d" " -f1)

# Set the correct root device & LVM settings
# Check if we have a multipathed environment
if [ "_\$mpathid" != "_" ]; then
    echo -e "(hd0)\t/dev/disk/by-id/scsi-\$mpathid" >/boot/grub/device.map
    echo -e "(hd0)\t/dev/disk/by-id/scsi-\$mpathid" >/mnt/etc/device.map
fi
]]>
        </source>
    </script>
    <script>
        <debug config:type="boolean">false</debug>
        <feedback config:type="boolean">false</feedback>
        <filename>config-chroot.sh</filename>
        <interpreter>shell</interpreter>
        <chrooted config:type="boolean">true</chrooted>
        <source><![CDATA[
#!/bin/bash
if [ -f /etc/device.map ]; then
    mv /etc/device.map /boot/grub/device.map
    /usr/sbin/grub <<EOF
root (hd0,0)
setup (hd0)
EOF
fi
]]>
        </source>
    </script>
</chroot-scripts>

I am planning to do a Debian / Ubuntu preseed version as well, so stay tuned.

You can download the whole AutoYaST configuration here: [autoyast_san.xml]({% postfile autoyast_san.xml %})