OLD | NEW |
(Empty) | |
| 1 #!/bin/bash |
| 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 2006, Kevin Krammer <kevin.krammer@gmx.at> |
| 11 # Copyright 2006, Jeremy White <jwhite@codeweavers.com> |
| 12 # |
| 13 # LICENSE: |
| 14 # |
| 15 # Permission is hereby granted, free of charge, to any person obtaining a |
| 16 # copy of this software and associated documentation files (the "Software"), |
| 17 # to deal in the Software without restriction, including without limitation |
| 18 # the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| 19 # and/or sell copies of the Software, and to permit persons to whom the |
| 20 # Software is furnished to do so, subject to the following conditions: |
| 21 # |
| 22 # The above copyright notice and this permission notice shall be included |
| 23 # in all copies or substantial portions of the Software. |
| 24 # |
| 25 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
| 26 # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 27 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| 28 # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR |
| 29 # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
| 30 # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
| 31 # OTHER DEALINGS IN THE SOFTWARE. |
| 32 # |
| 33 #--------------------------------------------- |
| 34 |
| 35 manualpage() |
| 36 { |
| 37 cat << _MANUALPAGE |
| 38 Name |
| 39 |
| 40 xdg-email - command line tool for sending mail using the user's preferred |
| 41 e-mail composer |
| 42 |
| 43 Synopsis |
| 44 |
| 45 xdg-email [--utf8] [--cc address] [--bcc address] [--subject text] [--body text |
| 46 ] [--attach file] [ mailto-uri | address(es) ] |
| 47 |
| 48 xdg-email { --help | --manual | --version } |
| 49 |
| 50 Description |
| 51 |
| 52 xdg-email opens the user's preferred e-mail composer in order to send a mail to |
| 53 address(es) or mailto-uri. RFC2368 defines mailto: URIs. xdg-email limits |
| 54 support to, cc, subject and body fields in mailto-uri, all other fields are |
| 55 silently ignored. address(es) must follow the syntax of RFC822. Multiple |
| 56 addresses may be provided as separate arguments. |
| 57 |
| 58 All information provided on the command line is used to prefill corresponding |
| 59 fields in the user's e-mail composer. The user will have the opportunity to |
| 60 change any of this information before actually sending the e-mail. |
| 61 |
| 62 xdg-email is for use inside a desktop session only. It is not recommended to |
| 63 use xdg-email as root. |
| 64 |
| 65 See http://portland.freedesktop.org/EmailConfig for information on how the user |
| 66 can change the e-mail composer that is used. |
| 67 |
| 68 Options |
| 69 |
| 70 --utf8 |
| 71 Indicates that all command line options that follow are in utf8. Without |
| 72 this option, command line options are expected to be encoded according to |
| 73 locale. If the locale already specifies utf8 this option has no effect. |
| 74 This option does not affect mailto URIs that are passed on the command |
| 75 line. |
| 76 --cc address |
| 77 Specify a recipient to be copied on the e-mail. |
| 78 --bcc address |
| 79 Specify a recipient to be blindly copied on the e-mail. |
| 80 --subject text |
| 81 Specify a subject for the e-mail. |
| 82 --body text |
| 83 Specify a body for the e-mail. Since the user will be able to make changes |
| 84 before actually sending the e-mail, this can be used to provide the user |
| 85 with a template for the e-mail. text may contain linebreaks. |
| 86 --attach file |
| 87 |
| 88 Specify an attachment for the e-mail. file must point to an existing file. |
| 89 |
| 90 Some e-mail applications require the file to remain present after xdg-email |
| 91 returns. |
| 92 |
| 93 --help |
| 94 Show command synopsis. |
| 95 --manual |
| 96 Show this manualpage. |
| 97 --version |
| 98 Show the xdg-utils version information. |
| 99 |
| 100 Environment Variables |
| 101 |
| 102 xdg-email honours the following environment variables: |
| 103 |
| 104 XDG_UTILS_DEBUG_LEVEL |
| 105 Setting this environment variable to a non-zero numerical value makes |
| 106 xdg-email do more verbose reporting on stderr. Setting a higher value |
| 107 increases the verbosity. |
| 108 |
| 109 Exit Codes |
| 110 |
| 111 An exit code of 0 indicates success while a non-zero exit code indicates |
| 112 failure. The following failure codes can be returned: |
| 113 |
| 114 1 |
| 115 Error in command line syntax. |
| 116 2 |
| 117 One of the files passed on the command line did not exist. |
| 118 3 |
| 119 A required tool could not be found. |
| 120 4 |
| 121 The action failed. |
| 122 5 |
| 123 No permission to read one of the files passed on the command line. |
| 124 |
| 125 Configuration |
| 126 |
| 127 Visit http://portland.freedesktop.org/EmailConfig for information how to |
| 128 configure xdg-email to use the email client of your choice. |
| 129 |
| 130 Examples |
| 131 |
| 132 xdg-email 'Jeremy White <jwhite@example.com>' |
| 133 |
| 134 xdg-email --attach /tmp/logo.png \ |
| 135 --subject 'Logo contest' \ |
| 136 --body 'Attached you find the logo for the contest.' \ |
| 137 'jwhite@example.com' |
| 138 |
| 139 xdg-email --subject 'Your password is about to expire' \ |
| 140 'jwhite@example.com' 'bastian@example.com' 'whipple@example.com' |
| 141 |
| 142 _MANUALPAGE |
| 143 } |
| 144 |
| 145 usage() |
| 146 { |
| 147 cat << _USAGE |
| 148 xdg-email - command line tool for sending mail using the user's preferred |
| 149 e-mail composer |
| 150 |
| 151 Synopsis |
| 152 |
| 153 xdg-email [--utf8] [--cc address] [--bcc address] [--subject text] [--body text |
| 154 ] [--attach file] [ mailto-uri | address(es) ] |
| 155 |
| 156 xdg-email { --help | --manual | --version } |
| 157 |
| 158 _USAGE |
| 159 } |
| 160 |
| 161 #@xdg-utils-common@ |
| 162 |
| 163 #---------------------------------------------------------------------------- |
| 164 # Common utility functions included in all XDG wrapper scripts |
| 165 #---------------------------------------------------------------------------- |
| 166 |
| 167 DEBUG() |
| 168 { |
| 169 [ -z "${XDG_UTILS_DEBUG_LEVEL}" ] && return 0; |
| 170 [ ${XDG_UTILS_DEBUG_LEVEL} -lt $1 ] && return 0; |
| 171 shift |
| 172 echo "$@" >&2 |
| 173 } |
| 174 |
| 175 #------------------------------------------------------------- |
| 176 # Exit script on successfully completing the desired operation |
| 177 |
| 178 exit_success() |
| 179 { |
| 180 if [ $# -gt 0 ]; then |
| 181 echo "$@" |
| 182 echo |
| 183 fi |
| 184 |
| 185 exit 0 |
| 186 } |
| 187 |
| 188 |
| 189 #----------------------------------------- |
| 190 # Exit script on malformed arguments, not enough arguments |
| 191 # or missing required option. |
| 192 # prints usage information |
| 193 |
| 194 exit_failure_syntax() |
| 195 { |
| 196 if [ $# -gt 0 ]; then |
| 197 echo "xdg-email: $@" >&2 |
| 198 echo "Try 'xdg-email --help' for more information." >&2 |
| 199 else |
| 200 usage |
| 201 echo "Use 'man xdg-email' or 'xdg-email --manual' for additional info." |
| 202 fi |
| 203 |
| 204 exit 1 |
| 205 } |
| 206 |
| 207 #------------------------------------------------------------- |
| 208 # Exit script on missing file specified on command line |
| 209 |
| 210 exit_failure_file_missing() |
| 211 { |
| 212 if [ $# -gt 0 ]; then |
| 213 echo "xdg-email: $@" >&2 |
| 214 fi |
| 215 |
| 216 exit 2 |
| 217 } |
| 218 |
| 219 #------------------------------------------------------------- |
| 220 # Exit script on failure to locate necessary tool applications |
| 221 |
| 222 exit_failure_operation_impossible() |
| 223 { |
| 224 if [ $# -gt 0 ]; then |
| 225 echo "xdg-email: $@" >&2 |
| 226 fi |
| 227 |
| 228 exit 3 |
| 229 } |
| 230 |
| 231 #------------------------------------------------------------- |
| 232 # Exit script on failure returned by a tool application |
| 233 |
| 234 exit_failure_operation_failed() |
| 235 { |
| 236 if [ $# -gt 0 ]; then |
| 237 echo "xdg-email: $@" >&2 |
| 238 fi |
| 239 |
| 240 exit 4 |
| 241 } |
| 242 |
| 243 #------------------------------------------------------------ |
| 244 # Exit script on insufficient permission to read a specified file |
| 245 |
| 246 exit_failure_file_permission_read() |
| 247 { |
| 248 if [ $# -gt 0 ]; then |
| 249 echo "xdg-email: $@" >&2 |
| 250 fi |
| 251 |
| 252 exit 5 |
| 253 } |
| 254 |
| 255 #------------------------------------------------------------ |
| 256 # Exit script on insufficient permission to read a specified file |
| 257 |
| 258 exit_failure_file_permission_write() |
| 259 { |
| 260 if [ $# -gt 0 ]; then |
| 261 echo "xdg-email: $@" >&2 |
| 262 fi |
| 263 |
| 264 exit 6 |
| 265 } |
| 266 |
| 267 check_input_file() |
| 268 { |
| 269 if [ ! -e "$1" ]; then |
| 270 exit_failure_file_missing "file '$1' does not exist" |
| 271 fi |
| 272 if [ ! -r "$1" ]; then |
| 273 exit_failure_file_permission_read "no permission to read file '$1'" |
| 274 fi |
| 275 } |
| 276 |
| 277 check_vendor_prefix() |
| 278 { |
| 279 file_label="$2" |
| 280 [ -n "$file_label" ] || file_label="filename" |
| 281 file=`basename "$1"` |
| 282 case "$file" in |
| 283 [a-zA-Z]*-*) |
| 284 return |
| 285 ;; |
| 286 esac |
| 287 |
| 288 echo "xdg-email: $file_label '$file' does not have a proper vendor prefix" >
&2 |
| 289 echo 'A vendor prefix consists of alpha characters ([a-zA-Z]) and is termina
ted' >&2 |
| 290 echo 'with a dash ("-"). An example '"$file_label"' is '"'example-$file'" >&
2 |
| 291 echo "Use --novendor to override or 'xdg-email --manual' for additional info
." >&2 |
| 292 exit 1 |
| 293 } |
| 294 |
| 295 check_output_file() |
| 296 { |
| 297 # if the file exists, check if it is writeable |
| 298 # if it does not exists, check if we are allowed to write on the directory |
| 299 if [ -e "$1" ]; then |
| 300 if [ ! -w "$1" ]; then |
| 301 exit_failure_file_permission_write "no permission to write to file '
$1'" |
| 302 fi |
| 303 else |
| 304 DIR=`dirname "$1"` |
| 305 if [ ! -w "$DIR" -o ! -x "$DIR" ]; then |
| 306 exit_failure_file_permission_write "no permission to create file '$1
'" |
| 307 fi |
| 308 fi |
| 309 } |
| 310 |
| 311 #---------------------------------------- |
| 312 # Checks for shared commands, e.g. --help |
| 313 |
| 314 check_common_commands() |
| 315 { |
| 316 while [ $# -gt 0 ] ; do |
| 317 parm="$1" |
| 318 shift |
| 319 |
| 320 case "$parm" in |
| 321 --help) |
| 322 usage |
| 323 echo "Use 'man xdg-email' or 'xdg-email --manual' for additional inf
o." |
| 324 exit_success |
| 325 ;; |
| 326 |
| 327 --manual) |
| 328 manualpage |
| 329 exit_success |
| 330 ;; |
| 331 |
| 332 --version) |
| 333 echo "xdg-email 1.0.1" |
| 334 exit_success |
| 335 ;; |
| 336 esac |
| 337 done |
| 338 } |
| 339 |
| 340 check_common_commands "$@" |
| 341 |
| 342 [ -z "${XDG_UTILS_DEBUG_LEVEL}" ] && unset XDG_UTILS_DEBUG_LEVEL; |
| 343 if [ ${XDG_UTILS_DEBUG_LEVEL-0} -lt 1 ]; then |
| 344 # Be silent |
| 345 xdg_redirect_output=" > /dev/null 2> /dev/null" |
| 346 else |
| 347 # All output to stderr |
| 348 xdg_redirect_output=" >&2" |
| 349 fi |
| 350 |
| 351 #-------------------------------------- |
| 352 # Checks for known desktop environments |
| 353 # set variable DE to the desktop environments name, lowercase |
| 354 |
| 355 detectDE() |
| 356 { |
| 357 if [ x"$KDE_FULL_SESSION" = x"true" ]; then DE=kde; |
| 358 elif [ x"$GNOME_DESKTOP_SESSION_ID" != x"" ]; then DE=gnome; |
| 359 elif xprop -root _DT_SAVE_MODE | grep ' = \"xfce4\"$' >/dev/null 2>&1; then
DE=xfce; |
| 360 fi |
| 361 } |
| 362 |
| 363 #---------------------------------------------------------------------------- |
| 364 # kfmclient exec/openURL can give bogus exit value in KDE <= 3.5.4 |
| 365 # It also always returns 1 in KDE 3.4 and earlier |
| 366 # Simply return 0 in such case |
| 367 |
| 368 kfmclient_fix_exit_code() |
| 369 { |
| 370 version=`kde${KDE_SESSION_VERSION}-config --version 2>/dev/null | grep KDE` |
| 371 major=`echo $version | sed 's/KDE: \([0-9]\).*/\1/'` |
| 372 minor=`echo $version | sed 's/KDE: [0-9]*\.\([0-9]\).*/\1/'` |
| 373 release=`echo $version | sed 's/KDE: [0-9]*\.[0-9]*\.\([0-9]\).*/\1/'` |
| 374 test "$major" -gt 3 && return $1 |
| 375 test "$minor" -gt 5 && return $1 |
| 376 test "$release" -gt 4 && return $1 |
| 377 return 0 |
| 378 } |
| 379 |
| 380 open_kde() |
| 381 { |
| 382 local client |
| 383 if [ -f /etc/SuSE-release ] ; then |
| 384 # Workaround for SUSE 10.0 |
| 385 client=`kreadconfig --file emaildefaults --group PROFILE_Default --key E
mailClient| cut -d ' ' -f 1` |
| 386 [ -z $client ] && client="kmail" |
| 387 if ! which $client > /dev/null 2> /dev/null; then |
| 388 DEBUG 3 "KDE has $client configured as email client which isn't inst
alled" |
| 389 if which gnome-open > /dev/null 2> /dev/null && which evolution > /d
ev/null 2> /dev/null; then |
| 390 DEBUG 3 "Try gnome-open instead" |
| 391 open_gnome "$1" |
| 392 fi |
| 393 fi |
| 394 fi |
| 395 DEBUG 1 "Running kmailservice \"$1\"" |
| 396 # KDE uses locale's encoding when decoding the URI, so set it to UTF-8 |
| 397 LC_ALL=C.UTF-8 kmailservice "$1" |
| 398 kfmclient_fix_exit_code $? |
| 399 |
| 400 if [ $? -eq 0 ]; then |
| 401 exit_success |
| 402 else |
| 403 exit_failure_operation_failed |
| 404 fi |
| 405 } |
| 406 |
| 407 open_gnome() |
| 408 { |
| 409 DEBUG 1 "Running gnome-open \"$1\"" |
| 410 gnome-open "$1" |
| 411 |
| 412 if [ $? -eq 0 ]; then |
| 413 exit_success |
| 414 else |
| 415 exit_failure_operation_failed |
| 416 fi |
| 417 } |
| 418 |
| 419 |
| 420 open_xfce() |
| 421 { |
| 422 DEBUG 1 "Running exo-open \"$1\"" |
| 423 exo-open "$1" |
| 424 |
| 425 if [ $? -eq 0 ]; then |
| 426 exit_success |
| 427 else |
| 428 exit_failure_operation_failed |
| 429 fi |
| 430 } |
| 431 |
| 432 open_generic() |
| 433 { |
| 434 IFS=":" |
| 435 for browser in $BROWSER; do |
| 436 if [ x"$browser" != x"" ]; then |
| 437 |
| 438 IFS=' ' |
| 439 browser_with_arg=${browser//'%s'/"$1"} |
| 440 |
| 441 if [ x"$browser_with_arg" = x"$browser" ]; then "$browser" "$1"; |
| 442 else $browser_with_arg; |
| 443 fi |
| 444 |
| 445 if [ $? -eq 0 ]; then exit_success; |
| 446 fi |
| 447 fi |
| 448 done |
| 449 |
| 450 exit_failure_operation_impossible "no method available for opening '$1'" |
| 451 } |
| 452 |
| 453 url_encode() |
| 454 { |
| 455 result=$(echo "$1" | $utf8 | awk ' |
| 456 BEGIN { |
| 457 for ( i=1; i<=255; ++i ) ord [ sprintf ("%c", i) "" ] = i + 0 |
| 458 e = "" |
| 459 linenr = 1 |
| 460 } |
| 461 { |
| 462 if ( linenr++ != 1 ) { |
| 463 e = e "%0D%0A" |
| 464 } |
| 465 for ( i=1; i<=length ($0); ++i ) { |
| 466 c = substr ($0, i, 1) |
| 467 if ( ord [c] > 127 ) { |
| 468 e = e "%" sprintf("%02X", ord [c]) |
| 469 } else if ( c ~ /[@a-zA-Z0-9.-]/ ) { |
| 470 e = e c |
| 471 } else { |
| 472 e = e "%" sprintf("%02X", ord [c]) |
| 473 } |
| 474 } |
| 475 } |
| 476 END { |
| 477 print e |
| 478 } |
| 479 ') |
| 480 } |
| 481 |
| 482 options= |
| 483 mailto= |
| 484 utf8="iconv -t utf8" |
| 485 while [ $# -gt 0 ] ; do |
| 486 parm="$1" |
| 487 shift |
| 488 |
| 489 case "$parm" in |
| 490 --utf8) |
| 491 utf8="cat" |
| 492 ;; |
| 493 |
| 494 --to) |
| 495 if [ -z "$1" ] ; then |
| 496 exit_failure_syntax "email address argument missing for --to" |
| 497 fi |
| 498 url_encode "$1" |
| 499 options="${options}to=${result}&" |
| 500 shift |
| 501 ;; |
| 502 |
| 503 --cc) |
| 504 if [ -z "$1" ] ; then |
| 505 exit_failure_syntax "email address argument missing for --cc" |
| 506 fi |
| 507 url_encode "$1" |
| 508 options="${options}cc=${result}&" |
| 509 shift |
| 510 ;; |
| 511 |
| 512 --bcc) |
| 513 if [ -z "$1" ] ; then |
| 514 exit_failure_syntax "email address argument missing for --bcc" |
| 515 fi |
| 516 url_encode "$1" |
| 517 options="${options}bcc=${result}&" |
| 518 shift |
| 519 ;; |
| 520 |
| 521 --subject) |
| 522 if [ -z "$1" ] ; then |
| 523 exit_failure_syntax "text argument missing for --subject option" |
| 524 fi |
| 525 url_encode "$1" |
| 526 options="${options}subject=${result}&" |
| 527 shift |
| 528 ;; |
| 529 |
| 530 --body) |
| 531 if [ -z "$1" ] ; then |
| 532 exit_failure_syntax "text argument missing for --body option" |
| 533 fi |
| 534 url_encode "$1" |
| 535 options="${options}body=${result}&" |
| 536 shift |
| 537 ;; |
| 538 |
| 539 --attach) |
| 540 if [ -z "$1" ] ; then |
| 541 exit_failure_syntax "file argument missing for --attach option" |
| 542 fi |
| 543 check_input_file "$1" |
| 544 file=`readlink -f "$1"` # Normalize path |
| 545 if [ -z "$file" -o ! -f "$file" ] ; then |
| 546 exit_failure_file_missing "file '$1' does not exist" |
| 547 fi |
| 548 |
| 549 url_encode "$file" |
| 550 options="${options}attach=${result}&" |
| 551 shift |
| 552 ;; |
| 553 |
| 554 -*) |
| 555 exit_failure_syntax "unexpected option '$parm'" |
| 556 ;; |
| 557 |
| 558 mailto:*) |
| 559 mailto="$parm" |
| 560 ;; |
| 561 |
| 562 *@*) |
| 563 url_encode "$parm" |
| 564 if [ -z "${mailto}" ] ; then |
| 565 mailto="mailto:"${result}"?" |
| 566 else |
| 567 options="${options}to=${result}&" |
| 568 fi |
| 569 ;; |
| 570 |
| 571 *) |
| 572 exit_failure_syntax "unexpected argument '$parm'" |
| 573 ;; |
| 574 esac |
| 575 done |
| 576 |
| 577 if [ -z "${mailto}" ] ; then |
| 578 # TO address is optional |
| 579 mailto="mailto:?" |
| 580 fi |
| 581 |
| 582 case $mailto in |
| 583 *\?) |
| 584 mailto="${mailto}${options}" |
| 585 ;; |
| 586 |
| 587 *\?*) |
| 588 mailto="${mailto}&${options}" |
| 589 ;; |
| 590 |
| 591 *) |
| 592 mailto="${mailto}?${options}" |
| 593 ;; |
| 594 esac |
| 595 |
| 596 # Strip trailing ? and & |
| 597 mailto=`echo "${mailto}"| sed 's/[?&]$//'` |
| 598 |
| 599 # Shouldn't happen |
| 600 [ x"${mailto}" != x"" ] || exit_failure_syntax |
| 601 |
| 602 if which xdg-email-hook.sh > /dev/null 2> /dev/null; then |
| 603 xdg-email-hook.sh "${mailto}" |
| 604 if [ $? -eq 0 ]; then |
| 605 exit_success |
| 606 else |
| 607 exit_failure_operation_failed |
| 608 fi |
| 609 fi |
| 610 |
| 611 detectDE |
| 612 |
| 613 if [ x"$DE" = x"" ]; then |
| 614 # if BROWSER variable is not set, check some well known browsers instead |
| 615 if [ x"$BROWSER" = x"" ]; then |
| 616 BROWSER=firefox:mozilla:netscape |
| 617 fi |
| 618 DE=generic |
| 619 fi |
| 620 |
| 621 case "$DE" in |
| 622 kde) |
| 623 open_kde "${mailto}" |
| 624 ;; |
| 625 |
| 626 gnome) |
| 627 open_gnome "${mailto}" |
| 628 ;; |
| 629 |
| 630 xfce) |
| 631 open_xfce "${mailto}" |
| 632 ;; |
| 633 |
| 634 generic) |
| 635 open_generic "${mailto}" |
| 636 ;; |
| 637 |
| 638 *) |
| 639 exit_failure_operation_impossible "no method available for opening '${mailto
}'" |
| 640 ;; |
| 641 esac |
OLD | NEW |