xdg-email 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038
  1. #!/bin/sh
  2. #---------------------------------------------
  3. # xdg-email
  4. #
  5. # Utility script to open the users favorite email program, using the
  6. # RFC 2368 mailto: URI spec
  7. #
  8. # Refer to the usage() function below for usage.
  9. #
  10. # Copyright 2009-2010, Fathi Boudra <fabo@freedesktop.org>
  11. # Copyright 2009-2010, Rex Dieter <rdieter@fedoraproject.org>
  12. # Copyright 2006, Kevin Krammer <kevin.krammer@gmx.at>
  13. # Copyright 2006, Jeremy White <jwhite@codeweavers.com>
  14. #
  15. # LICENSE:
  16. #
  17. # Permission is hereby granted, free of charge, to any person obtaining a
  18. # copy of this software and associated documentation files (the "Software"),
  19. # to deal in the Software without restriction, including without limitation
  20. # the rights to use, copy, modify, merge, publish, distribute, sublicense,
  21. # and/or sell copies of the Software, and to permit persons to whom the
  22. # Software is furnished to do so, subject to the following conditions:
  23. #
  24. # The above copyright notice and this permission notice shall be included
  25. # in all copies or substantial portions of the Software.
  26. #
  27. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  28. # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  29. # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  30. # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  31. # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  32. # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  33. # OTHER DEALINGS IN THE SOFTWARE.
  34. #
  35. #---------------------------------------------
  36. manualpage()
  37. {
  38. cat << _MANUALPAGE
  39. Name
  40. xdg-email -- command line tool for sending mail using the
  41. user's preferred e-mail composer
  42. Synopsis
  43. xdg-email [--utf8] [--cc address] [--bcc address] [--subject
  44. text] [--body text] [--attach file] [ mailto-uri | address(es)
  45. ]
  46. xdg-email { --help | --manual | --version }
  47. Description
  48. xdg-email opens the user's preferred e-mail composer in order
  49. to send a mail to address(es) or mailto-uri. RFC2368 defines
  50. mailto: URIs. xdg-email limits support to, cc, subject and body
  51. fields in mailto-uri, all other fields are silently ignored.
  52. address(es) must follow the syntax of RFC822. Multiple
  53. addresses may be provided as separate arguments.
  54. All information provided on the command line is used to prefill
  55. corresponding fields in the user's e-mail composer. The user
  56. will have the opportunity to change any of this information
  57. before actually sending the e-mail.
  58. xdg-email is for use inside a desktop session only. It is not
  59. recommended to use xdg-email as root.
  60. Options
  61. --utf8
  62. Indicates that all command line options that follow are
  63. in utf8. Without this option, command line options are
  64. expected to be encoded according to locale. If the
  65. locale already specifies utf8 this option has no effect.
  66. This option does not affect mailto URIs that are passed
  67. on the command line.
  68. --cc address
  69. Specify a recipient to be copied on the e-mail.
  70. --bcc address
  71. Specify a recipient to be blindly copied on the e-mail.
  72. --subject text
  73. Specify a subject for the e-mail.
  74. --body text
  75. Specify a body for the e-mail. Since the user will be
  76. able to make changes before actually sending the e-mail,
  77. this can be used to provide the user with a template for
  78. the e-mail. text may contain linebreaks.
  79. --attach file
  80. Specify an attachment for the e-mail. file must point to
  81. an existing file.
  82. Some e-mail applications require the file to remain
  83. present after xdg-email returns.
  84. --help
  85. Show command synopsis.
  86. --manual
  87. Show this manual page.
  88. --version
  89. Show the xdg-utils version information.
  90. Environment Variables
  91. xdg-email honours the following environment variables:
  92. XDG_UTILS_DEBUG_LEVEL
  93. Setting this environment variable to a non-zero
  94. numerical value makes xdg-email do more verbose
  95. reporting on stderr. Setting a higher value increases
  96. the verbosity.
  97. Exit Codes
  98. An exit code of 0 indicates success while a non-zero exit code
  99. indicates failure. The following failure codes can be returned:
  100. 1
  101. Error in command line syntax.
  102. 2
  103. One of the files passed on the command line did not
  104. exist.
  105. 3
  106. A required tool could not be found.
  107. 4
  108. The action failed.
  109. 5
  110. No permission to read one of the files passed on the
  111. command line.
  112. See Also
  113. xdg-open(1), xdg-mime(1), MIME applications associations
  114. specification, RFC 6068 - The 'mailto' URI Scheme
  115. Examples
  116. xdg-email 'Jeremy White <jwhite@example.com>'
  117. xdg-email --attach /tmp/logo.png \
  118. --subject 'Logo contest' \
  119. --body 'Attached you find the logo for the contest.' \
  120. 'jwhite@example.com'
  121. xdg-email --subject 'Your password is about to expire' \
  122. 'jwhite@example.com' 'bastian@example.com' 'whipple@example.co
  123. m'
  124. _MANUALPAGE
  125. }
  126. usage()
  127. {
  128. cat << _USAGE
  129. xdg-email -- command line tool for sending mail using the
  130. user's preferred e-mail composer
  131. Synopsis
  132. xdg-email [--utf8] [--cc address] [--bcc address] [--subject
  133. text] [--body text] [--attach file] [ mailto-uri | address(es)
  134. ]
  135. xdg-email { --help | --manual | --version }
  136. _USAGE
  137. }
  138. #@xdg-utils-common@
  139. #----------------------------------------------------------------------------
  140. # Common utility functions included in all XDG wrapper scripts
  141. #----------------------------------------------------------------------------
  142. DEBUG()
  143. {
  144. [ -z "${XDG_UTILS_DEBUG_LEVEL}" ] && return 0;
  145. [ ${XDG_UTILS_DEBUG_LEVEL} -lt $1 ] && return 0;
  146. shift
  147. echo "$@" >&2
  148. }
  149. # This handles backslashes but not quote marks.
  150. first_word()
  151. {
  152. read first rest
  153. echo "$first"
  154. }
  155. #-------------------------------------------------------------
  156. # map a binary to a .desktop file
  157. binary_to_desktop_file()
  158. {
  159. search="${XDG_DATA_HOME:-$HOME/.local/share}:${XDG_DATA_DIRS:-/usr/local/share:/usr/share}"
  160. binary="`which "$1"`"
  161. binary="`readlink -f "$binary"`"
  162. base="`basename "$binary"`"
  163. IFS=:
  164. for dir in $search; do
  165. unset IFS
  166. [ "$dir" ] || continue
  167. [ -d "$dir/applications" ] || [ -d "$dir/applnk" ] || continue
  168. for file in "$dir"/applications/*.desktop "$dir"/applications/*/*.desktop "$dir"/applnk/*.desktop "$dir"/applnk/*/*.desktop; do
  169. [ -r "$file" ] || continue
  170. # Check to make sure it's worth the processing.
  171. grep -q "^Exec.*$base" "$file" || continue
  172. # Make sure it's a visible desktop file (e.g. not "preferred-web-browser.desktop").
  173. grep -Eq "^(NoDisplay|Hidden)=true" "$file" && continue
  174. command="`grep -E "^Exec(\[[^]=]*])?=" "$file" | cut -d= -f 2- | first_word`"
  175. command="`which "$command"`"
  176. if [ x"`readlink -f "$command"`" = x"$binary" ]; then
  177. # Fix any double slashes that got added path composition
  178. echo "$file" | sed -e 's,//*,/,g'
  179. return
  180. fi
  181. done
  182. done
  183. }
  184. #-------------------------------------------------------------
  185. # map a .desktop file to a binary
  186. desktop_file_to_binary()
  187. {
  188. search="${XDG_DATA_HOME:-$HOME/.local/share}:${XDG_DATA_DIRS:-/usr/local/share:/usr/share}"
  189. desktop="`basename "$1"`"
  190. IFS=:
  191. for dir in $search; do
  192. unset IFS
  193. [ "$dir" ] && [ -d "$dir/applications" ] || [ -d "$dir/applnk" ] || continue
  194. # Check if desktop file contains -
  195. if [ "${desktop#*-}" != "$desktop" ]; then
  196. vendor=${desktop%-*}
  197. app=${desktop#*-}
  198. if [ -r $dir/applications/$vendor/$app ]; then
  199. file_path=$dir/applications/$vendor/$app
  200. elif [ -r $dir/applnk/$vendor/$app ]; then
  201. file_path=$dir/applnk/$vendor/$app
  202. fi
  203. fi
  204. if test -z "$file_path" ; then
  205. for indir in "$dir"/applications/ "$dir"/applications/*/ "$dir"/applnk/ "$dir"/applnk/*/; do
  206. file="$indir/$desktop"
  207. if [ -r "$file" ]; then
  208. file_path=$file
  209. break
  210. fi
  211. done
  212. fi
  213. if [ -r "$file_path" ]; then
  214. # Remove any arguments (%F, %f, %U, %u, etc.).
  215. command="`grep -E "^Exec(\[[^]=]*])?=" "$file_path" | cut -d= -f 2- | first_word`"
  216. command="`which "$command"`"
  217. readlink -f "$command"
  218. return
  219. fi
  220. done
  221. }
  222. #-------------------------------------------------------------
  223. # Exit script on successfully completing the desired operation
  224. exit_success()
  225. {
  226. if [ $# -gt 0 ]; then
  227. echo "$@"
  228. echo
  229. fi
  230. exit 0
  231. }
  232. #-----------------------------------------
  233. # Exit script on malformed arguments, not enough arguments
  234. # or missing required option.
  235. # prints usage information
  236. exit_failure_syntax()
  237. {
  238. if [ $# -gt 0 ]; then
  239. echo "xdg-email: $@" >&2
  240. echo "Try 'xdg-email --help' for more information." >&2
  241. else
  242. usage
  243. echo "Use 'man xdg-email' or 'xdg-email --manual' for additional info."
  244. fi
  245. exit 1
  246. }
  247. #-------------------------------------------------------------
  248. # Exit script on missing file specified on command line
  249. exit_failure_file_missing()
  250. {
  251. if [ $# -gt 0 ]; then
  252. echo "xdg-email: $@" >&2
  253. fi
  254. exit 2
  255. }
  256. #-------------------------------------------------------------
  257. # Exit script on failure to locate necessary tool applications
  258. exit_failure_operation_impossible()
  259. {
  260. if [ $# -gt 0 ]; then
  261. echo "xdg-email: $@" >&2
  262. fi
  263. exit 3
  264. }
  265. #-------------------------------------------------------------
  266. # Exit script on failure returned by a tool application
  267. exit_failure_operation_failed()
  268. {
  269. if [ $# -gt 0 ]; then
  270. echo "xdg-email: $@" >&2
  271. fi
  272. exit 4
  273. }
  274. #------------------------------------------------------------
  275. # Exit script on insufficient permission to read a specified file
  276. exit_failure_file_permission_read()
  277. {
  278. if [ $# -gt 0 ]; then
  279. echo "xdg-email: $@" >&2
  280. fi
  281. exit 5
  282. }
  283. #------------------------------------------------------------
  284. # Exit script on insufficient permission to write a specified file
  285. exit_failure_file_permission_write()
  286. {
  287. if [ $# -gt 0 ]; then
  288. echo "xdg-email: $@" >&2
  289. fi
  290. exit 6
  291. }
  292. check_input_file()
  293. {
  294. if [ ! -e "$1" ]; then
  295. exit_failure_file_missing "file '$1' does not exist"
  296. fi
  297. if [ ! -r "$1" ]; then
  298. exit_failure_file_permission_read "no permission to read file '$1'"
  299. fi
  300. }
  301. check_vendor_prefix()
  302. {
  303. file_label="$2"
  304. [ -n "$file_label" ] || file_label="filename"
  305. file=`basename "$1"`
  306. case "$file" in
  307. [[:alpha:]]*-*)
  308. return
  309. ;;
  310. esac
  311. echo "xdg-email: $file_label '$file' does not have a proper vendor prefix" >&2
  312. echo 'A vendor prefix consists of alpha characters ([a-zA-Z]) and is terminated' >&2
  313. echo 'with a dash ("-"). An example '"$file_label"' is '"'example-$file'" >&2
  314. echo "Use --novendor to override or 'xdg-email --manual' for additional info." >&2
  315. exit 1
  316. }
  317. check_output_file()
  318. {
  319. # if the file exists, check if it is writeable
  320. # if it does not exists, check if we are allowed to write on the directory
  321. if [ -e "$1" ]; then
  322. if [ ! -w "$1" ]; then
  323. exit_failure_file_permission_write "no permission to write to file '$1'"
  324. fi
  325. else
  326. DIR=`dirname "$1"`
  327. if [ ! -w "$DIR" ] || [ ! -x "$DIR" ]; then
  328. exit_failure_file_permission_write "no permission to create file '$1'"
  329. fi
  330. fi
  331. }
  332. #----------------------------------------
  333. # Checks for shared commands, e.g. --help
  334. check_common_commands()
  335. {
  336. while [ $# -gt 0 ] ; do
  337. parm="$1"
  338. shift
  339. case "$parm" in
  340. --help)
  341. usage
  342. echo "Use 'man xdg-email' or 'xdg-email --manual' for additional info."
  343. exit_success
  344. ;;
  345. --manual)
  346. manualpage
  347. exit_success
  348. ;;
  349. --version)
  350. echo "xdg-email 1.1.3"
  351. exit_success
  352. ;;
  353. esac
  354. done
  355. }
  356. check_common_commands "$@"
  357. [ -z "${XDG_UTILS_DEBUG_LEVEL}" ] && unset XDG_UTILS_DEBUG_LEVEL;
  358. if [ ${XDG_UTILS_DEBUG_LEVEL-0} -lt 1 ]; then
  359. # Be silent
  360. xdg_redirect_output=" > /dev/null 2> /dev/null"
  361. else
  362. # All output to stderr
  363. xdg_redirect_output=" >&2"
  364. fi
  365. #--------------------------------------
  366. # Checks for known desktop environments
  367. # set variable DE to the desktop environments name, lowercase
  368. detectDE()
  369. {
  370. # see https://bugs.freedesktop.org/show_bug.cgi?id=34164
  371. unset GREP_OPTIONS
  372. if [ -n "${XDG_CURRENT_DESKTOP}" ]; then
  373. case "${XDG_CURRENT_DESKTOP}" in
  374. # only recently added to menu-spec, pre-spec X- still in use
  375. Cinnamon|X-Cinnamon)
  376. DE=cinnamon;
  377. ;;
  378. ENLIGHTENMENT)
  379. DE=enlightenment;
  380. ;;
  381. # GNOME, GNOME-Classic:GNOME, or GNOME-Flashback:GNOME
  382. GNOME*)
  383. DE=gnome;
  384. ;;
  385. KDE)
  386. DE=kde;
  387. ;;
  388. # Deepin Desktop Environments
  389. DEEPIN|Deepin|deepin)
  390. DE=dde;
  391. ;;
  392. LXDE)
  393. DE=lxde;
  394. ;;
  395. LXQt)
  396. DE=lxqt;
  397. ;;
  398. MATE)
  399. DE=mate;
  400. ;;
  401. XFCE)
  402. DE=xfce
  403. ;;
  404. X-Generic)
  405. DE=generic
  406. ;;
  407. esac
  408. fi
  409. if [ x"$DE" = x"" ]; then
  410. # classic fallbacks
  411. if [ x"$KDE_FULL_SESSION" != x"" ]; then DE=kde;
  412. elif [ x"$GNOME_DESKTOP_SESSION_ID" != x"" ]; then DE=gnome;
  413. elif [ x"$MATE_DESKTOP_SESSION_ID" != x"" ]; then DE=mate;
  414. elif `dbus-send --print-reply --dest=org.freedesktop.DBus /org/freedesktop/DBus org.freedesktop.DBus.GetNameOwner string:org.gnome.SessionManager > /dev/null 2>&1` ; then DE=gnome;
  415. elif xprop -root _DT_SAVE_MODE 2> /dev/null | grep ' = \"xfce4\"$' >/dev/null 2>&1; then DE=xfce;
  416. elif xprop -root 2> /dev/null | grep -i '^xfce_desktop_window' >/dev/null 2>&1; then DE=xfce
  417. elif echo $DESKTOP | grep -q '^Enlightenment'; then DE=enlightenment;
  418. elif [ x"$LXQT_SESSION_CONFIG" != x"" ]; then DE=lxqt;
  419. fi
  420. fi
  421. if [ x"$DE" = x"" ]; then
  422. # fallback to checking $DESKTOP_SESSION
  423. case "$DESKTOP_SESSION" in
  424. gnome)
  425. DE=gnome;
  426. ;;
  427. LXDE|Lubuntu)
  428. DE=lxde;
  429. ;;
  430. MATE)
  431. DE=mate;
  432. ;;
  433. xfce|xfce4|'Xfce Session')
  434. DE=xfce;
  435. ;;
  436. esac
  437. fi
  438. if [ x"$DE" = x"" ]; then
  439. # fallback to uname output for other platforms
  440. case "$(uname 2>/dev/null)" in
  441. CYGWIN*)
  442. DE=cygwin;
  443. ;;
  444. Darwin)
  445. DE=darwin;
  446. ;;
  447. esac
  448. fi
  449. if [ x"$DE" = x"gnome" ]; then
  450. # gnome-default-applications-properties is only available in GNOME 2.x
  451. # but not in GNOME 3.x
  452. which gnome-default-applications-properties > /dev/null 2>&1 || DE="gnome3"
  453. fi
  454. if [ -f "$XDG_RUNTIME_DIR/flatpak-info" ]; then
  455. DE="flatpak"
  456. fi
  457. }
  458. #----------------------------------------------------------------------------
  459. # kfmclient exec/openURL can give bogus exit value in KDE <= 3.5.4
  460. # It also always returns 1 in KDE 3.4 and earlier
  461. # Simply return 0 in such case
  462. kfmclient_fix_exit_code()
  463. {
  464. version=`LC_ALL=C.UTF-8 kde-config --version 2>/dev/null | grep '^KDE'`
  465. major=`echo $version | sed 's/KDE.*: \([0-9]\).*/\1/'`
  466. minor=`echo $version | sed 's/KDE.*: [0-9]*\.\([0-9]\).*/\1/'`
  467. release=`echo $version | sed 's/KDE.*: [0-9]*\.[0-9]*\.\([0-9]\).*/\1/'`
  468. test "$major" -gt 3 && return $1
  469. test "$minor" -gt 5 && return $1
  470. test "$release" -gt 4 && return $1
  471. return 0
  472. }
  473. #----------------------------------------------------------------------------
  474. # Returns true if there is a graphical display attached.
  475. has_display()
  476. {
  477. if [ -n "$DISPLAY" ] || [ -n "$WAYLAND_DISPLAY" ]; then
  478. return 0
  479. else
  480. return 1
  481. fi
  482. }
  483. run_thunderbird()
  484. {
  485. local THUNDERBIRD MAILTO NEWMAILTO TO CC BCC SUBJECT BODY ATTACH
  486. THUNDERBIRD="$1"
  487. MAILTO=$(echo "$2" | sed 's/^mailto://')
  488. echo "$MAILTO" | grep -qs "^?"
  489. if [ "$?" = "0" ] ; then
  490. MAILTO=$(echo "$MAILTO" | sed 's/^?//')
  491. else
  492. MAILTO=$(echo "$MAILTO" | sed 's/^/to=/' | sed 's/?/\&/')
  493. fi
  494. MAILTO=$(echo "$MAILTO" | sed 's/&/\n/g')
  495. TO=$(/bin/echo -e $(echo "$MAILTO" | grep '^to=' | sed 's/^to=//;s/%\(..\)/\\x\1/g' | awk '{ printf "%s,",$0 }'))
  496. CC=$(/bin/echo -e $(echo "$MAILTO" | grep '^cc=' | sed 's/^cc=//;s/%\(..\)/\\x\1/g' | awk '{ printf "%s,",$0 }'))
  497. BCC=$(/bin/echo -e $(echo "$MAILTO" | grep '^bcc=' | sed 's/^bcc=//;s/%\(..\)/\\x\1/g' | awk '{ printf "%s,",$0 }'))
  498. SUBJECT=$(echo "$MAILTO" | grep '^subject=' | tail -n 1)
  499. BODY=$(echo "$MAILTO" | grep '^body=' | tail -n 1)
  500. ATTACH=$(/bin/echo -e $(echo "$MAILTO" | grep '^attach=' | sed 's/^attach=//;s/%\(..\)/\\x\1/g' | awk '{ printf "%s,",$0 }' | sed 's/,$//'))
  501. if [ -z "$TO" ] ; then
  502. NEWMAILTO=
  503. else
  504. NEWMAILTO="to='$TO'"
  505. fi
  506. if [ -n "$CC" ] ; then
  507. NEWMAILTO="${NEWMAILTO},cc='$CC'"
  508. fi
  509. if [ -n "$BCC" ] ; then
  510. NEWMAILTO="${NEWMAILTO},bcc='$BCC'"
  511. fi
  512. if [ -n "$SUBJECT" ] ; then
  513. NEWMAILTO="${NEWMAILTO},$SUBJECT"
  514. fi
  515. if [ -n "$BODY" ] ; then
  516. NEWMAILTO="${NEWMAILTO},$BODY"
  517. fi
  518. if [ -n "$ATTACH" ] ; then
  519. NEWMAILTO="${NEWMAILTO},attachment='${ATTACH}'"
  520. fi
  521. NEWMAILTO=$(echo "$NEWMAILTO" | sed 's/^,//')
  522. DEBUG 1 "Running $THUNDERBIRD -compose \"$NEWMAILTO\""
  523. "$THUNDERBIRD" -compose "$NEWMAILTO"
  524. if [ $? -eq 0 ]; then
  525. exit_success
  526. else
  527. exit_failure_operation_failed
  528. fi
  529. }
  530. open_kde()
  531. {
  532. if [ -n "$KDE_SESSION_VERSION" ] && [ "$KDE_SESSION_VERSION" -ge 5 ]; then
  533. local kreadconfig=kreadconfig$KDE_SESSION_VERSION
  534. else
  535. local kreadconfig=kreadconfig
  536. fi
  537. if which $kreadconfig >/dev/null 2>&1; then
  538. local profile=$($kreadconfig --file emaildefaults \
  539. --group Defaults --key Profile)
  540. if [ -n "$profile" ]; then
  541. local client=$($kreadconfig --file emaildefaults \
  542. --group "PROFILE_$profile" \
  543. --key EmailClient \
  544. | cut -d ' ' -f 1)
  545. if echo "$client" | grep -Eq 'thunderbird|icedove'; then
  546. run_thunderbird "$client" "$1"
  547. fi
  548. fi
  549. fi
  550. local command
  551. case "$KDE_SESSION_VERSION" in
  552. '') command=kmailservice ;;
  553. 4) command=kde-open ;;
  554. *) command=kde-open$KDE_SESSION_VERSION ;;
  555. esac
  556. if which $command >/dev/null 2>&1; then
  557. DEBUG 1 "Running $command \"$1\""
  558. if [ "$KDE_SESSION_VERSION" = 3 ]; then
  559. # KDE3 uses locale's encoding when decoding the URI,
  560. # so set it to UTF-8
  561. LC_ALL=C.UTF-8 $command "$1"
  562. else
  563. $command "$1"
  564. fi
  565. else
  566. DEBUG 1 "$command missing; trying generic mode instead."
  567. open_generic "$1"
  568. fi
  569. if [ $? = 0 ]; then
  570. exit_success
  571. else
  572. exit_failure_operation_failed
  573. fi
  574. }
  575. open_gnome3()
  576. {
  577. local client
  578. local desktop
  579. desktop=`xdg-mime query default "x-scheme-handler/mailto"`
  580. client=`desktop_file_to_binary "$desktop"`
  581. echo $client | grep -E 'thunderbird|icedove' > /dev/null 2>&1
  582. if [ $? -eq 0 ] ; then
  583. run_thunderbird "$client" "$1"
  584. fi
  585. if gio help open 2>/dev/null 1>&2; then
  586. DEBUG 1 "Running gio open \"$1\""
  587. gio open "$1"
  588. elif gvfs-open --help 2>/dev/null 1>&2; then
  589. DEBUG 1 "Running gvfs-open \"$1\""
  590. gvfs-open "$1"
  591. else
  592. DEBUG 1 "Running gnome-open \"$1\""
  593. gnome-open "$1"
  594. fi
  595. if [ $? -eq 0 ]; then
  596. exit_success
  597. else
  598. exit_failure_operation_failed
  599. fi
  600. }
  601. open_gnome()
  602. {
  603. local client
  604. client=`gconftool-2 --get /desktop/gnome/url-handlers/mailto/command | cut -d ' ' -f 1` || ""
  605. echo $client | grep -E 'thunderbird|icedove' > /dev/null 2>&1
  606. if [ $? -eq 0 ] ; then
  607. run_thunderbird "$client" "$1"
  608. fi
  609. if gio help open 2>/dev/null 1>&2; then
  610. DEBUG 1 "Running gio open \"$1\""
  611. gio open "$1"
  612. elif gvfs-open --help 2>/dev/null 1>&2; then
  613. DEBUG 1 "Running gvfs-open \"$1\""
  614. gvfs-open "$1"
  615. else
  616. DEBUG 1 "Running gnome-open \"$1\""
  617. gnome-open "$1"
  618. fi
  619. if [ $? -eq 0 ]; then
  620. exit_success
  621. else
  622. exit_failure_operation_failed
  623. fi
  624. }
  625. open_xfce()
  626. {
  627. DEBUG 1 "Running exo-open \"$1\""
  628. exo-open "$1"
  629. if [ $? -eq 0 ]; then
  630. exit_success
  631. else
  632. exit_failure_operation_failed
  633. fi
  634. }
  635. open_envvar()
  636. {
  637. local OLDIFS="$IFS"
  638. IFS=:
  639. for i in $MAILER; do
  640. IFS="$OLDIFS"
  641. eval "$i" '"$1"'
  642. if [ $? -eq 0 ]; then
  643. exit_success
  644. fi
  645. done
  646. exit_failure_operation_failed
  647. }
  648. open_flatpak()
  649. {
  650. gdbus call --session \
  651. --dest org.freedesktop.portal.Desktop \
  652. --object-path /org/freedesktop/portal/desktop \
  653. --method org.freedesktop.portal.OpenURI.OpenURI \
  654. "" "$1" {}
  655. if [ $? -eq 0 ]; then
  656. exit_success
  657. else
  658. exit_failure_operation_failed
  659. fi
  660. }
  661. open_generic()
  662. {
  663. local client
  664. local desktop
  665. desktop=`xdg-mime query default "x-scheme-handler/mailto"`
  666. client=`desktop_file_to_binary "$desktop"`
  667. echo $client | grep -E 'thunderbird|icedove' > /dev/null 2>&1
  668. if [ $? -eq 0 ] ; then
  669. run_thunderbird "$client" "$1"
  670. fi
  671. xdg-open "$1"
  672. local ret=$?
  673. # 3 means exit_failure_operation_impossible
  674. if [ $ret != 3 ]; then
  675. exit $ret
  676. fi
  677. IFS=":"
  678. for browser in $BROWSER; do
  679. if [ x"$browser" != x"" ]; then
  680. browser_with_arg=`printf "$browser" "$1" 2>/dev/null`
  681. if [ $? -ne 0 ]; then browser_with_arg=$browser;
  682. fi
  683. if [ x"$browser_with_arg" = x"$browser" ]; then "$browser" "$1";
  684. else $browser_with_arg;
  685. fi
  686. if [ $? -eq 0 ]; then exit_success;
  687. fi
  688. fi
  689. done
  690. exit_failure_operation_impossible "no method available for opening '$1'"
  691. }
  692. url_encode()
  693. {
  694. # The shell needs the default internal field separator
  695. # otherwise it would search for $utf8 as a command in whole.
  696. IFS=" "
  697. str=$(echo "$1" | $utf8)
  698. local ORIG_LANG="$LANG"
  699. local ORIG_LC_ALL="$LC_ALL"
  700. LANG=C
  701. LC_ALL=C
  702. result=$(echo "$str" | awk '
  703. BEGIN {
  704. for ( i=1; i<=255; ++i ) ord [ sprintf ("%c", i) "" ] = i + 0
  705. e = ""
  706. linenr = 1
  707. }
  708. {
  709. if ( linenr++ != 1 ) {
  710. e = e "%0D%0A"
  711. }
  712. for ( i=1; i<=length ($0); ++i ) {
  713. c = substr ($0, i, 1)
  714. if ( ord [c] > 127 ) {
  715. e = e "%" sprintf("%02X", ord [c])
  716. } else if ( c ~ /[@a-zA-Z0-9.\-\\\/]/ ) {
  717. e = e c
  718. } else {
  719. e = e "%" sprintf("%02X", ord [c])
  720. }
  721. }
  722. }
  723. END {
  724. print e
  725. }
  726. ')
  727. LANG="$ORIG_LANG"
  728. LC_ALL="$ORIG_LC_ALL"
  729. }
  730. options=
  731. mailto=
  732. utf8="iconv -t utf8"
  733. while [ $# -gt 0 ] ; do
  734. parm="$1"
  735. shift
  736. case "$parm" in
  737. --utf8)
  738. utf8="cat"
  739. ;;
  740. --to)
  741. if [ -z "$1" ] ; then
  742. exit_failure_syntax "email address argument missing for --to"
  743. fi
  744. url_encode "$1"
  745. options="${options}to=${result}&"
  746. shift
  747. ;;
  748. --cc)
  749. if [ -z "$1" ] ; then
  750. exit_failure_syntax "email address argument missing for --cc"
  751. fi
  752. url_encode "$1"
  753. options="${options}cc=${result}&"
  754. shift
  755. ;;
  756. --bcc)
  757. if [ -z "$1" ] ; then
  758. exit_failure_syntax "email address argument missing for --bcc"
  759. fi
  760. url_encode "$1"
  761. options="${options}bcc=${result}&"
  762. shift
  763. ;;
  764. --subject)
  765. if [ -z "$1" ] ; then
  766. exit_failure_syntax "text argument missing for --subject option"
  767. fi
  768. url_encode "$1"
  769. options="${options}subject=${result}&"
  770. shift
  771. ;;
  772. --body)
  773. if [ -z "$1" ] ; then
  774. exit_failure_syntax "text argument missing for --body option"
  775. fi
  776. url_encode "$1"
  777. options="${options}body=${result}&"
  778. shift
  779. ;;
  780. --attach)
  781. if [ -z "$1" ] ; then
  782. exit_failure_syntax "file argument missing for --attach option"
  783. fi
  784. check_input_file "$1"
  785. file=`readlink -f "$1"` # Normalize path
  786. if [ -z "$file" ] || [ ! -f "$file" ] ; then
  787. exit_failure_file_missing "file '$1' does not exist"
  788. fi
  789. url_encode "$file"
  790. options="${options}attach=${result}&"
  791. shift
  792. ;;
  793. -*)
  794. exit_failure_syntax "unexpected option '$parm'"
  795. ;;
  796. mailto:*)
  797. mailto="$parm"
  798. ;;
  799. *@*)
  800. url_encode "$parm"
  801. if [ -z "${mailto}" ] ; then
  802. mailto="mailto:"${result}"?"
  803. else
  804. options="${options}to=${result}&"
  805. fi
  806. ;;
  807. *)
  808. exit_failure_syntax "unexpected argument '$parm'"
  809. ;;
  810. esac
  811. done
  812. if [ -z "${mailto}" ] ; then
  813. # TO address is optional
  814. mailto="mailto:?"
  815. fi
  816. case $mailto in
  817. *\?)
  818. mailto="${mailto}${options}"
  819. ;;
  820. *\?*)
  821. mailto="${mailto}&${options}"
  822. ;;
  823. *)
  824. mailto="${mailto}?${options}"
  825. ;;
  826. esac
  827. # Strip trailing ? and &
  828. mailto=`echo "${mailto}"| sed 's/[?&]$//'`
  829. # Shouldn't happen
  830. [ x"${mailto}" != x"" ] || exit_failure_syntax
  831. if which xdg-email-hook.sh > /dev/null 2> /dev/null; then
  832. xdg-email-hook.sh "${mailto}"
  833. if [ $? -eq 0 ]; then
  834. exit_success
  835. else
  836. exit_failure_operation_failed
  837. fi
  838. fi
  839. detectDE
  840. if [ x"$DE" = x"" ]; then
  841. DE=generic
  842. fi
  843. if [ x"$MAILER" != x"" ]; then
  844. DE=envvar
  845. fi
  846. # if BROWSER variable is not set, check some well known browsers instead
  847. if [ x"$BROWSER" = x"" ]; then
  848. BROWSER=www-browser:links2:elinks:links:lynx:w3m
  849. if has_display; then
  850. BROWSER=x-www-browser:firefox:iceweasel:seamonkey:mozilla:epiphany:konqueror:chromium-browser:google-chrome:$BROWSER
  851. fi
  852. fi
  853. case "$DE" in
  854. envvar)
  855. open_envvar "${mailto}"
  856. ;;
  857. kde)
  858. open_kde "${mailto}"
  859. ;;
  860. gnome)
  861. open_gnome "${mailto}"
  862. ;;
  863. gnome3|cinnamon|lxde|mate)
  864. open_gnome3 "${mailto}"
  865. ;;
  866. xfce)
  867. open_xfce "${mailto}"
  868. ;;
  869. flatpak)
  870. open_flatpak "$url"
  871. ;;
  872. generic|lxqt|enlightenment)
  873. open_generic "${mailto}"
  874. ;;
  875. *)
  876. exit_failure_operation_impossible "no method available for opening '${mailto}'"
  877. ;;
  878. esac