The officially official Devuan Forum!

You are not logged in.

#1 2018-02-19 15:50:42

GNUser
Member
Registered: 2017-03-16
Posts: 570  

simple way to send email from terminal or script

Devuan has inspired me to do all my computing as simply as possible. Here's a little script I wrote so that I can send email from a script or terminal with virtually zero overhead (specifically, without having to install and configure an MTA such as exim or postfix). All you need is:

1. sudo apt-get install curl
2. put your smtp credentials at the top of the script
3. make this script executable and put it in your PATH (on my system, the script is called easymail)

I thought I'd share it here in case anyone else has use for it. If you see anything in it that could be improved, please let me know.

Cheers,
Bruno

#!/bin/sh

# Purpose: To send email as simply as possible (i.e., without needing to install an MTA 
# such as exim or postfix). The script's only dependencies are curl and coreutils on Linux,
# curl and gcoreutils on OpenBSD.
#
# Note about regular vs. root user: Either one can use this script :)
#
# Note about CA ssl certificates on computer/phone:
# If they are missing, add --insecure to the curl command.
#
# Author: Bruno "GNUser" Dantas
# License: GPLv3
# Version: 3.0 (27Mar2019)
# Changelog:
#	- working on Devuan ASCII and OpenBSD 6.4
#	- body not mandatory
#	- no bashisms

# smtp credentials
host='smtps://my.email.com'
port='993'
user='my-username'
password='secretPasswoRd'

main()
{
	get_stdin
	get_commandline_options "$@"
	build_eml_file
	wait_for_internet
	send_eml_file
}

show_usage()
{
	echo "Usage: easymail -d <destination> [-s <subject>] [-b <body>] [-a <attachment>]

Notes:
 - destination: an email address (if multiple, precede each one with -d)
 - subject: a string
 - body: stdin, -b string, or -b file (note: -b flag takes precedence over stdin). examples:
	 1. echo 'some string' | easymail
	 2. easymail </path/to/some-text-file
	 3. easymail -b 'some string'
	 4. easymail -b /path/to/some-text-file
 - attachment: a file (if multiple, precede each one with -a)

Example:
 easymail -d somebody@somewhere.com -s 'Devuan' -b 'Devuan rocks!' -a fork.pdf"
}

attach()
{
	# create an attachments file if one does not exist yet
	[ -z $attachments_file ] && attachments_file=$(mktemp)

	# now append the attachment to the attachments file
	filename="$(basename "$1")"
	echo "------7II5XTH4IPXG2QZOY8LJF98QQX4IR3
Content-Transfer-Encoding: base64
Content-Type: application/octet-stream;
 name=\"$filename\"
Content-Disposition: attachment;
 filename=\"$filename\";
" >>$attachments_file

	if uname | grep -qi BSD; then
		cat "$1" | b64encode poop | tail -n +2 >>$attachments_file
	else # Linux
		cat "$1" | base64 >>$attachments_file
	fi
}

cleanup()
{
	rm -f $eml_file $attachments_file
}
trap cleanup EXIT HUP TERM INT

get_stdin()
{
	if uname | grep -qi BSD; then
		body="$(gtimeout 1 dd bs=1 count=1 2>/dev/null && cat)"
	else # Linux
		body="$(timeout 1 dd bs=1 count=1 2>/dev/null && cat)"
	fi

	# dd has 1 sec to get 1 byte, which is plenty of time if there is data
	# in stdin waiting to be read. If dd succeeds, it passes its byte to stdout
	# and triggers cat, which has unlimited time to get remaining data.
	# This seems complicated but is necessary: using just cat causes script to 
	# hang if there is no data in stdin.
}

get_commandline_options()
{
	while [ "$#" -gt 0 ]; do
		case "$1" in
			-d)	
				curl_destination="${curl_destination}--mail-rcpt $2 "
				header_destination="${header_destination}$2, "
				shift 2
				;;
			-s) 
				subject="$2"
				shift 2
				;;
			-b) 
				body="$2"
				shift 2
				;;
			-a) 
				attach "$2"
				shift 2
				;;
			-*)
				echo "Invalid option: $1"
				shift
				;;
			*)
				shift
				;;
		esac
	done
}

build_eml_file()
{
	# create header
	eml_file=$(mktemp)
	echo "MIME-Version: 1.0
Content-Type: multipart/mixed; boundary=\"----7II5XTH4IPXG2QZOY8LJF98QQX4IR3\"
Content-Transfer-Encoding: 8bit
Subject: $subject
From: Easymail <easymail@suckless.nix>
Date: $(date)
To: $header_destination

------7II5XTH4IPXG2QZOY8LJF98QQX4IR3
Content-Transfer-Encoding: 8bit
Content-Type: text/plain;
 charset=UTF-8
" >$eml_file

	# append body
	if [ -f "$body" ]; then
		cat "$body" >>$eml_file
	else
		echo "$body" >>$eml_file
	fi

	# append attachment(s) if applicable
	if [ -f "$attachments_file" ]; then
		cat "$attachments_file" >>$eml_file
	fi
}

wait_for_internet()
{
	while true; do
		wget --spider --timeout=2 -o /dev/null duckduckgo.com && return 0
		sleep 1
	done
}

send_eml_file()
{
	curl --url ${host}:${port} --ssl-reqd --upload-file $eml_file $curl_destination --user ${user}:${password} >/dev/null 2>&1
}

if [ "$#" -le 1 ]; then
	show_usage
else
	main "$@"
fi

Last edited by GNUser (2019-03-29 19:18:41)

Offline

Board footer