Thanks to @danzel, I found the answer was indeed to use a .desktop file.
So I created a simple script that allows you to specify a set of different mailers - I use my work email (Outlook for web), my personal email (via ssh) and sometimes gmail.
Here's the code:
#!/usr/bin/ruby
# 1) Put "mailto.desktop" in /usr/share/applications
# 2) sudo update-desktop-database
# 3) System Prefs -> Details -> Default Applications
require 'uri'
# %SUBJECT% decoded subject, i.e.: "Hey guys!"
# %subject% encoded subject, i.e.: "Hey%20guys%21"
# Same for %to% and %body%
# Also %mailto% for initial value of "mailto:..."
MAILERS = {
'Home' => ['ssh','-t','my-home-server.com','elm','-s','"%subject%"','%to%'],
'Work' => ['browser','https://outlook.office.com/?path=/mail/action/compose&to=%mailto%'],
'Gmail' => ['browser','https://mail.google.com/mail/u/0/?&view=cm&fs=1&to=%TO%&su=%SUBJECT%&body=%BODY%']
}
def fatal(title,message)
system('zenity','--width','400','--height','250','--error','--title',title,'--text',message)
exit -1
end
def clean(str)
#'"'+str+'"'
str.sub(/"/,'')
end
#########################
# Figure out mailto:
#########################
mailtoStr=ARGV.join('')
mailtoStr.sub!(/^mailto:/,'')
mailto = mailtoStr.split(/[\?\&]/)
mailtoStr.sub!(/\?/,'&') # Outlook is confused if you use: 'mailto:addr@some.com?subject=...' instead of '..&subject..'
mailHash = Hash.new
mailto.each { |m|
m.match(/^([^=]+)=(.*)/m)
key,val = $1,$2
key,val = 'to',m unless key
mailHash[key.upcase] = clean(val)
mailHash[key.downcase] = clean(URI.decode(val))
}
fatal("No 'to' specified",'Need to specify an address in the mailto') unless mailHash['to']
FIELDS = %w(to body subject mailto)
def sendInfo(mailHash,mailtoStr,field)
return '' unless field
return mailtoStr if field=='mailto'
return '%'+field+'%' unless FIELDS.index(field.downcase)
mailHash[field] || ''
end
#########################
# Pick mailer
#########################
mailer = 'Work' if mailHash['to'].match(/@my-work-domain.com$/)
mailer ||= `zenity --width 400 --height 250 --title "Mailer select" --text "Choose mailer for #{mailHash['to']}:" --list --column "Mailer" #{MAILERS.keys.map { |m| '"'+m+'"' }.join(' ')}`
mailer.chomp!
fatal('Unknown Mailer',"Don't know mailer selection #{mailer} or no mailer selected") unless MAILERS[mailer]
cmd = MAILERS[mailer]
cmd.each { |c|
c.gsub!(/%([^%]+)%/) { sendInfo(mailHash,mailtoStr,$1) }
}
#p cmd
system(*cmd)
# Sometimes ssh is broken on my system...
system(*cmd) if cmd[0].match(/ssh/) && $?.exitstatus!=0
And the mailto.desktop which goes in /usr/share/applications:
[Desktop Entry]
Encoding=UTF-8
Name=Custom mailto Mail Handler
Comment=Handle mailto links
GenericName=Mail Client
Keywords=Email;E-mail
Exec=/home/dave/bin/mailto %u
Terminal=true
X-MultipleArgs=false
Type=Application
Icon=mail-send
Categories=Application;Network;Email;
MimeType=x-scheme-handler/mailto;application/x-xpinstall;
StartupNotify=true
I have "Terminal=true" because I use ssh, and that's where the ssh window goes, otherwise the terminal window disappears pretty quick. If you don't use any terminal based mailers you can set that to false.
.desktopfile for your script with the correct mime type. – danzel Feb 20 '20 at 07:16