I'm sending out a whole bunch of individual text messaged using AppleScript on a MacBook laptop linked to an iPhone.
If I create a message, copy paste it manually into Messages, and send that out manually, one message at a time (copy paste message, copy paste phone number, send) things works just fine. I can easily format the message in my draft, and the formatting is retained. If I try to do this via script, the linefeeds get lost.
Desired message:
Hello Everybody,
This is going to be a special meeting taking place on Friday, 10AM.
Please call in to the group meeting, access line xxxxxxxxxxx
Topic of Discussion: Quarterly Sales.
Great Job everybody, Sales are thru the roof this quarter; We're all
getting pay raises, yippee. Details shared at the meeting.
Again, thanks to all
Susan,
Sales Manager
And this is how it arrives.
Hello Everybody,This is going to be a special meeting taking place on
Friday, 10AM. Please call in to the group meeting, access line
xxxxxxxxxxxTopic of Discussion: Quarterly Sales. Great Job everybody,
Sales are thru the roof this quarter; We're all getting pay raises,
yippee. Details shared at the meeting. Again, thanks to all Susan,
Sales Manager
And here is the appleScript:
set textMessage to "Hello Everybody,\n\nThis is going to be a special meeting taking place
on Friday, 10AM. Please call in to the group meeting, access line xxxxxxxxxxx\n\nTopic
of Discussion: Quarterly Sales. \n\nGreat Job everybody, Sales are thru the roof this
quarter; We're all getting pay raises, yippee. Details shared at the meeting.
\n\nAgain, thanks to all \n\nSusan, \nSales Manager\n"
set phonelist to {"1999-555-6850", "1999-555-9496", "1999-555-7170", "1999-555-4445",
"1999-555-1182", "1999-555-7463", "1999-555-1809", "1999-555-8916", "1999-555-5139",
"1999-555-5252", "1999-555-6646", "1999-555-3642", "1999-555-2437", "1999-555-0755",
"1999-555-8732", "1999-555-6202", "1999-555-0310", "1999-555-7410", "1999-555-3300",
"1999-555-0655"}
set i to 0
activate application "Messages"
tell application "System Events" to tell process "Messages"
repeat with indPhone in phonelist
set i to i + 1
key code 45 using command down -- press Command + N to start a new window
keystroke indPhone -- input the phone number
delay 1
key code 36
key code 36 -- press Enter to focus on the message area
keystroke textMessage -- type some message
delay 1
key code 36 -- press Enter to send
say i
delay 5 -- Audio plus delay = success tracking.
-- If for some reason something goes wrong, I know where I am.
-- e.g. phone rings during the process.
end repeat
end tell
Note: reference.
Note#2. Oh, and note this isn't the actual message being sent. It's just a contrived sample for StackOverflow. This audience receiving the messages just doesn't understand what happens when someone replies to a group message. They just don't get it, sigh. So no, group text pages are NOT the answer. We want individual text messages, one per person. But thanks for that suggestion. Typically we're sending out just less than 100 messages with this technique, at one time.
Any thoughts on why we're losing the \n formatting when this runs as a script? If you run this exact script on your Mac, do you see the same results?
Edit: I'm going to share some screen shots off the phone.
What I want (created via manual copy & paste into Messages app):
Here's what I get with the script above (/n/n):
And here's what I get with the RobC & return & technique. (See comments)
Just dealing with the 'newline' problem... To get an inline carriage return you need to type control-return. To accomplish that with AppleScript, break the textMessage variable up into a list of paragraphs, then keystroke in each paragraph followed by key code 36 using control down to make the paragraph break.
set textMessageParts to {"Hello Everybody,", "", "This is going to be a special meeting taking place on Friday, 10AM. Please call in to the group meeting, access line xxxxxxxxxxx", "", "Topic of Discussion: Quarterly Sales.", "", "Great Job everybody, Sales are thru the roof this quarter; We're all getting pay raises, yippee. Details shared at the meeting. ", "", "Again, thanks to all", "", "Susan,", "Sales Manager"}
-- empty strings are added above to make two sequential line breaks
set phonelist to {"1999-555-6850", "1999-555-9496", "1999-555-7170", "1999-555-4445", "1999-555-1182", "1999-555-7463", "1999-555-1809", "1999-555-8916", "1999-555-5139", "1999-555-5252", "1999-555-6646", "1999-555-3642", "1999-555-2437", "1999-555-0755", "1999-555-8732", "1999-555-6202", "1999-555-0310", "1999-555-7410", "1999-555-3300", "1999-555-0655"}
set i to 0
activate application "Messages"
tell application "System Events" to tell process "Messages"
repeat with indPhone in phonelist
set i to i + 1
keystroke "n" using command down -- press Command + N to start a new window
keystroke indPhone -- input the phone number
delay 1
key code 36
key code 36 -- press Enter to focus on the message area
repeat with thisPara in textMessageParts
keystroke thisPara -- type one paragraph from the list
key code 36 using control down -- type an inline line break
end repeat
delay 1
key code 36 -- press Enter to send
say i
delay 5 -- Audio plus delay = success tracking.
-- If for some reason something goes wrong, I know where I am.
-- e.g. phone rings during the process.
end repeat
end tell
This code works (partially adapted from here):
set textMessage to "Hello Everybody,\n\nThis is going to be a special meeting taking place
on Friday, 10AM. Please call in to the group meeting, access line xxxxxxxxxxx\n\nTopic
of Discussion: Quarterly Sales. \n\nGreat Job everybody, Sales are thru the roof this
quarter; We're all getting pay raises, yippee. Details shared at the meeting.
\n\nAgain, thanks to all \n\nSusan, \nSales Manager\n"
set phonelist to {"1999-555-6850", "1999-555-9496", "1999-555-7170", "1999-555-4445",
"1999-555-1182", "1999-555-7463", "1999-555-1809", "1999-555-8916", "1999-555-5139",
"1999-555-5252", "1999-555-6646", "1999-555-3642", "1999-555-2437", "1999-555-0755",
"1999-555-8732", "1999-555-6202", "1999-555-0310", "1999-555-7410", "1999-555-3300",
"1999-555-0655"}
repeat with indPhone in phonelist
tell application "Messages"
set targetService to (id of 1st service whose service type = iMessage)
set theBuddy to buddy ("+1" & indPhone) of service id targetService
send textMessage to theBuddy
end tell
end repeat
So it turns out when I upgraded the macOS to Big Sur version 11.0.1 the script provided by Ted Wrigley crashed. Here is a corrected version, ready for copy paste.
set textMessageParts to {"Hello Everybody,", "", "This is going to be a special meeting taking place on Friday, 10AM. Please call in to the group meeting, access line xxxxxxxxxxx", "", "Topic of Discussion: Quarterly Sales.", "", "Great Job everybody, Sales are thru the roof this quarter; We're all getting pay raises, yippee. Details shared at the meeting. ", "", "Again, thanks to all", "", "Susan,", "Sales Manager"}
-- empty strings are added above to make two sequential line breaks
set phonelist to {"1999-555-6850", "1999-555-9496", "1999-555-7170", "1999-555-4445", "1999-555-1182", "1999-555-7463", "1999-555-1809", "1999-555-8916", "1999-555-5139", "1999-555-5252", "1999-555-6646", "1999-555-3642", "1999-555-2437", "1999-555-0755", "1999-555-8732", "1999-555-6202", "1999-555-0310", "1999-555-7410", "1999-555-3300", "1999-555-0655"}
set i to 0
activate application "Messages"
tell application "System Events" to tell process "Messages"
repeat with indPhone in phonelist
set i to i + 1
keystroke "n" using command down -- press Command + N to start a new window
delay 1
keystroke indPhone -- input the phone number
delay 1
key code 36
key code 36 -- press Enter twice to focus on the message area
repeat with thisPara in textMessageParts
keystroke thisPara -- paste one paragraph from the list
key code 36 using shift down -- insert an inline line break
end repeat
delay 1
key code 36 using command down -- press Command Enter to Send
log ("SMS completed: " & indPhone) -- Text completed to this phone #
say i -- audible progress feedback
delay 3 -- Delay to provide an opportunity to stop the script here.
-- If for some reason something goes wrong, I know where I am.
-- e.g. phone rings during the process.
end repeat
end tell
I wanted to add a few lessons learned in fixing this thing:
The log is probably a better way to track progress than an audio clue. You do have to make the log area visible in the Script Editor via top menu --> View --> Show Log. You will want to be in the "Messages Tab" to see the log entries.
key code {57, 36} is not the same as key code 36 using shift down. Not sure what's up with that. One method works, one does not.
Before you start the script / macro you need to ensure Messages is open and running on the MacOS.
You don't want to start the macro while Messages is half way complete with a previous message. Odd things happen.
Stopping the program while the macro is running is problematic. If you are stopping the action during the middle of a paste operation, the content intended for the Messages ends up pasted in the middle of the Script Editor. That was a total mess. If you must stop, ensure you haven't corrupted your original script.
For really long lists of phone numbers, you may need to use "option L" at end of each line as continuation character (¬) per S.O.63927015
Many thanks to Ted Wrigley for his input on the original question.
So, I finally got tired of manually sorting and archiving email on my Mac to get around some archaic mailbox size limits. I'm not a fan of the way Apple handles mail archiving, so I dug into a few examples that others had written to sort mail and slapped a short script together to filter through my email and archive everything older than 90 days. For the most part, easy stuff.
It is a tad annoying that Mail doesn't see "On My Mac" as a local account, so you need to adjust the code to blindly reference mailbox names.. but.. it works.
I think I'm just having an evaluation problem. I can sort the "Inbox" and archive mail from there quite easily.
on archive_email(target_account, target_mailbox, destination_account, destination_mailbox, oldemaildate)
tell application "Mail"
#Identify messages that need to be moved. If unread messages shouldn't be moved, change the end of the variable definition to read "is less than oldsentdate and read status is true)
set _msgs_to_capture to (every message of mailbox target_mailbox of account target_account whose date received is less than oldemaildate)
repeat with eachMessage in _msgs_to_capture
set archiveMailbox to (mailbox (destination_mailbox as string))
move eachMessage to archiveMailbox
end repeat
end archive_email
This doesn't work for the "Sent" folder, however. My guess is that the evaluation "whose date received is less than" is improper for the "sent" folder. Sadly, "whose date sent is..." doesn't seem to work either. I'm struggling to find the right variable and evaluation here.
The line bellow is perfectly working, assuming target_account and oldmaildate have correct values. To be sure, I replaced target_mailbox directly by "Sent Messages" :
set _msgs_to_capture to every message of mailbox "Sent Messages" of target_account whose date sent is less than oldemaildate
Please check values/types of your variables.
Also, I suggest you set the line below before the repeat loop and not inside, to increase speed :
set archiveMailbox to (mailbox (destination_mailbox as string))
You can do away with the repeat loop, which is inefficient, and achieve the move with a single command:
on archive_email(target_account as text, target_mailbox as text, ¬
destination_account as text, destination_mailbox as text, ¬
oldemaildate as date)
tell application "Mail" to ¬
move (every message ¬
of mailbox target_mailbox ¬
of account target_account ¬
whose date sent ¬
is less than oldemaildate) ¬
to mailbox destination_mailbox
end archive_email
Use date sent for Sent items, which I can confirm works.
System info: AppleScript version: "2.7", system version: "10.13.4"
Is there any way to get the last sent e-mail from Mail?
It can only access the top level sent mailbox.
tell application "Mail"
set mabo to the sent mailbox
set selected to messages of mabo
return properties of item 1 of selected
end tell
The reason I need this is that I want to get information about the e-mail that is beeing written. My thought was to get the frontmost window.
tell application "Mail"
set the win to windows
set theMessage to item 1 of win
get name of theMessage
end tell
It is working for the name but I do not get the sender or receipient. Any ideas?
As said, you just have to loop through each account, and each time, compare the date of the email with previous email date from other account.
here is the script : (I also add a test in case the sent box of one account is empty !)
tell application "Mail"
set LastDate to date "samedi 1 janvier 2000 00:00:00"
set {myLastMail, myAccount, myDate} to {"", "", LastDate}
repeat with CAccount in every account
if (count of every message in mailbox "Sent Messages" of CAccount) > 0 then
set X to first message of mailbox "Sent Messages" of CAccount
set MDate to date sent of X
if MDate > LastDate then
set LastDate to MDate
set {myLastMail, myAccount, myDate} to {X, CAccount, LastDate}
end if
end if
end repeat
-- the last email from all your accounts is the variables Mylastemail, in account MyAccount and at the date MyDate
end tell
Unfortunately the messages in the sent mailbox are unsorted in the AppleScript array.
You can use this code, but it could take a while depending on the number of messages in the mailbox (ca. 30 sec for 1000 messages).
tell application "Mail"
set sentMessages to messages of sent mailbox
set lastestMessage to item 1 of sentMessages
set latestDate to date received of lastestMessage
repeat with aMessage in sentMessages
if date received of contents of aMessage comes after latestDate then
copy contents of aMessage to lastestMessage
set latestDate to date received of lastestMessage
end if
end repeat
tell lastestMessage
set theSender to sender
set theRecipient to 1st recipient
end tell
end tell
The code bellow uses to work for me in all my Mail versions up to 4.6 (Snow Leopard). To be tested on later versions. Strangely, "last message" gives the oldest message in the mailbox and the "first message" gives the last message sent or received ! if you have many accounts, just loop on accounts names :
tell application "Mail"
-- to get the last message sent
set X to first message of mailbox "Sent Messages" of account "your_account_name"
-- to get the oldest message received in receiving box
set X to last message of mailbox "INBOX" of account "your_account_name"
open X --if want to see it
end tell
I have the below Applescript for Outlook 2011 (at bottom). I'm trying to move Inbox messages older than four months to the "on my computer" folder (on my computer of application).
When I run the script, this line always seems to return true, so it archives every message:
if time received of msg > (current date) - 4 * (4 * weeks) then
I'm posing this Nov 5, and the oldest messages in my inbox are Sep 1, so this if statement should not trigger.
Here is the Events log of a sample run:
tell application "Microsoft Outlook"
activate
get every message of inbox
count every message of inbox
current date
end tell
tell current application
current date
end tell
tell application "Microsoft Outlook"
get time received of item 1 of every message of inbox
(*time received of item 1 of every message of inbox*)
move item 1 of every message of inbox to on my computer
current date
end tell
tell current application
current date
end tell
tell application "Microsoft Outlook"
get time received of item 2 of every message of inbox
(*time received of item 2 of every message of inbox*)
move item 2 of every message of inbox to on my computer
current date
end tell
tell current application
current date
end tell
tell application "Microsoft Outlook"
get time received of item 3 of every message of inbox
(*time received of item 3 of every message of inbox*)
move item 3 of every message of inbox to on my computer
Full script:
tell application "Microsoft Outlook"
activate
if messages of inbox = {} then
error "No messages."
error -128
end if
repeat with msg in messages of inbox
if time received of msg > (current date) - 4 * (4 * weeks) then
move msg to on my computer
end if
end repeat
end tell
4 * (4 * weeks) is 4 months ago from Nov 5th, so that's about July 5th. If your time of message is Sept 1 then it surely will trigger it because Sept 1 is greater than July 5. Maybe you meant to use the less than (i.e. <) sign?
I am fairly new to Applescript. Even though the language itself is not hard to grasp, some commands are hard to find (For example for "Mail").
What I am trying to achieve is open "Mail" on my computer and select most recent 5 emails and open them in windows. I was able to open windows but the script I had was for "every" email in the mailbox.
The line I used was this.
set myMessages to every message of myInbox
What do I have to put instead of every message to open only a given number, lets say 5?
Getting every message of the inbox before you refine the list to the first five slows the script down. Ask for the first five of the the inbox.
tell application "Mail"
set myMessages to messages 1 through 5 of inbox
repeat with aMesseage in myMessages
open (contents of aMesseage)
end repeat
end tell
EDIT:
set myMessages to messages 1 through 5 of inbox whose read status = false
Try next:
set myMessages to every message of myInbox
set subList to items 1 through 5 of myMessages
See AppleScript list manipulation for details
Mails in list probably will be ordered (ASC or DESC). So you need first five or last five. For the last five you should also use list size from the link above.