AppleScript Mail Rule to Forward Message

I know Mail has the capability to create a rule to forward messages (I’m using that now), but using that capability does not allow me to edit the subject of the forwarded message. So I am trying to use AppleScript for that purpose. Here is my script so far, unfortunately it doesn’t work as intended:


using terms from application "Mail"
	on perform mail action with messages theMessages
		repeat with aMessage in theMessages
			try
				set theSubject to getMessageSubject(aMessage)
				set dateSent to getMessageDateSent(aMessage)
			end try
			set theSubject to dateSent & " " & theSubject
			forward aMessage as outgoing message to tom@gmail.com with properties (sender:"ken@gmail.com", subject:theSubject)
			send aMessage
		end repeat
	end perform mail action with messages
end using terms from

on getMessageSubject(aMessage)
	tell application "Mail" to return subject of aMessage
end getMessageSubject

on getMessageDateSent(aMessage)
	tell application "Mail" to return date sent of aMessage
end getMessageDateSent

The idea is to preface the original message subject with a date, make that the new subject, and forward the message.There seems to be something wrong or missing around line 9 or 10. Any assistance will be appreciated.

thanx

Shouldn’t there be curly braces rather than parentheses in that line? i.e. {properties:value} rather than ()?

Yes, probably… But I had tried that and still I couldn’t make it work. This is the script with the curly braces:


using terms from application "Mail"
   on perform mail action with messages theMessages
       repeat with aMessage in theMessages
           try
               set theSubject to getMessageSubject(aMessage)
               set dateSent to getMessageDateSent(aMessage)
           end try
           set theSubject to dateSent & " " & theSubject
           forward aMessage as outgoing message to "tom@gmail.com" with properties {sender:"ken@gmail.com", subject:theSubject}
           send aMessage
       end repeat
   end perform mail action with messages
end using terms from

on getMessageSubject(aMessage)
   tell application "Mail" to return subject of aMessage
end getMessageSubject

on getMessageDateSent(aMessage)
   tell application "Mail" to return date sent of aMessage
end getMessageDateSent

I hate (and I understate my feelings here) trying to script mail (or calendar) apps but… a couple of points:

The result of ‘forward’ is an outgoing message so you may want to edit that line.

You need to make ‘tom’ a recipient and set the recipient for the outgoing message. It won’t compile let alone work otherwise.

Try ‘with opening window’ on the ‘forward’ command. Here is an example that might give you some ideas, especially around preparing the outgoing message. Note that there is an extraneous double quote on line 3 which must be removed before the script will compile.

https://github.com/stacksjb/Mail-Forward-Applescript/blob/main/Mailforward

Finally, I might be mistaken here but I think that you will need to do more than ‘use’ terms from Mail and ‘tell’ it to process your messages. ‘using’ is more about enabling compilation outside of a tell statement than obviating the need for one.

Hi. You may want to perform a faux “forward” by creating a new message, which offers more editing flexibility. Parsed commands from the app’s dictionary should implicitly end wherever they belong, so there’s no need to separately address the app.

using terms from application "Mail"
	on perform mail action with messages theMessages
		repeat with aMessage in theMessages
			set {theSubject, dateSent} to {aMessage's subject, aMessage's date sent as rich text}
			tell (make outgoing message with properties {subject:(dateSent & " " & theSubject), content:"Look at this nonsense: " & aMessage's content, visible:true})
				make to recipient with properties {address:"address@domain.com"}
				--send --you can enable this, once you see the message is created properly
			end tell
		end repeat
	end perform mail action with messages
end using terms from

FWIW, I think that an outgoing message is an outgoing message, regardless of whether it is new or forwarded.

Marc Anthony’s method works but it does have the side effect of losing all of the original email’s metadata/headers. I guess it also won’t include any of the image/attachment content but perhaps that can be recreated as well.

You can adjust the fields of a forwarded message, like so:

			set sender to MsgSender
			set sentDate to (short date string of (get date sent of current_Message)) -- 2022-10-05
			set datedSubject to sentDate & space & subject -- 2022-10-05 The original subject
			set subject to datedSubject
			set my_recipient to make new to recipient at end of to recipients with properties {address:MsgRecipient}

If combined with the example referred to previously, it should meet the requirements.

NB The form of the short date string depends upon your date preferences.

While I sincerely appreciate the input, I must admit that I am seriously confused. Marc Anthony’s script worked fine… initially. However, I did want to use the “short date” format such as YYYY-MM-DD, so I tried to make that work. Then the script simply stopped working in the Mail rule. So I set the script back to Marc’s original and it still won’t work… at all. So I am seriously confused. Regardless, here is the script I tried to get working within a Mail Rule:


using terms from application "Mail"
	on perform mail action with messages theMessages
		repeat with aMessage in theMessages
			set {theSubject, dateSent} to {aMessage's subject, aMessage's date sent as rich text}
			set shortDateSent to (short date string of dateSent)
			set datedSubject to ShortDateSent & space & theSubject
			tell (make outgoing message with properties {subject:(datedSubject), content:"Look at this nonsense:" & space & aMessage's content, visible:true})
				make to recipient with properties {address:"test@gmail.com"}
				--send --you can enable this, once you see the message is created properly
			end tell
		end repeat
	end perform mail action with messages
end using terms from

As you can see I tried to use the suggestions provided by Mockman (thank you, sir). But as I mentioned above, I set the script back to Anthony’s original, which worked at first, but now also does not work???

Another thing is that I am a bit concerned by Mockman’s comment that attachments may not be included in the forwarded message. While I am not concerned with forwarding all the metadata and headers, attachments will be needed within the forwarded message.

Again, I am confused… Please help!

This worked for me. Your mileage….

using terms from application "Mail"
	on perform mail action with messages tMsgs -- for rule tsRul
		repeat with aMsg in tMsgs
			
			set fwdMsg to forward aMsg -- with opening window
			tell fwdMsg
				activate
				set sentDate to (short date string of (get date sent of aMsg))
				set datedSubject to sentDate & space & subject of aMsg
				set subject to datedSubject
				make new to recipient with properties {address:"destinationemailaddress"}
				-- send fwdMsg
			end tell
		end repeat
		
	end perform mail action with messages
end using terms from

A couple of comments…
‘for rule…’ seems optional but there might be some scenarios where it would be appropriate.
‘with opening window’ seems to be optional. Not sure when it would be necessary.
I’m not sure why but the destination address needs to be a text string rather than a variable.
Finally, getting the short date code doesn’t seem to work reliably (for me) except when explicitly requested as above.

Nothing I have written has come close to getting this Applescript to work. So I decided to do something simple. I wrote the following code to do nothing more than mark the incoming test message as having been read:


using terms from application "Mail"
	on perform mail action with messages theMessages for rule theRule
		tell application "Mail"
			repeat with eachMessage in theMessages
				set mark read to true
			end repeat
		end tell
	end perform mail action with messages
end using terms from

And… it doesn’t work.

If I set the rule to mark the message as read, that works fine. So I know the message is being seen by the rule. But Applescript doesn’t seem to work when called by a Mail rule. Not a least as I have studied and written.

Hi. I’m not certain if you’ve attempted to run my example code, as written, but using for rule the rule has resulted in malperformance for me in past forays into scripting Mail, so I would comment that out, especially as there’s nothing in the code that utilizes the rule anyway. As version-specific gremlins may be at play, it also helps to know more about the OS environment you’re using. If this is later than Mojave, there may be new bugs.

Thanx Marc… Actually, concerning the for rule the rule thing, I did try it both ways with same result… That is it simply doesn’t work.

As for versions, I am running Macos Monterey version 12.6 and Mail application version 16.0 (3696.120.41.1.1)

Thanx again for your comments. I am seriously thinking that there must be a bug running Applescripts in the rules of mail application.

Hello, again. Looking more closely at what you last wrote, the command “mark read” actually goes to the rule. I think you want “read status,” which is a message property, and you’d direct the command to eachMessage.

tell application "Mail"
	repeat with eachMessage in in theMessages
		set eachMessage's read status to true
	end repeat
end tell

Using mark read property makes sense only when creating the rule programatically. Once, without using repeat loops. Manually, you go to Preferences, select the rule to edit, add mark read action. It will work automatically without using repeat loops as well.

In short: the script needs to be added to the rule only for those actions that are not in the ready set of actions.

After several days work I finally got the script upon which I was working operational. I would like to thank everyone for the reply(s). They were very helpful.

Because it is now operating as intended, I thought I would take a few minutes and let members know what I did.

As I found it quite difficult to analyze and debug the script while it was being called from a Mac Mail rule, I decided to write the code to function on selected mail messages. Accordingly I wrote and debugged the following script:

Open this Scriplet in your Editor:


tell application "Mail"
   set theMessages to the selection
   repeat with aMessage in theMessages
       set forwardMessage to forward aMessage with opening window
       tell forwardMessage
           activate
           set dateReceived to (get date received of aMessage)
           set {year:y, month:m, day:d} to dateToConvert
           tell (y * 10000 + m * 100 + d) as string to rich text 1 thru 4 & "-" & rich text 5 thru 6 & "-" & rich text 7 thru 8
           set datedSubject to dateReceived & space & subject of aMessage
           set subject to datedSubject as rich text
           set sender to "<ken@gmail.com>"
           set myRecipient to make new to recipient at end of to recipients with properties {address:"<test@gmail.com>"}
           send forwardMessage
       end tell
   end repeat
end tell

Then it became a simple matter of altering the code to function from a Mail rule by commenting out line two, adding two lines of code to the beginning and end of the script. Now the script looks like this and functions being called from a Mail rule:

Open this Scriplet in your Editor:


using terms from application "Mail"
   on perform mail action with messages theMessages
       tell application "Mail"
           --set theMessages to the selection
           repeat with aMessage in theMessages
               set forwardMessage to forward aMessage with opening window
               tell forwardMessage
                   activate
                   set dateReceived to (get date received of aMessage)
                   tell script file "ConvertDate" to set dateReceived to my convertDate(dateReceived)
                   set datedSubject to dateReceived & space & subject of aMessage
                   set subject to datedSubject as rich text
                   set sender to "<ken@gmail.com>"
                   set myRecipient to make new to recipient at end of to recipients with properties {address:"<test@gmail.com>"}
                   send forwardMessage
               end tell
           end repeat
       end tell
   end perform mail action with messages
end using terms from

on convertDate(dateToConvert)
   set {year:y, month:m, day:d} to dateToConvert
   tell (y * 10000 + m * 100 + d) as string to text 1 thru 4 & "-" & text 5 thru 6 & "-" & text 7 thru 8
end convertDate