Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

_MailAutoSig Bookmark missing (Outlook 2010)

I wrote an addin a while back for Outlook that adds/removes an optional tagline below the signature in an outlook message. This add-in works with no issues.

I'm writing a second add-in that needs to potentially add information below that (whether or not the optional signature is there) and am again referencing the _MailAutoSig bookmark from the Word editor. The issue I'm running into is that this bookmark no longer seems to appear, nor does the bookmark from my other add-in.

One difference in the two pieces of code below is that the first one has the MailItem being converted from an object passed by ItemSend, whereas the second is processed BEFORE the ItemSend event.

Here is the code from what I am currently writing:

            Word.Document toMsg = msg.GetInspector.WordEditor as Word.Document;

        foreach (Word.Bookmark b in toMsg.Bookmarks)
            Debug.Print(b.ToString());

        Word.Range r_toMsg;

        try
        {
            string oBookmark = "_MailAutoSig";  // Outlook internal bookmark for location of the e-mail signature`
            object oBookmarkObj = oBookmark;
            if (toMsg.Bookmarks.Exists(oBookmark) == true)
                Debug.Print("sigbookmark");
            r_toMsg = toMsg.Bookmarks.get_Item(ref oBookmarkObj).Range;
        }
        catch
        {
            string oOffsiteBookmark = "OffsiteBookmark";
            object oOffsiteBookmarkObj = oOffsiteBookmark;

            if (toMsg.Bookmarks.Exists(oOffsiteBookmark) == true)  // if the custom bookmark exists, remove it
                Debug.Print("offsite bookmark");
        }
        finally
        { 
            r_toMsg = toMsg.Range(missing,missing);
        }

and here is code from my working add-in:

void InsertOffsiteSig(Outlook.MailItem oMsg)
{
    object oBookmarkName = "_MailAutoSig";  // Outlook internal bookmark for location of the e-mail signature
    string oOffsiteBookmark = "OffsiteBookmark";  // bookmark to be created in Outlook for the Offsite tagline
    object oOffsiteBookmarkObj = oOffsiteBookmark;

    Word.Document SigDoc = oMsg.GetInspector.WordEditor as Word.Document; // edit the message using Word

    string bf = oMsg.BodyFormat.ToString();  // determine the message body format (text, html, rtf)

    //  Go to the e-mail signature bookmark, then set the cursor to the very end of the range.
    //  This is where we will insert/remove our tagline, and the start of the new range of text

    Word.Range r = SigDoc.Bookmarks.get_Item(ref oBookmarkName).Range;
    object collapseEnd = Word.WdCollapseDirection.wdCollapseEnd;

    r.Collapse(ref collapseEnd);

    string[] taglines = GetRssItem();  // Get tagline information from the RSS XML file and place into an array


    // Loop through the array and insert each line of text separated by a newline

    foreach (string taglineText in taglines)
        r.InsertAfter(taglineText + "\n");
    r.InsertAfter("\n");

    // Add formatting to HTML/RTF messages

    if (bf != "olFormatPlain" && bf != "olFormatUnspecified")
    {
        SigDoc.Hyperlinks.Add(r, taglines[2]); // turn the link text into a hyperlink
        r.Font.Underline = 0;  // remove the hyperlink underline
        r.Font.Color = Word.WdColor.wdColorGray45;  // change all text to Gray45
        r.Font.Size = 8;  // Change the font size to 8 point
        r.Font.Name = "Arial";  // Change the font to Arial
    }

    r.NoProofing = -1;  // turn off spelling/grammar check for this range of text

    object range1 = r;
    SigDoc.Bookmarks.Add(oOffsiteBookmark, ref range1);  // define this range as our custom bookmark


    if (bf != "olFormatPlain" && bf != "olFormatUnspecified")
    {
        // Make the first line BOLD only for HTML/RTF messages

        Word.Find f = r.Find;
        f.Text = taglines[0];
        f.MatchWholeWord = true;
        f.Execute();
        while (f.Found)
        {
            r.Font.Bold = -1;
            f.Execute();
        }
    }
    else
    {
        // otherwise turn the plain text hyperlink into an active hyperlink
        // this is done here instead of above due to the extra formatting needed for HTML/RTF text

        Word.Find f = r.Find;


        f.Text = taglines[2];
            f.MatchWholeWord = true;
            f.Execute();
            SigDoc.Hyperlinks.Add(r, taglines[2]);
        }
        r.NoProofing = -1;  // disable spelling/grammar checking on the updated range
        r.Collapse(collapseEnd);
}
like image 443
Larry G. Wapnitsky Avatar asked May 13 '11 15:05

Larry G. Wapnitsky


1 Answers

The problem is that Microsoft converts the "Office HTML" (I'm not sure the proper term) to normal HTML before it fires the ItemSend() event, which causes the _MailAutoSig bookmark to disappear.

The only way to get the _MailAutoSig bookmark back is to first CANCEL the ItemSend() event, then fire off a timer to run a function which will in turn access the email object and manipulate it how you want, add a user property to mark the email has been processed, and then send the email again.

For example:

Dim modItem As Object 'need to hold the item somewhere so the timer can access it

Sub object_ItemSend(ByVal Item As Object, Cancel As Boolean)
    If Item.UserProperties.Item("isModded") Is Nothing Then
        'User has composed a mail and hit "Send", we need to make our modifications to the signature though
        modItem = item
        Cancel = True 'cancel the Send so we can make the modifications
        mytimer.Enabled = True 'fire off a timer to make the modifications
        Exit Sub
    Else
        Item.UserProperties.Item("isModded").Delete 'this flag will keep the email from ping-ponging between ItemSend and the timer
    End If
End Sub

'10 millisecond timer? I think the cancel is almost instant, but experiment
Sub mytimer_Timer()
    mytimer.Enabled = False
    If Not modItem Is Nothing Then
        modItem.HtmlBody = ...... the signature bookmark will be intact again, so make your modifications ......
        modItem.UserProperties.Add("isModded", olText) 'no ping-pong
        modItem.Send 'send it again
        modItem = Nothing
    End If
End Sub

I had to do something similar for a project where some Outlook fields were not set until I was in the ItemSend() event, so I was forcing the email to send, get my information, then cancel the send. It worked great.

Now, this was written off the top of my head, so I'm sure the code above will not be perfect, but it should give you the idea of what needs to be done.

like image 127
Brain2000 Avatar answered Nov 04 '22 12:11

Brain2000