Allow packing multipart MIME

This commit is contained in:
Konstantin Nazarov 2021-05-28 23:10:16 +00:00
parent c2e7aaa478
commit 574cc1acca
Signed by: knazarov
GPG key ID: 4CFE0A42FA409C22
2 changed files with 104 additions and 5 deletions

View file

@ -80,6 +80,16 @@ uuid()
echo echo
} }
gen_boundary()
{
for (( N=0; N < 32; ++N ))
do
B=$(( RANDOM%255 ))
printf '%02x' $B
done
echo
}
yesno() { yesno() {
PROMPT="$1" PROMPT="$1"
DEFAULT="$2" DEFAULT="$2"
@ -102,7 +112,7 @@ yesno() {
} }
get_headers() { get_headers() {
FILE="$1" HEADERS_FILE="$1"
FILTER="\ FILTER="\
{ \ { \
@ -110,11 +120,11 @@ get_headers() {
print \$0 \ print \$0 \
} \ } \
" "
awk "$FILTER" "$FILE" awk "$FILTER" "$HEADERS_FILE"
} }
get_body() { get_body() {
FILE="$1" BODY_FILE="$1"
FILTER="\ FILTER="\
{ \ { \
@ -122,7 +132,7 @@ get_body() {
if (\$0~/^$/) {body=1} \ if (\$0~/^$/) {body=1} \
} \ } \
" "
awk "$FILTER" "$FILE" awk "$FILTER" "$BODY_FILE"
} }
get_header() { get_header() {
FILE="$1" FILE="$1"
@ -230,16 +240,60 @@ unpack_mime() {
rm "$TMP" rm "$TMP"
} }
pack_part() {
PART_FILE="$1"
CONTENT_TYPE="$(file -b --mime-type "$PART_FILE")"
echo "Content-Disposition: attachment; filename=\"$(basename "$PART_FILE")\""
if [[ "$CONTENT_TYPE" =~ "text/" ]]; then
echo "Content-Type: text/plain"
echo
cat "$PART_FILE"
else
echo "Content-Type: $CONTENT_TYPE"
echo "Content-Transfer-Encoding: base64"
echo
cat "$PART_FILE" | base64
fi
}
pack_mime() { pack_mime() {
DIR="$1" DIR="$1"
FILE="$2" FILE="$2"
FILE_COUNT="$(ls "$DIR" | wc -l)"
if [[ "$FILE_COUNT" == "1" ]]; then
{
echo "MIME-Version: 1.0"
echo "Content-Type: text/plain; charset=utf-8"
echo "Content-Disposition: inline"
cat "$DIR/note.md"
} >> "$FILE"
return
fi
BOUNDARY="$(gen_boundary)"
{ {
echo "MIME-Version: 1.0" echo "MIME-Version: 1.0"
echo "Content-Type: multipart/mixed; boundary=$BOUNDARY"
get_headers "$DIR/note.md"
echo
echo "--$BOUNDARY"
echo "Content-Type: text/plain; charset=utf-8" echo "Content-Type: text/plain; charset=utf-8"
echo "Content-Disposition: inline" echo "Content-Disposition: inline"
cat "$DIR/note.md" echo
get_body "$DIR/note.md"
} >> "$FILE" } >> "$FILE"
find "$DIR/" -type f ! -name 'note.md' | while read FN
do
{
echo "--$BOUNDARY"
pack_part "$FN"
} >> "$FILE"
done
echo "--$BOUNDARY--" >> "$FILE"
} }
new_entry() { new_entry() {

45
test.sh
View file

@ -205,6 +205,50 @@ resume_editing() {
assert 'echo "$OUTPUT" | grep -o myline3' "myline3" assert 'echo "$OUTPUT" | grep -o myline3' "myline3"
} }
pack_multipart() {
mkdir "$TMP/inpdir"
cat > "$TMP/inpdir/note.md" <<- EOF
Subject: This is a header
This is a body
EOF
cat > "$TMP/inpdir/file.txt" <<- EOF
This is a text attachment
EOF
"$BASE_DIR/notes.sh" -n "$TMP/inpdir"
OUTPUT="$(cat "$(pwd)/notes/cur"/*)"
assert 'echo "$OUTPUT" | grep Subject' "Subject: This is a header"
assert 'echo "$OUTPUT" | grep -o "text attachment"' "text attachment"
BOUNDARY="$(cat "$(pwd)/notes/cur"/* | grep boundary= | cut -d '=' -f 2)"
#echo "boundary: $BOUNDARY"
OUTPUT="$(echo "$OUTPUT" | sed "s/$BOUNDARY/boundary/g")"
OUTPUT="$(echo "$OUTPUT" | grep -v "Date" | grep -v "X-Note-Id")"
read -d '' -r EXPECTED <<- EOF || true
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary=boundary
Subject: This is a header
--boundary
Content-Type: text/plain; charset=utf-8
Content-Disposition: inline
This is a body
--boundary
Content-Disposition: attachment; filename="file.txt"
Content-Type: text/plain
This is a text attachment
--boundary--
EOF
assert 'echo "$OUTPUT"' "$EXPECTED"
}
testcase new_note_from_stdin testcase new_note_from_stdin
testcase new_note_from_file testcase new_note_from_file
testcase new_note_from_dir testcase new_note_from_dir
@ -212,6 +256,7 @@ testcase list_notes
testcase export_note testcase export_note
testcase edit_note testcase edit_note
testcase resume_editing testcase resume_editing
testcase pack_multipart
if [[ "$RESULT" == "0" ]]; then if [[ "$RESULT" == "0" ]]; then
echo "All tests passed." echo "All tests passed."