~bzr-pqm/bzr/bzr.dev

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
17
import os
18
import subprocess
19
import tempfile
20
2681.1.9 by Aaron Bentley
Add support for mail-from-editor
21
from bzrlib import (
22
    email_message,
23
    errors,
24
    msgeditor,
25
    urlutils,
26
    )
2681.1.8 by Aaron Bentley
Add Thunderbird support to bzr send
27
28
29
class MailClient(object):
2681.1.11 by Aaron Bentley
Add docstrings, add compose_merge_request
30
    """A mail client that can send messages with attachements."""
2681.1.8 by Aaron Bentley
Add Thunderbird support to bzr send
31
2681.1.9 by Aaron Bentley
Add support for mail-from-editor
32
    def __init__(self, config):
33
        self.config = config
34
2681.1.11 by Aaron Bentley
Add docstrings, add compose_merge_request
35
    def compose(self, prompt, to, subject, attachment, mime_subtype,
36
                extension):
2681.1.8 by Aaron Bentley
Add Thunderbird support to bzr send
37
        raise NotImplementedError
38
2681.1.11 by Aaron Bentley
Add docstrings, add compose_merge_request
39
    def compose_merge_request(self, to, subject, directive):
40
        self.compose("Please describe these changes:", to, subject, directive,
41
            'x-patch', '.patch')
42
2681.1.8 by Aaron Bentley
Add Thunderbird support to bzr send
43
44
class Editor(MailClient):
2681.1.11 by Aaron Bentley
Add docstrings, add compose_merge_request
45
    """DIY mail client that uses commit message editor"""
2681.1.8 by Aaron Bentley
Add Thunderbird support to bzr send
46
2681.1.11 by Aaron Bentley
Add docstrings, add compose_merge_request
47
    def compose(self, prompt, to, subject, attachment, mime_subtype,
48
                extension):
49
        info = ("%s\n\nTo: %s\nSubject: %s\n\n%s" % (prompt, to, subject,
50
                attachment))
2681.1.9 by Aaron Bentley
Add support for mail-from-editor
51
        body = msgeditor.edit_commit_message(info)
52
        if body == '':
53
            raise errors.NoMessageSupplied()
54
        email_message.EmailMessage.send(self.config,
55
                                        self.config.username(),
56
                                        to,
57
                                        subject,
58
                                        body,
59
                                        attachment,
2681.1.11 by Aaron Bentley
Add docstrings, add compose_merge_request
60
                                        attachment_mime_subtype=mime_subtype)
2681.1.8 by Aaron Bentley
Add Thunderbird support to bzr send
61
62
63
class Thunderbird(MailClient):
2681.1.11 by Aaron Bentley
Add docstrings, add compose_merge_request
64
    """Mozilla Thunderbird (or Icedove)
65
66
    Note that Thunderbird 1.5 is buggy and does not support setting
67
    "to" simultaneously with including a attachment.
68
69
    There is a workaround if no attachment is present, but we always need to
70
    send attachments.
71
    """
72
73
    def compose(self, prompt, to, subject, attachment, mime_subtype,
74
                extension):
75
        fd, pathname = tempfile.mkstemp(extension, 'bzr-mail-')
2681.1.8 by Aaron Bentley
Add Thunderbird support to bzr send
76
        try:
77
            os.write(fd, attachment)
78
        finally:
79
            os.close(fd)
80
        cmdline = ['thunderbird']
81
        cmdline.extend(self._get_compose_commandline(to, subject, pathname))
82
        subprocess.call(cmdline)
83
84
    def _get_compose_commandline(self, to, subject, attach_path):
85
        message_options = {}
86
        if to is not None:
87
            message_options['to'] = to
88
        if subject is not None:
89
            message_options['subject'] = subject
90
        if attach_path is not None:
91
            message_options['attachment'] = urlutils.local_path_to_url(
92
                attach_path)
93
        options_list = ["%s='%s'" % (k, v) for k, v in
94
                        sorted(message_options.iteritems())]
95
        return ['-compose', ','.join(options_list)]