run python script as user

beeboo
Contributor

currently making an EA to determine the default mail client on the mac but if i run the python script on my machine without sudo, its the correct value, but if i sudo the script, its the wrong value.

is there a way i can run the script/command as the user or have it only give the result for the user?

i also tested running the script that changes from com.apple.mail to com.microsoft.Outlook but the user's EA still shows apple mail and when i ssh and run the command on his box as another user, it shows as apple mail too.

here is the line to change it:

LSSetDefaultHandlerForURLScheme("mailto", "com.microsoft.outlook")

here is the line to read it for the ea

LSCopyDefaultHandlerForURLScheme("mailto")
7 REPLIES 7

mm2270
Legendary Contributor III

Is your entire script in python, or are you just calling python and the subsequent command inside another script, like bash?
I'm not sure how it's done inside a proper python script, but with bash and other unix shells, you can use the launchctl asuser syntax to run either a command or an entire script file as the current user. If you do searches here on JN for "how do I run a command as the user" or something along those lines, you should pull up many threads that discuss ways to do it, including what I mentioned above.

Just as a quick caveat, I haven't tested this much on Catalina, so I'm not 100% sure if the launchctl trick still works on that OS, or on Big Sur. I think it does, but YMMV.

beeboo
Contributor

@mm2270 the whole this is in python, which is my limiting factor.

i dont know python well and i dont know of an easier way (without the MSFT app) to change the default mail app to something else.

id love to launch as user (i currently it use it on mojave and catalina machines for a few scripts), but its the combining of the 2 languages that is throwing me for a loop.

mm2270
Legendary Contributor III

I'm not going to be a great help here since my Python knowledge is still limited as well. I'm learning more about it, but what this calls for goes beyond my current knowledge of it for now at least.
But, I think from what I've seen in other scripts, bash shell commands can be called within Python much in the same way we can invoke Python within bash. In Python I think you use the subprocess command to place the shell command within that and then call it in the main Python code and capture it's output.

In searching the interwebs, I found these links which may help get you on the right track. It mentions the subprocess method in them.

https://stackabuse.com/executing-shell-commands-with-python/
https://code.tutsplus.com/articles/how-to-run-unix-commands-in-your-python-program--cms-25926

I'm sure there are many Python gurus here that would be able to do this pretty easily without needing to refer to websites or documentation though. Maybe one of them will chime in on how to do this so you don't have to go through a lot of trial and error.

tlarkin
Honored Contributor

can you post the code?

beeboo
Contributor

@tlarkin

here is the EA:

from LaunchServices import *
master_string=LSCopyDefaultHandlerForURLScheme("mailto")
print("<result>" + master_string + "</result>")

script to make changes:

#!/usr/bin/python

from LaunchServices import *

LSSetDefaultHandlerForURLScheme("mailto", "com.microsoft.outlook")
LSSetDefaultRoleHandlerForContentType("com.apple.ical.ics", kLSRolesAll, "com.microsoft.Outlook")
LSSetDefaultRoleHandlerForContentType("public.vcard", kLSRolesAll, "com.microsoft.Outloook")

master_string=LSCopyDefaultHandlerForURLScheme("mailto")

print("<result>" + master_string + "</result>")

I ran the script in a policy and this was the output

Script result: <result>com.microsoft.Outlook</result>

however, the EA result for the user still shows this:

com.apple.mail

so the difference i feel, is that its running it as ROOT vs the user which is why im getting mixed results.
eg:
running the script as ROOT means it changed it for ROOT not for the user
user opens a mailto link and it opens in Apple Mail
when i SSH to the machine and run the EA script locally to check (running it as a local admin, not as user), this is the result

>>> from LaunchServices import * >>> master_string=LSCopyDefaultHandlerForURLScheme("mailto") >>> >>> print("<result>" master_string "</result>") <result>com.apple.mail</result>

What do you guys think?

i dont know how to run this as a user as the command is python specific it looks like.
im pouring over subprocess as others have noted and am trying it to see if i can make any changes.

So far this is what i have but it doesnt work:

members = subprocess.check_output(['launchctl', 'asuser', str(uid(user)), sys.argv[0],
                                                LSCopyDefaultHandlerForURLScheme("mailto")])

result:

Traceback (most recent call last): File "/Users/jche/Desktop/Shell Scripts/EA/mailCLIENTea.py", line 39, in <module> LSCopyDefaultHandlerForURLScheme("mailto")]) NameError: name 'LSCopyDefaultHandlerForURLScheme' is not defined

tlarkin
Honored Contributor

you can deploy a script and then have launchctl run it as the user, then clean it up, or deploy it as a launch agent which runs at the user anyway

markdmatthews
Contributor

with Python 2.x being removed (and Python 3 no longer pre-installed) in macOS 12.3 or later I highly recommend using MailToOutlook 2.0 via: https://macadmins.software/tools/