/usr/bin/getmail is in getmail4 4.48.0-1.
This file is owned by root:root, with mode 0o755.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 | #!/usr/bin/python
import sys
if sys.hexversion < 0x2030300:
raise ImportError('getmail version 4 requires Python version 2.3.3 '
'or later')
import os.path
import time
import ConfigParser
import poplib
import imaplib
import pprint
from optparse import OptionParser, OptionGroup
import socket
import signal
# Optional gnome-keyring integration
try:
import gnomekeyring
import glib
glib.set_application_name('getmail')
# And test to see if it's actually available
if not gnomekeyring.is_available():
gnomekeyring = None
except ImportError:
gnomekeyring = None
options_bool = (
'read_all',
'delete',
'delivered_to',
'received',
'message_log_verbose',
'message_log_syslog',
'fingerprint',
)
options_int = (
'delete_after',
'delete_bigger_than',
'max_message_size',
'max_messages_per_session',
'max_bytes_per_session',
'verbose',
)
options_str = (
'message_log',
)
# Unix only
try:
import syslog
except ImportError:
pass
try:
from getmailcore import __version__, retrievers, destinations, filters, \
logging
from getmailcore.exceptions import *
from getmailcore.utilities import eval_bool, logfile, format_params, \
address_no_brackets, expand_user_vars, get_password
except ImportError, o:
sys.stderr.write('ImportError: %s\n' % o)
sys.exit(127)
log = logging.Logger()
log.addhandler(sys.stdout, logging.INFO, maxlevel=logging.INFO)
log.addhandler(sys.stderr, logging.WARNING)
defaults = {
'getmaildir' : '~/.getmail/',
'rcfile' : 'getmailrc',
'verbose' : 1,
'read_all' : True,
'delete' : False,
'delete_after' : 0,
'delete_bigger_than' : 0,
'max_message_size' : 0,
'max_messages_per_session' : 0,
'max_bytes_per_session' : 0,
'delivered_to' : True,
'received' : True,
'message_log' : None,
'message_log_verbose' : False,
'message_log_syslog' : False,
'logfile' : None,
'fingerprint' : False,
}
#######################################
def convert_to_sigint(unused1, unused2):
"""Catch a SIGTERM and raise a SIGINT so getmail exits normally and does
cleanup if killed with default signal.
"""
raise KeyboardInterrupt('from signal')
signal.signal(signal.SIGTERM, convert_to_sigint)
#######################################
def blurb():
log.info('getmail version %s\n' % __version__)
log.info('Copyright (C) 1998-2012 Charles Cazabon. Licensed under the '
'GNU GPL version 2.\n')
#######################################
def go(configs, idle):
"""Main code.
Returns True if all goes well, False if any error condition occurs.
"""
blurb()
summary = []
errorexit = False
idling = False
if len(configs) > 1 and idle:
log.info('more than one config file given with --idle, ignoring\n')
idle = False
for (configfile, retriever, _filters, destination, options) in configs:
if options['read_all'] and not options['delete']:
if idle:
# This is a nonsense combination of options; every time the
# server returns from IDLE, all messages will be re-retrieved.
log.error('%s: IDLE, read_all, and not delete - bad '
'combination, skipping\n'
% retriever)
continue
else:
# Slightly less nonsensical, but still weird.
log.warning('%s: read_all and not delete -- all messages will '
'be retrieved each time getmail is run\n'
% retriever)
oplevel = options['verbose']
logverbose = options['message_log_verbose']
now = int(time.time())
msgs_retrieved = 0
bytes_retrieved = 0
msgs_skipped = 0
if options['message_log_syslog']:
syslog.openlog('getmail', 0, syslog.LOG_MAIL)
try:
if not idling:
log.info('%s:\n' % retriever)
logline = 'Initializing %s:' % retriever
if options['logfile'] and logverbose:
options['logfile'].write(logline)
if options['message_log_syslog'] and logverbose:
syslog.syslog(syslog.LOG_INFO, logline)
retriever.initialize(options)
destination.retriever_info(retriever)
for mailbox in retriever.mailboxes:
if mailbox:
# For POP this is None and uninteresting
log.debug(' checking mailbox %s ...\n' % mailbox)
try:
retriever.select_mailbox(mailbox)
except getmailMailboxSelectError, o:
errorexit = True
log.info(' mailbox %s not selectable (%s) - verify the '
'mailbox exists and you have sufficient '
'permissions\n' % (mailbox, o))
continue
nummsgs = len(retriever)
fmtlen = len(str(nummsgs))
for (msgnum, msgid) in enumerate(retriever):
log.debug(' message %s ...\n' % msgid)
msgnum += 1
retrieve = False
reason = 'seen'
delete = False
timestamp = retriever.oldmail.get(msgid, None)
size = retriever.getmsgsize(msgid)
info = ('msg %*d/%*d (%d bytes)'
% (fmtlen, msgnum, fmtlen, nummsgs, size))
logline = '%s msgid %s' % (info, msgid)
if options['read_all'] or timestamp is None:
retrieve = True
if (options['max_message_size']
and size > options['max_message_size']):
retrieve = False
reason = 'oversized'
if (options['max_bytes_per_session']
and (bytes_retrieved + size)
> options['max_bytes_per_session']):
retrieve = False
reason = 'would surpass max_bytes_per_session'
try:
if retrieve:
try:
msg = retriever.getmsg(msgid)
except getmailRetrievalError, o:
errorexit = True
log.error(
'Retrieval error: server for %s is broken; '
'offered message %s but failed to provide it. '
'Please notify the administrator of the '
'server. Skipping message...\n'
% (retriever, msgid)
)
continue
msgs_retrieved += 1
bytes_retrieved += size
if oplevel > 1:
info += (' from <%s>'
% address_no_brackets(msg.sender))
if msg.recipient is not None:
info += (' to <%s>'
% address_no_brackets(msg.recipient))
logline += (' from <%s>'
% address_no_brackets(msg.sender))
if msg.recipient is not None:
logline += (' to <%s>'
% address_no_brackets(msg.recipient))
for mail_filter in _filters:
log.debug(' passing to filter %s\n'
% mail_filter)
msg = mail_filter.filter_message(msg, retriever)
if msg is None:
log.debug(' dropped by filter %s\n'
% mail_filter)
info += (' dropped by filter %s'
% mail_filter)
logline += (' dropped by filter %s'
% mail_filter)
retriever.delivered(msgid)
break
if msg is not None:
r = destination.deliver_message(msg,
options['delivered_to'], options['received'])
log.debug(' delivered to %s\n' % r)
info += ' delivered'
if oplevel > 1:
info += (' to %s' % r)
logline += (' delivered to %s' % r)
retriever.delivered(msgid)
if options['delete']:
delete = True
else:
logline += ' not retrieved (%s)' % reason
msgs_skipped += 1
log.debug(' not retrieving (timestamp %s)\n'
% timestamp)
if oplevel > 1:
info += ' not retrieved (%s)' % reason
if (options['delete_after'] and timestamp
and (now - timestamp) / 86400
>= options['delete_after']):
log.debug(
' older than %d days (%s seconds), will delete\n'
% (options['delete_after'], (now - timestamp))
)
delete = True
if options['delete'] and timestamp:
log.debug(' will delete\n')
delete = True
if (options['delete_bigger_than']
and size > options['delete_bigger_than']):
log.debug(' bigger than %d, will delete\n'
% options['delete_bigger_than'])
delete = True
if not retrieve and timestamp is None:
# We haven't retrieved this message. Don't delete it.
log.debug(' not yet retrieved, not deleting\n')
delete = False
if delete:
retriever.delmsg(msgid)
log.debug(' deleted\n')
info += ', deleted'
logline += ', deleted'
except getmailDeliveryError, o:
errorexit = True
log.error('Delivery error (%s)\n' % o)
info += ', delivery error (%s)' % o
if options['logfile']:
options['logfile'].write('Delivery error (%s)' % o)
if options['message_log_syslog']:
syslog.syslog(syslog.LOG_ERR,
'Delivery error (%s)' % o)
except getmailFilterError, o:
errorexit = True
log.error('Filter error (%s)\n' % o)
info += ', filter error (%s)' % o
if options['logfile']:
options['logfile'].write('Filter error (%s)' % o)
if options['message_log_syslog']:
syslog.syslog(syslog.LOG_ERR,
'Filter error (%s)' % o)
if (retrieve or delete or oplevel > 1):
log.info(' %s\n' % info)
if options['logfile'] and (retrieve or delete or logverbose):
options['logfile'].write(logline)
if options['message_log_syslog'] and (retrieve or delete
or logverbose):
syslog.syslog(syslog.LOG_INFO, logline)
if (options['max_messages_per_session']
and msgs_retrieved >=
options['max_messages_per_session']):
log.debug('hit max_messages_per_session (%d), breaking\n'
% options['max_messages_per_session'])
if oplevel > 1:
log.info(' max messages per session (%d)\n'
% options['max_messages_per_session'])
raise StopIteration('max_messages_per_session %d'
% options['max_messages_per_session'])
except StopIteration:
pass
except KeyboardInterrupt, o:
log.warning('%s: user aborted\n' % configfile)
if options['logfile']:
options['logfile'].write('user aborted')
except socket.timeout, o:
errorexit = True
retriever.abort()
if type(o) == tuple and len(o) > 1:
o = o[1]
log.error('%s: timeout (%s)\n' % (configfile, o))
if options['logfile']:
options['logfile'].write('timeout error (%s)' % o)
except (poplib.error_proto, imaplib.IMAP4.abort), o:
errorexit = True
retriever.abort()
log.error('%s: protocol error (%s)\n' % (configfile, o))
if options['logfile']:
options['logfile'].write('protocol error (%s)' % o)
except socket.gaierror, o:
errorexit = True
retriever.abort()
if type(o) == tuple and len(o) > 1:
o = o[1]
log.error('%s: error resolving name (%s)\n' % (configfile, o))
if options['logfile']:
options['logfile'].write('gaierror error (%s)' % o)
except socket.error, o:
errorexit = True
retriever.abort()
if type(o) == tuple and len(o) > 1:
o = o[1]
log.error('%s: socket error (%s)\n' % (configfile, o))
if options['logfile']:
options['logfile'].write('socket error (%s)' % o)
except getmailCredentialError, o:
errorexit = True
retriever.abort()
log.error('%s: credential/login error (%s)\n' % (configfile, o))
if options['logfile']:
options['logfile'].write('credential/login error (%s)' % o)
except getmailOperationError, o:
errorexit = True
retriever.abort()
log.error('%s: operation error (%s)\n' % (configfile, o))
if options['logfile']:
options['logfile'].write('getmailOperationError error (%s)' % o)
if options['message_log_syslog']:
syslog.syslog(syslog.LOG_ERR,
'getmailOperationError error (%s)' % o)
summary.append(
(retriever, msgs_retrieved, bytes_retrieved, msgs_skipped)
)
log.info(' %d messages (%d bytes) retrieved, %d skipped\n'
% (msgs_retrieved, bytes_retrieved, msgs_skipped))
if options['logfile'] and logverbose:
options['logfile'].write(
' %d messages (%d bytes) retrieved, %d skipped\n'
% (msgs_retrieved, bytes_retrieved, msgs_skipped)
)
log.debug('retriever %s finished\n' % retriever)
try:
if idle and not retriever.supports_idle:
log.info('--idle given, but retriever does not support IDLE\n')
idle = False
if idle and sys.version_info < (2, 5, 0):
log.info('--idle requires Python 2.5 or higher\n')
idle = False
if idle and not errorexit:
# TODO
# Okay, so what should really happen here is that when go_idle
# returns, getmail should use the *existing* connection to check
# for new messages and then call go_idle again once that is
# done. The current code layout doesn't lend itself very well to
# that since the message download code is coupled with the
# connection setup/teardown code.
#
# Therefore, we do a bit of a hack.
# We add the current config back into configs, so that when the
# main for loop over configs runs again, it will find the same
# config again, and thus download the new messages and then go
# back to IDLEing. Since the return value of go_idle changes the
# value of idling, a failed connection will cause it to become
# False, which will make the main go() loop reconnect, which is
# what we want.
# Expunge and close the mailbox to prevent the same messages
# being pulled again in some configurations.
retriever.close_mailbox()
try:
idling = retriever.go_idle(idle)
# Returned from idle
retriever.set_new_timestamp()
configs.append(configs[0])
continue
except KeyboardInterrupt, o:
# Because configs isn't appended to, this just means we'll
# quit, which is presumably what the user wanted
# The newline is to clear the ^C shown in terminal
log.info('\n')
pass
retriever.quit()
except getmailOperationError, o:
errorexit = True
log.debug('%s: operation error during quit (%s)\n'
% (configfile, o))
if options['logfile']:
options['logfile'].write('%s: operation error during quit (%s)'
% (configfile, o))
if sum([i for (unused, i, unused, unused) in summary]) and oplevel > 1:
log.info('Summary:\n')
for (retriever, msgs_retrieved, bytes_retrieved, unused) in summary:
log.info('Retrieved %d messages (%s bytes) from %s\n'
% (msgs_retrieved, bytes_retrieved, retriever))
return (not errorexit)
#######################################
def main():
try:
parser = OptionParser(version='%%prog %s' % __version__)
parser.add_option(
'-g', '--getmaildir',
dest='getmaildir', action='store', default=defaults['getmaildir'],
help='look in DIR for config/data files', metavar='DIR'
)
parser.add_option(
'-r', '--rcfile',
dest='rcfile', action='append', default=[],
help='load configuration from FILE (may be given multiple times)',
metavar='FILE'
)
parser.add_option(
'--dump',
dest='dump_config', action='store_true', default=False,
help='dump configuration and exit (debugging)'
)
parser.add_option(
'--trace',
dest='trace', action='store_true', default=False,
help='print extended trace information (extremely verbose)'
)
parser.add_option(
'-i', '--idle',
dest='idle', action='store', default='',
help='maintain connection and listen for new messages in FOLDER. '
'Only applies if a single rc file is given with a connection '
'to an IMAP server that supports the IDLE command',
metavar='FOLDER'
)
if gnomekeyring:
parser.add_option(
'--store-password-in-gnome-keyring',
dest='store_gnome_keyring', action='store_true', default=False,
help='store the POP/IMAP password in the Gnome keyring'
)
overrides = OptionGroup(
parser, 'Overrides',
'The following options override those specified in any '
'getmailrc file.'
)
overrides.add_option(
'-v', '--verbose',
dest='override_verbose', action='count',
help='operate more verbosely (may be given multiple times)'
)
overrides.add_option(
'--fingerprint',
dest='override_fingerprint', action='store_true',
help='show SSL/TLS fingerprint and connection information'
)
overrides.add_option(
'-q', '--quiet',
dest='override_verbose', action='store_const',
const=0,
help='operate quietly (only report errors)'
)
overrides.add_option(
'-d', '--delete',
dest='override_delete', action='store_true',
help='delete messages from server after retrieving'
)
overrides.add_option(
'-l', '--dont-delete',
dest='override_delete', action='store_false',
help='do not delete messages from server after retrieving'
)
overrides.add_option(
'-a', '--all',
dest='override_read_all', action='store_true',
help='retrieve all messages'
)
overrides.add_option(
'-n', '--new',
dest='override_read_all', action='store_false',
help='retrieve only unread messages'
)
parser.add_option_group(overrides)
(options, args) = parser.parse_args(sys.argv[1:])
if args:
raise getmailOperationError('unknown argument(s) %s ; try --help'
% args)
if options.trace:
log.clearhandlers()
if not options.rcfile:
options.rcfile.append(defaults['rcfile'])
s = ''
for attr in dir(options):
if attr.startswith('_'):
continue
if s:
s += ','
s += '%s="%s"' % (attr, pprint.pformat(getattr(options, attr)))
log.debug('parsed options: %s\n' % s)
getmaildir_type = 'Default'
if options.getmaildir != defaults['getmaildir']:
getmaildir_type = 'Specified'
getmaildir = expand_user_vars(options.getmaildir)
if not os.path.exists(getmaildir):
raise getmailOperationError(
'%s config/data dir "%s" does not exist - create '
'or specify alternate directory with --getmaildir option'
% (getmaildir_type, getmaildir)
)
if not os.path.isdir(getmaildir):
raise getmailOperationError(
'%s config/data dir "%s" is not a directory - fix '
'or specify alternate directory with --getmaildir option'
% (getmaildir_type, getmaildir)
)
if not os.access(getmaildir, os.W_OK):
raise getmailOperationError(
'%s config/data dir "%s" is not writable - fix permissions '
'or specify alternate directory with --getmaildir option'
% (getmaildir_type, getmaildir)
)
configs = []
for filename in options.rcfile:
path = os.path.join(os.path.expanduser(options.getmaildir),
filename)
log.debug('processing rcfile %s\n' % path)
if not os.path.exists(path):
raise getmailOperationError('configuration file %s does '
'not exist' % path)
elif not os.path.isfile(path):
raise getmailOperationError('%s is not a file' % path)
f = open(path, 'rb')
config = {
'verbose' : defaults['verbose'],
'read_all' : defaults['read_all'],
'delete' : defaults['delete'],
'delete_after' : defaults['delete_after'],
'delete_bigger_than' : defaults['delete_bigger_than'],
'max_message_size' : defaults['max_message_size'],
'max_messages_per_session' :
defaults['max_messages_per_session'],
'max_bytes_per_session' :
defaults['max_bytes_per_session'],
'delivered_to' : defaults['delivered_to'],
'received' : defaults['received'],
'logfile' : defaults['logfile'],
'message_log' : defaults['message_log'],
'message_log_verbose' : defaults['message_log_verbose'],
'message_log_syslog' : defaults['message_log_syslog'],
'fingerprint' : defaults['fingerprint'],
}
# Python's ConfigParser .getboolean() couldn't handle booleans in
# the defaults. Submitted a patch; they fixed it a different way.
# But for the extant, unfixed versions, an ugly hack....
parserdefaults = config.copy()
for (key, value) in parserdefaults.items():
if type(value) == bool:
parserdefaults[key] = str(value)
try:
configparser = ConfigParser.RawConfigParser(parserdefaults)
configparser.readfp(f, path)
for option in options_bool:
log.debug(' looking for option %s ... ' % option)
if configparser.has_option('options', option):
log.debug('got "%s"'
% configparser.get('options', option))
try:
config[option] = configparser.getboolean(
'options', option
)
log.debug('-> %s' % config[option])
except ValueError:
raise getmailConfigurationError(
'configuration file %s incorrect (option %s '
'must be boolean, not %s)'
% (path, option,
configparser.get('options', option))
)
else:
log.debug('not found')
log.debug('\n')
for option in options_int:
log.debug(' looking for option %s ... ' % option)
if configparser.has_option('options', option):
log.debug(
'got "%s"' % configparser.get('options', option)
)
try:
config[option] = configparser.getint('options',
option)
log.debug('-> %s' % config[option])
except ValueError:
raise getmailConfigurationError(
'configuration file %s incorrect (option %s '
'must be integer, not %s)'
% (path, option,
configparser.get('options', option))
)
else:
log.debug('not found')
log.debug('\n')
# Message log file
for option in options_str:
log.debug(' looking for option %s ... ' % option)
if configparser.has_option('options', option):
log.debug('got "%s"'
% configparser.get('options', option))
config[option] = configparser.get('options', option)
log.debug('-> %s' % config[option])
else:
log.debug('not found')
log.debug('\n')
if config['message_log']:
try:
config['logfile'] = logfile(config['message_log'])
except IOError, o:
raise getmailConfigurationError(
'error opening message_log file %s (%s)'
% (config['message_log'], o)
)
# Clear out the ConfigParser defaults before processing further
# sections
configparser._defaults = {}
# Retriever
log.debug(' getting retriever\n')
retriever_type = configparser.get('retriever', 'type')
log.debug(' type="%s"\n' % retriever_type)
retriever_func = getattr(retrievers, retriever_type)
if not callable(retriever_func):
raise getmailConfigurationError(
'configuration file %s specifies incorrect '
'retriever type (%s)'
% (path, retriever_type)
)
retriever_args = {
'getmaildir' : options.getmaildir,
'configparser' : configparser,
}
for (name, value) in configparser.items('retriever'):
if name in ('type', 'configparser'):
continue
if name == 'password':
log.debug(' parameter %s=*\n' % name)
else:
log.debug(' parameter %s="%s"\n' % (name, value))
retriever_args[name] = value
log.debug(' instantiating retriever %s with args %s\n'
% (retriever_type, format_params(retriever_args)))
try:
retriever = retriever_func(**retriever_args)
log.debug(' checking retriever configuration for %s\n'
% retriever)
retriever.checkconf()
except getmailOperationError, o:
log.error('Error initializing retriever: %s\n' % o)
continue
# Retriever is okay. Check if user wants us to store the
# password in a Gnome keyring for future use.
if gnomekeyring and options.store_gnome_keyring:
# Need to get the password first, if the user hasn't put
# it in the rc file.
if retriever.conf.get('password', None) is None:
password = get_password(
str(retriever), retriever.conf['username'],
retriever.conf['server'], retriever.received_with,
log
)
else:
password = retriever.conf['password']
gnomekeyring.set_network_password_sync(
# keyring=None, user, domain=None, server, object=None,
# protocol, authtype=None, port=0
None, retriever.conf['username'], None,
retriever.conf['server'], None, retriever.received_with,
None, 0, password
)
log.info('Stored password in Gnome keyring. Exiting.\n')
raise SystemExit()
# Destination
log.debug(' getting destination\n')
destination_type = configparser.get('destination', 'type')
log.debug(' type="%s"\n' % destination_type)
destination_func = getattr(destinations, destination_type)
if not callable(destination_func):
raise getmailConfigurationError(
'configuration file %s specifies incorrect destination '
'type (%s)'
% (path, destination_type)
)
destination_args = {'configparser' : configparser}
for (name, value) in configparser.items('destination'):
if name in ('type', 'configparser'):
continue
if name == 'password':
log.debug(' parameter %s=*\n' % name)
else:
log.debug(' parameter %s="%s"\n' % (name, value))
destination_args[name] = value
log.debug(' instantiating destination %s with args %s\n'
% (destination_type, format_params(destination_args)))
destination = destination_func(**destination_args)
# Filters
log.debug(' getting filters\n')
_filters = []
filtersections = [
section.lower() for section in configparser.sections()
if section.lower().startswith('filter')
]
filtersections.sort()
for section in filtersections:
log.debug(' processing filter section %s\n' % section)
filter_type = configparser.get(section, 'type')
log.debug(' type="%s"\n' % filter_type)
filter_func = getattr(filters, filter_type)
if not callable(filter_func):
raise getmailConfigurationError(
'configuration file %s specifies incorrect filter '
'type (%s)'
% (path, filter_type)
)
filter_args = {'configparser' : configparser}
for (name, value) in configparser.items(section):
if name in ('type', 'configparser'):
continue
if name == 'password':
log.debug(' parameter %s=*\n' % name)
else:
log.debug(' parameter %s="%s"\n' % (name, value))
filter_args[name] = value
log.debug(' instantiating filter %s with args %s\n'
% (filter_type, format_params(filter_args)))
mail_filter = filter_func(**filter_args)
_filters.append(mail_filter)
except ConfigParser.NoSectionError, o:
raise getmailConfigurationError(
'configuration file %s missing section (%s)' % (path, o)
)
except ConfigParser.NoOptionError, o:
raise getmailConfigurationError(
'configuration file %s missing option (%s)' % (path, o)
)
except (ConfigParser.DuplicateSectionError,
ConfigParser.InterpolationError,
ConfigParser.MissingSectionHeaderError,
ConfigParser.ParsingError), o:
raise getmailConfigurationError(
'configuration file %s incorrect (%s)' % (path, o)
)
except getmailConfigurationError, o:
raise getmailConfigurationError(
'configuration file %s incorrect (%s)' % (path, o)
)
# Apply overrides from commandline
for option in ('read_all', 'delete', 'verbose', 'fingerprint'):
val = getattr(options, 'override_%s' % option)
if val is not None:
log.debug('overriding option %s from commandline %s\n'
% (option, val))
config[option] = val
if config['verbose'] > 2:
config['verbose'] = 2
if not options.trace and config['verbose'] == 0:
log.clearhandlers()
log.addhandler(sys.stderr, logging.WARNING)
configs.append((os.path.basename(filename), retriever, _filters,
destination, config.copy()))
if options.dump_config:
# Override any "verbose = 0" in the config file
log.clearhandlers()
log.addhandler(sys.stdout, logging.INFO, maxlevel=logging.INFO)
log.addhandler(sys.stderr, logging.WARNING)
blurb()
for (filename, retriever, _filters, destination, config) in configs:
log.info('getmail configuration:\n')
log.info(' getmail version %s\n' % __version__)
log.info(' Python version %s\n' % sys.version)
log.info(' retriever: ')
retriever.showconf()
if _filters:
for _filter in _filters:
log.info(' filter: ')
_filter.showconf()
log.info(' destination: ')
destination.showconf()
log.info(' options:\n')
names = config.keys()
names.sort()
for name in names:
log.info(' %s : %s\n' % (name, config[name]))
log.info('\n')
sys.exit()
# Go!
success = go(configs, options.idle)
if not success:
raise SystemExit(127)
except KeyboardInterrupt:
log.warning('Operation aborted by user (keyboard interrupt)\n')
sys.exit(0)
except getmailConfigurationError, o:
log.error('Configuration error: %s\n' % o)
sys.exit(2)
except getmailOperationError, o:
log.error('Error: %s\n' % o)
sys.exit(3)
except StandardError, o:
log.critical(
'\nException: please read docs/BUGS and include the '
'following information in any bug report:\n\n'
)
log.critical(' getmail version %s\n' % __version__)
log.critical(' Python version %s\n\n' % sys.version)
log.critical('Unhandled exception follows:\n')
(exc_type, value, tb) = sys.exc_info()
import traceback
tblist = (traceback.format_tb(tb, None)
+ traceback.format_exception_only(exc_type, value))
if type(tblist) != list:
tblist = [tblist]
for line in tblist:
log.critical(' %s\n' % line.rstrip())
log.critical('\nPlease also include configuration information '
'from running getmail\n')
log.critical('with your normal options plus "--dump".\n')
sys.exit(4)
#######################################
if __name__ == '__main__':
main()
|