~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/mail_client.py

  • Committer: Jonathan Lange
  • Date: 2009-06-10 08:05:05 UTC
  • mto: This revision was merged to the branch mainline in revision 4433.
  • Revision ID: jml@canonical.com-20090610080505-lmch4q01z1q7deu2
MoreĀ unusedĀ imports.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2007-2010 Canonical Ltd
 
1
# Copyright (C) 2007 Canonical Ltd
2
2
#
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
89
89
 
90
90
 
91
91
class Editor(MailClient):
92
 
    __doc__ = """DIY mail client that uses commit message editor"""
 
92
    """DIY mail client that uses commit message editor"""
93
93
 
94
94
    supports_body = True
95
95
 
230
230
 
231
231
 
232
232
class ExternalMailClient(BodyExternalMailClient):
233
 
    __doc__ = """An external mail client."""
 
233
    """An external mail client."""
234
234
 
235
235
    supports_body = False
236
236
 
237
237
 
238
238
class Evolution(BodyExternalMailClient):
239
 
    __doc__ = """Evolution mail client."""
 
239
    """Evolution mail client."""
240
240
 
241
241
    _client_commands = ['evolution']
242
242
 
257
257
                              help=Evolution.__doc__)
258
258
 
259
259
 
260
 
class Mutt(BodyExternalMailClient):
261
 
    __doc__ = """Mutt mail client."""
 
260
class Mutt(ExternalMailClient):
 
261
    """Mutt mail client."""
262
262
 
263
263
    _client_commands = ['mutt']
264
264
 
265
 
    def _get_compose_commandline(self, to, subject, attach_path, body=None):
 
265
    def _get_compose_commandline(self, to, subject, attach_path):
266
266
        """See ExternalMailClient._get_compose_commandline"""
267
267
        message_options = []
268
268
        if subject is not None:
270
270
        if attach_path is not None:
271
271
            message_options.extend(['-a',
272
272
                self._encode_path(attach_path, 'attachment')])
273
 
        if body is not None:
274
 
            # Store the temp file object in self, so that it does not get
275
 
            # garbage collected and delete the file before mutt can read it.
276
 
            self._temp_file = tempfile.NamedTemporaryFile(
277
 
                prefix="mutt-body-", suffix=".txt")
278
 
            self._temp_file.write(body)
279
 
            self._temp_file.flush()
280
 
            message_options.extend(['-i', self._temp_file.name])
281
273
        if to is not None:
282
274
            message_options.extend(['--', self._encode_safe(to)])
283
275
        return message_options
286
278
 
287
279
 
288
280
class Thunderbird(BodyExternalMailClient):
289
 
    __doc__ = """Mozilla Thunderbird (or Icedove)
 
281
    """Mozilla Thunderbird (or Icedove)
290
282
 
291
283
    Note that Thunderbird 1.5 is buggy and does not support setting
292
284
    "to" simultaneously with including a attachment.
321
313
 
322
314
 
323
315
class KMail(ExternalMailClient):
324
 
    __doc__ = """KDE mail client."""
 
316
    """KDE mail client."""
325
317
 
326
318
    _client_commands = ['kmail']
327
319
 
341
333
 
342
334
 
343
335
class Claws(ExternalMailClient):
344
 
    __doc__ = """Claws mail client."""
 
336
    """Claws mail client."""
345
337
 
346
338
    supports_body = True
347
339
 
387
379
 
388
380
 
389
381
class XDGEmail(BodyExternalMailClient):
390
 
    __doc__ = """xdg-email attempts to invoke the user's preferred mail client"""
 
382
    """xdg-email attempts to invoke the user's preferred mail client"""
391
383
 
392
384
    _client_commands = ['xdg-email']
393
385
 
409
401
 
410
402
 
411
403
class EmacsMail(ExternalMailClient):
412
 
    __doc__ = """Call emacsclient to have a mail buffer.
 
404
    """Call emacsclient to have a mail buffer.
413
405
 
414
406
    This only work for emacs >= 22.1 due to recent -e/--eval support.
415
407
 
424
416
 
425
417
    _client_commands = ['emacsclient']
426
418
 
427
 
    def __init__(self, config):
428
 
        super(EmacsMail, self).__init__(config)
429
 
        self.elisp_tmp_file = None
430
 
 
431
419
    def _prepare_send_function(self):
432
420
        """Write our wrapper function into a temporary file.
433
421
 
504
492
        if attach_path is not None:
505
493
            # Do not create a file if there is no attachment
506
494
            elisp = self._prepare_send_function()
507
 
            self.elisp_tmp_file = elisp
508
495
            lmmform = '(load "%s")' % elisp
509
496
            mmform  = '(bzr-add-mime-att "%s")' % \
510
497
                self._encode_path(attach_path, 'attachment')
519
506
 
520
507
 
521
508
class MAPIClient(BodyExternalMailClient):
522
 
    __doc__ = """Default Windows mail client launched using MAPI."""
 
509
    """Default Windows mail client launched using MAPI."""
523
510
 
524
511
    def _compose(self, prompt, to, subject, attach_path, mime_subtype,
525
512
                 extension, body=None):
539
526
                              help=MAPIClient.__doc__)
540
527
 
541
528
 
542
 
class MailApp(BodyExternalMailClient):
543
 
    __doc__ = """Use MacOS X's Mail.app for sending email messages.
544
 
 
545
 
    Although it would be nice to use appscript, it's not installed
546
 
    with the shipped Python installations.  We instead build an
547
 
    AppleScript and invoke the script using osascript(1).  We don't
548
 
    use the _encode_safe() routines as it's not clear what encoding
549
 
    osascript expects the script to be in.
550
 
    """
551
 
 
552
 
    _client_commands = ['osascript']
553
 
 
554
 
    def _get_compose_commandline(self, to, subject, attach_path, body=None,
555
 
                                from_=None):
556
 
       """See ExternalMailClient._get_compose_commandline"""
557
 
 
558
 
       fd, self.temp_file = tempfile.mkstemp(prefix="bzr-send-",
559
 
                                         suffix=".scpt")
560
 
       try:
561
 
           os.write(fd, 'tell application "Mail"\n')
562
 
           os.write(fd, 'set newMessage to make new outgoing message\n')
563
 
           os.write(fd, 'tell newMessage\n')
564
 
           if to is not None:
565
 
               os.write(fd, 'make new to recipient with properties'
566
 
                   ' {address:"%s"}\n' % to)
567
 
           if from_ is not None:
568
 
               # though from_ doesn't actually seem to be used
569
 
               os.write(fd, 'set sender to "%s"\n'
570
 
                   % sender.replace('"', '\\"'))
571
 
           if subject is not None:
572
 
               os.write(fd, 'set subject to "%s"\n'
573
 
                   % subject.replace('"', '\\"'))
574
 
           if body is not None:
575
 
               # FIXME: would be nice to prepend the body to the
576
 
               # existing content (e.g., preserve signature), but
577
 
               # can't seem to figure out the right applescript
578
 
               # incantation.
579
 
               os.write(fd, 'set content to "%s\\n\n"\n' %
580
 
                   body.replace('"', '\\"').replace('\n', '\\n'))
581
 
 
582
 
           if attach_path is not None:
583
 
               # FIXME: would be nice to first append a newline to
584
 
               # ensure the attachment is on a new paragraph, but
585
 
               # can't seem to figure out the right applescript
586
 
               # incantation.
587
 
               os.write(fd, 'tell content to make new attachment'
588
 
                   ' with properties {file name:"%s"}'
589
 
                   ' at after the last paragraph\n'
590
 
                   % self._encode_path(attach_path, 'attachment'))
591
 
           os.write(fd, 'set visible to true\n')
592
 
           os.write(fd, 'end tell\n')
593
 
           os.write(fd, 'end tell\n')
594
 
       finally:
595
 
           os.close(fd) # Just close the handle but do not remove the file.
596
 
       return [self.temp_file]
597
 
mail_client_registry.register('mail.app', MailApp,
598
 
                              help=MailApp.__doc__)
599
 
 
600
 
 
601
529
class DefaultMail(MailClient):
602
 
    __doc__ = """Default mail handling.  Tries XDGEmail (or MAPIClient on Windows),
 
530
    """Default mail handling.  Tries XDGEmail (or MAPIClient on Windows),
603
531
    falls back to Editor"""
604
532
 
605
533
    supports_body = True
634
562
mail_client_registry.register('default', DefaultMail,
635
563
                              help=DefaultMail.__doc__)
636
564
mail_client_registry.default_key = 'default'
637
 
 
638