3 # NOTE: THIS PROGRAM DOES NOT WORK!
4 # It is intended as a regression test source for the Python support in etags.
5 # If you want a working version, you'll find it in the fetchmail distribution.
15 # Define the data structures the GUIs will be tossing around
19 self
.foreground
= FALSE
; # Run in background
20 self
.daemon
= 300 # Default to 5-minute timeout
21 self
.syslog
= FALSE
# Use syslogd for logging?
22 self
.logfile
= None # No logfile, initially
27 str = str + ("set syslog\n")
29 str = str + ("set logfile \"%s\"\n" % (self
.logfile
,));
30 if not self
.foreground
and self
.daemon
:
31 str = str + ("set daemon %s\n" % (self
.daemon
,))
35 return "[Server: " + repr(self
) + "]"
39 self
.pollname
= None # Poll label
40 self
.via
= None # True name of host
41 self
.active
= TRUE
# Poll status
42 self
.interval
= 0 # Skip interval
43 self
.protocol
= 'auto' # Default to auto protocol
44 self
.port
= 0 # Port number to use
45 self
.uidl
= FALSE
# Don't use RFC1725 UIDLs by default
46 self
.auth
= "password" # Default to password authentication
47 self
.timeout
= 300 # 5-minute timeout
48 self
.envelope
= "Received" # Envelope-address header
49 self
.aka
= [] # List of DNS aka names
50 self
.dns
= TRUE
# Enable DNS lookup on multidrop
51 self
.localdomains
= [] # Domains to be considered local
52 self
.interface
= None # IP address and range
53 self
.monitor
= None # IP address and range
54 self
.userlist
= [] # List of user entries for site
56 ('pollname', 'String'),
58 ('active', 'Boolean'),
60 ('protocol', 'String'),
66 ('envelope', 'String'),
69 # leave localdomains out
70 ('interface', 'String'),
71 ('monitor', 'String'))
73 def dump(self
, folded
):
75 if self
.active
: str = str + "poll"
76 else: str = str + "skip"
77 str = str + (" " + self
.pollname
)
78 if self
.via
!= self
.pollname
:
79 str = str + " via " + self
.via
80 if self
.protocol
!= ServerDefaults
.protocol
:
81 str = str + " with proto " + self
.protocol
82 if self
.port
!= defaultports
[self
.protocol
]:
83 str = str + " port " + `self
.port`
84 if self
.timeout
!= ServerDefaults
.timeout
:
85 str = str + " timeout " + `self
.timeout`
86 if self
.interval
!= ServerDefaults
.interval
:
87 str = str + " interval " + `self
.interval`
88 if self
.envelope
!= ServerDefaults
.envelope
:
89 str = str + " envelope " + self
.envelope
90 if self
.auth
!= ServerDefaults
.auth
:
91 str = str + " auth " + self
.auth
92 if self
.dns
!= ServerDefaults
.dns
or self
.uidl
!= ServerDefaults
.uidl
:
93 str = str + " and options"
94 if self
.dns
!= ServerDefaults
.dns
:
95 str = str + flag2str(self
.dns
, 'dns')
96 if self
.uidl
!= ServerDefaults
.uidl
:
97 str = str + flag2str(self
.uidl
, 'uidl')
98 if folded
: str = str + "\n\t"
105 if self
.aka
and self
.localdomains
: str = str + " "
106 if self
.localdomains
:
107 str = str + ("localdomains")
108 for x
in self
.localdomains
:
110 if (self
.aka
or self
.localdomains
):
116 if self
.interface
: str = str + " interface " + self
.interface
117 if self
.monitor
: str = str + " monitor " + self
.monitor
118 if (self
.interface
or self
.monitor
):
122 if str[-1] == "\t": str = str[0:-1]
126 return self
.dump(TRUE
)
129 return "[Server: " + self
.dump(FALSE
) + "]"
133 self
.username
= "" # Remote username
134 self
.localnames
= None # Local names
135 self
.password
= "" # Password for mail account access
136 self
.smpthost
= 'localhost' # Host to forward to
137 self
.mda
= "" # Mail Delivery Agent
138 self
.preconnect
= "" # Connection setup
139 self
.postconnect
= "" # Connection wrapup
140 self
.keep
= FALSE
# Keep messages
141 self
.flush
= FALSE
# Flush messages
142 self
.fetchall
= FALSE
# Fetch old messages
143 self
.rewrite
= TRUE
# Rewrite message headers
144 self
.forcecr
= FALSE
# Force LF -> CR/LF
145 self
.stripcr
= FALSE
# Strip CR
146 self
.pass8bits
= FALSE
# Force BODY=7BIT
147 self
.dropstatus
= FALSE
# Force BODY=7BIT
148 self
.limit
= 0 # Message size limit
149 self
.fetchlimit
= 0 # Max messages fetched per batch
150 self
.batchlimit
= 0 # Max message forwarded per batch
152 ('username', 'String')
154 # leave out localnames
155 ('password', 'String')
156 ('smtphost', 'String')
157 ('preconnect', 'String')
158 ('postconnect', 'String')
162 ('fetchall', 'Boolean')
163 ('rewrite', 'Boolean')
164 ('forcecr', 'Boolean')
165 ('stripcr', 'Boolean')
166 ('pass8bits', 'Boolean')
167 ('dropstatus', 'Boolean')
169 ('fetchlimit', 'Int')
170 ('batchlimit', 'Int'))
174 str = str + "user " + self
.user
;
175 if self
.password
: str = str + "with password " + self
.password
177 str = str + "localnames"
178 for x
in self
.localnames
:
180 if (self
.keep
or self
.flush
or self
.fetchall
or self
.rewrite
or
181 self
.forcecr
or self
.stripcr
or self
.pass8bits
or self
.dropstatus
):
182 str = str + " options"
183 if self
.keep
!= UserDefaults
.keep
:
184 str = str + flag2str(self
.keep
, 'keep')
185 if self
.flush
!= UserDefaults
.flush
:
186 str = str + flag2str(self
.flush
, 'flush')
187 if self
.fetchall
!= UserDefaults
.fetchall
:
188 str = str + flag2str(self
.fetchall
, 'fetchall')
189 if self
.rewrite
!= UserDefaults
.rewrite
:
190 str = str + flag2str(self
.rewrite
, 'rewrite')
191 if self
.forcecr
!= UserDefaults
.forcecr
:
192 str = str + flag2str(self
.forcecr
, 'forcecr')
193 if self
.stripcr
!= UserDefaults
.stripcr
:
194 str = str + flag2str(self
.stripcr
, 'stripcr')
195 if self
.pass8bits
!= UserDefaults
.pass8bits
:
196 str = str + flag2str(self
.pass8bits
, 'pass8bits')
197 if self
.dropstatus
!= UserDefaults
.dropstatus
:
198 str = str + flag2str(self
.dropstatus
, 'dropstatus')
199 if self
.limit
!= UserDefaults
.limit
:
200 str = str + " limit " + `self
.limit`
201 if self
.fetchlimit
!= UserDefaults
.fetchlimit
:
202 str = str + " fetchlimit " + `self
.fetchlimit`
203 if self
.batchlimit
!= UserDefaults
.batchlimit
:
204 str = str + " batchlimit " + `self
.batchlimit`
207 return "[User: " + repr(self
) + "]"
213 defaultports
= {"auto":0,
215 "POP3":110, "APOP":110, "KPOP":1109, "IMAP":143,
219 protolist
= ("auto", "POP2", "POP3", "APOP", "KPOP", "IMAP", "IMAP-K4", "ETRN")
221 authlist
= ("password", "kerberos")
223 def flag2str(value
, string
):
224 # make a string representation of a .fetchmailrc flag or negated flag
228 if value
== FALSE
: str = str + ("no ")
232 class LabeledEntry(Frame
):
233 # widget consisting of entry field with caption to left
234 def bind(self
, key
, action
):
235 self
.E
.bind(key
, action
)
238 def __init__(self
, Master
, text
, textvar
, width
):
239 Frame
.__init
__(self
, Master
)
240 self
.L
= Label(self
, {'text':text
, 'width':width
, 'anchor':'w'})
241 self
.E
= Entry(self
, {'textvar':textvar
})
242 self
.L
.pack({'side':'left'})
243 self
.E
.pack({'side':'left', 'expand':'1', 'fill':'x'})
245 def ButtonBar(frame
, legend
, ref
, alternatives
, command
):
246 # horizontal bar of radio buttons, caption to left, picking from a string list
248 Label(bar
, text
=legend
).pack(side
=LEFT
)
249 for alt
in alternatives
:
251 {'text':alt
, 'variable':ref
, 'value':alt
, 'command':command
}).pack(side
=LEFT
)
255 def helpwin(helpdict
):
256 # help message window with a self-destruct button
258 helpwin
.title(helpdict
['title'])
259 helpwin
.iconname(helpdict
['title'])
260 Label(helpwin
, text
=helpdict
['banner']).pack()
261 textwin
= Message(helpwin
, text
=helpdict
['text'], width
=600)
263 Button(helpwin
, text
='Done',
264 command
=lambda x
=helpwin
: Widget
.destroy(x
),
265 relief
=SUNKEN
, bd
=2).pack()
267 class ListEdit(Frame
):
268 # edit a list of values (duplicates not allowed) with a supplied editor hook
269 def __init__(self
, newlegend
, list, editor
, master
):
273 # Set up a widget to accept new sites
274 self
.newval
= StringVar(master
)
275 newwin
= LabeledEntry(master
, newlegend
, self
.newval
, '16')
276 newwin
.bind('<Double-1>', self
.handleNew
)
277 newwin
.bind('<Return>', self
.handleNew
)
278 newwin
.pack(side
=TOP
, fill
=X
, anchor
=E
)
280 # Create the sitelist for site-configuration selection
281 listframe
= Frame(master
)
282 scroll
= Scrollbar(listframe
)
283 listwidget
= Listbox(listframe
, height
=0, selectmode
='browse')
286 listwidget
.insert('end', dnsname
)
287 listframe
.pack(side
=TOP
, expand
=YES
, fill
=BOTH
)
288 listwidget
.config(yscrollcommand
=scroll
.set, relief
=SUNKEN
)
289 listwidget
.pack(side
=LEFT
, expand
=YES
, fill
=BOTH
)
290 scroll
.config(command
=listwidget
.yview
, relief
=SUNKEN
)
291 scroll
.pack(side
=RIGHT
, fill
=BOTH
)
292 listwidget
.config(selectmode
=SINGLE
, setgrid
=TRUE
)
293 listwidget
.bind('<Double-1>', self
.handleList
);
294 listwidget
.bind('<Return>', self
.handleList
);
295 self
.listwidget
= listwidget
299 Button(bf
, text
='Edit', command
=self
.editItem
).pack(side
=LEFT
)
300 Button(bf
, text
='Delete', command
=self
.deleteItem
).pack(side
=RIGHT
)
303 def handleList(self
, event
):
306 def handleNew(self
, event
):
307 item
= self
.newval
.get()
308 entire
= self
.listwidget
.get(0, self
.listwidget
.index('end'));
309 if item
and (not entire
) or (not item
in self
.listwidget
.get(0, self
.listwidget
.index('end'))):
310 self
.listwidget
.insert('end', item
)
311 if self
.list != None: self
.list.append(item
)
315 index
= self
.listwidget
.curselection()[0]
316 if index
and self
.editor
:
317 label
= self
.listwidget
.get(index
);
318 apply(self
.editor
, (label
,))
320 def deleteItem(self
):
321 index
= self
.listwidget
.curselection()[0]
323 self
.listwidget
.delete(index
)
324 if self
.list != None: del self
.list[index
]
326 def ConfirmQuit(frame
, context
):
329 text
= 'Really quit ' + context
+ ' without saving?',
331 strings
= ('Yes', 'No'),
335 # First, code to set the global fetchmail run controls.
339 'title' : 'Fetchmail configurator help',
340 'banner': 'Configurator help',
342 In the `Configurator Controls' panel, you can:
344 Press `Save' to save the new fetchmail configuration you have created.
345 Press `Quit' to exit without saving.
346 Press `Help' to bring up this help message.
348 In the `Configurator Controls' panel, you can set the following options that
349 control how fetchmail runs:
352 Number of seconds to wait between polls in the background.
353 Ignored if the `Run in Foreground?' option is on.
356 If empty, emit progress and error messages to stderr.
357 Otherwise this gives the name of the files to write to.
358 This field is ignored if the "Log to syslog?" option is on.
360 In the `Remote Mail Configurations' panel, you can:
362 1. Enter the name of a new remote mail server you want fetchmail to query.
364 To do this, simply enter a label for the poll configuration in the
365 `New Server:' box. The label should be a DNS name of the server (unless
366 you are using ssh or some other tunneling method and will fill in the `via'
367 option on the site configuration screen).
369 2. Change the configuration of an existing site.
371 To do this, find the site's label in the listbox and double-click it.
372 This will take you to a site configuration dialogue.
375 class ControlEdit(Frame
):
376 def PostControls(self
):
377 self
.foreground
= BooleanVar(self
)
378 self
.foreground
.set(self
.controls
.foreground
)
379 self
.daemon
= StringVar(self
)
380 self
.daemon
.set(`self
.controls
.daemon`
)
381 self
.syslog
= BooleanVar(self
)
382 self
.syslog
.set(self
.controls
.syslog
);
383 self
.logfile
= StringVar(self
)
384 if self
.controls
.logfile
: self
.logfile
.set(self
.controls
.logfile
);
386 gf
= Frame(self
, relief
=RAISED
, bd
= 5)
389 text
='Fetchmail Run Controls',
390 bd
=2).pack(side
=TOP
, pady
=10)
392 df
= Frame(gf
, relief
=RAISED
, bd
=2)
396 {'text':'Run in foreground?',
397 'variable':self
.foreground
,
398 'relief':GROOVE
}).pack(side
=LEFT
,anchor
=W
)
400 # Set the poll interval
401 de
= LabeledEntry(df
, ' Poll interval:', self
.daemon
, '14')
402 de
.pack(side
=RIGHT
, anchor
=E
)
406 sf
= Frame(gf
, relief
=RAISED
, bd
=2)
408 # Use syslog for logging?
410 {'text':'Log to syslog?',
411 'variable':self
.syslog
,
412 'relief':GROOVE
}).pack(side
=LEFT
, anchor
=W
)
415 log
= LabeledEntry(sf
, ' Logfile:', self
.logfile
, '14')
416 log
.pack(side
=RIGHT
, anchor
=E
)
421 def GatherControls(self
):
422 self
.controls
.daemon
= self
.daemon
.get()
423 self
.controls
.foreground
= self
.foreground
.get()
424 self
.controls
.logfile
= self
.logfile
.get()
425 self
.controls
.syslog
= self
.syslog
.get()
428 # Server editing stuff.
431 'title' : 'Server options help',
432 'banner': 'Server Options',
434 The server options screen controls fetchmail
435 options that apply to one of your mailservers.
437 Once you have a mailserver configuration set
438 up as you like it, you can select `Save' to
439 store it in the server list maintained in
440 the main configuration window.
442 If you wish to discard changes to a server
443 configuration, select `Quit'.
447 'title' : 'Run Control help',
448 'banner': 'Run Controls',
450 If the `Poll normally' checkbox is on, the host is polled as part of
451 the normal operation of fetchmail when it is run with no arguments.
452 If it is off, fetchmail will only query this host when it is given as
453 a command-line argument.
455 The `True name of server' box should specify the actual DNS name
456 to query. By default this is the same as the poll name.
458 Normally each host described in the file is queried once each
459 poll cycle. If `Cycles to skip between polls' is greater than 0,
460 that's the number of poll cycles that are skipped between the
461 times this post is actually polled.
463 The `Server timeout' is the number of seconds fetchmail will wait
464 for a reply from the mailserver before concluding it is hung and
469 'title' : 'Protocol and Port help',
470 'banner': 'Protocol and Port',
472 These options control the remote-mail protocol
473 and TCP/IP service port used to query this
476 The `Protocol' button bar offers you a choice of
477 all the different protocols available. The `auto'
478 protocol is a special mode that probes the host
479 ports for POP3 and IMAP to see if either is
482 Normally the TCP/IP service port to use is
483 dictated by the protocol choice. The `Port'
484 field lets you set a non-standard port.
488 'title' : 'Security option help',
489 'banner': 'Security',
491 These options control the security procedure used
492 to protect mail transfer
494 Normally the mail fetch is validated using an
495 ordinary password logon. If your server speaks
496 MIT Kerberos IV it is possible to pre-authenticate
497 the exxchange with a Kerberos ticket.
499 The `interface' and `monitor' options are available
500 only for Linux systems. See the fetchmail manual page
501 for details on these.
505 'title' : 'Multidrop option help',
506 'banner': 'Multidrop',
508 These options are only useful with multidrop mode.
509 See the manual page for extended discussion.
512 class ServerEdit(Frame
):
513 def __init__(self
, host
, sitelist
, master
=None):
514 Frame
.__init
__(self
, master
)
516 self
.master
.title('Fetchmail host ' + host
);
517 self
.master
.iconname('Fetchmail host ' + host
);
518 self
.server
= Server()
519 self
.server
.pollname
= host
520 self
.server
.via
= host
521 self
.sitelist
= sitelist
523 self
.createWidgets(host
)
526 # we can't abstract this away, execs would happen in the wrong scope
527 for x
in self
.server
.typemap
:
528 target
= "self." + x
[0]
529 source
= "self.server." + x
[0]
530 if x
[1] == 'Boolean':
531 exec target
+ " = BooleanVar(self)"
533 exec target
+ ".set(" + source
+ ")"
534 elif x
[1] == 'String':
535 exec target
+ " = StringVar(self)"
537 exec target
+ ".set(" + source
+ ")"
539 exec target
+ " = IntVar(self)"
541 exec target
+ ".set(" + source
+ ")"
544 for x
in self
.server
.typemap
:
545 setattr(self
.server
, x
[0], getattr(self
, x
[0]).get())
548 if ConfirmQuit(self
, 'server option editing'):
549 Widget
.destroy(self
.master
)
553 self
.sitelist
.append(self
.server
)
554 Widget
.destroy(self
.master
)
556 def refreshPort(self
):
557 proto
= self
.protocol
.get()
558 self
.port
.set(defaultports
[proto
])
559 if not proto
in ("POP3", "APOP", "KPOP"): self
.uidl
= FALSE
561 def createWidgets(self
, host
):
562 topwin
= Frame(self
, relief
=RAISED
, bd
=5)
563 Label(topwin
, text
="Server options for " + host
).pack(side
=TOP
,pady
=10)
564 Button(topwin
, text
='Save', fg
='blue',
565 command
=self
.save
).pack(side
=LEFT
)
566 Button(topwin
, text
='Quit', fg
='blue',
567 command
=self
.nosave
).pack(side
=LEFT
)
568 Button(topwin
, text
='Help', fg
='blue',
569 command
=lambda: helpwin(serverhelp
)).pack(side
=RIGHT
)
572 ctlwin
= Frame(self
, relief
=RAISED
, bd
=5)
573 Label(ctlwin
, text
="Run Controls").pack(side
=TOP
)
574 Checkbutton(ctlwin
, text
='Poll ' + host
+ ' normally?', variable
=self
.active
).pack(side
=TOP
)
575 LabeledEntry(ctlwin
, 'True name of ' + host
+ ':',
576 self
.via
, '30').pack(side
=TOP
, fill
=X
)
577 LabeledEntry(ctlwin
, 'Cycles to skip between polls:',
578 self
.interval
, '30').pack(side
=TOP
, fill
=X
)
579 LabeledEntry(ctlwin
, 'Server timeout (seconds):',
580 self
.timeout
, '30').pack(side
=TOP
, fill
=X
)
581 Button(ctlwin
, text
='Help', fg
='blue',
582 command
=lambda: helpwin(controlhelp
)).pack(side
=RIGHT
)
585 protwin
= Frame(self
, relief
=RAISED
, bd
=5)
586 Label(protwin
, text
="Protocol and Port").pack(side
=TOP
)
587 pb
= ButtonBar(protwin
, 'Protocol:', self
.protocol
, protolist
, self
.refreshPort
)
588 LabeledEntry(protwin
, 'TCP/IP service port to query:',
589 self
.port
, '30').pack(side
=TOP
, fill
=X
)
591 text
="Track seen POP3 messages with client-side UIDL list?",
592 variable
=self
.uidl
).pack(side
=TOP
)
593 Button(protwin
, text
='Help', fg
='blue',
594 command
=lambda: helpwin(protohelp
)).pack(side
=RIGHT
)
597 secwin
= Frame(self
, relief
=RAISED
, bd
=5)
598 Label(secwin
, text
="Security").pack(side
=TOP
)
599 ButtonBar(secwin
, 'Authorization mode:',
600 self
.auth
, authlist
, None).pack(side
=TOP
)
602 if os
.popen("uname").readlines()[0] == 'Linux\n':
603 LabeledEntry(secwin
, 'Interface to check before polling:',
604 self
.interface
, '30').pack(side
=TOP
, fill
=X
)
605 LabeledEntry(secwin
, 'IP addresses to watch for activity:',
606 self
.monitor
, '30').pack(side
=TOP
, fill
=X
)
608 Button(secwin
, text
='Help', fg
='blue',
609 command
=lambda: helpwin(sechelp
)).pack(side
=RIGHT
)
612 mdropwin
= Frame(self
, relief
=RAISED
, bd
=5)
613 Label(mdropwin
, text
="Multidrop options").pack(side
=TOP
)
614 LabeledEntry(mdropwin
, 'Envelope address header:',
615 self
.envelope
, '30').pack(side
=TOP
, fill
=X
)
616 Checkbutton(mdropwin
, text
="Enable multidrop DNS lookup?",
617 variable
=self
.dns
).pack(side
=TOP
)
618 Label(mdropwin
, text
="DNS aliases").pack(side
=TOP
)
619 ListEdit("New site alias: ", self
.server
.aka
, None, mdropwin
)
620 Label(mdropwin
, text
="Domains to be considered local").pack(side
=TOP
)
621 ListEdit("New local domain: ", self
.server
.localdomains
, None,mdropwin
)
622 Button(mdropwin
, text
='Help', fg
='blue',
623 command
=lambda: helpwin(multihelp
)).pack(side
=RIGHT
)
624 mdropwin
.pack(fill
=X
)
626 userwin
= Frame(self
, relief
=RAISED
, bd
=5)
627 Label(userwin
, text
="User entries for " + host
).pack(side
=TOP
)
628 ListEdit("New user: ", None, self
.edituser
, userwin
)
631 def edituser(self
, user
):
632 UserEdit(user
, self
.server
.userlist
, Toplevel())
639 'title' : 'User option help',
640 'banner': 'User options',
645 class UserEdit(Frame
):
646 def __init__(self
, user
, userlist
, master
=None):
647 Frame
.__init
__(self
, master
)
649 self
.master
.title('Fetchmail user ' + user
);
650 self
.master
.iconname('Fetchmail user ' + user
);
652 self
.user
.remote
= user
653 self
.user
.localnames
= [user
]
654 self
.userlist
= userlist
656 self
.createWidgets(user
)
659 # we can't abstract this away, execs would happen in the wrong scope
660 for x
in self
.user
.typemap
:
661 target
= "self." + x
[0]
662 source
= "self.user." + x
[0]
663 if x
[1] == 'Boolean':
664 exec target
+ " = BooleanVar(self)"
666 exec target
+ ".set(" + source
+ ")"
667 elif x
[1] == 'String':
668 exec target
+ " = StringVar(self)"
670 exec target
+ ".set(" + source
+ ")"
672 exec target
+ " = IntVar(self)"
674 exec target
+ ".set(" + source
+ ")"
677 for x
in self
.user
.typemap
:
678 setattr(self
.user
, x
[0], getattr(self
, x
[0]).get())
681 if ConfirmQuit(self
, 'user option editing'):
682 Widget
.destroy(self
.master
)
686 self
.userlist
.append(self
.user
)
687 Widget
.destroy(self
.master
)
689 def createWidgets(self
):
690 topwin
= Frame(self
, relief
=RAISED
, bd
=5)
692 text
="User options for " + self
.user
.remote
).pack(side
=TOP
,pady
=10)
693 Button(topwin
, text
='Save', fg
='blue',
694 command
=self
.save
).pack(side
=LEFT
)
695 Button(topwin
, text
='Quit', fg
='blue',
696 command
=self
.nosave
).pack(side
=LEFT
)
697 Button(topwin
, text
='Help', fg
='blue',
698 command
=lambda: helpwin(userhelp
)).pack(side
=RIGHT
)
701 secwin
= Frame(self
, relief
=RAISED
, bd
=5)
702 Label(secwin
, text
="Authentication").pack(side
=TOP
)
703 LabeledEntry(mdropwin
, 'Password:',
704 self
.password
, '30').pack(side
=TOP
, fill
=X
)
705 LabeledEntry(mdropwin
, 'Remote folder:',
706 self
.folder
, '30').pack(side
=TOP
, fill
=X
)
709 names
= Frame(self
, relief
=RAISED
, bd
=5)
710 Label(names
, text
="Local names").pack(side
=TOP
)
711 ListEdit("New local name: ", self
.localnames
, None, names
)
714 targwin
= Frame(self
, relief
=RAISED
, bd
=5)
715 Label(targwin
, text
="Forwarding Options").pack(side
=TOP
)
716 LabeledEntry(targwin
, 'System to forward to:',
717 self
.smtphost
, '30').pack(side
=TOP
, fill
=X
)
718 LabeledEntry(targwin
, 'Connection setup command:',
719 self
.preconnect
, '30').pack(side
=TOP
, fill
=X
)
720 LabeledEntry(targwin
, 'Connection wrapup command:',
721 self
.postconnect
, '30').pack(side
=TOP
, fill
=X
)
722 LabeledEntry(targwin
, 'Local delivery agent:',
723 self
.mda
, '30').pack(side
=TOP
, fill
=X
)
726 optwin
= Frame(self
, relief
=RAISED
, bd
=5)
727 Checkbutton(optwin
, "Suppress deletion of messages after reading",
729 Checkbutton(optwin
, "Flush seen messages before retrieval",
731 Checkbutton(optwin
, "Fetch old messages as well as new",
733 Checkbutton(optwin
, "Rewrite To/Cc/Bcc messages to enable reply",
735 Checkbutton(optwin
, "Force CR/LF at end of each line",
737 Checkbutton(optwin
, "Strip CR from end of eacgh line",
739 Checkbutton(optwin
, "Pass 8 bits even theough SMTP says 7BIT",
741 Checkbutton(optwin
, "Drop Status lines from forwarded messages",
745 limwin
= Frame(self
, relief
=RAISED
, bd
=5)
746 Label(limwin
, text
="Resource Limits").pack(side
=TOP
)
747 LabeledEntry(limwin
, 'Message size limit:',
748 self
.limit
, '30').pack(side
=TOP
, fill
=X
)
749 LabeledEntry(limwin
, 'Maximum messages to fetch each poll:',
750 self
.fetchlimit
, '30').pack(side
=TOP
, fill
=X
)
751 LabeledEntry(limwin
, 'Maximum messages to forward each poll:',
752 self
.batchlimit
, '30').pack(side
=TOP
, fill
=X
)
756 # Configure drives the configuration dialogue. It may call multiple
757 # instances of ServerEdit to do its job.
760 class Configure(Frame
, ControlEdit
):
761 def __init__(self
, master
=None):
762 Frame
.__init
__(self
, master
)
763 self
.master
.title('fetchmail configurator');
764 self
.master
.iconname('fetchmail configurator');
767 self
.controls
= Controls()
769 self
.MakeSitelist(master
)
772 def MakeDispose(self
):
773 # Set the disposal of the given configuration
774 dispose
= Frame(self
, relief
=RAISED
, bd
=5);
776 text
='Configurator Controls',
777 bd
=2).pack(side
=TOP
, pady
=10)
778 Button(dispose
, text
='Save', fg
='blue',
779 command
=self
.save
).pack(side
=LEFT
)
780 Button(dispose
, text
='Quit', fg
='blue',
781 command
=self
.nosave
).pack(side
=LEFT
)
782 Button(dispose
, text
='Help', fg
='blue',
783 command
=lambda: helpwin(confighelp
)).pack(side
=RIGHT
)
784 dispose
.pack(side
=TOP
, fill
=X
);
786 def MakeSitelist(self
, master
):
787 lf
= Frame(master
, relief
=RAISED
, bd
=5)
789 text
='Remote Mail Server Configurations',
790 bd
=2).pack(side
=TOP
, pady
=10)
791 ListEdit('New Server:', None, self
.editsite
, lf
)
794 def editsite(self
, site
):
795 ServerEdit(site
, self
.sites
, Toplevel())
798 self
.GatherControls()
799 sys
.stdout
.write("# Configuration created %s\n" % time
.ctime(time
.time()))
800 sys
.stdout
.write(`self
.controls`
)
801 for site
in self
.sites
:
802 sys
.stdout
.write(`site`
)
803 for user
in self
.sites
.userlist
:
804 sys
.stdout
.write(`user`
)
808 if ConfirmQuit(self
, "configuration editor"):
811 if __name__
== '__main__':
812 ServerDefaults
= Server()
813 UserDefaults
= User()
814 Configure().mainloop()
816 # The following sets edit modes for GNU EMACS