--!movie
--!encoding=utf-8
--****************************************************************************
-- @file Curl SMTP demo
-- @author Valentin Schmidt
-- @version 0.6
-- @requires Curl Xtra + wrapper lib "curl"
-- @requires FileIO Xtra + wrapper lib "file"
-- @requires lib "base64"
-- @requires lib "date"
--****************************************************************************
global $
----------------------------------------
--
----------------------------------------
on startMovie
_player.debugPlaybackEnabled = 1
-- libs
$.import("base64")
$.import("curl")
$.import("date")
$.import("file")
host = "wp227.webpack.hosteurope.de" -- actual smtp host here
port = 465 -- 465 for SSL, 587 for STARTTLS
usr = "******" -- actual username here
pwd = "******" -- actual password here
from = "me@dasdeck.com"
recipients = "john@domain.com" -- or: recipients = ["john@domain.com", "me@dasdeck.com"]
subject = "SMTP/SSL with Curl Xtra"
message_plain = ""
put "Hi John," & $.CRLF & $.CRLF after message_plain
put "this is the plain text part of an email sent with Curl Xtra." & $.CRLF after message_plain
put "The email has an attached video file and an inline image." & $.CRLF & $.CRLF after message_plain
put "[image]" & $.CRLF & $.CRLF after message_plain
put "Cheers," & $.CRLF after message_plain
put "Valentin" & $.CRLF after message_plain
message_html = ""
put "<!DOCTYPE HTML><html lang='en'><head><meta charset='utf-8'></head>" & $.CRLF after message_html
put "<body>" & $.CRLF after message_html
put "<b>Hi John,</b><br><br>" & $.CRLF after message_html
put "this is the HTML part of an email sent with Curl Xtra.<br>" & $.CRLF after message_html
put "The email has an attached video file and an inline image.<br><br>" & $.CRLF after message_html
put "<img src='{{1}}' width='256' height='256' alt='lena'><br><br>" & $.CRLF after message_html
put "Cheers,<br>" & $.CRLF after message_html
put "Valentin" & $.CRLF after message_html
put "</body>" & $.CRLF after message_html
put "</html>" & $.CRLF after message_html
files_attached = ["C:\test\bbb_360p_24fps_10sec.mp4"]
files_inline = ["C:\test\lena_256.jpg"]
res = sendMail(host, port, usr, pwd, from, recipients, subject, message_plain, message_html, files_attached, files_inline)
if res = 0 then
put "Email sent successfully"
else
put "Error sending email: " & curl_error(res)
end if
end
----------------------------------------
-- Sends email with SMTP
-- @param {string} host
-- @param {integer} port - standard SMTP ports: 25=no security, 465=SSL/TLS, 587=STARTTLS
-- @param {string} usr
-- @param {string} pwd
-- @param {string} from
-- @param {string|list} recipients - single recipient as string or multiple recipients as list
-- @param {string} subject
-- @param {string} message_plain - the plain text part
-- @param {string} [message_html=VOID] - the HTML part (optional)
-- @param {list} [files_attached=VOID] - list of files attached to email (optional)
-- @param {list} [files_inline=VOID] - list of files embedded into HTML part (optional)
-- @param {boolean} [force_ssl=FALSE] - force SSL also for port <> 465
-- @return {integer} curl error code, 0 = success
----------------------------------------
on sendMail (host, port, usr, pwd, from, recipients, subject, message_plain, message_html, files_attached, files_inline, force_ssl)
if stringP(recipients) then recipients = [recipients]
if voidP(message_html) then message_html = ""
if voidP(files_inline) then files_inline = []
if voidP(files_attached) then files_attached = []
to_header = recipients[1]
repeat with i = 2 to recipients.count
put ", " & recipients[i] after to_header
end repeat
if port=465 or force_ssl then
smpt_url = "smtps://"
else
smpt_url = "smtp://"
end if
put usr & ":" & pwd & "@" & host & ":" & string(port) after smpt_url
-- create message, save as temporary file
tmpFile = $.PATH & "~mail.eml" -- in case of an installed app, use the user's TMP dir instead
fp = $.file.fopen(tmpFile, "wb")
-- to keep the spam score as low as possible, we add both Date and Message-ID headers
fp.writeString("Date: " && $.date.createUTCDateString() & $.CRLF)
fp.writeString("Message-ID: <" & uid() & "@" & host & ">" & $.CRLF)
fp.writeString("To: " & to_header & $.CRLF)
fp.writeString("From: " & from & $.CRLF)
fp.writeString("Subject: " & mime_encode(subject) & $.CRLF)
fp.writeString("User-Agent: Curl Xtra/" & xtraVersion(#curl) & $.CRLF) -- completely optional
fp.writeString("MIME-Version: 1.0" & $.CRLF)
cnt_files_attached = count(files_attached)
cnt_files_inline = count(files_inline)
if cnt_files_attached=0 and message_html="" then
fp.writeString("Content-Type: text/plain; charset=utf-8" & $.CRLF)
fp.writeString("Content-Transfer-Encoding: 8bit" & $.CRLF)
fp.writeString($.CRLF)
fp.writeString(message_plain)
else
if cnt_files_attached then
boundary_mixed = "------------" & uid()
fp.writeString("Content-Type: multipart/mixed; boundary=" & QUOTE & boundary_mixed & QUOTE & $.CRLF & $.CRLF)
fp.writeString("This is a multi-part message in MIME format." & $.CRLF)
if message_html<>"" then
-- files_attached and html
fp.writeString("--" & boundary_mixed & $.CRLF)
boundary_alternative = "------------" & uid()
fp.writeString("Content-Type: multipart/alternative; boundary=" & QUOTE & boundary_alternative & QUOTE & $.CRLF & $.CRLF)
write_mime_part(fp, "text/plain", message_plain, boundary_alternative)
if cnt_files_inline then
fp.writeString("--" & boundary_alternative & $.CRLF)
boundary_related = "------------" & uid()
fp.writeString("Content-Type: multipart/related; boundary=" & QUOTE & boundary_related & QUOTE & $.CRLF & $.CRLF)
content_ids = []
repeat with i = 1 to cnt_files_inline
content_ids[i] = "part" & i & "." & uid() & "@" & host
pos = offset("{{" & i & "}}", message_html)
if pos then
message_html = message_html.char[1..pos-1] & "cid:" & content_ids[i] & message_html.char[pos+length("{{" & i & "}}")..message_html.length]
end if
end repeat
write_mime_part(fp, "text/html", message_html, boundary_related)
repeat with i = 1 to cnt_files_inline
f = files_inline[i]
fn = $.file.getFileName(f)
fp.writeString("--" & boundary_related & $.CRLF)
fp.writeString("Content-Type: " & mime_type($.file.getFileType(f)) & "; name=" & QUOTE & fn & QUOTE & $.CRLF)
fp.writeString("Content-Transfer-Encoding: base64" & $.CRLF)
fp.writeString("Content-ID: <" & content_ids[i] & ">" & $.CRLF)
fp.writeString("Content-Disposition: inline; filename=" & QUOTE & fn & QUOTE & $.CRLF & $.CRLF)
fp.writeString($.base64.encode($.file.getBytes(f), True) & $.CRLF & $.CRLF)
end repeat
fp.writeString("--" & boundary_related & "--" & $.CRLF & $.CRLF)
else
write_mime_part(fp, "text/html", message_html, boundary_alternative)
end if
fp.writeString("--" & boundary_alternative & "--" & $.CRLF & $.CRLF)
else
-- files_attached, no html
write_mime_part(fp, "text/plain", message_plain, boundary_mixed)
end if
repeat with f in files_attached
fn = $.file.getFileName(f)
fp.writeString("--" & boundary_mixed & $.CRLF)
fp.writeString("Content-Type: " & mime_type($.file.getFileType(f)) & "; name=" & QUOTE & fn & QUOTE & $.CRLF)
fp.writeString("Content-Transfer-Encoding: base64" & $.CRLF)
fp.writeString("Content-Disposition: attachment; filename=" & QUOTE & fn & QUOTE & $.CRLF & $.CRLF)
fp.writeString($.base64.encode($.file.getBytes(f), True) & $.CRLF & $.CRLF)
end repeat
fp.writeString("--" & boundary_mixed & "--" & $.CRLF)
else
-- html, no files_attached
boundary_alternative = "------------" & uid()
fp.writeString("Content-Type: multipart/alternative; boundary=" & QUOTE & boundary_alternative & QUOTE & $.CRLF & $.CRLF)
fp.writeString("This is a multi-part message in MIME format." & $.CRLF)
write_mime_part(fp, "text/plain", message_plain, boundary_alternative)
if cnt_files_inline then
fp.writeString("--" & boundary_alternative & $.CRLF)
boundary_related = "------------" & uid()
fp.writeString("Content-Type: multipart/related; boundary=" & QUOTE & boundary_related & QUOTE & $.CRLF & $.CRLF)
content_ids = []
repeat with i = 1 to cnt_files_inline
content_ids[i] = "part" & i & "." & uid() & "@" & host
pos = offset("{{" & i & "}}", message_html)
if pos then
message_html = message_html.char[1..pos-1] & "cid:" & content_ids[i] & message_html.char[pos+length("{{" & i & "}}")..message_html.length]
end if
end repeat
write_mime_part(fp, "text/html", message_html, boundary_related)
repeat with i = 1 to cnt_files_inline
f = files_inline[i]
fn = $.file.getFileName(f)
fp.writeString("--" & boundary_related & $.CRLF)
fp.writeString("Content-Type: " & mime_type($.file.getFileType(f)) & "; name=" & QUOTE & fn & QUOTE & $.CRLF)
fp.writeString("Content-Transfer-Encoding: base64" & $.CRLF)
fp.writeString("Content-ID: <" & content_ids[i] & ">" & $.CRLF)
fp.writeString("Content-Disposition: inline; filename=" & QUOTE & fn & QUOTE & $.CRLF & $.CRLF)
fp.writeString($.base64.encode($.file.getBytes(f), True) & $.CRLF & $.CRLF)
end repeat
fp.writeString("--" & boundary_related & "--" & $.CRLF & $.CRLF)
else
write_mime_part(fp, "text/html", message_html, boundary_alternative)
end if
fp.writeString("--" & boundary_alternative & "--" & $.CRLF)
end if
end if
$.file.fclose(fp)
-- get a CURL handle (xtra instance)
ch = $.curl.init()
-- specify options
--ch.setOption($.curl.CURLOPT.VERBOSE, 1) -- for debugging, prints to stdout
ch.setOption($.curl.CURLOPT.URL, smpt_url)
ch.setOption($.curl.CURLOPT.MAIL_FROM, from)
ch.setOption($.curl.CURLOPT.MAIL_RCPT, recipients)
ch.setOption($.curl.CURLOPT.SSL_VERIFYPEER, 0)
ch.setOption($.curl.CURLOPT.SSL_VERIFYHOST, 0)
ch.setOption($.curl.CURLOPT.UPLOAD, 1)
ch.setSourceFile(tmpFile)
-- execute request
res = ch.exec()
$.file.delete(tmpFile)
return res
end
----------------------------------------
--
----------------------------------------
on write_mime_part (fp, content_type, str, boundary)
fp.writeString("--" & boundary & $.CRLF)
fp.writeString("Content-Type: " & content_type & "; charset=utf-8" & $.CRLF)
fp.writeString("Content-Transfer-Encoding: 8bit" & $.CRLF)
fp.writeString($.CRLF)
fp.writeString(str)
fp.writeString($.CRLF & $.CRLF)
end
----------------------------------------
--
----------------------------------------
on mime_encode (str)
return "=?UTF-8?B?" & $.base64.encode(str) & "?="
end
----------------------------------------
--
----------------------------------------
on mime_type (t)
case t of
"3gp": return "video/3gpp"
"3g2": return "video/3gpp2"
"7z": return "application/x-7z-compressed"
"aac": return "audio/aac"
"abw": return "application/x-abiword"
"aif", "aiff": return "audio/x-aiff"
"arc": return "application/octet-stream"
"avi": return "video/x-msvideo"
"azw": return "application/vnd.amazon.ebook"
"bin": return "application/octet-stream"
"bmp": return "image/bmp"
"bz": return "application/x-bzip"
"bz2": return "application/x-bzip2"
"csh": return "application/x-csh"
"css": return "text/css"
"csv": return "text/csv"
"dcr", "dir", "dxr": return "application/x-director"
"doc": return "application/msword"
"docx": return "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
"eot": return "application/vnd.ms-fontobject"
"epub": return "application/epub+zip"
"gif": return "image/gif"
"gz": return "application/gzip"
"htm", "html": return "text/html"
"ico": return "image/x-icon"
"ics": return "text/calendar"
"jar": return "application/java-archive"
"jpeg", "jpg": return "image/jpeg"
"js": return "application/javascript"
"json": return "application/json"
"mid", "midi": return "audio/midi"
"mov": return "video/quicktime"
"mp3": return "audio/mpeg"
"mp4": return "video/mp4"
"mpg", "mpeg": return "video/mpeg"
"mpkg": return "application/vnd.apple.installer+xml"
"odp": return "application/vnd.oasis.opendocument.presentation"
"ods": return "application/vnd.oasis.opendocument.spreadsheet"
"odt": return "application/vnd.oasis.opendocument.text"
"oga","ogg": return "audio/ogg"
"ogv": return "video/ogg"
"otf": return "font/otf"
"png": return "image/png"
"pdf": return "application/pdf"
"ppt": return "application/vnd.ms-powerpoint"
"pptx": return "application/vnd.openxmlformats-officedocument.presentationml.presentation"
"rar": return "application/x-rar-compressed"
"rtf": return "application/rtf"
"sh": return "application/x-sh"
"svg": return "image/svg+xml"
"swf": return "application/x-shockwave-flash"
"tar": return "application/x-tar"
"tif", "tiff": return "image/tiff"
"ts": return "application/typescript"
"ttf": return "font/ttf"
"txt": return "text/plain"
"vsd": return "application/vnd.visio"
"wav": return "audio/wav"
"weba": return "audio/webm"
"webm": return "video/webm"
"webp": return "image/webp"
"woff": return "font/woff"
"woff2": return "font/woff2"
"xhtml": return "application/xhtml+xml"
"xls": return "application/vnd.ms-excel"
"xlsx": return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
"xml": return "application/xml"
"zip": return "application/zip"
end case
return "application/octet-stream"
end
----------------------------------------
--
----------------------------------------
on xtraVersion (xtraName)
xtraName = symbol(xtraName)
repeat with x in _player.scriptingXtraList
if value("x.name") = xtraName then return value("x.version")
end repeat
end
----------------------------------------
-- "unique id" - not guaranteed to be unique, but most likely
----------------------------------------
on uid
return string(random(the maxInteger) & "-" & random(the maxInteger) & "-" & random(the maxInteger))
end