~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/mail_client.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2009-10-13 06:08:53 UTC
  • mfrom: (4737.1.1 merge-2.0-into-devel)
  • Revision ID: pqm@pqm.ubuntu.com-20091013060853-erk2aaj80fnkrv25
(andrew) Merge lp:bzr/2.0 into lp:bzr, including fixes for #322807,
        #389413, #402623 and documentation improvements.

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
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
16
 
17
 
from __future__ import absolute_import
18
 
 
19
17
import errno
20
18
import os
21
19
import subprocess
22
20
import sys
23
21
import tempfile
 
22
import urllib
24
23
 
25
24
import bzrlib
26
25
from bzrlib import (
27
 
    config as _mod_config,
28
26
    email_message,
29
27
    errors,
30
28
    msgeditor,
91
89
 
92
90
 
93
91
class Editor(MailClient):
94
 
    __doc__ = """DIY mail client that uses commit message editor"""
 
92
    """DIY mail client that uses commit message editor"""
95
93
 
96
94
    supports_body = True
97
95
 
112
110
        if body == '':
113
111
            raise errors.NoMessageSupplied()
114
112
        email_message.EmailMessage.send(self.config,
115
 
                                        self.config.get('email'),
 
113
                                        self.config.username(),
116
114
                                        to,
117
115
                                        subject,
118
116
                                        body,
232
230
 
233
231
 
234
232
class ExternalMailClient(BodyExternalMailClient):
235
 
    __doc__ = """An external mail client."""
 
233
    """An external mail client."""
236
234
 
237
235
    supports_body = False
238
236
 
239
237
 
240
238
class Evolution(BodyExternalMailClient):
241
 
    __doc__ = """Evolution mail client."""
 
239
    """Evolution mail client."""
242
240
 
243
241
    _client_commands = ['evolution']
244
242
 
260
258
 
261
259
 
262
260
class Mutt(BodyExternalMailClient):
263
 
    __doc__ = """Mutt mail client."""
 
261
    """Mutt mail client."""
264
262
 
265
263
    _client_commands = ['mutt']
266
264
 
288
286
 
289
287
 
290
288
class Thunderbird(BodyExternalMailClient):
291
 
    __doc__ = """Mozilla Thunderbird (or Icedove)
 
289
    """Mozilla Thunderbird (or Icedove)
292
290
 
293
291
    Note that Thunderbird 1.5 is buggy and does not support setting
294
292
    "to" simultaneously with including a attachment.
312
310
            message_options['attachment'] = urlutils.local_path_to_url(
313
311
                attach_path)
314
312
        if body is not None:
315
 
            options_list = ['body=%s' % urlutils.quote(self._encode_safe(body))]
 
313
            options_list = ['body=%s' % urllib.quote(self._encode_safe(body))]
316
314
        else:
317
315
            options_list = []
318
316
        options_list.extend(["%s='%s'" % (k, v) for k, v in
323
321
 
324
322
 
325
323
class KMail(ExternalMailClient):
326
 
    __doc__ = """KDE mail client."""
 
324
    """KDE mail client."""
327
325
 
328
326
    _client_commands = ['kmail']
329
327
 
343
341
 
344
342
 
345
343
class Claws(ExternalMailClient):
346
 
    __doc__ = """Claws mail client."""
 
344
    """Claws mail client."""
347
345
 
348
346
    supports_body = True
349
347
 
354
352
        """See ExternalMailClient._get_compose_commandline"""
355
353
        compose_url = []
356
354
        if from_ is not None:
357
 
            compose_url.append('from=' + urlutils.quote(from_))
 
355
            compose_url.append('from=' + urllib.quote(from_))
358
356
        if subject is not None:
359
 
            # Don't use urlutils.quote_plus because Claws doesn't seem
 
357
            # Don't use urllib.quote_plus because Claws doesn't seem
360
358
            # to recognise spaces encoded as "+".
361
359
            compose_url.append(
362
 
                'subject=' + urlutils.quote(self._encode_safe(subject)))
 
360
                'subject=' + urllib.quote(self._encode_safe(subject)))
363
361
        if body is not None:
364
362
            compose_url.append(
365
 
                'body=' + urlutils.quote(self._encode_safe(body)))
 
363
                'body=' + urllib.quote(self._encode_safe(body)))
366
364
        # to must be supplied for the claws-mail --compose syntax to work.
367
365
        if to is None:
368
366
            raise errors.NoMailAddressSpecified()
379
377
                 extension, body=None, from_=None):
380
378
        """See ExternalMailClient._compose"""
381
379
        if from_ is None:
382
 
            from_ = self.config.get('email')
 
380
            from_ = self.config.get_user_option('email')
383
381
        super(Claws, self)._compose(prompt, to, subject, attach_path,
384
382
                                    mime_subtype, extension, body, from_)
385
383
 
389
387
 
390
388
 
391
389
class XDGEmail(BodyExternalMailClient):
392
 
    __doc__ = """xdg-email attempts to invoke the user's preferred mail client"""
 
390
    """xdg-email attempts to invoke the user's preferred mail client"""
393
391
 
394
392
    _client_commands = ['xdg-email']
395
393
 
411
409
 
412
410
 
413
411
class EmacsMail(ExternalMailClient):
414
 
    __doc__ = """Call emacsclient to have a mail buffer.
 
412
    """Call emacsclient to have a mail buffer.
415
413
 
416
414
    This only work for emacs >= 22.1 due to recent -e/--eval support.
417
415
 
521
519
 
522
520
 
523
521
class MAPIClient(BodyExternalMailClient):
524
 
    __doc__ = """Default Windows mail client launched using MAPI."""
 
522
    """Default Windows mail client launched using MAPI."""
525
523
 
526
524
    def _compose(self, prompt, to, subject, attach_path, mime_subtype,
527
525
                 extension, body=None):
542
540
 
543
541
 
544
542
class MailApp(BodyExternalMailClient):
545
 
    __doc__ = """Use MacOS X's Mail.app for sending email messages.
 
543
    """Use MacOS X's Mail.app for sending email messages.
546
544
 
547
545
    Although it would be nice to use appscript, it's not installed
548
546
    with the shipped Python installations.  We instead build an
601
599
 
602
600
 
603
601
class DefaultMail(MailClient):
604
 
    __doc__ = """Default mail handling.  Tries XDGEmail (or MAPIClient on Windows),
 
602
    """Default mail handling.  Tries XDGEmail (or MAPIClient on Windows),
605
603
    falls back to Editor"""
606
604
 
607
605
    supports_body = True
618
616
        """See MailClient.compose"""
619
617
        try:
620
618
            return self._mail_client().compose(prompt, to, subject,
621
 
                                               attachment, mime_subtype,
 
619
                                               attachment, mimie_subtype,
622
620
                                               extension, basename, body)
623
621
        except errors.MailClientNotFound:
624
622
            return Editor(self.config).compose(prompt, to, subject,
625
 
                          attachment, mime_subtype, extension, body)
 
623
                          attachment, mimie_subtype, extension, body)
626
624
 
627
625
    def compose_merge_request(self, to, subject, directive, basename=None,
628
626
                              body=None):
637
635
                              help=DefaultMail.__doc__)
638
636
mail_client_registry.default_key = 'default'
639
637
 
640
 
opt_mail_client = _mod_config.RegistryOption('mail_client',
641
 
        mail_client_registry, help='E-mail client to use.', invalid='error')
 
638