Keeping sort order in writing contents of selected mail to a file

I would like to write a selection of mail messages to a file.

The messages are all contained in a separate folder and they are sorted in date order (Sort By/Newest Message on Top) and not “Organise by conversation”. The folder contains emails sent and received.

I select all the mails in that folder and run the following script, but the emails are not organised by date in the resulting file.

For example, if the emails containing emails with the following dates (and sorted in that order):

25/02/2022
28/02/2022
28/02/2022
28/02/2022
28/02/2022
02/03/2022
02/03/2022
04/03/2022
04/03/2022

The resulting file from the script produces the following:

28/02/2022
28/02/2022
28/02/2022
04/03/2022
25/02/2022
02/03/2022
04/03/2022
02/03/2022
28/02/2022

Is it possible to save the files sorted by date order?

Any help would be gratefully received.

The AppleScript:

set myData to ""
tell application "Mail"
	
	-- set selection of mail
	set theMessages to the selection
	
	--	extract data from selected mail
	repeat with aMessage in theMessages
		-- set mySrc to (extract name from sender)
		
		-- set mySrc to (extract name from sender of aMessage)
		set theSName to (extract name from sender of aMessage)
		set theSAddress to (extract address from sender of aMessage)
		set theDate to date sent of aMessage
		set theDateReceived to date received of aMessage
		set theRName to the (name of first to recipient of aMessage)
		set theRAddress to the (address of the first to recipient of aMessage)
		set theMessage to the content of aMessage
		
		set SFirstName to first word of theSName
		set SLastName to word -1 of theSName
		
		set vDate to (day of theDateReceived) & " " & (month of theDateReceived) & " " & (year of theDateReceived)
		
		set vTime to the time string of theDateReceived
		
		
		set myData to myData & return & ¬
			"## *Date*: " & vDate & " at: " & vTime & return & return & ¬
			"### *From*: " & SFirstName & " " & SLastName & " (" & theSAddress & ") ⸺ " & return & ¬
			"### *To*: " & theRName & " (" & theRAddress & ¬
			")" & return & return & return & ¬
			"### *Content of message*: " & return & return & theMessage & return & return & "_________________________________" & return
	end repeat
end tell

-- set destination folder and file name for data written (in myData)
set filepath to (path to desktop as string) & "mail.txt"


-- write data in variable myDat to file 
try
	set openfile to open for access file filepath with write permission
	
	write myData to openfile
	
	close access openfile
on error
	try
		close access file filepath
	end try
end try

macOS 12.2 - Mail, version : 15.0 (3693.60.0.1.1)

Model: iMac
AppleScript: 2.11
Browser: Safari 605.1.15
Operating System: macOS 12

Hello,

For an unknown reason it seems thet calling a selection of messages doesn’t return them sorted.
put this log in the script
< log theMessages > and lok at it

For example, in same arragement as yours I get for the list of message’s id
{8257, 8255, 8253, 8251, 8256, 8254, 8252}
With 8251 the older and 8257 the most recent

So my idea is that you should first retreive the IDs, sort them and after call the messages one by one corresponding to ID’s sorted list.

Hope this helps
JB

This is a way to sort the fetched selection in date descending order


tell application "Mail"
	set theMessages to the selection
	set IDList to {}
	set dateSentList to {}
	repeat with aMessage in theMessages
		copy aMessage's date sent to the end of dateSentList
		--copy aMessage's id to the end of IDList -- if you prefer to sort by «IDs» instead of «date sent»
	end repeat
end tell

set MsgDates to (sortinglist(dateSentList))
--set IDList to reverse of (sortinglist(IDList)) -- if you prefer to sort by «IDs» instead of «date sent»

set orderedMessages to {}

tell application "Mail" -- to put selected mails in date descending order
	repeat with aDate in MsgDates
		repeat with i from 1 to count items in MsgDates
			if (date sent of item i of theMessages) as date = aDate as date then
				copy (item i of theMessages) to the end of orderedMessages
				exit repeat
			end if
		end repeat
		log orderedMessages
	end repeat
end tell

return orderedMessages

on sortinglist(listIn) -- inspiré de l'algorithme QuickSort
	if (count item in listIn) = 0 then return {}
	set thepivot to (first item of listIn)
	set head to {}
	set tail to {}
	considering numeric strings
		repeat with i from 2 to length of listIn
			set tempItem to item i of listIn
			if tempItem ≤ thepivot then
				set the beginning of head to (tempItem)
			else
				set the end of tail to (tempItem)
			end if
			if i = (count item in listIn) then
				if (count items in head) > 1 then
					set head to sortinglist(head)
				end if
				if (count items in tail) > 1 then
					set tail to sortinglist(tail)
				end if
			end if
		end repeat
	end considering
	return (head & thepivot & tail) as list
end sortinglist

with the right ordered list you can apply your own script of writing a text file

HTH,
J. B.

Hi. Mail’s viewer changes the data’s display, rather than enforcing a sort against it. As you state you’re using a whole folder—i.e. a mailbox—just get its contents; it should already be sorted by arrival time. This is an abbreviated version for testing.

set aList to {}
tell application "Mail"
	repeat with this in mailbox "TEST"'s messages --adjust to your folder's name, asssumed at root level and not sub-account
		tell this's sender to set {xtracNom, xtracAddr} to {extract name from it, extract address from it}
		set aList's end to this's {date received, to recipient 1's name, to recipient 1's address, date sent} & {xtracNom's word 1, xtracAddr's word -1} & return
	end repeat
end tell
set text item delimiters to return
tell application "Finder" to set isTarget to (make file) as alias
write (aList as text) to isTarget
set text item delimiters to ""

Joseph and Marc Anthony

Thank you both for your responses.

My knowledge of AppleScript is very basic so would really appreciate a little more help.

Joseph,

I can (sort of) understand your script, but I have not sure how I can apply it to write some of the data from the emails to a file.

Marc Anthony,

You mention

repeat with this in mailbox "TEST"'s messages --adjust to your folder's name, asssumed at root level and not sub-account

Is it possible to target a subfolder.

I have various accounts:

  1. exchange
  2. xxx@yyy.com
  3. aaa@bbb.org.uk

If I wished to target for example the mailbox called Exchange, which has the folder structure underneath:

is it possible to target the subfolder “2022_001 (xxx)” with your code?

Any further help would be gratefully received.

Hi. Something like below could replace that line
[format] repeat with this in account “exchange”'s mailbox 1 whose name is “2022_001 (xxx)”
[/format]

Or you could iterate through respective mailboxes, if the subfolder is common.

tell application "Mail" to repeat with anAcct in {"exchange", "xxx@yyy.com", "aaa@bbb.org.uk"}
	repeat with this in (account anAcct's mailbox 1 whose name begins with "2022_")
		--insert commands to do things with this's messages
	end repeat
end repeat

Hi.

I don’t know how it works in Mail, but I’m guessing it would be more efficient to resolve that reference with a ‘get’, otherwise it might have to happen behind the scenes every time round the repeat for every instruction involving ‘this’.

repeat with this in (get account anAcct's mailbox 1 whose name begins with "2022_")

I haven’t tested the explicit get in Mail; you’re probably right, although the iterative scale—and therefore the potential benefit—is unspecified.