Search code examples
bashemail-attachments

Email Bash script not attaching all the files to the email


I am trying to create a bash script that sends email with all the .xlsx (MS Excel) files in a directory as attachment.

The problem here is that the code is not sending all the files. For exampole, i have five xlsx files but the following code is only attaching three on them.

for attachment in "$attachment_dir"/*.xlsx; do
    if [ -f "$attachment" ]; then
        filename=$(basename "$attachment")
        attachment_data=$(base64 -w 0 "$attachment")

        email+=$(cat <<EOF

--boundary_1234
Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet; name="$filename"
Content-Disposition: attachment; filename="$filename"
Content-Transfer-Encoding: base64

$attachment_data
EOF
)
    fi
done

Please help with what is wrong here.

I have tried following code also but it is also only sending one excel file as attachment.

#!/bin/bash

# Directory containing the .xlsx files
attachment_dir="."

# HTML file for the email body
html_file="abc.html"

# Email details
recipient="abc@abc.com"
subject="Email Subject"
sender="abc@abc.com"
body=$(cat "$html_file")

# Create a temporary directory for storing the attachments
temp_dir=$(mktemp -d)

# Copy all .xlsx files to the temporary directory
find "$attachment_dir" -name "*.xlsx" -type f -exec cp {} "$temp_dir" \;

# Create the email
email=$(cat <<EOF
To: $recipient
From: $sender
Subject: $subject
Content-Type: multipart/mixed; boundary=boundary_1234

--boundary_1234
Content-Type: text/html

$body
EOF
)

# Add attachments to the email
for attachment in "$temp_dir"/*.xlsx; do
    if [ -f "$attachment" ]; then
        filename=$(basename "$attachment")
        attachment_data=$(base64 -w 0 "$attachment")

        email+=$(cat <<EOF

--boundary_1234
Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet; name="$filename"
Content-Disposition: attachment; filename="$filename"
Content-Transfer-Encoding: base64

$attachment_data
EOF
)
    fi
done

# Add closing boundary to the email
email+="\n--boundary_1234--"

# Send the email using sendmail
echo -e "$email" | sendmail -t

# Clean up the temporary directory
rm -rf "$temp_dir"

Solution

  • This is not an answer, merely a formatted comment.

    I don't really know why you code is failing to send the attachments. It can be somewhat streamlined though. I have a similar script that looks like this in part

        boundary="_====-boundary-${$}-$(date +%Y%m%d%H%M%S)-====_"
    
        {
            echo "From: $from"
            echo "To: $to"
            echo "Cc: $cc"
            echo "Subject: $subject"
            echo "Content-Type: multipart/mixed; boundary=\"$boundary\""
            echo "Mime-Version: 1.0"
            echo
            echo "This is a multi-part message in MIME format."
            echo
            printf -- "--%s\n" "$boundary"
            echo "Content-Type: text/plain; charset=ISO-8859-1"
            echo
            echo "$body"
            echo
            for filename in "${attachments[@]}"; do
                # attach it if it's readable and non-zero size
                if [[ -r "$filename" ]] && [[ -s "$filename" ]]; then
                    printf -- "--%s\n" "$boundary"
                    echo "Content-Transfer-Encoding: base64"
                    echo "Content-Type: application/octet-stream; name=$(basename "$filename")"
                    echo "Content-Disposition: attachment; filename=$(basename "$filename")"
                    echo
                    base64 "$filename"
                    echo
                fi
            done
            printf -- "--%s--\n" "$boundary"
        } | /usr/lib/sendmail -oi -t
    

    There's not a big difference with yours, but I wonder if the devil is in the details.