長いhtml文字列をbashスクリプトに引数として渡します(ファイル名が長すぎます)。

長いhtml文字列をbashスクリプトに引数として渡します(ファイル名が長すぎます)。

bashスクリプトへの入力としてhtml文字列を渡します。

script.py


def bash(commandStr):
    subprocess.Popen(commandStr, shell=True, executable="/bin/bash")
  
def sendmail(subject, to, body):
    bash(f"./email.sh '{to}' '{subject}' '{body}'")

email.sh

#!/bin/bash

# args: 1 - TO address
#       2 - subject
#       3 - body

(
echo "To: $1";
echo "Subject: $2";
echo "Content-Type: text/html";
echo "MIME-Version: 1.0";
echo "";
echo "$3";
) | sendmail -t

これはhtmlのサブセットのみが正常に送信され、エラーが発生しますFile name too long

私のbashスクリプトにパラメータとして完全なHTML文字列を提供したいと思います。私はbashスクリプトを初めて使用するので、この問題を解決するより良い方法があるかもしれませんが、私はよくわかりません。私の1つの制限は、実際にPythonでbashスクリプトを呼び出す必要があることです。 bashスクリプトに長いHTML文字列をパラメータとして渡す方法は?

ベストアンサー1

TL、DR:bashを使用しないでください。必要ありません。

2つの質問があります。最大のものは議論への言及です。もう1つの可能性はコマンドラインの長さ制限です。

主な問題

TL、博士:

  1. 必要でない場合は、シェルを呼び出さないでください。
  2. より一般的には、何かを何度も解析する必要がある状況に陥らないようにしてください。きちんとするのが難しい場合が多いです。

次のようなbashコマンドを実行しています。

./email.sh '[email protected]' 'Something happened' '<html>
<body>
You are heading for trouble.
</body>
</html>'

Bashはコマンドを解析し、./email.sh3つの引数を使ってプログラムを実行します。プログラムは./email.sh偶然別のbashインスタンスを実行していますが、これは偶然の一致です。両方の目的で同じシェルを使用する必要はありません。

しかし、単一引用符を含むようにHTMLのテキストを変更するとどうなりますか?

./email.sh '[email protected]' 'Something happened' '<html>
<body>
You're heading for trouble.
</body>
</html>'

に渡された3番目のパラメータはで./email.sh終わりますYoure。 4番目の引数heading、5番目の引数for、6番目の引数があり、一度trouble.返さ./email.shれると、bashはコマンドを解析して実行しようとすると</body>エラーが発生します。

bash: -c: line 4: syntax error near unexpected token `newline'
bash: -c: line 4: `</body>'

わずかに異なるHTMLを使用すると、さまざまなエラーが発生する可能性があります。コンピュータ上で任意のコマンドを実行することができ、電子メールに何かを注入する可能性のある悪意のある行為者によって指定されたコマンドです。あなたのコードは巨大なセキュリティホールです!

xkcd327

短い解決策

途中で大きな打撃を加えても無駄です。それはまったく役に立たず、大きなエラーを追加します。

def sendmail(subject, to, body):
    subprocess.Popen(["./email.sh", to, subject, body])

よりシンプルで実際に動作します。

より強力なソリューション

電子メール本文が長すぎると、コマンドラインの長さ(コマンド名、パラメータ、環境変数)に制限がある可能性があります。制限は表示されるバイト数ですgetconf ARG_MAX

これを防ぐには、電子メール本文をコマンドライン引数ではなく入力に渡すことができます。

def sendmail(subject, to, body):
    subprocess.Popen(["./email.sh", to, subject], input=body.encode('utf-8'))

utf-8必要に応じて正しい文字セットに置き換えてください。)

#!/bin/bash

# args: 1 - TO address
#       2 - subject
# stdin: body

(
echo "To: $1";
echo "Subject: $2";
echo "Content-Type: text/html";
echo "MIME-Version: 1.0";
echo "";
cat
) | sendmail -t

バッシュを使うのはなぜですか?

このメール転送スクリプトが表示される場合は、bashを使用する必要はありません。 Pythonではこれをすべて行うことができます。

def sendmail(subject, to, body):
    mail = f"""\
To: f{to}
Subject: f{subject}
Content-Type: text/html
MIME-Version: 1.0

f{body}"""
    subprocess.Popen(["sendmail", "-t"], input=mail.encode('utf-8'))

おすすめ記事