Save Apple Mail And Attachments As PDF

Hi Yvan,

Thank you for the script you’ve created. I’ve been looking for this for years.

I don’t know to script but I was able to modify your script to save the attachments in different folders. Is there any way you can review this code and see if it can be edited to do the following:

  1. Skip making a folder if there are no attachments.
  2. Make this script simpler in order to increase the speed of printing and saving files in separate folders.

Thank you in advance,

Fernando Silva

my Germaine() # With this added step the script will not save globals in its file.

on Germaine()
# =======================================*=

set mySelf to {"Mr. Fernando Silva", "Silva Fernando", "Fernando Silva"} # I USE BOTH FORMATS, EDIT TO FIT YOUR NEEDS

# =*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=

# Define the folder where files will be stored
set attachmentsFolder to (choose folder) as text

tell application "Mail"
    activate
    set theMessages to (get selection)
end tell

---------------------------------------
repeat with eachMessage in theMessages
    # Open a mail and treat it
    tell application "Mail"
        open eachMessage
        delay 0.5
        set wName to name of window 1
        
        tell eachMessage # extract datas from the selected message
            set sender_Name to extract name from its sender
            set sender_Mail to extract address from its sender
            set mail_Subject to subject
            set mail_Date to date received # will keep the time component
            set target_name to (name of its to recipient)
        end tell # the message
    end tell # application Mail
    
    # No longer speak to application Mail
    
    tell mail_Date
        set theYear to year
        set theMonth to its month as number
        set theDay to day
        set theHour to its hours
        set theMinutes to its minutes
        set theSeconds to its seconds
    end tell
    set begName to (theYear as text) & " " & text -2 thru -1 of ((100 + theMonth) as text) & " " & text -2 thru -1 of ((100 + theDay) as text) & space & text -2 thru -1 of ((100 + theHour) as text) & "" & text -2 thru -1 of ((100 + theMinutes) as text) -- & " Email "
    
    if sender_Name is in mySelf then
        set begName to begName & " to [" & target_name & "]"
    else
        set begName to begName & " from [" & sender_Name & "]"
    end if
    
    set thePDFname to begName & " - " & my remplace(mail_Subject, {":", "/"}, "-") & ".pdf" # I know, I'm a bit paranoid
    set posixFolderPath to POSIX path of attachmentsFolder
    set pdfPath to POSIX path of (posixFolderPath & thePDFname)
    
    -- Print the opened email as PDF
    tell application "System Events"
        tell process "Mail"
            set frontmost to true
            set windowName to name of window 1
            keystroke "p" using {command down} # Issue the Print shortcut
            tell window wName
                repeat
                    try
                        if (exists pop up button 1 of sheet 1) then exit repeat
                    end try
                    delay 0.2
                end repeat
                
                tell sheet 1
                    set PDFButton to first menu button
                    click PDFButton
                    tell menu 1 of PDFButton
                        name of menu items
                        --> {"Ouvrir le PDF dans Aperçu", "Enregistrer au format PDF…", "Enregistrer au format PostScript…", "Faxer le document PDF…", missing value, "@ PDF-BAT.qfilter", "@ PDF-prépresse CMJN.qfilter", "@ PDF-web.qfilter", "@ PDFX3-ISO.qfilter", "Add PDF to iTunes", "Envoyer le document PDF par courrier électronique", "Enregistrer le document PDF dans le dossier de reçus web", missing value, "Modifier le menu…"}
                        click menu item 2
                    end tell
                    repeat
                        if exists sheet 1 then exit repeat # the Print sheet exists, exit the loop!
                        delay 0.1
                    end repeat
                end tell # sheet 1
                
                tell sheet 1 of sheet 1
                    set wichElements to class of UI elements
                    if wichElements contains combo box then # maybe Mojave
                        get position of combo boxes --> {{910, 118}, {910, 148}}
                        set value of combo box 1 to thePDFname
                    else -- Yosemite, El Capitan, Sierra, High Sierra
                        --> {static text, text field, UI element, static text, text field, group, radio group, group, pop up button, text field, splitter group, text field, static text, button, text field, static text, text field, static text, static text, text field, button, button, button}
                        get position of text fields --> {{1262, 194}, {1262, 224}, {1458, 263}, {1086, 646}, {1086, 616}, {1086, 552}, {1086, 584}}
                        set value of text field 1 to thePDFname
                    end if
                end tell # sheet 1 of sheet 1
                
                keystroke "g" using {command down, shift down}
                repeat until exists sheet 1 of sheet 1 of sheet 1
                    delay 0.02
                end repeat
                tell sheet 1 of sheet 1 of sheet 1
                    --name of UI elements
                    set wichElements to class of UI elements # According to system in use, may be
                    --> {static text, combo box, button, button} -- El Capitan, Sierra, High Sierra, maybe Mojave
                    --> {static text, text field, button, button} -- … Yosemite
                    if wichElements contains combo box then
                        set SaveIndex to -1
                        set value of combo box 1 to posixFolderPath
                    else
                        set SaveIndex to 1
                        set value of text item 1 to posixFolderPath
                    end if
                    name of buttons --> {"Aller", "Annuler"}
                    click button 1
                end tell # sheet 1 of sheet 1 of sheet 1
                
                tell sheet 1 of sheet 1
                    --name of UI elements # According to system in use, may be
                    --> {"Enregistrer", "Nouveau dossier", "Annuler"}
                    --> {"Nouveau dossier", "Annuler", "Enregistrer"}
                    click button SaveIndex
                end tell # sheet 1 of sheet 1
            end tell -- window wName
        end tell # process Mail
    end tell # "System Events"
    
    
    
    # MAKES FOLDER
    set folderName to begName & " - " & my remplace(mail_Subject, {":", "/"}, "-") # Change the name if you wish
    set downloadFolder to attachmentsFolder # Don't change this instruction
    set attachmentsFolders to downloadFolder & folderName & ":" # Don't remove the ending colon
    
    
    
    
    
    
    tell application "System Events"
        
        if not (exists folder attachmentsFolders) then
            make new folder at end of folder downloadFolder with properties {name:folderName}
        end if
        
    end tell
    
    
    
    
    
    #SAVES ATTACHMENTS IN FOLDER
    tell application "Mail"
        set selectedMessages to the selection
        repeat with theMessage in selectedMessages
            repeat with theAttachment in theMessage's mail attachments
                set PosixName to name of theAttachment
                # CAUTION, if the name of the file contain some slashes,
                # it replace them by colons. So the next instruction reset the slashs.
                set originalName to my remplace(PosixName, ":", "/")
                set savePath to attachmentsFolders & originalName
                
                
                try
                    save theAttachment in file (savePath)
                end try
            end repeat
        end repeat
        
        # MAKES FOLDER
        set folderName to begName & " - " & my remplace(mail_Subject, {":", "/"}, "-") # Change the name if you wish
        set downloadFolder to attachmentsFolder # Don't change this instruction
        set attachmentsFolders to downloadFolder & folderName & ":" # Don't remove the ending colon
        
        
        
        
        
        
        tell application "System Events"
            
            if not (exists folder attachmentsFolders) then
                make new folder at end of folder downloadFolder with properties {name:folderName}
            end if
            
        end tell
        
        tell application "Finder"
            set packageFolder to attachmentsFolder
            set posixPath to quoted form of POSIX path of packageFolder
            do shell script "find " & posixPath & " -name '.DS_Store' -type f -delete && find " & posixPath & " -empty -type d -delete"
        end tell
        
        #CLOSES EMAIL WINDOWS THAT ARE OPEN
        try
            repeat while exists window wName
                close window wName
                delay 0.1
            end repeat
            
            
            
        end try
    end tell
end repeat

end Germaine

#=====
(*
replace every occurences of d1 by d2 in text t
*)
on remplace(t, d1, d2)
local oTIDs, l
set {oTIDs, AppleScript’s text item delimiters} to {AppleScript’s text item delimiters, d1}
set l to text items of t
set AppleScript’s text item delimiters to d2
set t to l as text
set AppleScript’s text item delimiters to oTIDs
return t
end remplace

#=====


–» HANLDERS

on exTant(_path) # Takes an HFS, Posix, or ~/Posix path as input.
local _path
try
if _path starts with “~/” then
set _path to (POSIX path of (path to home folder as text)) & text 3 thru -1 of _path
end if
if _path starts with “/” then
alias POSIX file _path
else if _path contains “:” then
alias _path
end if
return true
on error
return false
end try
end exTant

Model: MacBook Pro (Retina, 15-inch, Mid 2014)
AppleScript: 2.11 (203.1)
Browser: Safari 537.36
Operating System: macOS 10.14

Hi, Thanks@Yvan Koenig Script works great, Chucks out pdf on message every time

Issue: I believe its not related to script at all, → the pdf contents are truncated at the bottom & right side of each page

Any suggestions wud be welcome

Cheers

Hi all,

this is an old post and the operating system has been updated in the meantime.

In regards to exporting an email to PDF from Mail, there is no need to go through the print dialog box. In the file menu there is an “Export to PDF” item which can be activated using System Events.

This is much easier since the printer settings (such as black and white) will interfere with the quality of the PDF.

David. Thanks for the post and the excellent suggestion.

For several years now, I’ve been using a functionally similar (export-to-PDF) approach to save a Safari page to PDF, and it generally works well. Setting the file name and clicking on the Save button are both straightforward with GUI scripting, but I’ve never had any success changing the Where: folder. Have you been able to accomplish this?

Yes indeed! When the save-as dialog comes up, you just have to tell System Events to hit Shift Command G and then put the destination path into the next dialog that appears. The destination path needs to be in posix format.

2 Likes

Thanks. That works great.

1 Like

Is the script supposed to work. This is my result:

Cmd-p works:

keystroke “p” using {command down}

But the next step of “Save as PDF…” doesn’t do anything:

click menu item 2

If you’re exporting from Mail, then have you seen this comment posted earlier:

I thought that this was in addition to the original script and not a replacement.

I’m a total novice with System Events and couldn’t get this to work at all:

tell application “Mail”
activate
end tell

tell application “System Events”

tell process “Mail”
set theFileMenu to menu bar item “File” of menu bar 1
click menu item “Export to PDF…” of theFileMenu
end tell
end tell

This makes an error:

System Events got an error: Can’t get menu item “Export to PDF…” of menu bar item “File” of menu bar 1 of application process “Mail”.

I’m just testing so there is no error handling at all. I make sure that an email is selected.

bwill. The following worked reliably on my Sonoma computer:

tell application "Mail" to activate

tell application "System Events" to tell process "Mail"
	click menu item "Export as PDF…" of menu "File" of menu bar 1
	delay 0.5
	keystroke return
end tell
1 Like

Thanks! I found the problem. My script uses “Export TO” and not “Export AS”. I know why I never used System Events.

Everything works, and a PDF is created on the desktop, but, there seems to be some sort of formatting issue, see posted PDF.
Pharmacological Intervention.pdf (352.8 KB)

I often encounter that issue, which also occurs with Mail’s print-to-PDF option. One workaround is to increase or decrease the size of the email (command-plus or command-minus keyboard shortcut) before exporting, but that’s kludgey. No good solutions that I’m aware of. :frowning:

Hi. Scripting Newbie here and I’m really really sorry to have to ask but is there an easy way for me to learn how to implement this script? Thanks in advance…