AppleScript: Email als PDF speichern, mit Attachments

23/03/2010
Mich hat heute eine Email erreicht, in der mir folgende Aufgabe beschrieben wurde (Ich hoffe mal Udo ist mit der Veröffentlichung einverstanden, hätte ich selber nicht besser formulieren können.):
Ich möchte eine Mail in Mail.app anklicken, danach sollte die Mail als pdf (wie unter Ablage Drucken PDF Als PDF sichern) in einem speziellen Ordner auf dem Schreibtisch mit folgendem Namen (Sendedatum, E-Mail-Adresse und Betreff aus Mail) gesichert werden. Der eventuelle Anhang sollte ebenfalls in diesem Ordner gesichert werden. Die Mail kann danach gelöscht werden.
zusammen mit dieser Aufgabenstellung und den ersten Code-Zeilen von Udo ist dann das hier entstanden (ich mag zwar GUI-Scripting nicht, aber das hier ROCKT ;-) ):
Code zum markieren einmal anklicken Code im Skript-Editor öffnen

-- Save Mail as PDF and it's attachments to folder

--  Created by hubionmac (22.03.2010) requested by Udo

global frontmost_message_viewer

--this is the posix (unix) path of the folder you would like to store the messages in

tell application "Finder" to set mymailboxpath to POSIX path of ((desktop) as alias) & "mail_box/"

tell application "Mail"

set myselection to my check_message_viewer_and_return_selection()

--works only with one selected message for many reasons...

if (count of myselection) = 1 then

repeat with currentMail in myselection

set currentSender to my (getEmail(sender of currentMail))

set currentDateSent to my getDatestring(date sent of currentMail)

set currentSubject to my replace_chars(my replace_chars(subject of currentMail, ":", "-"), "/", ":") --Doppelpunkte kommen bei Dateinamen nicht so gut

set currentFolder2Store to mymailboxpath & currentDateSent & " " & currentSender & " " & currentSubject & "/" as text

my create_messagefolder(currentFolder2Store)

repeat with a in (every mail attachment of currentMail)

set current_a_name to name of a

set current_a_name to my checkname_with_pdf_suffix(current_a_name, (POSIX file currentFolder2Store) as alias, false)

save a in (((POSIX file currentFolder2Store) as text) & current_a_name) as text

end repeat

set desktop_pdf_name to my checkname_with_pdf_suffix("1.pdf", path to desktop, false)

set the clipboard to desktop_pdf_name

my print_current_mail_as_pdf()

repeat until (index of window of frontmost_message_viewer) is 1

delay 1

end repeat

my move_desktop_pdf(desktop_pdf_name, currentFolder2Store)

--open destination folder in finder ( did it really work? YES!! =))

do shell script "open " & quoted form of currentFolder2Store

end repeat

else

error "Sorry, ich kann zur Zeit nur mit einer ausgewählten Email hantieren"

end if

end tell

to move_desktop_pdf(desktop_pdf_name, currentFolder2Store)

--used to move the printed pdf to it's final destination

set finalname to checkname_with_pdf_suffix("__message.pdf", (POSIX file currentFolder2Store) as alias, false)

try

tell application "Finder" to do shell script "mv " & POSIX path of ((desktop) as alias) & quoted form of desktop_pdf_name & " " & quoted form of currentFolder2Store & quoted form of finalname

on error msg

error "Fehler beim Bewegen der gedruckten Nachricht:  " & msg as text

end try

end move_desktop_pdf

to getEmail(mailstring)

-- if an email contains the senders name like "Mr.Bla <bla@bla.com>" then returns just the email not leaves the name

if mailstring contains "<" then

return (characters ((offset of "<" in mailstring) + 1) through ((offset of ">" in mailstring) - 1) of mailstring) as text

else

return mailstring

end if

end getEmail

to getDatestring(thedate)

--format a date to a string like 2010-03-22

set monthnum to characters -2 through -1 of ("0" & ((month of thedate) as integer)) as text

set daynum to characters -2 through -1 of ("0" & ((day of thedate) as integer)) as text

set yearnum to year of the thedate

return yearnum & "-" & monthnum & "-" & daynum as text

end getDatestring

to create_messagefolder(thepath_posix)

--I love mkdir -p, simple, short, easy to use

try

do shell script "mkdir -p " & quoted form of thepath_posix

on error msg

error msg

end try

end create_messagefolder

to replace_chars(this_text, search_string, replacement_string)

--this replaces characters

--used for folder and filenames, since a : must not be used for that

if this_text contains the search_string then

set AppleScript's text item delimiters to the search_string

set the item_list to every text item of this_text

set AppleScript's text item delimiters to the replacement_string

set this_text to the item_list as string

set AppleScript's text item delimiters to ""

end if

return this_text

end replace_chars

to checkname_with_pdf_suffix(n, D, looped)

--check if filename exists in D

-- so if "A File.pdf" exists it names it "A File 1.pdf","A File 2.pdf",...

tell application "Finder"

set thefiles to name of every item of (D as alias)

end tell

if thefiles contains n then

if looped = false then

set n to ((characters 1 through -5 of n) & " 1" & (characters -4 through -1 of n)) as text

my checkname_with_pdf_suffix(n, D, true)

else

set tmp to (last word of ((characters 1 through -5 of n) as text) as integer)

set tmpcount to (count of characters of (tmp as text)) + 5

set tmp to tmp + 1

set n to ((characters 1 through (-1 * tmpcount) of n) & tmp & (characters -4 through -1 of n)) as text

my checkname_with_pdf_suffix(n, D, true)

end if

else

return n

end if

end checkname_with_pdf_suffix

to print_current_mail_as_pdf()

--hopefully works on every mac in every language =)

-- GUI-Scripting is not the best way, but somehow the only way at the moment :-/

tell application "Mail"

activate

tell application "System Events"

tell process "Mail"

keystroke "p" using command down

set p to "false"

repeat with i from 1 to 10

if (count of every sheet of window 1) > 0 then

set p to "ready"

exit repeat

end if

delay 1

end repeat

if p = "ready" then

click menu button 1 of sheet 1 of window 1

delay 0.25

key code 125

key code 125

delay 0.25

keystroke return

delay 1

click text field 1 of window 1

keystroke "a" using command down

keystroke "v" using command down

keystroke "d" using command down

keystroke return

else

error "timeout"

end if

end tell

end tell

end tell

end print_current_mail_as_pdf

to check_message_viewer_and_return_selection()

-- check if frontmost window is a message viewer, otherwhise tell the user to RTFM!... wait there is no manual... don't care error change user!

tell application "Mail"

set frontmost_message_viewer to {}

repeat with i from 1 to count of every message viewer

if index of window of message viewer i = 1 then

set frontmost_message_viewer to message viewer i

exit repeat

end if

end repeat

if frontmost_message_viewer = {} then

error "Ist ja gar kein Message Viewer im Vordergrund, so kann ich einfach nicht arbeiten!"

else

return selection

end if

end tell

end check_message_viewer_and_return_selection

In habe mal auf das Löschen der Email verzichtet (das soll mal jeder lieber alleine rein schreiben), aber es scheint wunderbar zu funktionieren. Bin mal gespannt ob es auch bei anderen läuft...Update vom 27.09.2011:

-- Save Mail as PDF and it's attachments to folder

--  Created by hubionmac (29.09.2010)

-- 29.09.2010 

-- -Auswahl von mehren Emails wird nun auch möglich

-- -Abgesendete Emails werden als solche erkannt und in einem anderen Verzeichnis mit Empfänger-Adresse im Ordnernamen gespeichert (req. by Andreas)

-- 27.09.2011 made it work with local mailboxes, too

global frontmost_message_viewer

--this is the posix (unix) path of the folder you would like to store the messages in

tell application "Finder" to set mymailboxpath to POSIX path of ((desktop) as alias) & "received_mail_box/"

tell application "Finder" to set mysentmailboxpath to POSIX path of ((desktop) as alias) & "sent_mail_box/"

tell application "Mail"

set myselection to my check_message_viewer_and_return_selection()

repeat with currentMail in myselection

open currentMail

set currentSender to my (getEmail(sender of currentMail))

set currentDateSent to my getDatestring(date sent of currentMail)

set currentSubject to my replace_chars(my replace_chars(subject of currentMail, ":", "-"), "/", ":") --Doppelpunkte kommen bei Dateinamen nicht so gut

if my is_in_sent_mail(currentMail) is true then

--if the file was sent FROM this email account

set sentToEmail to address of item 1 of to recipient of currentMail

set currentFolder2Store to mysentmailboxpath & sentToEmail & " " & currentDateSent & " " & currentSubject & "/" as rich text

else

--if the email was sent TO this email account 

try

set myemail to item 1 of (get email addresses of account of mailbox of currentMail)

on error

--27.09.2011 added to make it work with local mailboxes, too

set myemail to item 1 of (get address of to recipient of currentMail)

end try

set currentFolder2Store to mymailboxpath & currentDateSent & " " & currentSender & " " & currentSubject & " send to" & myemail & "/" as rich text

end if

my create_messagefolder(currentFolder2Store)

repeat with a in (every mail attachment of currentMail)

set current_a_name to name of a

set current_a_name to my checkname_with_pdf_suffix(current_a_name, (POSIX file currentFolder2Store) as alias, false)

save a in (((POSIX file currentFolder2Store) as rich text) & current_a_name) as rich text

end repeat

set desktop_pdf_name to my checkname_with_pdf_suffix("1.pdf", path to desktop, false)

set the clipboard to desktop_pdf_name

tell application "System Events"

tell process "Mail"

set wc to count of every window

end tell

end tell

my print_current_mail_as_pdf()

tell application "System Events"

tell process "Mail"

repeat until (count of every window) is wc

end repeat

end tell

end tell

my move_desktop_pdf(desktop_pdf_name, currentFolder2Store)

--close last_message window

activate

tell application "System Events"

tell process "Mail"

keystroke "w" using command down

end tell

end tell

--open destination folder in finder ( did it really work? YES!! =))

--do shell script "open " & quoted form of currentFolder2Store

end repeat

end tell

to move_desktop_pdf(desktop_pdf_name, currentFolder2Store)

--used to move the printed pdf to it's final destination

set finalname to checkname_with_pdf_suffix("__message.pdf", (POSIX file currentFolder2Store) as alias, false)

try

tell application "Finder" to do shell script "mv " & POSIX path of ((desktop) as alias) & quoted form of desktop_pdf_name & " " & quoted form of currentFolder2Store & quoted form of finalname

on error msg

error "Fehler beim Bewegen der gedruckten Nachricht:  " & msg as text

end try

end move_desktop_pdf

to getEmail(mailstring)

-- if an email contains the senders name like "Mr.Bla <bla@bla.com>" then returns just the email not leaves the name

if mailstring contains "<" then

return (characters ((offset of "<" in mailstring) + 1) through ((offset of ">" in mailstring) - 1) of mailstring) as text

else

return mailstring

end if

end getEmail

to getDatestring(thedate)

--format a date to a string like 2010-03-22

set monthnum to characters -2 through -1 of ("0" & ((month of thedate) as integer)) as text

set daynum to characters -2 through -1 of ("0" & ((day of thedate) as integer)) as text

set yearnum to year of the thedate

return yearnum & "-" & monthnum & "-" & daynum as text

end getDatestring

to create_messagefolder(thepath_posix)

--I love mkdir -p, simple, short, easy to use

try

do shell script "mkdir -p " & quoted form of thepath_posix

on error msg

error msg

end try

end create_messagefolder

to replace_chars(this_text, search_string, replacement_string)

--this replaces characters

--used for folder and filenames, since a : must not be used for that

if this_text contains the search_string then

set AppleScript's text item delimiters to the search_string

set the item_list to every text item of this_text

set AppleScript's text item delimiters to the replacement_string

set this_text to the item_list as string

set AppleScript's text item delimiters to ""

end if

return this_text

end replace_chars

to checkname_with_pdf_suffix(n, D, looped)

--check if filename exists in D

-- so if "A File.pdf" exists it names it "A File 1.pdf","A File 2.pdf",...

tell application "Finder"

set thefiles to name of every item of (D as alias)

end tell

if thefiles contains n then

if looped = false then

set n to ((characters 1 through -5 of n) & " 1" & (characters -4 through -1 of n)) as text

my checkname_with_pdf_suffix(n, D, true)

else

set tmp to (last word of ((characters 1 through -5 of n) as text) as integer)

set tmpcount to (count of characters of (tmp as text)) + 5

set tmp to tmp + 1

set n to ((characters 1 through (-1 * tmpcount) of n) & tmp & (characters -4 through -1 of n)) as text

my checkname_with_pdf_suffix(n, D, true)

end if

else

return n

end if

end checkname_with_pdf_suffix

to print_current_mail_as_pdf()

--hopefully works on every mac in every language =)

-- GUI-Scripting is not the best way, but somehow the only way at the moment :-/

tell application "Mail"

activate

tell application "System Events"

tell process "Mail"

keystroke "p" using command down

set p to "false"

repeat until 0 = 1

if (count of every sheet of window 1) > 0 then

set p to "ready"

exit repeat

end if

end repeat

if p = "ready" then

click menu button 1 of sheet 1 of window 1

delay 0.25

key code 125

key code 125

delay 0.25

set cwc to count of every window

keystroke return

repeat until 1 = 0

if (cwc + 1) = (count of every window) then

exit repeat

end if

end repeat

click text field 1 of window 1

keystroke "a" using command down

keystroke "v" using command down

keystroke "d" using command down

keystroke return

else

error "timeout"

end if

end tell

end tell

end tell

end print_current_mail_as_pdf

to check_message_viewer_and_return_selection()

-- check if frontmost window is a message viewer, otherwhise tell the user to RTFM!... wait there is no manual... don't care error change user!

tell application "Mail"

set frontmost_message_viewer to {}

repeat with i from 1 to count of every message viewer

if index of window of message viewer i = 1 then

set frontmost_message_viewer to message viewer i

exit repeat

end if

end repeat

if frontmost_message_viewer = {} then

error "Ist ja gar kein Message Viewer im Vordergrund, so kann ich einfach nicht arbeiten!"

else

return selection

end if

end tell

end check_message_viewer_and_return_selection

on is_in_sent_mail(amessage)

tell application "Mail"

set sentmailboxes to every mailbox of sent mailbox

set currentmailbox to mailbox of amessage

repeat with i from 1 to (count of sentmailboxes)

if item i of sentmailboxes = currentmailbox then

return true

end if

end repeat

return false

end tell

end is_in_sent_mail

33 Comments

AppleMail: Sende Email als Attachment einer anderen…

12/02/2010
Ok, die Sinnfrage stelle ich mal nicht. Wenn jemand aber wie z.B. in Thunderbird eine Email nicht als Text, sondern die gesamte Email (Header inkl.) als Attachment verschicken möchte, der könnte eine dieser AppleScript-Funktionen nutzen, um das zu erreichen:
Code zum markieren einmal anklicken Code im Skript-Editor öffnen

on create_mail_emlx_files_attachment_of_selection()

tell application "Mail"

-- get the mail selection

set myMessages to selection

--do it to every selected mail

repeat with m in myMessages

--get the folder where the emlx file is stored in

set mypath to quoted form of POSIX path of ((account directory of account of mailbox of m) as alias)

--get the id of that message (should be unique within each account)

set myid to id of m

--find the folder where this unique email (by id) is stored in

set myfolder to quoted form of (paragraph 1 of (do shell script "find " & mypath & " -name '" & myid & "*.emlx*' -exec dirname {} \\;"))

--create a compressed tar archive of this message and open this gzipped files with Apple Mail (-> attach it to a new message).

do shell script "cd " & myfolder & ";tar -rf " & myid & ".tar " & myid & "*.emlx*;gzip " & myid & ".tar;mv " & myid & ".tar.gz /tmp/;open -a /Applications/Mail.app /tmp/" & myid & ".tar.gz"

end repeat

end tell

end create_mail_emlx_files_attachment_of_selection


on create_mail_source_attachment_of_selection()

tell application "Mail"

-- get the mail selection

set myMessages to selection

--do it to every selected mail

repeat with m in myMessages

set myid to id of m

set mysource to quoted form of ((source of m) as text)

do shell script "cd /tmp/;echo " & mysource & "|cat>/tmp/" & myid & ".txt;gzip " & myid & ".txt;open -a /Applications/Mail.app " & myid & ".txt.gz"

end repeat

end tell

end create_mail_source_attachment_of_selection

No Comments

Mail-Regel-Skript: Attachments sichern

20/01/2010
Hier ein simples Skript, welches Anhänge von Emails in einem vordefinierten Ordner sichert. Das kann man an eine Mail-Regel hängen.
Code zum markieren einmal anklicken Code im Skript-Editor öffnen

-- hubionmac.com 2010-01

-- script to be added to a Apple Mail rule

--saves attachmens of new mails into a folder

on perform_mail_action(info)

tell application "Mail"

tell application "Finder" to set mypath to (folder "Mail Attachments Saved" of desktop) as text

set theMessages to |SelectedMessages| of info

repeat with thisMessage in theMessages

try

repeat with a in (every mail attachment of thisMessage)

set current_a_name to name of a

set current_a_name to my checkname_with_pdf_suffix(current_a_name, mypath as alias, false)

save a in mypath & current_a_name

end repeat

on error msg

do shell script "echo " & quoted form of msg & " | cat>>~/Desktop/MailscriptErrorLog.txt"

end try

end repeat

end tell

end perform_mail_action



on checkname_with_pdf_suffix(n, D, looped)

tell application "Finder"

set thefiles to name of every item of (D as alias)

end tell

if thefiles contains n then

if looped = false then

set n to ((characters 1 through -5 of n) & " 1" & (characters -4 through -1 of n)) as text

my checkname_with_pdf_suffix(n, D, true)

else

set tmp to (last word of ((characters 1 through -5 of n) as text) as integer)

set tmpcount to (count of characters of (tmp as text)) + 5

set tmp to tmp + 1

set n to ((characters 1 through (-1 * tmpcount) of n) & tmp & (characters -4 through -1 of n)) as text

my checkname_with_pdf_suffix(n, D, true)

end if

else

return n

end if

end checkname_with_pdf_suffix

8 Comments

Mail Attachments sichern

17/09/2009
.emlx Dateien sind der Speicherort für Emails ab Mac OSX... ehm 10.5? Hier ein dirty-work-around zum automatischen Speichern von Anhängen in Apple Mail, da es direkt via AppleScript noch nicht möglich zu sein scheint siehe Update weiter unten (Automator zählt nicht ;-) ). Geht aber leider nur mit IMAP-Postfächern
Code zum markieren einmal anklicken

--© hubionmac.com 17.09.2009

--Stores attached pdfs (of an email received via IMAP) on your desktop

-- renames them by date received.... !!!MV overwrites existiting files!!!!

tell application "Mail"

set a to selection

end tell

repeat with s in a

tell application "Mail" to set current_date to date received of s

--convert applescript date to date string

set current_date to AppleScriptDateToString(current_date)

tell application "Mail"

--this works only on imap account, because there attachments are stored in a searate folder, not inline in .emlx-files

set attachments_path to do shell script "find ~/Library/Mail/ -name " & (id of s)

set current_attachments to do shell script "find " & quoted form of attachments_path & " -type f -iname \"*.pdf\" -exec mv {} ~/Desktop/" & current_date & ".pdf \\;"

end tell

get current_date

end repeat




on AppleScriptDateToString(a)

set b to current date

set monthnames to {}

repeat with i from 1 to 12

set month of b to i

set monthnames to monthnames & {(month of b) as text}

end repeat

set Y to (year of b)

set M to 0

repeat with t in monthnames

set M to M + 1

if t as text = (month of b) as text then

exit repeat

end if

end repeat

set M to Twodigits(M)

set D to Twodigits(day of b)

set hh to Twodigits(hours of b)

set mm to (minutes of b)

set ss to Twodigits(seconds of b)

--"2009-12-17 01:26:49"

--return Y & "-" & M & "-" & D & " " & hh & ":" & mm & ":" & ss as text

--"2009-12-17 01:28"

--return Y & "-" & M & "-" & D & " " & hh & ":" & mm as text

--"2009-12-17"

return Y & "-" & M & "-" & D as text

end AppleScriptDateToString

on Twodigits(a)

return (characters -2 through -1 of (("0" & a) as text)) as text

end Twodigits

UPDATE

Dieser Code ist deutlich besser, kommt mit bereits vergebenen Dateinamen klar und funktioniert auch mit jeder Art von Apple-Mail-Account =)
Code zum markieren einmal anklicken

(**

hubionmac.com 17.09.2009

save pdfs from seleceted email messages and save them in one folder

renames attachments by date received and from address like:

2009-12-09 from Steve Jobs <steve@apple.com>.pdf

2009-12-09 from Steve Jobs <steve@apple.com> 1.pdf

2009-12-09 from Steve Jobs <steve@apple.com> 2.pdf 


**)

set theAttachmentPath to (path to desktop) as text

tell application "Mail"

set a to selection

end tell

repeat with s in a

tell application "Mail"

set current_date to date received of s

set CurrentSender to sender of s

end tell

set current_date to AppleScriptDateToString(current_date)

tell application "Mail" to set Attached to mail attachments of s

repeat with ThisAttach in Attached

tell application "Mail" to set FileName to name of ThisAttach

if FileName ends with ".pdf" then

set FileName to current_date & " from " & CurrentSender & ".pdf" as text

set FileName to checkname_with_pdf_suffix(FileName, theAttachmentPath, false)

tell application "Mail" to save ThisAttach in theAttachmentPath & (FileName)

end if

end repeat

end repeat



on AppleScriptDateToString(a)

set b to a

set monthnames to {}

repeat with i from 1 to 12

set month of b to i

set monthnames to monthnames & {(month of b) as text}

end repeat

set Y to (year of b)

set M to 0

repeat with t in monthnames

set M to M + 1

if t as text = (month of b) as text then

exit repeat

end if

end repeat

set M to Twodigits(M)

set D to Twodigits(day of b)

set hh to Twodigits(hours of b)

set mm to (minutes of b)

set ss to Twodigits(seconds of b)

--"2009-12-17 01:26:49"

--return Y & "-" & M & "-" & D & " " & hh & ":" & mm & ":" & ss as text

--"2009-12-17 01:28"

--return Y & "-" & M & "-" & D & " " & hh & ":" & mm as text

--"2009-12-17"

return Y & "-" & M & "-" & D as text

end AppleScriptDateToString

on Twodigits(a)

return (characters -2 through -1 of (("0" & a) as text)) as text

end Twodigits



on checkname_with_pdf_suffix(n, D, looped)

tell application "Finder"

set thefiles to name of every item of (D as alias)

end tell

if thefiles contains n then

if looped = false then

set n to ((characters 1 through -5 of n) & " 1" & (characters -4 through -1 of n)) as text

checkname_with_pdf_suffix(n, D, true)

else

set tmp to (last word of ((characters 1 through -5 of n) as text) as integer)

set tmpcount to (count of characters of (tmp as text)) + 5

set tmp to tmp + 1

set n to ((characters 1 through (-1 * tmpcount) of n) & tmp & (characters -4 through -1 of n)) as text

checkname_with_pdf_suffix(n, D, true)

end if

else

return n

end if

end checkname_with_pdf_suffix

No Comments