1
# Copyright (C) 2007 Canonical Ltd
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.
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.
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
29
from bzrlib.lazy_import import lazy_import
30
lazy_import(globals(), """
35
class MailClient(object):
36
"""A mail client that can send messages with attachements."""
38
def __init__(self, config):
41
def compose(self, prompt, to, subject, attachment, mime_subtype,
43
raise NotImplementedError
45
def compose_merge_request(self, to, subject, directive):
46
prompt = self._get_merge_prompt("Please describe these changes:", to,
48
self.compose(prompt, to, subject, directive,
51
def _get_merge_prompt(self, prompt, to, subject, attachment):
55
class Editor(MailClient):
56
"""DIY mail client that uses commit message editor"""
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'))
62
def compose(self, prompt, to, subject, attachment, mime_subtype,
64
body = msgeditor.edit_commit_message(prompt)
66
raise errors.NoMessageSupplied()
67
email_message.EmailMessage.send(self.config,
68
self.config.username(),
73
attachment_mime_subtype=mime_subtype)
76
class Evolution(MailClient):
77
"""Evolution mail client."""
79
_client_commands = ['evolution']
81
def _get_client_commands(self):
82
if sys.platform == 'win32':
83
return [win32utils.get_app_path(i) for i in self._client_commands]
85
return self._client_commands
87
def compose(self, prompt, to, subject, attachment, mime_subtype,
89
fd, pathname = tempfile.mkstemp(extension, 'bzr-mail-')
91
os.write(fd, attachment)
94
for name in self._get_client_commands():
96
cmdline.extend(self._get_compose_commandline(to, subject,
99
subprocess.call(cmdline)
101
if e.errno != errno.ENOENT:
106
raise errors.MailClientNotFound(self._client_commands)
108
def _get_compose_commandline(self, to, subject, attach_path):
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))]
119
class Thunderbird(Evolution):
120
"""Mozilla Thunderbird (or Icedove)
122
Note that Thunderbird 1.5 is buggy and does not support setting
123
"to" simultaneously with including a attachment.
125
There is a workaround if no attachment is present, but we always need to
129
_client_commands = ['thunderbird', 'mozilla-thunderbird', 'icedove']
131
def _get_compose_commandline(self, to, subject, attach_path):
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(
140
options_list = ["%s='%s'" % (k, v) for k, v in
141
sorted(message_options.iteritems())]
142
return ['-compose', ','.join(options_list)]