E-Mails mit Lua via SSMTP versenden

SSMTP

Das Programm SSMTP ist ein sehr einfacher Mail-Transport Agent, der bei Bedarf die zu versendene E-Mail an einen entsprechenden Server weiterleitet. Es leitet die — auf vielen Unix-Systemen verwendeten — Befehle zum E-Mail-Versand sendmail sowie mail auf sich um. Das Programm läuft jedoch nicht als Server und bricht bei Fehlern schlicht mit einer Fehlermeldung den Versand ab. SSMTP ist auf vielen Linux-Distributionen über Pakete verfügbar und somit leicht installierbar. Seine Konfiguration hängt von dem verwendeten Provider und dessen E-Mail-Einstellungen ab. Für einen einfachen Provider kann die folgende Konfiguration der Datei /etc/ssmtp.conf (oder — in Abhängigkeit der verwendeten Distribution — aber auch /etc/ssmtp/ssmtp.conf) möglicherweise als Beispiel dienen.

root=postmaster
mailhub=smtp.provider.net:465
hostname=mein.server.com
FromLineOverride=NO
UseTLS=YES
AuthUser=username
AuthPass=passwort

Auf der Shell kann die Konfiguration durch den Befehl
printf "SUBJECT: Betreff-Zeile\nFROM: von@mir.de\nTO: zu@dir.de\n\nHallo\nBody" | ssmtp zu@dir.de
getestet werden. Man beachte, dass der Empfänger zu@dir.de hier doppelt angegeben wird: Die erste Angabe dient dabei lediglich der Anzeige in der E-Mail, die dem Empfänger (zweite Angabe) angezeigt wird.

Achtung: Die in der Datei revaliases hinterlegten Daten für einzelne System-Benutzer haben Vorrang und überschreiben somit die beim Abschicken angegebenen FROM-Adresse.

Lua

Die Skript-Sprache Lua hat sich als sehr effizient und performant erwiesen, so dass es gerne im VoIP- sowie im Game-Umfeld eingesetzt wird. Aber auch im Web-Bereich findet es mit bspw. HASERL oder in LuCi Verwendung.

Das einfache Versenden einer reinen Text-E-Mail ist über den Umweg eines Shell-Befehles möglich.

local sendto = "zu@dir.de"
local sendfrom = "von@mir.de"
local subject = "Betreff-Zeile"
local body ="Text der E-Mail\nmit dem Zeichen \\\"\\\\\\n\\\" werden die Zeilen voneinander getrennt."
local header ="Subject: "..subject .."\nFrom: "..sendfrom.."\nTo: "..sendto .."\n"

os.execute("echo -e \""..header .."\n"..body.."\" |ssmtp ".. sendto)

Sollen jedoch auch Dateien der E-Mail beigefügt werden, so sollte der Inhalt der E-Mail richtig als mehrteilig formatiert werden. Da Dateien im Allgemeinen oft nicht nur ASCII-Zeichen beinhalten, sind diese vor dem Versand mit Base64 zu encodieren.

-- Lua 5.1+ base64 v3.0 (c) 2009 by Alex Kloss 
-- licensed under the terms of the LGPL2
local b='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
function base64(data)
    return ((data:gsub('.', function(x)
        local r,b='',x:byte()
        for i=8,1,-1 do r=r..(b%2^i-b%2^(i-1)>0 and '1' or '0') end
        return r;
    end)..'0000'):gsub('%d%d%d?%d?%d?%d?', function(x)
        if (#x < 6) then return '' end
        local c=0
        for i=1,6 do c=c+(x:sub(i,i)=='1' and 2^(6-i) or 0) end
        return b:sub(c+1,c+1)
    end)..({ '', '==', '=' })[#data%3+1])
end

Damit kann der Versand einer TIFF-Datei und einer PDF-Datei mit Lua wie folgt geschehen.

local sendto = "zu@dir.de"
local sendfrom = "von@mir.de"
local subject = "Betreff-Zeile"
local body ="Text der E-Mail\nmit dem Zeichen \\\"\\\\\\n\\\" werden die Zeilen voneinander getrennt."
local files = {"/pfad/zur/Datei.tif","/pfad/zur/Datei.pdf"}

local header ="Subject: "..subject .."\nFrom: "..sendfrom.."\nTo: "..sendto .."\n"
local contentType = {["tif"]="image/tiff",["pdf"]="application/pdf",["wav"]="audio/wav"}
local boundary = "--------voiscout-boundary-------"
local mailbody = "MIME-Version: 1.0\n"..
      "Content-Type: multipart/mixed; boundary="..boundary.."\n\n"..
      "This is a multi-part message in MIME format.\n--"..boundary.."\n" ..
      "Content-Type: text/plain; charset=iso-8859-1\n"..
      "Content-Transfer-Encoding: 8bit\n\n"..body.."\n--"..boundary

for i,file in ipairs(files) do
  local filename = file:match("[^/]*$")
  local f = io.open(file, "r")
  if f then
     local filecontent = f:read("*all")
     f:close()
     if filecontent then
        mailbody = mailbody .."\n"..
            "Content-Type: "..contentType[filename:match("[^\.]*$")].."; name=\\\""..filename.."\\\"\n"..
            "Content-Transfer-Encoding: base64\n"..
            "Content-Disposition: attachment; filename=\\\""..filename.."\\\"\n\n" 
            ..base64(filecontent).."\n--"..boundary
      end 
   end 
end                                                           
os.execute("echo -e \""..header..mailbody.."--\" |ssmtp "..sendto)