~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/mail_client.py

Merge MAPI support from Lukáš Lalinsky

Show diffs side-by-side

added added

removed removed

Lines of Context:
17
17
import errno
18
18
import os
19
19
import subprocess
 
20
import sys
20
21
import tempfile
21
22
 
22
23
from bzrlib import (
23
24
    email_message,
24
25
    errors,
25
26
    msgeditor,
 
27
    osutils,
26
28
    urlutils,
27
29
    )
28
30
 
68
70
                                        attachment_mime_subtype=mime_subtype)
69
71
 
70
72
 
71
 
class Evolution(MailClient):
72
 
    """Evolution mail client."""
73
 
 
74
 
    _client_commands = ['evolution']
 
73
class ExternalMailClient(MailClient):
 
74
    """An external mail client."""
75
75
 
76
76
    def compose(self, prompt, to, subject, attachment, mime_subtype,
77
77
                extension):
80
80
            os.write(fd, attachment)
81
81
        finally:
82
82
            os.close(fd)
 
83
        self._compose(prompt, to, subject, pathname, mime_subtype, extension)
 
84
 
 
85
    def _compose(self, prompt, to, subject, attach_path, mime_subtype,
 
86
                extension):
83
87
        for name in self._client_commands:
84
88
            cmdline = [name]
85
 
            cmdline.extend(self._get_compose_commandline(to, subject,
86
 
                                                         pathname))
 
89
            cmdline.extend(self._get_compose_commandline(to, subject, 
 
90
                                                         attach_path))
87
91
            try:
88
92
                subprocess.call(cmdline)
89
93
            except OSError, e:
95
99
            raise errors.MailClientNotFound(self._client_commands)
96
100
 
97
101
    def _get_compose_commandline(self, to, subject, attach_path):
 
102
        raise NotImplementedError
 
103
 
 
104
 
 
105
class Evolution(ExternalMailClient):
 
106
    """Evolution mail client."""
 
107
 
 
108
    _client_commands = ['evolution']
 
109
 
 
110
    def _get_compose_commandline(self, to, subject, attach_path):
98
111
        message_options = {}
99
112
        if subject is not None:
100
113
            message_options['subject'] = subject
105
118
        return ['mailto:%s?%s' % (to or '', '&'.join(options_list))]
106
119
 
107
120
 
108
 
class Thunderbird(Evolution):
 
121
class Thunderbird(ExternalMailClient):
109
122
    """Mozilla Thunderbird (or Icedove)
110
123
 
111
124
    Note that Thunderbird 1.5 is buggy and does not support setting
131
144
        return ['-compose', ','.join(options_list)]
132
145
 
133
146
 
134
 
class XDGEmail(Evolution):
 
147
class XDGEmail(ExternalMailClient):
135
148
    """xdg-email attempts to invoke the user's preferred mail client"""
136
149
 
137
150
    _client_commands = ['xdg-email']
145
158
        return commandline
146
159
 
147
160
 
 
161
class MAPIClient(ExternalMailClient):
 
162
    """Default Windows mail client launched using MAPI."""
 
163
 
 
164
    def _compose(self, prompt, to, subject, attach_path, mime_subtype,
 
165
                 extension):
 
166
        from bzrlib.util import simplemapi
 
167
        try:
 
168
            simplemapi.SendMail(to or '', subject or '', '', attach_path)
 
169
        except simplemapi.MAPIError, e:
 
170
            if e.code != simplemapi.MAPI_USER_ABORT:
 
171
                raise errors.MailClientNotFound(['MAPI supported mail client'
 
172
                                                 ' (error %d)' % (e.code,)])
 
173
 
 
174
 
148
175
class DefaultMail(MailClient):
149
 
    """Default mail handling.  Tries XDGEmail, falls back to Editor"""
 
176
    """Default mail handling.  Tries XDGEmail (or MAPIClient on Windows),
 
177
    falls back to Editor"""
 
178
 
 
179
    def _mail_client(self):
 
180
        if osutils.supports_mapi():
 
181
            return MAPIClient(self.config)
 
182
        else:
 
183
            return XDGEmail(self.config)
150
184
 
151
185
    def compose(self, prompt, to, subject, attachment, mime_subtype,
152
186
                extension):
153
187
        try:
154
 
            return XDGEmail(self.config).compose(prompt, to, subject,
155
 
                            attachment, mimie_subtype, extension)
 
188
            return self._mail_client().compose(prompt, to, subject,
 
189
                                               attachment, mimie_subtype,
 
190
                                               extension)
156
191
        except errors.MailClientNotFound:
157
192
            return Editor(self.config).compose(prompt, to, subject,
158
193
                          attachment, mimie_subtype, extension)
159
194
 
160
195
    def compose_merge_request(self, to, subject, directive):
161
196
        try:
162
 
            return XDGEmail(self.config).compose_merge_request(to, subject,
163
 
                            directive)
 
197
            return self._mail_client().compose_merge_request(to, subject,
 
198
                                                             directive)
164
199
        except errors.MailClientNotFound:
165
200
            return Editor(self.config).compose_merge_request(to, subject,
166
201
                          directive)