/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to breezy/mail_client.py

  • Committer: Jelmer Vernooij
  • Date: 2017-10-27 00:18:42 UTC
  • mto: This revision was merged to the branch mainline in revision 6799.
  • Revision ID: jelmer@jelmer.uk-20171027001842-o77sekj0g2t2zwbn
Properly escape backslashes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
 
17
19
import errno
18
20
import os
19
21
import subprocess
20
22
import sys
21
23
import tempfile
22
 
import urllib
23
24
 
24
 
import bzrlib
25
 
from bzrlib import (
 
25
import breezy
 
26
from . import (
 
27
    config as _mod_config,
26
28
    email_message,
27
29
    errors,
28
30
    msgeditor,
34
36
mail_client_registry = registry.Registry()
35
37
 
36
38
 
 
39
class MailClientNotFound(errors.BzrError):
 
40
 
 
41
    _fmt = "Unable to find mail client with the following names:"\
 
42
        " %(mail_command_list_string)s"
 
43
 
 
44
    def __init__(self, mail_command_list):
 
45
        mail_command_list_string = ', '.join(mail_command_list)
 
46
        errors.BzrError.__init__(
 
47
            self, mail_command_list=mail_command_list,
 
48
            mail_command_list_string=mail_command_list_string)
 
49
 
 
50
 
 
51
class NoMessageSupplied(errors.BzrError):
 
52
 
 
53
    _fmt = "No message supplied."
 
54
 
 
55
 
 
56
class NoMailAddressSpecified(errors.BzrError):
 
57
 
 
58
    _fmt = "No mail-to address (--mail-to) or output (-o) specified."
 
59
 
 
60
 
37
61
class MailClient(object):
38
62
    """A mail client that can send messages with attachements."""
39
63
 
105
129
                extension, basename=None, body=None):
106
130
        """See MailClient.compose"""
107
131
        if not to:
108
 
            raise errors.NoMailAddressSpecified()
 
132
            raise NoMailAddressSpecified()
109
133
        body = msgeditor.edit_commit_message(prompt, start_message=body)
110
134
        if body == '':
111
 
            raise errors.NoMessageSupplied()
 
135
            raise NoMessageSupplied()
112
136
        email_message.EmailMessage.send(self.config,
113
 
                                        self.config.username(),
 
137
                                        self.config.get('email'),
114
138
                                        to,
115
139
                                        subject,
116
140
                                        body,
182
206
                                                         **kwargs))
183
207
            try:
184
208
                subprocess.call(cmdline)
185
 
            except OSError, e:
 
209
            except OSError as e:
186
210
                if e.errno != errno.ENOENT:
187
211
                    raise
188
212
            else:
189
213
                break
190
214
        else:
191
 
            raise errors.MailClientNotFound(self._client_commands)
 
215
            raise MailClientNotFound(self._client_commands)
192
216
 
193
217
    def _get_compose_commandline(self, to, subject, attach_path, body):
194
218
        """Determine the commandline to use for composing a message
250
274
        if body is not None:
251
275
            message_options['body'] = body
252
276
        options_list = ['%s=%s' % (k, urlutils.escape(v)) for (k, v) in
253
 
                        sorted(message_options.iteritems())]
 
277
                        sorted(message_options.items())]
254
278
        return ['mailto:%s?%s' % (self._encode_safe(to or ''),
255
279
            '&'.join(options_list))]
256
280
mail_client_registry.register('evolution', Evolution,
310
334
            message_options['attachment'] = urlutils.local_path_to_url(
311
335
                attach_path)
312
336
        if body is not None:
313
 
            options_list = ['body=%s' % urllib.quote(self._encode_safe(body))]
 
337
            options_list = ['body=%s' % urlutils.quote(self._encode_safe(body))]
314
338
        else:
315
339
            options_list = []
316
340
        options_list.extend(["%s='%s'" % (k, v) for k, v in
317
 
                        sorted(message_options.iteritems())])
 
341
                        sorted(message_options.items())])
318
342
        return ['-compose', ','.join(options_list)]
319
343
mail_client_registry.register('thunderbird', Thunderbird,
320
344
                              help=Thunderbird.__doc__)
352
376
        """See ExternalMailClient._get_compose_commandline"""
353
377
        compose_url = []
354
378
        if from_ is not None:
355
 
            compose_url.append('from=' + urllib.quote(from_))
 
379
            compose_url.append('from=' + urlutils.quote(from_))
356
380
        if subject is not None:
357
 
            # Don't use urllib.quote_plus because Claws doesn't seem
 
381
            # Don't use urlutils.quote_plus because Claws doesn't seem
358
382
            # to recognise spaces encoded as "+".
359
383
            compose_url.append(
360
 
                'subject=' + urllib.quote(self._encode_safe(subject)))
 
384
                'subject=' + urlutils.quote(self._encode_safe(subject)))
361
385
        if body is not None:
362
386
            compose_url.append(
363
 
                'body=' + urllib.quote(self._encode_safe(body)))
 
387
                'body=' + urlutils.quote(self._encode_safe(body)))
364
388
        # to must be supplied for the claws-mail --compose syntax to work.
365
389
        if to is None:
366
 
            raise errors.NoMailAddressSpecified()
 
390
            raise NoMailAddressSpecified()
367
391
        compose_url = 'mailto:%s?%s' % (
368
392
            self._encode_safe(to), '&'.join(compose_url))
369
393
        # Collect command-line options.
377
401
                 extension, body=None, from_=None):
378
402
        """See ExternalMailClient._compose"""
379
403
        if from_ is None:
380
 
            from_ = self.config.get_user_option('email')
 
404
            from_ = self.config.get('email')
381
405
        super(Claws, self)._compose(prompt, to, subject, attach_path,
382
406
                                    mime_subtype, extension, body, from_)
383
407
 
394
418
    def _get_compose_commandline(self, to, subject, attach_path, body=None):
395
419
        """See ExternalMailClient._get_compose_commandline"""
396
420
        if not to:
397
 
            raise errors.NoMailAddressSpecified()
 
421
            raise NoMailAddressSpecified()
398
422
        commandline = [self._encode_safe(to)]
399
423
        if subject is not None:
400
424
            commandline.extend(['--subject', self._encode_safe(subject)])
527
551
 
528
552
        This implementation uses MAPI via the simplemapi ctypes wrapper
529
553
        """
530
 
        from bzrlib.util import simplemapi
 
554
        from .util import simplemapi
531
555
        try:
532
556
            simplemapi.SendMail(to or '', subject or '', body or '',
533
557
                                attach_path)
534
 
        except simplemapi.MAPIError, e:
 
558
        except simplemapi.MAPIError as e:
535
559
            if e.code != simplemapi.MAPI_USER_ABORT:
536
 
                raise errors.MailClientNotFound(['MAPI supported mail client'
 
560
                raise MailClientNotFound(['MAPI supported mail client'
537
561
                                                 ' (error %d)' % (e.code,)])
538
562
mail_client_registry.register('mapi', MAPIClient,
539
563
                              help=MAPIClient.__doc__)
616
640
        """See MailClient.compose"""
617
641
        try:
618
642
            return self._mail_client().compose(prompt, to, subject,
619
 
                                               attachment, mimie_subtype,
 
643
                                               attachment, mime_subtype,
620
644
                                               extension, basename, body)
621
 
        except errors.MailClientNotFound:
 
645
        except MailClientNotFound:
622
646
            return Editor(self.config).compose(prompt, to, subject,
623
 
                          attachment, mimie_subtype, extension, body)
 
647
                          attachment, mime_subtype, extension, body)
624
648
 
625
649
    def compose_merge_request(self, to, subject, directive, basename=None,
626
650
                              body=None):
628
652
        try:
629
653
            return self._mail_client().compose_merge_request(to, subject,
630
654
                    directive, basename=basename, body=body)
631
 
        except errors.MailClientNotFound:
 
655
        except MailClientNotFound:
632
656
            return Editor(self.config).compose_merge_request(to, subject,
633
657
                          directive, basename=basename, body=body)
634
658
mail_client_registry.register('default', DefaultMail,
635
659
                              help=DefaultMail.__doc__)
636
660
mail_client_registry.default_key = 'default'
637
661
 
638
 
 
 
662
opt_mail_client = _mod_config.RegistryOption('mail_client',
 
663
        mail_client_registry, help='E-mail client to use.', invalid='error')