~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/mail_client.py

  • Committer: Xavier Maillard
  • Date: 2008-04-13 11:48:00 UTC
  • mto: (3364.1.1 bzr.ab.integration)
  • mto: This revision was merged to the branch mainline in revision 3365.
  • Revision ID: xma@gnu.org-20080413114800-b3tp394elic1793b
Replace mail-mode call with compose-mail from GNU Emacs.

This patch is a modified version of the current revno 3323.

It overloads it by:

1. defining a different python class EmacsMail "MUA agnostic".

   To use this option, just put these lines into ~/.bazaar/bazaar.conf
    
[DEFAULT]
mail_client = emacsclient

2. supporting any mail client of GNU Emacs family (mail-mode,
   message-mode, ...) The right tool will be called according to the
   value of the variable ``mail-user-agent``. So Virtually any Emacs
   mail client will work transparently if registered against
   ``mail-user-agent``.

3. adding a wrapper function around MIME attachment. This allow us not
   to have many different functions/classes to attach a file but one.

4. tests have been updated to follow the changes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
306
306
        return commandline
307
307
 
308
308
 
309
 
class EmacsMailMode(ExternalMailClient):
310
 
    """Call emacsclient in mail-mode.
311
 
    
312
 
    This only work for emacs >= 22.1.
 
309
class EmacsMail(ExternalMailClient):
 
310
    """Call emacsclient to have a mail buffer.
 
311
 
 
312
    This only work for emacs >= 22.1 due to recent -e/--eval support.
 
313
 
 
314
    The good news is that this implementation will work with all mail
 
315
    agents registered against ``mail-user-agent``. So there is no need
 
316
    to instantiate ExternalMailClient for each and every GNU Emacs
 
317
    MUA.
 
318
 
 
319
    Users just have to ensure that ``mail-user-agent`` is set according
 
320
    to their tastes.
313
321
    """
 
322
 
314
323
    _client_commands = ['emacsclient']
315
324
 
 
325
    def _prepare_send_function(self):
 
326
        """Write our wrapper function into a temporary file.
 
327
 
 
328
        This temporary file will be loaded at runtime in
 
329
        _get_compose_commandline function.
 
330
 
 
331
        FIXME: this function does not remove the file. That's a wanted
 
332
        behaviour since _get_compose_commandline won't run the send
 
333
        mail function directly but return the eligible command line.
 
334
        Removing our temporary file here would prevent our sendmail
 
335
        function to work.
 
336
 
 
337
        A possible workaround could be to load the function here with
 
338
        emacsclient --eval '(load temp)' but this is not robust since
 
339
        emacs could have been stopped between here and the call to
 
340
        mail client.
 
341
        """
 
342
 
 
343
        _defun = r"""(defun bzr-add-mime-att (file)
 
344
  "Attach FILe to a mail buffer as a MIME attachment."
 
345
  (let ((agent mail-user-agent))
 
346
    (mail-text)
 
347
    (newline)
 
348
    (if (and file (file-exists-p file))
 
349
        (cond
 
350
         ((eq agent 'sendmail-user-agent)
 
351
          (etach-attach file))
 
352
         ((or (eq agent 'message-user-agent)(eq agent 'gnus-user-agent))
 
353
          (mml-attach-file file "text/x-patch" "BZR merge" "attachment"))
 
354
         (t
 
355
          (message "Unhandled MUA")))
 
356
      (error "File %s does not exist." file))))
 
357
"""
 
358
 
 
359
        fd, temp_file = tempfile.mkstemp(prefix="emacs-bzr-send-",
 
360
                                         suffix=".el")
 
361
        try:
 
362
            os.write(fd, _defun)
 
363
        finally:
 
364
            os.close(fd) # Just close the handle but do not remove the file.
 
365
        return temp_file
 
366
 
316
367
    def _get_compose_commandline(self, to, subject, attach_path):
317
368
        commandline = ["--eval"]
318
 
        # Ensure we can at least have an empty mail-mode buffer
 
369
 
319
370
        _to = "nil"
320
371
        _subject = "nil"
321
372
 
323
374
            _to = ("\"%s\"" % self._encode_safe(to))
324
375
        if subject is not None:
325
376
            _subject = ("\"%s\"" % self._encode_safe(subject))
326
 
        mmform = "(mail nil %s %s)" % (_to ,_subject)
327
 
 
328
 
        # call mail-mode, move the point to body and insert a new blank line
329
 
        # we *must* force this point movement for the case when To is not passed
330
 
        # with --mail-to. Without this, the patch could be inserted at the wrong place
331
 
        commandline.append(mmform)
332
 
        commandline.append("(mail-text)")
333
 
        commandline.append("(newline)")
334
 
 
335
 
        # ... and put a MIME attachment (if any)
 
377
 
 
378
        # Funcall the default mail composition function
 
379
        # This will work with any mail mode including default mail-mode
 
380
        # User must tweak mail-user-agent variable to tell what function
 
381
        # will be called inside compose-mail.
 
382
        mail_cmd = "(compose-mail %s %s)" % (_to, _subject)
 
383
        commandline.append(mail_cmd)
 
384
 
 
385
        # Try to attach a MIME attachment using our wrapper function
336
386
        if attach_path is not None:
337
 
            ifform = "(attach \"%s\")" % self._encode_path(attach_path,'attachment')
338
 
            commandline.append(ifform)
 
387
            # Do not create a file if there is no attachment
 
388
            lmmform = '(load "%s")' % self._prepare_send_function()
 
389
            mmform  = '(bzr-add-mime-att "%s")' % \
 
390
                self._encode_path(attach_path, 'attachment')
 
391
            commandline.append(lmmform)
 
392
            commandline.append(mmform)
 
393
 
339
394
        return commandline
340
395
 
341
396