/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
2681.1.8 by Aaron Bentley
Add Thunderbird support to bzr send
1
# Copyright (C) 2007 Canonical Ltd
2
#
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
#
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
2681.1.18 by Aaron Bentley
Refactor to increase code sharing, allow multiple command names for tbird
17
import errno
2681.1.8 by Aaron Bentley
Add Thunderbird support to bzr send
18
import os
19
import subprocess
2681.4.1 by Alexander Belchenko
win32: looking for full path of mail client executable in registry
20
import sys
2681.1.8 by Aaron Bentley
Add Thunderbird support to bzr send
21
import tempfile
22
2681.1.9 by Aaron Bentley
Add support for mail-from-editor
23
from bzrlib import (
24
    email_message,
25
    errors,
26
    msgeditor,
27
    urlutils,
28
    )
2681.4.1 by Alexander Belchenko
win32: looking for full path of mail client executable in registry
29
from bzrlib.lazy_import import lazy_import
30
lazy_import(globals(), """
31
import win32utils
32
""")
2681.1.8 by Aaron Bentley
Add Thunderbird support to bzr send
33
34
35
class MailClient(object):
2681.1.11 by Aaron Bentley
Add docstrings, add compose_merge_request
36
    """A mail client that can send messages with attachements."""
2681.1.8 by Aaron Bentley
Add Thunderbird support to bzr send
37
2681.1.9 by Aaron Bentley
Add support for mail-from-editor
38
    def __init__(self, config):
39
        self.config = config
40
2681.1.11 by Aaron Bentley
Add docstrings, add compose_merge_request
41
    def compose(self, prompt, to, subject, attachment, mime_subtype,
42
                extension):
2681.1.8 by Aaron Bentley
Add Thunderbird support to bzr send
43
        raise NotImplementedError
44
2681.1.11 by Aaron Bentley
Add docstrings, add compose_merge_request
45
    def compose_merge_request(self, to, subject, directive):
2681.1.21 by Aaron Bentley
Refactor prompt generation to make it testable, test it with unicode
46
        prompt = self._get_merge_prompt("Please describe these changes:", to,
47
                                        subject, directive)
48
        self.compose(prompt, to, subject, directive,
2681.1.11 by Aaron Bentley
Add docstrings, add compose_merge_request
49
            'x-patch', '.patch')
50
2681.1.21 by Aaron Bentley
Refactor prompt generation to make it testable, test it with unicode
51
    def _get_merge_prompt(self, prompt, to, subject, attachment):
52
        return ''
53
2681.1.8 by Aaron Bentley
Add Thunderbird support to bzr send
54
55
class Editor(MailClient):
2681.1.11 by Aaron Bentley
Add docstrings, add compose_merge_request
56
    """DIY mail client that uses commit message editor"""
2681.1.8 by Aaron Bentley
Add Thunderbird support to bzr send
57
2681.1.21 by Aaron Bentley
Refactor prompt generation to make it testable, test it with unicode
58
    def _get_merge_prompt(self, prompt, to, subject, attachment):
59
        return "%s\n\nTo: %s\nSubject: %s\n\n%s" % (prompt, to, subject,
60
                attachment.decode('utf-8', 'replace'))
61
2681.1.11 by Aaron Bentley
Add docstrings, add compose_merge_request
62
    def compose(self, prompt, to, subject, attachment, mime_subtype,
63
                extension):
2681.1.21 by Aaron Bentley
Refactor prompt generation to make it testable, test it with unicode
64
        body = msgeditor.edit_commit_message(prompt)
2681.1.9 by Aaron Bentley
Add support for mail-from-editor
65
        if body == '':
66
            raise errors.NoMessageSupplied()
67
        email_message.EmailMessage.send(self.config,
68
                                        self.config.username(),
69
                                        to,
70
                                        subject,
71
                                        body,
72
                                        attachment,
2681.1.11 by Aaron Bentley
Add docstrings, add compose_merge_request
73
                                        attachment_mime_subtype=mime_subtype)
2681.1.8 by Aaron Bentley
Add Thunderbird support to bzr send
74
75
2681.1.18 by Aaron Bentley
Refactor to increase code sharing, allow multiple command names for tbird
76
class Evolution(MailClient):
77
    """Evolution mail client."""
78
79
    _client_commands = ['evolution']
80
2681.4.1 by Alexander Belchenko
win32: looking for full path of mail client executable in registry
81
    def _get_client_commands(self):
82
        if sys.platform == 'win32':
83
            return [win32utils.get_app_path(i) for i in self._client_commands]
84
        else:
85
            return self._client_commands
86
2681.1.18 by Aaron Bentley
Refactor to increase code sharing, allow multiple command names for tbird
87
    def compose(self, prompt, to, subject, attachment, mime_subtype,
88
                extension):
89
        fd, pathname = tempfile.mkstemp(extension, 'bzr-mail-')
90
        try:
91
            os.write(fd, attachment)
92
        finally:
93
            os.close(fd)
2681.4.1 by Alexander Belchenko
win32: looking for full path of mail client executable in registry
94
        for name in self._get_client_commands():
2681.1.18 by Aaron Bentley
Refactor to increase code sharing, allow multiple command names for tbird
95
            cmdline = [name]
96
            cmdline.extend(self._get_compose_commandline(to, subject,
97
                                                         pathname))
98
            try:
99
                subprocess.call(cmdline)
100
            except OSError, e:
101
                if e.errno != errno.ENOENT:
102
                    raise
103
            else:
104
                break
105
        else:
106
            raise errors.MailClientNotFound(self._client_commands)
107
108
    def _get_compose_commandline(self, to, subject, attach_path):
109
        message_options = {}
110
        if subject is not None:
111
            message_options['subject'] = subject
112
        if attach_path is not None:
113
            message_options['attach'] = attach_path
114
        options_list = ['%s=%s' % (k, urlutils.escape(v)) for (k, v) in
115
                        message_options.iteritems()]
116
        return ['mailto:%s?%s' % (to or '', '&'.join(options_list))]
117
118
119
class Thunderbird(Evolution):
2681.1.11 by Aaron Bentley
Add docstrings, add compose_merge_request
120
    """Mozilla Thunderbird (or Icedove)
121
122
    Note that Thunderbird 1.5 is buggy and does not support setting
123
    "to" simultaneously with including a attachment.
124
125
    There is a workaround if no attachment is present, but we always need to
126
    send attachments.
127
    """
128
2681.1.18 by Aaron Bentley
Refactor to increase code sharing, allow multiple command names for tbird
129
    _client_commands = ['thunderbird', 'mozilla-thunderbird', 'icedove']
2681.1.8 by Aaron Bentley
Add Thunderbird support to bzr send
130
131
    def _get_compose_commandline(self, to, subject, attach_path):
132
        message_options = {}
133
        if to is not None:
134
            message_options['to'] = to
135
        if subject is not None:
136
            message_options['subject'] = subject
137
        if attach_path is not None:
138
            message_options['attachment'] = urlutils.local_path_to_url(
139
                attach_path)
140
        options_list = ["%s='%s'" % (k, v) for k, v in
141
                        sorted(message_options.iteritems())]
142
        return ['-compose', ','.join(options_list)]