I have a script that I'm using to automate a small workflow but I am stuck trying to get the Subject to list the current month.
Here is my script:
tell application "Finder" to set selectedItem to item 1 of (get selection)
set theAttachment to selectedItem as alias
set fileName to name of selectedItem
tell application "Microsoft Outlook"
set newMessage to make new outgoing message with properties {subject:"(current month) as string Message from John Doe"}
tell newMessage
make new attachment with properties {file:theAttachment}
end tell
open newMessage
get newMessage
end tell
Is this possible? I've tried searching online and in Script Debugger but I keep coming up short. Thanks in advance.
I don't use Microsoft Outlook, so I'm going to assume that your script executes without error, but simply produces an undesired result, namely an new outgoing email with the words "(current month) as string Message from John Doe" in the subject line.
On this basis, to get your subject line to contain only the current month, find the relevant line in your script that contains this:
{subject:"(current month) as string Message from John Doe"}
and replace it with this
{subject:(current date)'s month as text}
If you want the subject line to include additional text after the month, as your original script does, then you can instead replace it with this:
{subject:((current date)'s month as text) & " Message from John Doe"}
Related
I'm new to Applescript and I've built this from code I've found online, and can't really get it to work.
What I want to do is the following
A rule in Apple Mail will trigger the script to find 2 text strings inside the body of the mail.
I want to extract two things from the e-mail
Due date (Återlämningsdatum)
Title of the book (Titel)
Then I want to create a todo in Things with the title of the book as name of the todo and the due date as due date.
The problem I run into now is that I don't get any data from the mail, just a empty todo is created.
Any ideas?
E-mail below
2017-03-22 18:43:55
MALMÖ STADSBIBLIOTEK
Stadsbiblioteket
Låntagarnummer: **********
Utlån
-------------------------
Titel: Ägg : recept & teknik / Tove Nilsson ; [fotografi: Charlie Drevstam]
Exemplarnummer: 3054550018
Återlämningsdatum: 2017-04-19
-------------------------
Antal utlånade material: 1
Code below
use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions
set subjectText to "Återlämningsdatum: "
set contentSearch to "Titel: "
using terms from application "Mail"
on perform mail action with messages theMessages for rule theRule
tell application "Mail"
set theContent to content
set theDate to my getFirstWordAfterSearchText(subjectText, theContent)
set theTitle to my getFirstWordAfterSearchText(contentSearch, theContent)
end tell
end perform mail action with messages
end using terms from
tell application "Things3"
set newToDo to make new to do
set name of newToDo to theTitle
set due date of newToDo to theDate
end tell
(*============== SUBROUTINES =================*)
on getFirstWordAfterSearchText(searchString, theText)
try
set {tids, AppleScript's text item delimiters} to {AppleScript's text item delimiters, searchString}
set textItems to text items of theText
set AppleScript's text item delimiters to tids
return (first word of (item 2 of textItems))
on error theError
return ""
end try
end getFirstWordAfterSearchText
In my testing, your script returns the following values:
theDate: "2017"
theTitle: "Ägg"
So, I'm assuming you should perhaps get a blank to-do named "Ägg" ? If not, you could try:
tell application "Things3" to make new to do with properties ¬
{name: theTitle, due date: theDate}
(although I neither use nor own Things 3, so cannot test this for you).
Anyway, to address the original problem, the issue is in only asking your handler getFirstWordAfterSearchText to return the first word. I don't speak Swedish, but it looks to me that the title contains more than one word. The date most definitely does, as each word is separated by a hyphen (which is considered a non-word character in AppleScript).
My suggestion would be to split the email content into paragraphs, isolate the lines of text that start with either "Titel" or "Återlämningsdatum", then return those lines, excluding any unwanted words. Here's a handler that does this:
to getFirstParagraphThatStarts on searchString ¬
from theText ¬
apart from excludedStrings : null
local searchString, theText, excludedStrings
repeat with P in theText's paragraphs
if P starts with the searchString then exit repeat
end repeat
set the text item delimiters to {null} & the excludedStrings
text items of P as text
end getFirstParagraphThatStarts
I called the handler much like you did yours:
set theDate to getFirstParagraphThatStarts on subjectText from theContent
set theTitle to getFirstParagraphThatStarts on contentSearch from theContent
(I omitted the apart from parameter to begin with, to test the return result before any exclusions were imposed). The return result was this:
theDate: "Återlämningsdatum: 2017-04-19"
theTitle: "Titel: Ägg : recept & teknik / Tove Nilsson ; [fotografi: Charlie Drevstam]"
Then I added in the apart from parameter:
set theDate ¬
to getFirstParagraphThatStarts on subjectText ¬
from theContent ¬
apart from subjectText
set theTitle ¬
to getFirstParagraphThatStarts on contentSearch ¬
from theContent ¬
apart from contentSearch
and the return results were as follows:
theDate: "2017-04-19"
theTitle: "Ägg : recept & teknik / Tove Nilsson ; [fotografi: Charlie Drevstam]"
which, I think, is more along the lines of what you are wanting.
ADDENDUM 1: Dates
Another thought I had regarding Things 3 is that the due date property might require an actual AppleScript date object, rather than just a string that looks like it might be a date. That is, "2017-04-19" might not be a valid due date. Again, I neither use nor own Things 3, so this is just speculation.
AppleScript date formats are intrinsically tied to your system settings. As I have my system date/time preferences set to use international ISO-8601 date representations, i.e. yyyy-mm-dd, I can create the AppleScript date object straight from theDate variable like so:
date theDate
If this is the case with you, and it turns out that you do require a date object, then you can simply set due date of newToDo to date theDate, or (if using my suggested code from above):
tell application "Things3" to make new to do with properties ¬
{name: theTitle, due date: date theDate}
If, however, your system settings are set differently, you'll need to construct the AppleScript date object yourself. Here's a handler that will do this:
to makeASdate out of {year:y, month:m, day:d}
local y, m, d
tell (the current date) to set ¬
[ASdate, year, its month, day, time] to ¬
[it, y, m, d, 0]
ASdate
end makeASdate
You would then use your theDate variable with this handler like so:
makeASdate out of {year:word 1, month:word 2, day:word 3} of theDate
--> date "Wednesday, 19 April 2017 at 0:00:00"
ADDENDUM 2: Scripting Mail (added 2018-08-12)
After further testing and debugging, you've found that there are other issues with your script that stop it from functioning. This was an oversight on my part, as I ought to have highlighted these errors initially, but became focussed on your handler returning incomplete strings that I neglected to come back to the rest of the script and address its other problems.
The problem section, as you've discerned, is this one here:
using terms from application "Mail"
on perform mail action with messages theMessages for rule theRule
tell application "Mail"
set theContent to content
set theDate to my getFirstWordAfterSearchText(subjectText, theContent)
set theTitle to my getFirstWordAfterSearchText(contentSearch, theContent)
end tell
end perform mail action with messages
end using terms from
You tell application "Mail" to set theContent to content, however, you haven't specified what the content belongs to (or, rather, implicitly, you've specified that the content belongs to application "Mail", which it doesn't).
Presumably, you wish to refer to the content of theMessages that are sent through to this script by your mail rules ?
The other major thing to note is that on perform mail action with messages is an event handler, i.e. it responds to an event taking place in Mail, which causes the handler to be invoked. Defining other handlers elsewhere in the script is perfectly fine; but having stray lines of code that don't belong to any explicit handler will therefore belong to an implicit (hidden) on run handler. This, in a way, is an event handler as well: it responds to a script being run, which is problematic if the script is also being asked to respond to a Mail event simultaneously.
Therefore, the tell app "Things3" block needs to be moved, and I imagine the variable declarations at the beginning need to be housed as well.
Bearing all this in mind, I reworked your script to quite a large extent, whilst also trying to keep it resembling your original so it was somewhat recognisable:
using terms from application "Mail"
on perform mail action with messages theMessages for rule theRule
set dateToken to "Återlämningsdatum: "
set titleToken to "Titel: "
repeat with M in theMessages
set theContent to getMessageContent for M
set datum to restOfLineMatchedAtStart by dateToken from theContent
set titel to restOfLineMatchedAtStart by titleToken from theContent
if false is not in [datum, titel] then
set D to makeASdate out of (datum's words as list)
createToDoWithDueDate on D given name:titel
end if
end repeat
end perform mail action with messages
end using terms from
to makeASdate out of {Y, M, D}
local Y, M, D
tell (the current date) to set ¬
[ASdate, year, its month, day, time] to ¬
[it, Y, M, D, 0]
ASdate
end makeASdate
to createToDoWithDueDate on D as date given name:N as text
tell application "Things3" to make new to do ¬
with properties {name:N, due date:D}
end createToDoWithDueDate
to getMessageContent for msg
local msg
tell application "Mail" to return msg's content
end getMessageContent
on restOfLineMatchedAtStart by searchString from theText
local searchString, theText
ignoring white space
repeat with P in theText's paragraphs
if P starts with the searchString then
set i to (length of searchString) + (offset of searchString in P)
try
return text i thru -1 of P
on error -- matched entire line
return ""
end try
end if
end repeat
end ignoring
false -- no match
end restOfLineMatchedAtStart
Now, as I don't use Mail and cannot test these mail rules out myself, there could be one or two minor tweaks that you'll discover need to be made before it's running properly. On the other hand, it might run correctly as it is, which would amaze me. But, having spent a lot of time thinking about each line of code, I'm hopeful it's close to what you need.
The major change you can see is that every piece of code now belongs inside a handler. The custom handlers each get called from inside the main event handler, on perform mail action with messages. I also changed some of the variable names, mainly as part of my mental debugging that was going on (I changed them several times, and have left them to what their last meaningful label was in my head).
Let me know how it goes. Report back any errors.
NOTE: Don't forget, however, that this script is designed to be called by the Mail application in response to a mail rule being actioned. Running it from within Script Editor will not do anything.
I am trying to send attachments via Mail App and have a list of file names without extension in the source text file. Each line will be looped until all lines in the text file finished.
How do I make a path for the attachment using looped lines of the source text and add the extension to the end?
This is what I use to read the lines from the text file and loop them
set lns to paragraphs of (read file srcFile as «class utf8»)
repeat with ln in lns
This is what the send attachment part of the script look
set theAttachmentFile to "Macintosh HD:Users:attachmentfolder" + ln + ".pdf"
The above is not working.
Thanks!
If your text file contains only file name without path and extension, I assume that the folder path where these files are stored is known before in the script: correct ?
About extension, it is much easier to store it also in the text file for 2 reasons : if you don't, you need to get every file whose name contains "xxx", and cross your fingers that you find one an only one file. if there are 2 files with same title but different extension...you can't select !
The script for creating new email and add attachment should be :
Tell Application "Mail"
Set newMessage to make new outgoing message with properties {visible:true, subject:My_Subject, content:My_Content}
tell newMessage
make new to recipient at end of to recipients with properties {name:"", address:send_to_addr}
make new attachment with properties {file name:TheAttachmentFile} at after the last paragraph
end tell
end tell
I use a google account, say myaccount#google.com for work and I use aliases for the various projects I'm working on. Thus, for project1, I use myaccount+projet1#google.com, for project2 myaccount+projet2#google.com and so on. I do not need to add additional account in Mail since GMail ignores what's after the "+" sign.
Now, in the configuration of my mail account, I put all the addresses (including the ones with aliases) in the "Email address" field, separated by commas. So I can send a message from any of my emails myaccount+project*#google.com.
My question is about the "reply-to" header that I have to manually choose in order to receive the mail in the right folder. I looked in the settings and could not find a solution. Do you know any way to do it automatically (set the reply-to header the same as the from)? Apple script perhaps?
I know that I can use the "default write" command but that only allows to specify one specific "reply-to" header to all the emails, which is not what I'm looking for.
Thank you in advance.
Here is my WIP, I'm posting it now incase I never finish it. Hopefully I'll update this with an example that reads the required fields, rather than being hardcoded.
(3rd and probably final update)
Apologies if this doesn't do exactly what you need, but it did exactly what I needed, and I believe you requirements are simpler than mine.
-- Reply to current message with additional header changes.
-- (To be triggered from Keyboard Maestro, or ControllerMate on Alt-R)
-- function to read/focus/change data in message field
-- usage: set fieldValue to message_field("reply_to", false)
-- message_field("reply to", "moron")
on message_field(fieldname, newValue)
local tElements, tElement, tField, tValue, tClass
tell application "System Events"
tell process "Mail"
set frontmost to true
set tElements to scroll areas of window 1
repeat with tElement in tElements
set tName to get name of tElement as string
try
set tField to text field 1 of tElement
ignoring white space and punctuation
if (name of tField as string = fieldname) then
try
set tValue to get value of tField as string
on error
set tValue to ""
end try
set focused of tField to true
if (newValue ≠ false) then
set value of tField to newValue -- as string
end if
exit repeat
end if
end ignoring
end try
end repeat
end tell
end tell
return tValue
end message_field
-- split function (julifos # macscripter.net)
to split(someText, delimiter)
set AppleScript's text item delimiters to delimiter
set someText to someText's text items
set AppleScript's text item delimiters to {""} --> restore delimiters to default value
return someText
end split
-- Get information from current/selected message
tell application "Mail"
set theSignatureName to "Signature #1"
set theMessages to the selected messages of the front message viewer
set theMessage to first item of theMessages
-- Get the email address (ours, hopefully) the message was sent to
set theMessageWasTo to address of first to recipient of theMessage as string
-- Unfortunately, it seesm that Mail doesn't honour the existing Reply-To header
-- when a reply is triggered from a script, instead of from the Reply menu.
-- So here is a bit of a dance to get it.
set theMessageHeaders to headers of theMessage
try
set theMessageReplyToWas to first item of {reply to} of theMessage -- (thx to Brian Christmas)
tell me to set theMessageReplyToWas to item 1 of split(theMessageReplyToWas, ",")
on error
set theMessageReplyToWas to sender of theMessage
end try
-- you can also use: set temp to {deleted status, all headers, was replied to, flag index, date received, message id, background color, subject, read status, flagged status, message size, date sent, junk mail status, source, sender, was forwarded, was redirected, content} of foo
-- set Theheaders to all headers of theMessage -- If you want to get all the headers in text form and process manually
-- set mySource to source of theMessage -- If you want the message source
set theOutgoingMessage to reply theMessage with opening window
-- I want to set "Reply-To" to be the address the message was sent to
tell me to message_field("reply to", theMessageWasTo)
tell theOutgoingMessage
-- I don't like this, as it adds an extra recipient
make new to recipient with properties {address:theMessageWasTo}
-- so I'll do it my way
tell me to message_field("to", theMessageWasTo)
end tell
-- It's easier if you just want to change the sender or signature or something
-- set message signature of theOutgoingMessage to signature theSignatureName
-- set sender of theOutgoingMessage to "Federico Viticci "
end tell
-- Now all that remains is to set the focus back to the body of the message.
I am new to AppleScript and I cannot seem to find any good sources to help me with my problem.
Given a file with dates and descriptions:
September 5, 2013
Event 1.
September 8, 2013
Event 2.
etc.
I want to parse the file for the Date and event information, then create events in the Mac Calendar app that are at these days (with these descriptions ad the event titles). However, I am stuck with the following code:
tell application "Finder"
set Names to paragraphs of (read (choose file with prompt "Pick text file containing track names"))
repeat with nextLine in Names
set x to "Thursday, " & nextLine & " 12:00:00 AM"
if nextLine starts with "Sept" then
tell application "Calendar"
tell calendar "My Calendar"
make new event with properties {description:"Event Description", summary:"Event Name", location:"Event Location", start date:date x, allday event:true}
end tell
end tell
end if
end repeat
end tell
The code does not work yet because it complains about the improper date format, and on top of that I have no idea how I could get the second line to be read with the date line.
Any help would be appreciated, Thanks.
I solved the date parsing issue on my system by changing the external file format to:
5 September 2013
This could be a local system date format setting, as that is how mine is defined in the Language & Text - System Preference. Explore your settings first perhaps.
I've reworked your script a bit below to show you how to get at the event name by changing the loop to an index based one.
Also i've dropped the tell "Finder" block as it is not needed, you were not using any commands from the Finder in this case.
I also renamed some of your variables to be more legible (subjective), other tweaks are commented in the script.
set cal_data to the paragraphs of (read (choose file with prompt "Pick text file containing track names"))
set c to the count of cal_data
repeat with i from 1 to c
set currentLine to item i of cal_data
if currentLine contains "September" then
set dt to date (currentLine) -- Dropped the time as an all day event does not need this and the date parse will auto set it to 12:00am
set ev_name to item (i + 1) of cal_data -- The next item in cal_data should be the event name
tell application "Calendar"
tell calendar "My Calendar"
make new event with properties {description:"Event Description", summary:ev_name, location:"Event Location", start date:dt, allday event:true}
end tell
end tell
end if
end repeat
Hopefully this should get you onto the next steps.
I am trying to write a script that does the following job: it goes through all of the emails in the mailbox, finds the ones that have the word "French" in their subject line and then copies all the subject lines of those emails in a text file. Here is what I came up with
tell application "TextEdit"
make new document
end tell
tell application "Mail"
tell the mailbox "Inbox" of account "tigeresque#gmail.com"
set numm to count of messages
repeat with kk from 1 to numm
set wordsub to subject of the message kk
tell application "TextEdit"
if "French" is in wordsub then
set paragraph kk of front document to wordsub & return
end if
end tell
end repeat
end tell
end tell
Unfortunately, I keep receiving the error
"TextEdit got an error: The index of the event is too large to be valid."
and I have already spent a couple of hours trying to fix it without much success. Could you please take a look at my code and see what is wrong with it?
Your main problem is that the number of paragraphs in TextEdit and the number of email messages have nothing to do with each other, so if you're counting on the number of messages then TextEdit will not understand it. For example you may have 50 messages but TextEdit does not have 50 paragraphs so it errors. As such we just use a separate counter for TextEdit.
I made other changes too. I often see errors happen by having one "tell application" block of code inside another... so I separated them. Also notice that the only code inside of any "tell application" block is only what is necessary for that application to handle. This too avoids errors. These are good habits to have when programming.
Therefore give this a try...
set searchWord to "French"
set emailAddress to "tigeresque#gmail.com"
tell application "Mail"
set theSubjects to subject of messages of mailbox "INBOX" of account emailAddress
end tell
set paraCounter to 1
repeat with i from 1 to count of theSubjects
set thisSubject to item i of theSubjects
if thisSubject contains searchWord then
tell application "TextEdit"
set paragraph paraCounter of front document to thisSubject & return
end tell
set paraCounter to paraCounter + 1
end if
end repeat