Jump to content
Macro Express Forums

Challenge: a macro to "decide" what to do with an email message


Recommended Posts

 

The challenge is to write a Macro Express script to analyze an email message, and on the basis of the analysis, automatically do something to the message. For example, the macro might move the message to a certain folder, flag it as important, delete the message, or whatever.


To provide data for your macro, gather information from the user interface of your favourite email program. For example, your script might copy the name of the sender, the subject line, the message body, the date, etc.


To simplify the challenge consider extracting only one or two pieces of information. Perhaps the name of the sender and/or the subject line. Then the rules for deciding what to do might look something like this (in pseudo code):


If %Sender% = "Sandy.Smith@organization.com" Then

    (Steps to move message to the "Sandy Smith" folder)

End if


If %Subject% Contains "election" Then

    (Steps to flag message as Important)

End if


Try not be be tempted to develop an "artificial intelligence" by adding super complex rules. A script like this, built in Macro Express, won't be completely bullet-proof. Although the functionality of your solution might be limited, the goal is to make the script a useful tool for keeping one's Inbox organized. So I hope you have fun with it. It's intended as an exercise for stretching our skills with Macro Express.


I'll post my solution soon. My script for Outlook 2019 is hotkey activated, and moves the current message into one of three folders based on (1) who the message is from, and (2) keywords that appear in the body of message. It consists of about 50 lines of code, plus comments. Although my solution was not trivially simple to develop, neither was it super-complex.

Link to comment
Share on other sites

Many email applications support rules. Gmail even. I use Outlook. I would recommend a user exhaust every opportunity to use the program's capabilities before writing a macro. Since I use an application with this capability, I've never had to write a macro like this so I'll not be participating in your challenge. Just tossing this information out there because many don't realize they already have a way to do this natively. 

Link to comment
Share on other sites

Hi Cory,

 

I was wondering whether someone was going to suggest built-in rules!

 

Building a set of rules is the smart way to meet the challenge. But the reason for this challenge is less about doing things efficiently, and more about scratch-building one's own software tools... because the exercise can deepen one's appreciation of what can be accomplished with Macro Express.

 

You appear to be one of the most sophisticated macro developers on this forum, so I would be very curious to learn how you might tackle this challenge.

Link to comment
Share on other sites

Edit: I simplified all three scripts by removing an unnecessary variable. The revisions make the rules easier to understand.

My solution, which serves as replacement for Outlook 2019's Move to Folder commands, consists of three scripts:

 

- A list of rules. The nickname for the macro is "Move Message Rules"

- A script to move the selected message from the main Outlook 2019 user interface. I suggest setting the macro scope to window, partial match = " - Outlook"

- A script to move the open message. To ensure availability in HTML, Plain Text, and RTF messages, set the scope to window, partial match = " - Message ("

 

 

I assigned Alt + M as the hotkey to activate the two scripts because M is the first letter in "Move" but of course you can use anything you want.

 

To simplify the challenge, I decided to analyze the body of email messages, only. The method for capturing the body is different when viewing the message in the main Outlook user interface, and when viewing the message in its own window. That's why I had to write two different scripts.

 

In rough outline, here’s how these macros work:

 

1. Navigate to the body of the message.

 

2. Select and copy the message.

 

3. Apply the rules: For example, if a message contains "ABC" and "DEF" then let the target folder be "XYZ".

 

4. Invoke Outlook's "Move Item" (or "Move Items") dialog box.

 

5. The dialog box has a tree view that can be forced to display every Outlook folder. Keypad * is the hotkey to expand a node on a tree view so it shows all "branches".

 

6. Navigate to the target folder by using the incremental search built into the tree view: Any item can be reached by quickly typing its exact name. The scripts "type" the folder name into the tree view. Each Outlook folder name must be unique for this to work reliably. If no rule applies, navigate to the "Inbox" folder and stop.

 

7. The scripts do not actually move messages. To complete the operation, you must press Enter.

 

 

Nickname: Move Message Rules

Scope: Global

Activation: None

 

 

// "Rules" for determining which folder to move message to based on words that appear in the body.

Variable Set String %FolderPath% to "Inbox" // Set default target folder as "Inbox" to use when no rule applies

If Variable %Body% Contains "Gooderham"

  Variable Set String %FolderPath% to "Movie reviews"

End If

If Variable %Body% Contains "Sandy"

  AND

If Variable %Body% Contains "Smith"

  Variable Set String %FolderPath% to "Sandy Smith"

End If

// Add other rules here...

 

 

<COMMENT Value="\"Rules\" for determining which folder to move message to based on words that appear in the body."/>

<COMMENT/>

<VARIABLE SET STRING Option="\x00" Destination="%FolderPath%" Value="Inbox" NoEmbeddedVars="FALSE" _COMMENT="Set default target folder as \"Inbox\" to use when no rule applies"/>

<COMMENT/>

<IF VARIABLE Variable="%Body%" Condition="\x06" Value="Gooderham" IgnoreCase="TRUE"/>

<VARIABLE SET STRING Option="\x00" Destination="%FolderPath%" Value="Movie reviews" NoEmbeddedVars="FALSE"/>

<END IF/>

<COMMENT/>

<IF VARIABLE Variable="%Body%" Condition="\x06" Value="Sandy" IgnoreCase="FALSE"/>

<AND/>

<IF VARIABLE Variable="%Body%" Condition="\x06" Value="Smith" IgnoreCase="FALSE"/>

<VARIABLE SET STRING Option="\x00" Destination="%FolderPath%" Value="Sandy Smith" NoEmbeddedVars="FALSE"/>

<END IF/>

<COMMENT/>

<COMMENT Value="Add other rules here..."/>

 

 

 

 

Nickname: Move to Folder from Main UI

Scope = " - Outlook"

Activation: Alt + M

 

 

// Guess which folder a message should be moved to...

// ... based on the rules listed in "Move Message Rules"

// This script copies the body of a selected message from the Reading Pane. So the Reading Pane must be "On!"

// It navigates from pane to pane, captures a control at each stop, and extracts its class.// We're looking for the Reading Pane. Its class is "_Wwg"

// Navigate via Ctrl + Tab from pane to pane, up to four times, until the Reading Pane is reached:

// Capture the control for each pane as it gains focus

// The body has been reached when the class for the focused control = "_WwG"

//     1. "OutlookGrid" = The class of the list of messages.

//     2. "_WwG" = The class of the message part of the Reading Pane

//     3. "Awesome Bar" = The class of toolbar at the bottom of the Folder View

//     4. "NetUIHWND" = The class of the Folder View

//     Then wrap to the start

Text Type (Simulate Keystrokes): <ESC> // In case the ribbon has focus, shift focus back to the main UI.

Variable Set Bool %IsMessageFound% to "False" // Set flag to indicate whether the script has visited all panes

// Four panes can be reached via Ctrl + Tab for me, but there may be more for others. So adjust if needed.

Repeat Start (Repeat 4 times)

  Text Type (Simulate Keystrokes): <CONTROL><TAB>

  Delay: 30 milliseconds // Need a short delay for focus to settle on the next control

  Capture Control from Focused Control into %FocusedControl%

  Get Control Class from %FocusedControl% into %ControlClass%

    If Variable %ControlClass% Equals "_WwG" // The Reading Pane has focus

    Variable Set Bool %IsMessageFound% to "True"

    Text Type (Simulate Keystrokes): <CONTROL>a<CONTROL>c<HOME> // Select, copy, and deselect the message

    Variable Set String %Body% from the clipboard contents

    Text Type (Simulate Keystrokes): <SHIFT><CONTROL><TAB> // Navigate to the list of emails

    Repeat Exit

  End If

End Repeat

If Variable %IsMessageFound% Equals "False" // Signal error if Reading Pane not found. May need to increase # of loops.

  MessageBox: Can't find the "Reading Pane"

  Macro Stop

End If

Macro Run: Move Message Rules

// Press Outlook hotkey to move to folder

Text Type (Simulate Keystrokes): <CONTROL><SHIFT>v

Delay: 100 milliseconds

// Navigate to the top of the tree view

Text Type (Simulate Keystrokes): <HOME>

// Expose all folders in the topmost item in the tree view

Text Type (Simulate Keystrokes): <KEYP*>

// Use the incremental search built into the tree view to navigate to the target folder

 

  Text Type (Simulate Keystrokes): %FolderPath% // Set default target folder as "Inbox" to use when no rule applies

 

<COMMENT Value="Guess which folder a message should be moved to..."/>

<COMMENT Value="... based on the rules listed in \"Move Message Rules\""/>

<COMMENT/>

<COMMENT Value="This script copies the body of a selected message from the Reading Pane. So the Reading Pane must be \"On!\""/>

<COMMENT Value="It navigates from pane to pane, captures a control at each stop, and extracts its class. "/>

<COMMENT Value="We're looking for the Reading Pane. Its class is \"_Wwg\""/>

<COMMENT/>

<COMMENT Value="Navigate via Ctrl + Tab from pane to pane, up to four times, until the Reading Pane is reached:"/>

<COMMENT Value="Capture the control for each pane as it gains focus"/>

<COMMENT Value="The body has been reached when the class for the focused control = \"_WwG\""/>

<COMMENT/>

<COMMENT Value="    1. \"OutlookGrid\" = The class of the list of messages."/>

<COMMENT Value="    2. \"_WwG\" = The class of the message part of the Reading Pane"/>

<COMMENT Value="    3. \"Awesome Bar\" = The class of toolbar at the bottom of the Folder View"/>

<COMMENT Value="    4. \"NetUIHWND\" = The class of the Folder View"/>

<COMMENT Value="    Then wrap to the start"/>

<COMMENT/>

<TEXT TYPE Action="0" Text="<ESC>" _COMMENT="In case the ribbon has focus, shift focus back to the main UI."/>

<COMMENT/>

<VARIABLE SET BOOL Destination="%IsMessageFound%" Command="263" Value="FALSE" _COMMENT="Set flag to indicate whether the script has visited all panes"/>

<COMMENT/>

<COMMENT Value="Four panes can be reached via Ctrl + Tab for me, but there may be more for others. So adjust if needed."/>

<REPEAT START Start="1" Step="1" Count="4" Save="FALSE"/>

<TEXT TYPE Action="0" Text="<CONTROL><TAB>"/>

<DELAY Flags="\x02" Time="30" _COMMENT="Need a short delay for focus to settle on the next control"/>

<CAPTURE CONTROL Option="\x01" Control="%FocusedControl%" UseText="TRUE"/>

<GET CONTROL CLASS TextVar="%ControlClass%" ControlVar="%FocusedControl%"/>

<COMMENT/>

<IF VARIABLE Variable="%ControlClass%" Condition="\x00" Value="_WwG" IgnoreCase="FALSE" _COMMENT="The Reading Pane has focus"/>

<VARIABLE SET BOOL Destination="%IsMessageFound%" Command="263" Value="TRUE"/>

<TEXT TYPE Action="0" Text="<CONTROL>a<CONTROL>c<HOME>" _COMMENT="Select, copy, and deselect the message"/>

<VARIABLE SET STRING Option="\x02" Destination="%Body%" NoEmbeddedVars="FALSE"/>

<TEXT TYPE Action="0" Text="<SHIFT><CONTROL><TAB>" _COMMENT="Navigate to the list of emails"/>

<REPEAT EXIT/>

<END IF/>

<END REPEAT/>

<COMMENT/>

<IF VARIABLE Variable="%IsMessageFound%" Condition="\x00" Value="False" IgnoreCase="FALSE" _COMMENT="Signal error if Reading Pane not found. May need to increase # of loops."/>

<MESSAGEBOX Caption="Can't find the \"Reading Pane\"" Message="The \"Reading Pane\" might be set to \"Off.\" Make sure it's \"On.\" Or try again!" Icon="4"/>

<MACRO STOP/>

<END IF/>

<COMMENT/>

<MACRO RUN Use_ID="FALSE" Name="Move Message Rules" ID="-1" Wait="TRUE"/>

<COMMENT/>

<COMMENT Value="Press Outlook hotkey to move to folder"/>

<TEXT TYPE Action="0" Text="<CONTROL><SHIFT>v"/>

<DELAY Flags="\x02" Time="100"/>

<COMMENT/>

<COMMENT Value="Navigate to the top of the tree view"/>

<TEXT TYPE Action="0" Text="<HOME>"/>

<COMMENT/>

<COMMENT Value="Expose all folders in the topmost item in the tree view"/>

<TEXT TYPE Action="0" Text="<KEYP*>"/>

<COMMENT/>

<COMMENT Value="Use the incremental search built into the tree view to navigate to the target folder"/>

<TEXT TYPE Action="0" Text="%FolderPath%"/>

 

 

Nickname: Move to Folder from Open Message

Scope = " - Message ("

Activation: Alt + M

 

 

// Guess which folder a message should be moved to...

// ... based on the rules listed in "Move Message Rules"

// This script finds the body of a message, and copies it.

// It navigates from field to field, captures a control at each stop, and extracts its class.// We're looking for the body of the message. Its class is "_Wwg"

// Navigate via Tab from field to field until the body is reached:

// Capture the control for each field as it gains focus

// The body has been reached when the class for the focused control = "_WwG"

Repeat Until %1% Equals "2"

  Capture Control from Focused Control into %FocusedControl%

  Get Control Class from %FocusedControl% into %ControlClass%

  If Variable %ControlClass% Does not Equal "_WwG" // If the body does not have focus, keep tabbing until it's found

    Text Type (Simulate Keystrokes): <TAB>

  Else

    Text Type (Simulate Keystrokes): <CONTROL>a<CONTROL>c<HOME> // Select, copy, and deselect the message

    Variable Set String %Body% from the clipboard contents

    Repeat Exit

  End If

End Repeat

Macro Run: Move Message Rules

// Press Outlook key sequence to move a message to a folder

// Bug in Outlook 2019: Ctrl + Shift + V fails if message has been made editable...

// Therefore, we must go through the ribbons

Text Type (Simulate Keystrokes): <ALT>hmvo // Home > MoVe > Other...

Delay: 100 milliseconds

// Navigate to the top of the tree view

Text Type (Simulate Keystrokes): <HOME>

// Expose all folders in the topmost item in the tree view

Text Type (Simulate Keystrokes): <KEYP*>

// Use the incremental search built into the tree view to navigate to the target folder

Text Type (Simulate Keystrokes): %FolderPath%

 

 

<COMMENT Value="Guess which folder a message should be moved to..."/>

<COMMENT Value="... based on the rules listed in \"Move Message Rules\""/>

<COMMENT/>

<COMMENT Value="This script finds the body of a message, and copies it."/>

<COMMENT Value="It navigates from field to field, captures a control at each stop, and extracts its class. "/>

<COMMENT Value="We're looking for the body of the message. Its class is \"_Wwg\""/>

<COMMENT/>

<COMMENT Value="Navigate via Tab from field to field until the body is reached:"/>

<COMMENT Value="Capture the control for each field as it gains focus"/>

<COMMENT Value="The body has been reached when the class for the focused control = \"_WwG\""/>

<COMMENT/>

<REPEAT UNTIL Variable="%1%" Condition="\x00" Value="2"/>

<CAPTURE CONTROL Option="\x01" Control="%FocusedControl%" UseText="TRUE"/>

<GET CONTROL CLASS TextVar="%ControlClass%" ControlVar="%FocusedControl%"/>

<IF VARIABLE Variable="%ControlClass%" Condition="\x01" Value="_WwG" IgnoreCase="FALSE" _COMMENT="If the body does not have focus, keep tabbing until it's found"/>

<TEXT TYPE Action="0" Text="<TAB>"/>

<ELSE/>

<TEXT TYPE Action="0" Text="<CONTROL>a<CONTROL>c<HOME>" _COMMENT="Select, copy, and deselect the message"/>

<VARIABLE SET STRING Option="\x02" Destination="%Body%" NoEmbeddedVars="FALSE"/>

<REPEAT EXIT/>

<END IF/>

<END REPEAT/>

<COMMENT/>

<MACRO RUN Use_ID="FALSE" Name="Move Message Rules" ID="-1" Wait="TRUE"/>

<COMMENT/>

<COMMENT Value="Press Outlook key sequence to move a message to a folder"/>

<COMMENT Value="Bug in Outlook 2019: Ctrl + Shift + V fails if message has been made editable..."/>

<COMMENT Value="Therefore, we must go through the ribbons "/>

<COMMENT/>

<TEXT TYPE Action="0" Text="<ALT>hmvo" _COMMENT="&Home > &MOve > &Other..."/>

<DELAY Flags="\x02" Time="100"/>

<COMMENT/>

<COMMENT Value="Navigate to the top of the tree view"/>

<TEXT TYPE Action="0" Text="<HOME>"/>

<COMMENT/>

<COMMENT Value="Expose all folders in the topmost item in the tree view"/>

<TEXT TYPE Action="0" Text="<KEYP*>"/>

<COMMENT/>

<COMMENT Value="Use the incremental search built into the tree view to navigate to the target folder"/>

<TEXT TYPE Action="0" Text="%FolderPath%"/>

 

Edited by acantor
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
×
×
  • Create New...