GJ.
GJ.

Reputation: 5364

How to use a password from the keychain within an applescript running within Mail.app?

I'm trying to set up an applescript that performs (via python imaplib...) certain manipulations on my gmail account (which isn't configured with IMAP in Mail.app, only POP).

For that, the script needs to login using my password. If it weren't for security considerations, I could simply hardcode my password into the python script...

Is there a way that such an applescript triggered inside Mail.app (e.g. by a rule) can use my password stored inside the keychain?

Upvotes: 6

Views: 8860

Answers (5)

irgendwr
irgendwr

Reputation: 607

I adapted this answer to support non-ASCII characters, since this causes the password to be hex-encoded.

Please note that this may return the wrong password in case your password matches all of the following conditions: 1) only uses characters 0-9, lower-case a-f and 2) has an even length. This is due to the workaround of decoding the password in case it is hex-encoded due to containing non-ASCII characters.

getPW("name of keychain item")

on getPW(keychainItemName)
    do shell script "pw=$(security find-generic-password -wl " & quoted form of keychainItemName & "); [[ \"$pw\" =~ ^([0-9a-f][0-9a-f])+$ ]] && echo \"$pw\" | xxd -r -p && echo || echo \"$pw\""
    return (result as text)
end getPW

In case the password is guaranteed to not contain non-ASCII characters, you can use this:

on getPW(keychainItemName)
    do shell script "security find-generic-password -wl " & quoted form of keychainItemName
    return (result as text)
end getPW

Upvotes: 0

Danny Parker
Danny Parker

Reputation: 1773

An updated answer as I don't think this was available before. security now has a -w option that outputs just the password without any need for parsing the output.

This gives us this solution in python:

pw = subprocess.check_output(["security", "find-generic-password", "-wl", "MY_KEYCHAIN_ID"])

This will still trigger the prompt for the user password, the same as the other solutions.

Upvotes: 0

ofstudio
ofstudio

Reputation: 787

I'm use this one

# Replace %ACCOUNT_NAME% with account name of Keychain item
get_pw () {
  security 2>&1 >/dev/null find-generic-password -ga "%ACCOUNT_NAME%" \
  | sed 's/password: "\(.*\)"/\1/'
}
PASS=$(get_pw)

Upvotes: 0

kopischke
kopischke

Reputation: 3413

There is such a way, it is called Keychain Access Scripting, and Apple deprecated it with OS X 10.7, dropping the necessary extension from AppleScript. However, you can either use the security shell utility like detailed on the TextMate blog (be sure to read the comments – there are a few gotchas to that), or, and I’d recommend that, use the third party replacement for Apple’s component, Daniel Jalkut’s excellent Usable Keychain Scripting app. Once installed, the following bit of AppleScript will retrieve your password (assuming the account name is “GMail”):

tell application "Usable Keychain Scripting" to get password of first generic item of current keychain whose account is "GMail"

Upvotes: 2

regulus6633
regulus6633

Reputation: 19030

The following is copied out of a script in my script library...

-- If you need to use a password in a script you can use the keychain to store the password and have the script retrieve it. This way your password is protected because you don't need to store passwords in clear text in a script.

-- Create the password item - Open Keychain Access application and select the keychain in the left column. Then click File>New Password Item..., give it a name, put your account shortname in account, and enter the password. Highlight it in the password list and get information on it. Under the Attributes button enter its kind as generic key. This is chosen because there aren't many of them and the search is much faster.

-- NOTE: In 10.7 apple removed keychain scripting and thus we now use the security command line tool

getPW("name of keychain item")

on getPW(keychainItemName)
    do shell script "security 2>&1 >/dev/null find-generic-password -gl " & quoted form of keychainItemName & " | awk '{print $2}'"
    return (text 2 thru -2 of result)
end getPW

Upvotes: 7

Related Questions