Dobrý, nebránil bych se použití jednoho malého cat místo hromady ech :) Návratové kódy lze číst v cyklu dokud za 3cif. číslem není mezera (${tmp:3:1} != " "), a to pak ověřit že je to to co čekáme (EHLO -> 250, AUTH LOGIN -> 334, $user -> dtto, $pass -> 235, MAIL FROM -> 250, RCPT TO -> dtto, DATA -> 354, . -> 250).
Jasně, tvůj proof of concept po refaktoringu dopadl takto. Díky procedurálnímu přístupu se výkonná část omezila na dvě funkce, zpráva samotná se snáze zapíše bez \r v úvodu skriptu, a komunikace se serverm v hlavní části je o něco čitelnější a snáze upravitelná např. pro jiné typy autentizace, např. když se musíte logovat. Upozorňui že SMTP protokol jsem nijak detailně nezkoumal, v zásadě jsem vyšel jen z toho tvého funkčního návrhu.
#!/bin/bash
from="me@exmaple.org"
to="you@example.org"
subject="Ignore"
message="Test message 1
2
3
4
5"
signature="My Signature"
mailserver="localhost"
servername="myserver"
#user="username"
#pass=""
header="Subject: $subject
From: $from
To: $to
Reply-To: $from
Return-Path: $from
Content-type: text/plain
X-Mailer: Bash"
msg="$header
$message
--
$signature
."
#auth=`perl -MMIME::Base64 -e "print encode_base64(\"\0$user\0$pass\");"`
#auth=$(echo -ne "\0$user\0$pass" | openssl enc -base64)
parse_reply() {
local rcode="$1"
local reply=""
while [[ ${reply:3:1} != " " ]]; do
read -r reply <&9
echo "$reply"
done
if [[ "${reply:0:3}" != "$rcode" ]]; then
echo "ERROR? Unexpected reply code: ${reply:0:3} != $rcode"
fi
}
snd() {
local msg="$1"$'\x0a'
local rcode="$2"
echo "$msg"
echo -en "${msg//$'\x0a'/$'\x0d\x0a'}" >&9
parse_reply "$rcode"
}
exec 9<>/dev/tcp/$mailserver/25
parse_reply "220"
snd "EHLO $servername" 250
#snd "AUTH PLAIN $auth"
#snd "$user"
#snd "$pass"
snd "MAIL FROM: <$from>" 250
snd "RCPT TO: <$to>" 250
snd "DATA" 354
snd "$msg" 250
snd "QUIT" 221
9>&-
9<&-
exit 0