summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Khirnov <anton@khirnov.net>2021-01-26 11:38:03 +0100
committerAnton Khirnov <anton@khirnov.net>2021-01-26 11:38:03 +0100
commitdae098901104de7027c48dae2b9da08be2a17fac (patch)
treed432fc4ce4fdd2cbed835175f89b0fe48364319d
parent5cb88d559ae462dad80d346d44f12dcc9eb3ec10 (diff)
account: stop using call_cmd_async() to run sendmail
It does not actually save any code. The new code also uses a shell as is documented. Remove call_cmd_async(), as it no longer has any callers.
-rw-r--r--alot/account.py37
-rw-r--r--alot/commands/envelope.py10
-rw-r--r--alot/commands/globals.py1
-rw-r--r--alot/helper.py38
4 files changed, 28 insertions, 58 deletions
diff --git a/alot/account.py b/alot/account.py
index 4112ce53..1db65a5f 100644
--- a/alot/account.py
+++ b/alot/account.py
@@ -4,6 +4,7 @@
# This file is released under the GNU GPL, version 3 or a later revision.
# For further details see the COPYING file
import abc
+import asyncio
import glob
import logging
import mailbox
@@ -11,9 +12,7 @@ import operator
import os
import re
-from .helper import call_cmd_async
-from .helper import split_commandstring
-
+from urwid.util import detected_encoding
class Address:
@@ -348,20 +347,22 @@ class SendmailAccount(Account):
"""Pipe the given mail to the configured sendmail command. Display a
short message on success or a notification on error.
:param mail: the mail to send out
- :type mail: :class:`email.message.Message` or string
+ :type mail: bytes
:raises: class:`SendingMailFailed` if sending failes
"""
- cmdlist = split_commandstring(self.cmd)
-
- try:
- # make sure self.mail is a string
- out, err, code = await call_cmd_async(cmdlist, stdin=str(mail))
- if code != 0:
- msg = 'The sendmail command {} returned with code {}{}'.format(
- self.cmd, code, ':\n' + err.strip() if err else '.')
- raise Exception(msg)
- except Exception as e:
- logging.error(str(e))
- raise SendingMailFailed(str(e))
- logging.info('sent mail successfully')
- logging.info(out)
+ P = asyncio.subprocess.PIPE
+
+ child = await asyncio.create_subprocess_shell(self.cmd, P, P, P)
+ out, err = await child.communicate(mail)
+
+ if child.returncode != 0:
+ msg = 'Calling sendmail command %s failed with code %s' % \
+ (self.cmd, child.returncode)
+ if err:
+ msg += '; stderr:\n %s' % \
+ err.decode(detected_encoding, errors = 'backslashreplace')
+ raise SendingMailFailed(msg)
+
+ if out:
+ logging.info('sendmail output:\n%s',
+ out.decode(detected_encoding, errors = 'backslashreplace'))
diff --git a/alot/commands/envelope.py b/alot/commands/envelope.py
index fa45f669..b138195d 100644
--- a/alot/commands/envelope.py
+++ b/alot/commands/envelope.py
@@ -265,8 +265,16 @@ class SendCommand(Command):
clearme = ui.notify('sending..', timeout=-1)
if self.envelope is not None:
self.envelope.sending = True
+
+ # FIXME XXX horrible hack, fix the type fuckery
+ to_send = self.mail
+ if isinstance(to_send, str):
+ to_send = to_send.encode('ascii')
+ else:
+ to_send = to_send.as_bytes()
+
try:
- await account.send_mail(self.mail)
+ await account.send_mail(to_send)
except SendingMailFailed as e:
if self.envelope is not None:
self.envelope.account = account
diff --git a/alot/commands/globals.py b/alot/commands/globals.py
index 3e53a450..e30192c6 100644
--- a/alot/commands/globals.py
+++ b/alot/commands/globals.py
@@ -251,7 +251,6 @@ class ExternalCommand(Command):
ret = ''
# TODO: these can probably be refactored in terms of helper.call_cmd
- # and helper.call_cmd_async
if self.in_thread:
try:
if self.shell:
diff --git a/alot/helper.py b/alot/helper.py
index 9ba3c411..4bdb9731 100644
--- a/alot/helper.py
+++ b/alot/helper.py
@@ -168,44 +168,6 @@ def call_cmd(cmdlist, stdin=None):
return out, err, ret
-async def call_cmd_async(cmdlist, stdin=None, env=None):
- """Given a command, call that command asynchronously and return the output.
-
- This function only handles `OSError` when creating the subprocess, any
- other exceptions raised either durring subprocess creation or while
- exchanging data with the subprocess are the caller's responsibility to
- handle.
-
- If such an `OSError` is caught, then returncode will be set to 1, and the
- error value will be set to the str() value of the exception.
-
- :type cmdlist: list of str
- :param stdin: string to pipe to the process
- :type stdin: str
- :return: Tuple of stdout, stderr, returncode
- :rtype: tuple[str, str, int]
- """
- termenc = urwid.util.detected_encoding
- cmdlist = [s.encode(termenc) for s in cmdlist]
-
- environment = os.environ.copy()
- if env is not None:
- environment.update(env)
- logging.debug('ENV = %s', environment)
- logging.debug('CMD = %s', cmdlist)
- try:
- proc = await asyncio.create_subprocess_exec(
- *cmdlist,
- env=environment,
- stdout=asyncio.subprocess.PIPE,
- stderr=asyncio.subprocess.PIPE,
- stdin=asyncio.subprocess.PIPE if stdin else None)
- except OSError as e:
- return ('', str(e), 1)
- out, err = await proc.communicate(stdin.encode(termenc) if stdin else None)
- return (out.decode(termenc), err.decode(termenc), proc.returncode)
-
-
def guess_mimetype(blob):
"""
uses file magic to determine the mime-type of the given data blob.