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
30
class MailClient(object):
31
"""A mail client that can send messages with attachements."""
33
def __init__(self, config):
36
def compose(self, prompt, to, subject, attachment, mime_subtype,
38
raise NotImplementedError
40
def compose_merge_request(self, to, subject, directive):
41
prompt = self._get_merge_prompt("Please describe these changes:", to,
43
self.compose(prompt, to, subject, directive,
46
def _get_merge_prompt(self, prompt, to, subject, attachment):
50
class Editor(MailClient):
51
"""DIY mail client that uses commit message editor"""
53
def _get_merge_prompt(self, prompt, to, subject, attachment):
54
return "%s\n\nTo: %s\nSubject: %s\n\n%s" % (prompt, to, subject,
55
attachment.decode('utf-8', 'replace'))
57
def compose(self, prompt, to, subject, attachment, mime_subtype,
59
body = msgeditor.edit_commit_message(prompt)
61
raise errors.NoMessageSupplied()
62
email_message.EmailMessage.send(self.config,
63
self.config.username(),
68
attachment_mime_subtype=mime_subtype)
71
class Evolution(MailClient):
72
"""Evolution mail client."""
74
_client_commands = ['evolution']
76
def compose(self, prompt, to, subject, attachment, mime_subtype,
78
fd, pathname = tempfile.mkstemp(extension, 'bzr-mail-')
80
os.write(fd, attachment)
83
for name in self._client_commands:
85
cmdline.extend(self._get_compose_commandline(to, subject,
88
subprocess.call(cmdline)
90
if e.errno != errno.ENOENT:
95
raise errors.MailClientNotFound(self._client_commands)
97
def _get_compose_commandline(self, to, subject, attach_path):
99
if subject is not None:
100
message_options['subject'] = subject
101
if attach_path is not None:
102
message_options['attach'] = attach_path
103
options_list = ['%s=%s' % (k, urlutils.escape(v)) for (k, v) in
104
message_options.iteritems()]
105
return ['mailto:%s?%s' % (to or '', '&'.join(options_list))]
108
class Thunderbird(Evolution):
109
"""Mozilla Thunderbird (or Icedove)
111
Note that Thunderbird 1.5 is buggy and does not support setting
112
"to" simultaneously with including a attachment.
114
There is a workaround if no attachment is present, but we always need to
118
_client_commands = ['thunderbird', 'mozilla-thunderbird', 'icedove']
120
def _get_compose_commandline(self, to, subject, attach_path):
123
message_options['to'] = to
124
if subject is not None:
125
message_options['subject'] = subject
126
if attach_path is not None:
127
message_options['attachment'] = urlutils.local_path_to_url(
129
options_list = ["%s='%s'" % (k, v) for k, v in
130
sorted(message_options.iteritems())]
131
return ['-compose', ','.join(options_list)]
134
class XDGEmail(Evolution):
135
"""xdg-email attempts to invoke the user's preferred mail client"""
137
_client_commands = ['xdg-email']
139
def _get_compose_commandline(self, to, subject, attach_path):
141
if subject is not None:
142
commandline.extend(['--subject', subject])
143
if attach_path is not None:
144
commandline.extend(['--attach', attach_path])