Talking to myself

Someone at work here presented me with a poser: make Outlook include one's own email address as a BCC when sending an email. I know you can check a box to get Outlook to CC yourself, and you can also get Outlook to save messages in the Sent Items folder, but he really wanted to be BCC'd, so I thought, why not have a look...

Now, there's an easy way and a hard way. The boring easy way is to hook Application.ItemSend and append the user's address to the message recipients. After a little discussion we concluded that he preferred to have the address appear in the BCC line when the message was being composed, to give a little extra confidence (and a reminder) that the address would be included, and also to let him remove the address for those messages not worth copying to himself. Quite a while ago now, I outlined how to add a handler for Inspectors.NewInspector in the NoReplyAll add-in: this is a convenient place to hook up an email address - but only if the user is composing a message (either a new message or a reply/forward) and not if the user is merely reading a received one.

Here's a reasonable NewInspector handler:

 private void OnNewInspector(Outlook.Inspector inspector)
{
    var item = inspector.CurrentItem as Outlook.MailItem;
    if (item != null)
    {
        if (string.IsNullOrEmpty(item.EntryID))
           AddSelfToBcc(item);
       Marshal.ReleaseComObject(item);
    }
}

An investigation showed that an empty EntryID seems to be a good indication that the mail item is a newly composed one - according to the documentation, only saved items have non-empty values, thus I think the only time I'll see empty within the NewInspector is when the message is indeed a newly created one. And see an earlier blog post about why I have the occasional ReleaseComObject call in my code.

Before exploring AddSelfToBcc, a question to be answered is which email address should be used? If you only have a single email account attached to Outlook, the answer is pretty straightforward, but if you have more than one, then what's the obvious choice? I could be lazy and make the user specify which address to use in some settings page, or I could always use the address in the default account, but I thought I'd show off a bit and pick an address appropriate to the message... What this really means is that for a new message, use the default account; for a reply, use whatever address the original message was sent to. The next issue is how to get hold of that address...

MailItem.Sender sounded like it might be a nice option but, unfortunately, it's only set for received messages. However, MailItem.SendUsingAccount is valid and gets us one step closer:

 private void AddSelfToBcc(Outlook.MailItem item)
{
    var account = item.SendUsingAccount;
    var user = account.CurrentUser;
    var self = user.Address;
    Marshal.ReleaseComObject(user);
    Marshal.ReleaseComObject(account);

    var recipients = item.GetProperty.Recipients;
    bool found = false;
    foreach (Outlook.Recipient recipient in recipients)
        if (recipient.Address == self)
        {
            found = true;
            break;
        }
    if (!found)
    {
        var newRecipient = recipients.Add(self);
        newRecipient.Type = (int)Outlook.OlMailRecipientType.olBCC;
        newRecipient.Resolve();
        Marshal.ReleaseComObject(newRecipient);
    }
    Marshal.ReleaseComObject(recipients);
}

Rather than unconditionally adding the address, I do a quick check to see if it's already there (as might be the case, say, when responding to a the latest in a sequence of emails to and fro); and note the call to Recipient.Resolve - it makes the displayed string look just a little nicer by getting Outlook to, well, resolve it.

As well as NewInspector, Outlook 2013's inline response mechanism adds a new mechanism for displaying new messages. We can handle Explorer.InlineResponse in just the same way as NewInspector to add an email address (though there's no need to check if the message is a newly composed one or a received one, since it'll always be a new message).

Finally, I'm debating whether or not to include this in the next release of NoReplyAll - it's got nothing to do with disabling replies, but it is kinda cool...