Mime attachment with mailx/sendmail in FreeBSD (FreeNAS)

I want to attach a log file to an notification email in FreeNAS. As I understand it, I need to manually MIME encode the log file and append it to the body of the email. Has anyone ever done this? I tried putting the log into the body of the email but it is too long.

mutt is unfortunately not included in FreeNAS.

This might be the answer:

https://backreference.org/2013/05/22/send-email-with-attachments-from-script-or-command-line/


Not sure why this isn’t working…

(   echo "Subject: Log Test ${RANDOM}"
    echo "Mime-Version: 1.0"
    echo "Content-Type: multipart/mixed; boundary=\"d29a0c638b540b23e9a29a3a9aebc900aeeb6a82\""
    echo "Content-Transfer-Encoding: 7bit"
    echo ""
    echo "--d29a0c638b540b23e9a29a3a9aebc900aeeb6a82"
    echo ""
    echo "Content-Type: text/html; charset=\"UTF-8\""
    echo "Content-Transfer-Encoding: 7bit"
    echo "Content-Disposition: inline"
    echo ""
    echo "HELLO"
    echo ""
    echo "--d29a0c638b540b23e9a29a3a9aebc900aeeb6a82"
    echo ""
    echo "Content-Type: text/plain"
    echo "Content-Transfer-Encoding: base64"
    echo "Content-Disposition: attachment; filename=\"log.txt\""
    echo ""
    base64 "${__LOG}"
    echo "--d29a0c638b540b23e9a29a3a9aebc900aeeb6a82--"

  ) | sendmail root

00


Solution

I got it. No empty space allowed after the boundary.

(   echo "Subject: Log Test ${RANDOM}"
    echo "Mime-Version: 1.0"
    echo "Content-Type: multipart/mixed; boundary=\"d29a0c638b540b23e9a29a3a9aebc900aeeb6a82\""
    echo "Content-Transfer-Encoding: 7bit"
    echo ""
    echo "--d29a0c638b540b23e9a29a3a9aebc900aeeb6a82"
    echo "Content-Type: text/html; charset=\"UTF-8\""
    echo "Content-Transfer-Encoding: 7bit"
    echo "Content-Disposition: inline"
    echo ""
    echo "HELLO"
    echo ""
    echo "--d29a0c638b540b23e9a29a3a9aebc900aeeb6a82"
    echo "Content-Type: text/plain"
    echo "Content-Transfer-Encoding: base64"
    echo "Content-Disposition: attachment; filename=\"log.txt\""
    echo ""
    base64 "${__LOG}"
    echo "--d29a0c638b540b23e9a29a3a9aebc900aeeb6a82--"

  ) | sendmail root

This will work on FreeNAS if you have email notifications setup and root is your notification user (which is default I believe).

2 Likes

Have you tried uuencode?

Nevermind

1 Like

I did and it did technically work (in gmail), but it’s largely dependent on the email client since it was originally intended for sending file contents as plaintext in the body of an email.

Also, gmail attaches it both unencoded and encoded as a file called noname which I wasn’t a fan of.

I mostly had luck with it sending images. They embedded much better than without.

1 Like

Interesting. I’ll keep that in mind. I’ve remote-hosted inline images and brought them in with html, but if uuencode is simpler, I’d be happy to do that instead.

Was your use case an image in a signature? That’s where I’ve had to manually embed images in the past.

Why not install mutt in a jail? I guess for a one-off email that’s a bit obnoxious.

1 Like

Yeah, that was my thought. Imo, the solution is less intricate than configuring a jail.

That said, it would be really really nice if the FreeBSD version of mailx had the -a option…

You could always make a feature request :smiley:

2 Likes

That’s a great idea.

I have not dealt directly with the FreeBSD people before. Is that something I should take to them or do I need to figure out who’s specifically maintaining FreeBSD’s mailx package?

Maybe I should just ask FreeNAS to add mutt? I already have an active redmine account with them.

For FreeBSD you’d probably have to propose an actual patch, though you could reach out to the maintainer and try asking nicely. For FreeNAS you could propose the -a feature and make a really good business case and hope whoever makes decisions about feature requests sees as it worth the developer $/time.

If you really want mutt, just install it in a jail. Configuring a jail isn’t inherently intricate, so unless you’re doing something out of the ordinary (maybe like trying to give the jail access to all the log files of the host) it would just be a matter of clicking through the wizard. Having one general purpose jail for random shenanigans so you can install packages at will, access files, snapshot rollback etc is probably not a terrible idea. The jail gives you a safety net to make sure FreeNAS keeps working in spite of you.

I have almost no idea what it would take to support attachments in mailx. Maybe some mimetypes. Maybe all you want is plain text and it’s easy enough. I do have some experience with email attachments (on the receiving end, and in Haskell, so…) so I’d happily help with guidance, code review, and advocating in FreeBSD. The fact that it doesn’t already exist though makes me suspect there are reasonable alternative ways about this, so I wonder how much effort it really is worth.

Oh wait you already got it figured out? Derp. I must have skimmed past the last part of the original post.

1 Like

Yeah the empty space would to it, I remember that much :smiley:

1 Like

The Linux versions of mailx seem to all have an -a option where you just attach a file and that’s it. It makes sense. It’s not like mime is complicated, it’s just long-winded. Unfortunately, FreeBSD’s mailx doesn’t have it.

So the log file was quickly becoming too large so I needed to implement some compression. If the attachment is too large, the message is not received at all.

I’m not sure how best to deal with this since you can’t know the compressed file size before compressing it, and it’s not like you can just head or tail the compressed file to get a portion of it.

What I might do is compress the file, measure the size and then if it needs to be concatenated, cut down the original by percentage (+ some headroom) and then recompress and retest on a loop until it is small enough to email (ideally only taking one iteration). First though, I have to figure out what the actual size limit is and where it’s being limited (sendmail on the box, gmail smtp or on the receiving end).

Here is my current solution which is to just compress the log file. No guarantee that will be enough to get it through though…

echo "--${mime_boundary}" &&
echo "Content-Type: application/x-gzip" &&
echo "Content-Transfer-Encoding: base64" &&
echo "Content-Disposition: attachment; filename=\"log.txt.gz\"" &&
echo "" &&
echo "$( gzip -9c "${__LOG}" | base64 )" &&
echo "--${mime_boundary}--"

Have you heard of the split command?

1 Like

And send it in multiple emails? I’m pretty sure it’s hitting max total attachment size, although I could be wrong.

I think knocking the log level down to info might be the best option. I like the idea of having the debug so you get really good forensic detail on the backup, but a 5MB log file for every backup is pretty far into overkill territory.

You can pipe it through pandoc with the -t html option? Then you can even format it with markdown and the -f markdown option to make it pretty

That looks like a nice tool. Don’t think it’s something FreeNAS will ever implement though.

I mean you can mount / as rw, install it from FreeBSD ports, then remount / as ro. Nobody will ever know

1 Like

Yeah I know it’s possible, but I don’t want to introduce any additional dependencies. It’s important that I be able to copy this script onto any system and run it with minimal complications.

Currently the script only requires rclone to be installed/configured, and sendmail to have a functional smtp configuration (and bash to be upgraded in macos).

1 Like

/ is rw now, but it’s better to just make a jail if you want to install random additional software.

2 Likes